Annotation of src/usr.bin/telnet/telnet.c, Revision 1.16
1.16 ! millert 1: /* $OpenBSD: telnet.c,v 1.15 2002/03/22 13:49:28 hin Exp $ */
1.2 niklas 2: /* $NetBSD: telnet.c,v 1.7 1996/02/28 21:04:15 thorpej Exp $ */
3:
1.1 deraadt 4: /*
5: * Copyright (c) 1988, 1990, 1993
6: * The Regents of the University of California. All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
1.16 ! millert 16: * 3. Neither the name of the University nor the names of its contributors
1.1 deraadt 17: * may be used to endorse or promote products derived from this software
18: * without specific prior written permission.
19: *
20: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30: * SUCH DAMAGE.
31: */
32:
1.4 art 33: #include "telnet_locl.h"
1.9 millert 34: #include <curses.h>
35: #include <term.h>
1.1 deraadt 36:
1.4 art 37: #define strip(x) (eight ? (x) : ((x) & 0x7f))
1.1 deraadt 38:
39: static unsigned char subbuffer[SUBBUFSIZE],
40: *subpointer, *subend; /* buffer for sub-options */
41: #define SB_CLEAR() subpointer = subbuffer;
42: #define SB_TERM() { subend = subpointer; SB_CLEAR(); }
43: #define SB_ACCUM(c) if (subpointer < (subbuffer+sizeof subbuffer)) { \
44: *subpointer++ = (c); \
45: }
46:
47: #define SB_GET() ((*subpointer++)&0xff)
48: #define SB_PEEK() ((*subpointer)&0xff)
49: #define SB_EOF() (subpointer >= subend)
50: #define SB_LEN() (subend - subpointer)
51:
52: char options[256]; /* The combined options */
53: char do_dont_resp[256];
54: char will_wont_resp[256];
55:
56: int
1.4 art 57: eight = 3,
58: binary = 0,
1.1 deraadt 59: autologin = 0, /* Autologin anyone? */
60: skiprc = 0,
61: connected,
62: showoptions,
63: In3270, /* Are we in 3270 mode? */
64: ISend, /* trying to send network data in */
65: debug = 0,
66: crmod,
67: netdata, /* Print out network data flow */
68: crlf, /* Should '\r' be mapped to <CR><LF> (or <CR><NUL>)? */
69: #if defined(TN3270)
70: noasynchtty = 0,/* User specified "-noasynch" on command line */
71: noasynchnet = 0,/* User specified "-noasynch" on command line */
72: askedSGA = 0, /* We have talked about suppress go ahead */
73: #endif /* defined(TN3270) */
74: telnetport,
1.15 hin 75: wantencryption = 0,
1.1 deraadt 76: SYNCHing, /* we are in TELNET SYNCH mode */
77: flushout, /* flush output */
78: autoflush = 0, /* flush output when interrupting? */
79: autosynch, /* send interrupt characters with SYNCH? */
80: localflow, /* we handle flow control locally */
81: restartany, /* if flow control enabled, restart on any character */
82: localchars, /* we recognize interrupt/quit */
83: donelclchars, /* the user has set "localchars" */
84: donebinarytoggle, /* the user has put us in binary */
85: dontlecho, /* do we suppress local echoing right now? */
86: globalmode,
87: clienteof = 0;
88:
89: char *prompt = 0;
90:
1.15 hin 91: int scheduler_lockout_tty = 0;
92:
1.1 deraadt 93: cc_t escape;
94: cc_t rlogin;
95: #ifdef KLUDGELINEMODE
96: cc_t echoc;
97: #endif
98:
99: /*
100: * Telnet receiver states for fsm
101: */
102: #define TS_DATA 0
103: #define TS_IAC 1
104: #define TS_WILL 2
105: #define TS_WONT 3
106: #define TS_DO 4
107: #define TS_DONT 5
108: #define TS_CR 6
109: #define TS_SB 7 /* sub-option collection */
110: #define TS_SE 8 /* looking for sub-option end */
111:
112: static int telrcv_state;
113: #ifdef OLD_ENVIRON
114: unsigned char telopt_environ = TELOPT_NEW_ENVIRON;
115: #else
116: # define telopt_environ TELOPT_NEW_ENVIRON
117: #endif
118:
119: jmp_buf toplevel = { 0 };
120: jmp_buf peerdied;
121:
122: int flushline;
123: int linemode;
124:
125: #ifdef KLUDGELINEMODE
126: int kludgelinemode = 1;
127: #endif
128:
129: /*
130: * The following are some clocks used to decide how to interpret
131: * the relationship between various variables.
132: */
133:
134: Clocks clocks;
135:
136:
137: /*
138: * Initialize telnet environment.
139: */
140:
141: void
142: init_telnet()
143: {
144: env_init();
145:
146: SB_CLEAR();
1.4 art 147: memset((char *)options, 0, sizeof options);
1.1 deraadt 148:
149: connected = In3270 = ISend = localflow = donebinarytoggle = 0;
1.4 art 150: #if defined(AUTHENTICATION) || defined(ENCRYPTION)
1.1 deraadt 151: auth_encrypt_connect(connected);
1.4 art 152: #endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */
1.1 deraadt 153: restartany = -1;
154:
155: SYNCHing = 0;
156:
157: /* Don't change NetTrace */
158:
159: escape = CONTROL(']');
160: rlogin = _POSIX_VDISABLE;
161: #ifdef KLUDGELINEMODE
162: echoc = CONTROL('E');
163: #endif
164:
165: flushline = 1;
166: telrcv_state = TS_DATA;
167: }
168:
169:
170: /*
171: * These routines are in charge of sending option negotiations
172: * to the other side.
173: *
174: * The basic idea is that we send the negotiation if either side
175: * is in disagreement as to what the current state should be.
176: */
177:
178: void
179: send_do(c, init)
1.13 mpech 180: int c, init;
1.1 deraadt 181: {
182: if (init) {
183: if (((do_dont_resp[c] == 0) && my_state_is_do(c)) ||
184: my_want_state_is_do(c))
185: return;
186: set_my_want_state_do(c);
187: do_dont_resp[c]++;
188: }
189: NET2ADD(IAC, DO);
190: NETADD(c);
1.12 hin 191: printoption("SENT",DO, c);
1.1 deraadt 192: }
193:
194: void
195: send_dont(c, init)
1.13 mpech 196: int c, init;
1.1 deraadt 197: {
198: if (init) {
199: if (((do_dont_resp[c] == 0) && my_state_is_dont(c)) ||
200: my_want_state_is_dont(c))
201: return;
202: set_my_want_state_dont(c);
203: do_dont_resp[c]++;
204: }
205: NET2ADD(IAC, DONT);
206: NETADD(c);
207: printoption("SENT", DONT, c);
208: }
209:
210: void
211: send_will(c, init)
1.13 mpech 212: int c, init;
1.1 deraadt 213: {
214: if (init) {
215: if (((will_wont_resp[c] == 0) && my_state_is_will(c)) ||
216: my_want_state_is_will(c))
217: return;
218: set_my_want_state_will(c);
219: will_wont_resp[c]++;
220: }
221: NET2ADD(IAC, WILL);
222: NETADD(c);
223: printoption("SENT", WILL, c);
224: }
225:
226: void
227: send_wont(c, init)
1.13 mpech 228: int c, init;
1.1 deraadt 229: {
230: if (init) {
231: if (((will_wont_resp[c] == 0) && my_state_is_wont(c)) ||
232: my_want_state_is_wont(c))
233: return;
234: set_my_want_state_wont(c);
235: will_wont_resp[c]++;
236: }
237: NET2ADD(IAC, WONT);
238: NETADD(c);
239: printoption("SENT", WONT, c);
240: }
241:
242:
243: void
244: willoption(option)
245: int option;
246: {
247: int new_state_ok = 0;
248:
249: if (do_dont_resp[option]) {
250: --do_dont_resp[option];
251: if (do_dont_resp[option] && my_state_is_do(option))
252: --do_dont_resp[option];
253: }
254:
255: if ((do_dont_resp[option] == 0) && my_want_state_is_dont(option)) {
256:
257: switch (option) {
258:
259: case TELOPT_ECHO:
260: # if defined(TN3270)
261: /*
262: * The following is a pain in the rear-end.
263: * Various IBM servers (some versions of Wiscnet,
264: * possibly Fibronics/Spartacus, and who knows who
265: * else) will NOT allow us to send "DO SGA" too early
266: * in the setup proceedings. On the other hand,
267: * 4.2 servers (telnetd) won't set SGA correctly.
268: * So, we are stuck. Empirically (but, based on
269: * a VERY small sample), the IBM servers don't send
270: * out anything about ECHO, so we postpone our sending
271: * "DO SGA" until we see "WILL ECHO" (which 4.2 servers
272: * DO send).
273: */
274: {
275: if (askedSGA == 0) {
276: askedSGA = 1;
277: if (my_want_state_is_dont(TELOPT_SGA))
278: send_do(TELOPT_SGA, 1);
279: }
280: }
281: /* Fall through */
282: case TELOPT_EOR:
283: #endif /* defined(TN3270) */
284: case TELOPT_BINARY:
285: case TELOPT_SGA:
286: settimer(modenegotiated);
287: /* FALL THROUGH */
288: case TELOPT_STATUS:
289: #if defined(AUTHENTICATION)
290: case TELOPT_AUTHENTICATION:
291: #endif
1.4 art 292: #if defined(ENCRYPTION)
293: case TELOPT_ENCRYPT:
294: #endif
1.1 deraadt 295: new_state_ok = 1;
296: break;
297:
298: case TELOPT_TM:
299: if (flushout)
300: flushout = 0;
301: /*
302: * Special case for TM. If we get back a WILL,
303: * pretend we got back a WONT.
304: */
305: set_my_want_state_dont(option);
306: set_my_state_dont(option);
307: return; /* Never reply to TM will's/wont's */
308:
309: case TELOPT_LINEMODE:
310: default:
311: break;
312: }
313:
314: if (new_state_ok) {
315: set_my_want_state_do(option);
316: send_do(option, 0);
317: setconnmode(0); /* possibly set new tty mode */
318: } else {
319: do_dont_resp[option]++;
320: send_dont(option, 0);
321: }
322: }
323: set_my_state_do(option);
1.4 art 324: #if defined(ENCRYPTION)
325: if (option == TELOPT_ENCRYPT)
326: encrypt_send_support();
327: #endif
328:
1.1 deraadt 329: }
330:
331: void
332: wontoption(option)
333: int option;
334: {
335: if (do_dont_resp[option]) {
336: --do_dont_resp[option];
337: if (do_dont_resp[option] && my_state_is_dont(option))
338: --do_dont_resp[option];
339: }
340:
341: if ((do_dont_resp[option] == 0) && my_want_state_is_do(option)) {
342:
343: switch (option) {
344:
345: #ifdef KLUDGELINEMODE
346: case TELOPT_SGA:
347: if (!kludgelinemode)
348: break;
349: /* FALL THROUGH */
350: #endif
351: case TELOPT_ECHO:
352: settimer(modenegotiated);
353: break;
354:
355: case TELOPT_TM:
356: if (flushout)
357: flushout = 0;
358: set_my_want_state_dont(option);
359: set_my_state_dont(option);
360: return; /* Never reply to TM will's/wont's */
361:
1.4 art 362: #ifdef ENCRYPTION
363: case TELOPT_ENCRYPT:
364: encrypt_not();
365: break;
366: #endif
1.1 deraadt 367: default:
368: break;
369: }
370: set_my_want_state_dont(option);
371: if (my_state_is_do(option))
372: send_dont(option, 0);
373: setconnmode(0); /* Set new tty mode */
374: } else if (option == TELOPT_TM) {
375: /*
376: * Special case for TM.
377: */
378: if (flushout)
379: flushout = 0;
380: set_my_want_state_dont(option);
381: }
382: set_my_state_dont(option);
383: }
384:
385: static void
386: dooption(option)
387: int option;
388: {
389: int new_state_ok = 0;
390:
391: if (will_wont_resp[option]) {
392: --will_wont_resp[option];
393: if (will_wont_resp[option] && my_state_is_will(option))
394: --will_wont_resp[option];
395: }
396:
397: if (will_wont_resp[option] == 0) {
398: if (my_want_state_is_wont(option)) {
399:
400: switch (option) {
401:
402: case TELOPT_TM:
403: /*
404: * Special case for TM. We send a WILL, but pretend
405: * we sent WONT.
406: */
407: send_will(option, 0);
408: set_my_want_state_wont(TELOPT_TM);
409: set_my_state_wont(TELOPT_TM);
410: return;
411:
412: # if defined(TN3270)
413: case TELOPT_EOR: /* end of record */
414: # endif /* defined(TN3270) */
415: case TELOPT_BINARY: /* binary mode */
416: case TELOPT_NAWS: /* window size */
417: case TELOPT_TSPEED: /* terminal speed */
418: case TELOPT_LFLOW: /* local flow control */
419: case TELOPT_TTYPE: /* terminal type option */
420: case TELOPT_SGA: /* no big deal */
1.4 art 421: #if defined(ENCRYPTION)
422: case TELOPT_ENCRYPT: /* encryption variable option */
423: #endif
1.1 deraadt 424: new_state_ok = 1;
425: break;
426:
427: case TELOPT_NEW_ENVIRON: /* New environment variable option */
428: #ifdef OLD_ENVIRON
429: if (my_state_is_will(TELOPT_OLD_ENVIRON))
430: send_wont(TELOPT_OLD_ENVIRON, 1); /* turn off the old */
431: goto env_common;
432: case TELOPT_OLD_ENVIRON: /* Old environment variable option */
433: if (my_state_is_will(TELOPT_NEW_ENVIRON))
434: break; /* Don't enable if new one is in use! */
435: env_common:
436: telopt_environ = option;
437: #endif
438: new_state_ok = 1;
439: break;
440:
441: #if defined(AUTHENTICATION)
442: case TELOPT_AUTHENTICATION:
443: if (autologin)
444: new_state_ok = 1;
445: break;
446: #endif
447:
448: case TELOPT_XDISPLOC: /* X Display location */
449: if (env_getvalue((unsigned char *)"DISPLAY"))
450: new_state_ok = 1;
451: break;
452:
453: case TELOPT_LINEMODE:
454: #ifdef KLUDGELINEMODE
455: kludgelinemode = 0;
456: send_do(TELOPT_SGA, 1);
457: #endif
458: set_my_want_state_will(TELOPT_LINEMODE);
459: send_will(option, 0);
460: set_my_state_will(TELOPT_LINEMODE);
461: slc_init();
462: return;
463:
464: case TELOPT_ECHO: /* We're never going to echo... */
465: default:
466: break;
467: }
468:
469: if (new_state_ok) {
470: set_my_want_state_will(option);
471: send_will(option, 0);
472: setconnmode(0); /* Set new tty mode */
473: } else {
474: will_wont_resp[option]++;
475: send_wont(option, 0);
476: }
477: } else {
478: /*
479: * Handle options that need more things done after the
480: * other side has acknowledged the option.
481: */
482: switch (option) {
483: case TELOPT_LINEMODE:
484: #ifdef KLUDGELINEMODE
485: kludgelinemode = 0;
486: send_do(TELOPT_SGA, 1);
487: #endif
488: set_my_state_will(option);
489: slc_init();
490: send_do(TELOPT_SGA, 0);
491: return;
492: }
493: }
494: }
495: set_my_state_will(option);
496: }
497:
498: static void
499: dontoption(option)
500: int option;
501: {
502:
503: if (will_wont_resp[option]) {
504: --will_wont_resp[option];
505: if (will_wont_resp[option] && my_state_is_wont(option))
506: --will_wont_resp[option];
507: }
508:
509: if ((will_wont_resp[option] == 0) && my_want_state_is_will(option)) {
510: switch (option) {
511: case TELOPT_LINEMODE:
512: linemode = 0; /* put us back to the default state */
513: break;
514: #ifdef OLD_ENVIRON
515: case TELOPT_NEW_ENVIRON:
516: /*
517: * The new environ option wasn't recognized, try
518: * the old one.
519: */
520: send_will(TELOPT_OLD_ENVIRON, 1);
521: telopt_environ = TELOPT_OLD_ENVIRON;
522: break;
523: #endif
524: }
525: /* we always accept a DONT */
526: set_my_want_state_wont(option);
527: if (my_state_is_will(option))
528: send_wont(option, 0);
529: setconnmode(0); /* Set new tty mode */
530: }
531: set_my_state_wont(option);
532: }
533:
534: /*
1.11 provos 535: * This routine will turn a pipe separated list of names in the buffer
1.9 millert 536: * into an array of pointers to NUL terminated names. We toss out any
537: * bad, duplicate, or verbose names (names with spaces).
1.1 deraadt 538: */
539:
1.14 millert 540: int is_unique(char *, char **, char **);
1.5 art 541:
1.1 deraadt 542: static char *name_unknown = "UNKNOWN";
543: static char *unknown[] = { 0, 0 };
544:
545: char **
546: mklist(buf, name)
547: char *buf, *name;
548: {
1.13 mpech 549: int n;
550: char c, *cp, **argvp, *cp2, **argv, **avt;
1.1 deraadt 551:
552: if (name) {
1.2 niklas 553: if ((int)strlen(name) > 40) {
1.1 deraadt 554: name = 0;
555: unknown[0] = name_unknown;
556: } else {
557: unknown[0] = name;
558: upcase(name);
559: }
560: } else
561: unknown[0] = name_unknown;
562: /*
563: * Count up the number of names.
564: */
1.9 millert 565: for (n = 1, cp = buf; *cp; cp++) {
1.1 deraadt 566: if (*cp == '|')
567: n++;
568: }
569: /*
570: * Allocate an array to put the name pointers into
571: */
572: argv = (char **)malloc((n+3)*sizeof(char *));
573: if (argv == 0)
574: return(unknown);
575:
576: /*
577: * Fill up the array of pointers to names.
578: */
579: *argv = 0;
580: argvp = argv+1;
581: n = 0;
582: for (cp = cp2 = buf; (c = *cp); cp++) {
583: if (c == '|' || c == ':') {
584: *cp++ = '\0';
585: /*
586: * Skip entries that have spaces or are over 40
587: * characters long. If this is our environment
588: * name, then put it up front. Otherwise, as
589: * long as this is not a duplicate name (case
590: * insensitive) add it to the list.
591: */
592: if (n || (cp - cp2 > 41))
593: ;
594: else if (name && (strncasecmp(name, cp2, cp-cp2) == 0))
595: *argv = cp2;
596: else if (is_unique(cp2, argv+1, argvp))
597: *argvp++ = cp2;
598: if (c == ':')
599: break;
600: /*
601: * Skip multiple delimiters. Reset cp2 to
602: * the beginning of the next name. Reset n,
603: * the flag for names with spaces.
604: */
605: while ((c = *cp) == '|')
606: cp++;
607: cp2 = cp;
608: n = 0;
609: }
610: /*
611: * Skip entries with spaces or non-ascii values.
612: * Convert lower case letters to upper case.
613: */
1.4 art 614: #define ISASCII(c) (!((c)&0x80))
615: if ((c == ' ') || !ISASCII(c))
1.1 deraadt 616: n = 1;
617: else if (islower(c))
618: *cp = toupper(c);
619: }
1.2 niklas 620:
1.1 deraadt 621: /*
622: * Check for an old V6 2 character name. If the second
623: * name points to the beginning of the buffer, and is
624: * only 2 characters long, move it to the end of the array.
625: */
626: if ((argv[1] == buf) && (strlen(argv[1]) == 2)) {
627: --argvp;
628: for (avt = &argv[1]; avt < argvp; avt++)
629: *avt = *(avt+1);
630: *argvp++ = buf;
631: }
632:
633: /*
634: * Duplicate last name, for TTYPE option, and null
635: * terminate the array. If we didn't find a match on
636: * our terminal name, put that name at the beginning.
637: */
638: cp = *(argvp-1);
639: *argvp++ = cp;
640: *argvp = 0;
641:
642: if (*argv == 0) {
643: if (name)
644: *argv = name;
645: else {
646: --argvp;
647: for (avt = argv; avt < argvp; avt++)
648: *avt = *(avt+1);
649: }
650: }
651: if (*argv)
652: return(argv);
653: else
654: return(unknown);
655: }
656:
657: int
658: is_unique(name, as, ae)
1.13 mpech 659: char *name, **as, **ae;
1.1 deraadt 660: {
1.13 mpech 661: char **ap;
662: int n;
1.1 deraadt 663:
664: n = strlen(name) + 1;
665: for (ap = as; ap < ae; ap++)
666: if (strncasecmp(*ap, name, n) == 0)
667: return(0);
668: return (1);
669: }
670:
671: int resettermname = 1;
672:
673: char *
674: gettermname()
675: {
676: char *tname;
677: static char **tnamep = 0;
678: static char **next;
1.10 millert 679: int errret;
1.1 deraadt 680:
681: if (resettermname) {
682: resettermname = 0;
683: if (tnamep && tnamep != unknown)
684: free(tnamep);
685: if ((tname = (char *)env_getvalue((unsigned char *)"TERM")) &&
1.10 millert 686: (setupterm(tname, 1, &errret) == OK)) {
1.9 millert 687: tnamep = mklist(ttytype, tname);
1.1 deraadt 688: } else {
1.2 niklas 689: if (tname && ((int)strlen(tname) <= 40)) {
1.1 deraadt 690: unknown[0] = tname;
691: upcase(tname);
692: } else
693: unknown[0] = name_unknown;
694: tnamep = unknown;
695: }
696: next = tnamep;
697: }
698: if (*next == 0)
699: next = tnamep;
700: return(*next++);
701: }
702: /*
703: * suboption()
704: *
705: * Look at the sub-option buffer, and try to be helpful to the other
706: * side.
707: *
708: * Currently we recognize:
709: *
710: * Terminal type, send request.
711: * Terminal speed (send request).
712: * Local flow control (is request).
713: * Linemode
714: */
715:
716: static void
717: suboption()
718: {
719: unsigned char subchar;
720:
721: printsub('<', subbuffer, SB_LEN()+2);
722: switch (subchar = SB_GET()) {
723: case TELOPT_TTYPE:
724: if (my_want_state_is_wont(TELOPT_TTYPE))
725: return;
726: if (SB_EOF() || SB_GET() != TELQUAL_SEND) {
727: return;
728: } else {
729: char *name;
730: unsigned char temp[50];
731: int len;
732:
733: #if defined(TN3270)
734: if (tn3270_ttype()) {
735: return;
736: }
737: #endif /* defined(TN3270) */
738: name = gettermname();
739: len = strlen(name) + 4 + 2;
740: if (len < NETROOM()) {
1.4 art 741: snprintf((char *)temp, sizeof(temp),
742: "%c%c%c%c%s%c%c", IAC, SB, TELOPT_TTYPE,
743: TELQUAL_IS, name, IAC, SE);
1.1 deraadt 744: ring_supply_data(&netoring, temp, len);
745: printsub('>', &temp[2], len-2);
746: } else {
747: ExitString("No room in buffer for terminal type.\n", 1);
748: /*NOTREACHED*/
749: }
750: }
751: break;
752: case TELOPT_TSPEED:
753: if (my_want_state_is_wont(TELOPT_TSPEED))
754: return;
755: if (SB_EOF())
756: return;
757: if (SB_GET() == TELQUAL_SEND) {
758: long ospeed, ispeed;
759: unsigned char temp[50];
760: int len;
761:
762: TerminalSpeeds(&ispeed, &ospeed);
763:
1.4 art 764: snprintf((char *)temp, sizeof(temp),
1.5 art 765: "%c%c%c%c%ld,%ld%c%c", IAC, SB, TELOPT_TSPEED,
1.4 art 766: TELQUAL_IS, ospeed, ispeed, IAC, SE);
1.1 deraadt 767: len = strlen((char *)temp+4) + 4; /* temp[3] is 0 ... */
768:
769: if (len < NETROOM()) {
770: ring_supply_data(&netoring, temp, len);
771: printsub('>', temp+2, len - 2);
772: }
773: /*@*/ else printf("lm_will: not enough room in buffer\n");
774: }
775: break;
776: case TELOPT_LFLOW:
777: if (my_want_state_is_wont(TELOPT_LFLOW))
778: return;
779: if (SB_EOF())
780: return;
781: switch(SB_GET()) {
782: case LFLOW_RESTART_ANY:
783: restartany = 1;
784: break;
785: case LFLOW_RESTART_XON:
786: restartany = 0;
787: break;
788: case LFLOW_ON:
789: localflow = 1;
790: break;
791: case LFLOW_OFF:
792: localflow = 0;
793: break;
794: default:
795: return;
796: }
797: setcommandmode();
798: setconnmode(0);
799: break;
800:
801: case TELOPT_LINEMODE:
802: if (my_want_state_is_wont(TELOPT_LINEMODE))
803: return;
804: if (SB_EOF())
805: return;
806: switch (SB_GET()) {
807: case WILL:
808: lm_will(subpointer, SB_LEN());
809: break;
810: case WONT:
811: lm_wont(subpointer, SB_LEN());
812: break;
813: case DO:
814: lm_do(subpointer, SB_LEN());
815: break;
816: case DONT:
817: lm_dont(subpointer, SB_LEN());
818: break;
819: case LM_SLC:
820: slc(subpointer, SB_LEN());
821: break;
822: case LM_MODE:
823: lm_mode(subpointer, SB_LEN(), 0);
824: break;
825: default:
826: break;
827: }
828: break;
829:
830: #ifdef OLD_ENVIRON
831: case TELOPT_OLD_ENVIRON:
832: #endif
833: case TELOPT_NEW_ENVIRON:
834: if (SB_EOF())
835: return;
836: switch(SB_PEEK()) {
837: case TELQUAL_IS:
838: case TELQUAL_INFO:
839: if (my_want_state_is_dont(subchar))
840: return;
841: break;
842: case TELQUAL_SEND:
843: if (my_want_state_is_wont(subchar)) {
844: return;
845: }
846: break;
847: default:
848: return;
849: }
850: env_opt(subpointer, SB_LEN());
851: break;
852:
853: case TELOPT_XDISPLOC:
854: if (my_want_state_is_wont(TELOPT_XDISPLOC))
855: return;
856: if (SB_EOF())
857: return;
858: if (SB_GET() == TELQUAL_SEND) {
859: unsigned char temp[50], *dp;
860: int len;
861:
862: if ((dp = env_getvalue((unsigned char *)"DISPLAY")) == NULL) {
863: /*
864: * Something happened, we no longer have a DISPLAY
865: * variable. So, turn off the option.
866: */
867: send_wont(TELOPT_XDISPLOC, 1);
868: break;
869: }
1.4 art 870: snprintf((char *)temp, sizeof(temp),
871: "%c%c%c%c%s%c%c", IAC, SB, TELOPT_XDISPLOC,
1.1 deraadt 872: TELQUAL_IS, dp, IAC, SE);
873: len = strlen((char *)temp+4) + 4; /* temp[3] is 0 ... */
874:
875: if (len < NETROOM()) {
876: ring_supply_data(&netoring, temp, len);
877: printsub('>', temp+2, len - 2);
878: }
879: /*@*/ else printf("lm_will: not enough room in buffer\n");
880: }
881: break;
882:
883: #if defined(AUTHENTICATION)
884: case TELOPT_AUTHENTICATION: {
885: if (!autologin)
886: break;
887: if (SB_EOF())
888: return;
889: switch(SB_GET()) {
890: case TELQUAL_IS:
891: if (my_want_state_is_dont(TELOPT_AUTHENTICATION))
892: return;
893: auth_is(subpointer, SB_LEN());
894: break;
895: case TELQUAL_SEND:
896: if (my_want_state_is_wont(TELOPT_AUTHENTICATION))
897: return;
898: auth_send(subpointer, SB_LEN());
899: break;
900: case TELQUAL_REPLY:
901: if (my_want_state_is_wont(TELOPT_AUTHENTICATION))
902: return;
903: auth_reply(subpointer, SB_LEN());
904: break;
905: case TELQUAL_NAME:
906: if (my_want_state_is_dont(TELOPT_AUTHENTICATION))
907: return;
908: auth_name(subpointer, SB_LEN());
909: break;
910: }
911: }
912: break;
913: #endif
1.4 art 914: #if defined(ENCRYPTION)
915: case TELOPT_ENCRYPT:
916: if (SB_EOF())
917: return;
918: switch(SB_GET()) {
919: case ENCRYPT_START:
920: if (my_want_state_is_dont(TELOPT_ENCRYPT))
921: return;
922: encrypt_start(subpointer, SB_LEN());
923: break;
924: case ENCRYPT_END:
925: if (my_want_state_is_dont(TELOPT_ENCRYPT))
926: return;
927: encrypt_end();
928: break;
929: case ENCRYPT_SUPPORT:
930: if (my_want_state_is_wont(TELOPT_ENCRYPT))
931: return;
932: encrypt_support(subpointer, SB_LEN());
933: break;
934: case ENCRYPT_REQSTART:
935: if (my_want_state_is_wont(TELOPT_ENCRYPT))
936: return;
937: encrypt_request_start(subpointer, SB_LEN());
938: break;
939: case ENCRYPT_REQEND:
940: if (my_want_state_is_wont(TELOPT_ENCRYPT))
941: return;
942: /*
943: * We can always send an REQEND so that we cannot
944: * get stuck encrypting. We should only get this
945: * if we have been able to get in the correct mode
946: * anyhow.
947: */
948: encrypt_request_end();
949: break;
950: case ENCRYPT_IS:
951: if (my_want_state_is_dont(TELOPT_ENCRYPT))
952: return;
953: encrypt_is(subpointer, SB_LEN());
954: break;
955: case ENCRYPT_REPLY:
956: if (my_want_state_is_wont(TELOPT_ENCRYPT))
957: return;
958: encrypt_reply(subpointer, SB_LEN());
959: break;
960: case ENCRYPT_ENC_KEYID:
961: if (my_want_state_is_dont(TELOPT_ENCRYPT))
962: return;
963: encrypt_enc_keyid(subpointer, SB_LEN());
964: break;
965: case ENCRYPT_DEC_KEYID:
966: if (my_want_state_is_wont(TELOPT_ENCRYPT))
967: return;
968: encrypt_dec_keyid(subpointer, SB_LEN());
969: break;
970: default:
971: break;
972: }
973: break;
974: #endif
1.1 deraadt 975: default:
976: break;
977: }
978: }
979:
980: static unsigned char str_lm[] = { IAC, SB, TELOPT_LINEMODE, 0, 0, IAC, SE };
981:
982: void
983: lm_will(cmd, len)
984: unsigned char *cmd;
985: int len;
986: {
987: if (len < 1) {
988: /*@*/ printf("lm_will: no command!!!\n"); /* Should not happen... */
989: return;
990: }
991: switch(cmd[0]) {
992: case LM_FORWARDMASK: /* We shouldn't ever get this... */
993: default:
994: str_lm[3] = DONT;
995: str_lm[4] = cmd[0];
996: if (NETROOM() > sizeof(str_lm)) {
997: ring_supply_data(&netoring, str_lm, sizeof(str_lm));
998: printsub('>', &str_lm[2], sizeof(str_lm)-2);
999: }
1000: /*@*/ else printf("lm_will: not enough room in buffer\n");
1001: break;
1002: }
1003: }
1004:
1005: void
1006: lm_wont(cmd, len)
1007: unsigned char *cmd;
1008: int len;
1009: {
1010: if (len < 1) {
1011: /*@*/ printf("lm_wont: no command!!!\n"); /* Should not happen... */
1012: return;
1013: }
1014: switch(cmd[0]) {
1015: case LM_FORWARDMASK: /* We shouldn't ever get this... */
1016: default:
1017: /* We are always DONT, so don't respond */
1018: return;
1019: }
1020: }
1021:
1022: void
1023: lm_do(cmd, len)
1024: unsigned char *cmd;
1025: int len;
1026: {
1027: if (len < 1) {
1028: /*@*/ printf("lm_do: no command!!!\n"); /* Should not happen... */
1029: return;
1030: }
1031: switch(cmd[0]) {
1032: case LM_FORWARDMASK:
1033: default:
1034: str_lm[3] = WONT;
1035: str_lm[4] = cmd[0];
1036: if (NETROOM() > sizeof(str_lm)) {
1037: ring_supply_data(&netoring, str_lm, sizeof(str_lm));
1038: printsub('>', &str_lm[2], sizeof(str_lm)-2);
1039: }
1040: /*@*/ else printf("lm_do: not enough room in buffer\n");
1041: break;
1042: }
1043: }
1044:
1045: void
1046: lm_dont(cmd, len)
1047: unsigned char *cmd;
1048: int len;
1049: {
1050: if (len < 1) {
1051: /*@*/ printf("lm_dont: no command!!!\n"); /* Should not happen... */
1052: return;
1053: }
1054: switch(cmd[0]) {
1055: case LM_FORWARDMASK:
1056: default:
1057: /* we are always WONT, so don't respond */
1058: break;
1059: }
1060: }
1061:
1062: static unsigned char str_lm_mode[] = {
1063: IAC, SB, TELOPT_LINEMODE, LM_MODE, 0, IAC, SE
1064: };
1065:
1066: void
1067: lm_mode(cmd, len, init)
1068: unsigned char *cmd;
1069: int len, init;
1070: {
1071: if (len != 1)
1072: return;
1073: if ((linemode&MODE_MASK&~MODE_ACK) == *cmd)
1074: return;
1075: if (*cmd&MODE_ACK)
1076: return;
1077: linemode = *cmd&(MODE_MASK&~MODE_ACK);
1078: str_lm_mode[4] = linemode;
1079: if (!init)
1080: str_lm_mode[4] |= MODE_ACK;
1081: if (NETROOM() > sizeof(str_lm_mode)) {
1082: ring_supply_data(&netoring, str_lm_mode, sizeof(str_lm_mode));
1083: printsub('>', &str_lm_mode[2], sizeof(str_lm_mode)-2);
1084: }
1085: /*@*/ else printf("lm_mode: not enough room in buffer\n");
1086: setconnmode(0); /* set changed mode */
1087: }
1088:
1089:
1090:
1091: /*
1092: * slc()
1093: * Handle special character suboption of LINEMODE.
1094: */
1095:
1096: struct spc {
1097: cc_t val;
1098: cc_t *valp;
1099: char flags; /* Current flags & level */
1100: char mylevel; /* Maximum level & flags */
1101: } spc_data[NSLC+1];
1102:
1103: #define SLC_IMPORT 0
1104: #define SLC_EXPORT 1
1105: #define SLC_RVALUE 2
1106: static int slc_mode = SLC_EXPORT;
1107:
1108: void
1109: slc_init()
1110: {
1.13 mpech 1111: struct spc *spcp;
1.1 deraadt 1112:
1113: localchars = 1;
1114: for (spcp = spc_data; spcp < &spc_data[NSLC+1]; spcp++) {
1115: spcp->val = 0;
1116: spcp->valp = 0;
1117: spcp->flags = spcp->mylevel = SLC_NOSUPPORT;
1118: }
1119:
1120: #define initfunc(func, flags) { \
1121: spcp = &spc_data[func]; \
1.4 art 1122: if ((spcp->valp = tcval(func))) { \
1.1 deraadt 1123: spcp->val = *spcp->valp; \
1124: spcp->mylevel = SLC_VARIABLE|flags; \
1125: } else { \
1126: spcp->val = 0; \
1127: spcp->mylevel = SLC_DEFAULT; \
1128: } \
1129: }
1130:
1131: initfunc(SLC_SYNCH, 0);
1132: /* No BRK */
1133: initfunc(SLC_AO, 0);
1134: initfunc(SLC_AYT, 0);
1135: /* No EOR */
1136: initfunc(SLC_ABORT, SLC_FLUSHIN|SLC_FLUSHOUT);
1137: initfunc(SLC_EOF, 0);
1138: #ifndef SYSV_TERMIO
1139: initfunc(SLC_SUSP, SLC_FLUSHIN);
1140: #endif
1141: initfunc(SLC_EC, 0);
1142: initfunc(SLC_EL, 0);
1143: #ifndef SYSV_TERMIO
1144: initfunc(SLC_EW, 0);
1145: initfunc(SLC_RP, 0);
1146: initfunc(SLC_LNEXT, 0);
1147: #endif
1148: initfunc(SLC_XON, 0);
1149: initfunc(SLC_XOFF, 0);
1150: #ifdef SYSV_TERMIO
1151: spc_data[SLC_XON].mylevel = SLC_CANTCHANGE;
1152: spc_data[SLC_XOFF].mylevel = SLC_CANTCHANGE;
1153: #endif
1154: initfunc(SLC_FORW1, 0);
1155: #ifdef USE_TERMIO
1156: initfunc(SLC_FORW2, 0);
1157: /* No FORW2 */
1158: #endif
1159:
1160: initfunc(SLC_IP, SLC_FLUSHIN|SLC_FLUSHOUT);
1161: #undef initfunc
1162:
1163: if (slc_mode == SLC_EXPORT)
1164: slc_export();
1165: else
1166: slc_import(1);
1167:
1168: }
1169:
1170: void
1171: slcstate()
1172: {
1173: printf("Special characters are %s values\n",
1174: slc_mode == SLC_IMPORT ? "remote default" :
1175: slc_mode == SLC_EXPORT ? "local" :
1176: "remote");
1177: }
1178:
1179: void
1180: slc_mode_export()
1181: {
1182: slc_mode = SLC_EXPORT;
1183: if (my_state_is_will(TELOPT_LINEMODE))
1184: slc_export();
1185: }
1186:
1187: void
1188: slc_mode_import(def)
1189: int def;
1190: {
1191: slc_mode = def ? SLC_IMPORT : SLC_RVALUE;
1192: if (my_state_is_will(TELOPT_LINEMODE))
1193: slc_import(def);
1194: }
1195:
1196: unsigned char slc_import_val[] = {
1197: IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_VARIABLE, 0, IAC, SE
1198: };
1199: unsigned char slc_import_def[] = {
1200: IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_DEFAULT, 0, IAC, SE
1201: };
1202:
1203: void
1204: slc_import(def)
1205: int def;
1206: {
1207: if (NETROOM() > sizeof(slc_import_val)) {
1208: if (def) {
1209: ring_supply_data(&netoring, slc_import_def, sizeof(slc_import_def));
1210: printsub('>', &slc_import_def[2], sizeof(slc_import_def)-2);
1211: } else {
1212: ring_supply_data(&netoring, slc_import_val, sizeof(slc_import_val));
1213: printsub('>', &slc_import_val[2], sizeof(slc_import_val)-2);
1214: }
1215: }
1216: /*@*/ else printf("slc_import: not enough room\n");
1217: }
1218:
1219: void
1220: slc_export()
1221: {
1.13 mpech 1222: struct spc *spcp;
1.1 deraadt 1223:
1224: TerminalDefaultChars();
1225:
1226: slc_start_reply();
1227: for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) {
1228: if (spcp->mylevel != SLC_NOSUPPORT) {
1229: if (spcp->val == (cc_t)(_POSIX_VDISABLE))
1230: spcp->flags = SLC_NOSUPPORT;
1231: else
1232: spcp->flags = spcp->mylevel;
1233: if (spcp->valp)
1234: spcp->val = *spcp->valp;
1235: slc_add_reply(spcp - spc_data, spcp->flags, spcp->val);
1236: }
1237: }
1238: slc_end_reply();
1239: (void)slc_update();
1240: setconnmode(1); /* Make sure the character values are set */
1241: }
1242:
1243: void
1244: slc(cp, len)
1.13 mpech 1245: unsigned char *cp;
1.1 deraadt 1246: int len;
1247: {
1.13 mpech 1248: struct spc *spcp;
1249: int func,level;
1.1 deraadt 1250:
1251: slc_start_reply();
1252:
1253: for (; len >= 3; len -=3, cp +=3) {
1254:
1255: func = cp[SLC_FUNC];
1256:
1257: if (func == 0) {
1258: /*
1259: * Client side: always ignore 0 function.
1260: */
1261: continue;
1262: }
1263: if (func > NSLC) {
1264: if ((cp[SLC_FLAGS] & SLC_LEVELBITS) != SLC_NOSUPPORT)
1265: slc_add_reply(func, SLC_NOSUPPORT, 0);
1266: continue;
1267: }
1268:
1269: spcp = &spc_data[func];
1270:
1271: level = cp[SLC_FLAGS]&(SLC_LEVELBITS|SLC_ACK);
1272:
1273: if ((cp[SLC_VALUE] == (unsigned char)spcp->val) &&
1274: ((level&SLC_LEVELBITS) == (spcp->flags&SLC_LEVELBITS))) {
1275: continue;
1276: }
1277:
1278: if (level == (SLC_DEFAULT|SLC_ACK)) {
1279: /*
1280: * This is an error condition, the SLC_ACK
1281: * bit should never be set for the SLC_DEFAULT
1282: * level. Our best guess to recover is to
1283: * ignore the SLC_ACK bit.
1284: */
1285: cp[SLC_FLAGS] &= ~SLC_ACK;
1286: }
1287:
1288: if (level == ((spcp->flags&SLC_LEVELBITS)|SLC_ACK)) {
1289: spcp->val = (cc_t)cp[SLC_VALUE];
1290: spcp->flags = cp[SLC_FLAGS]; /* include SLC_ACK */
1291: continue;
1292: }
1293:
1294: level &= ~SLC_ACK;
1295:
1296: if (level <= (spcp->mylevel&SLC_LEVELBITS)) {
1297: spcp->flags = cp[SLC_FLAGS]|SLC_ACK;
1298: spcp->val = (cc_t)cp[SLC_VALUE];
1299: }
1300: if (level == SLC_DEFAULT) {
1301: if ((spcp->mylevel&SLC_LEVELBITS) != SLC_DEFAULT)
1302: spcp->flags = spcp->mylevel;
1303: else
1304: spcp->flags = SLC_NOSUPPORT;
1305: }
1306: slc_add_reply(func, spcp->flags, spcp->val);
1307: }
1308: slc_end_reply();
1309: if (slc_update())
1310: setconnmode(1); /* set the new character values */
1311: }
1312:
1313: void
1314: slc_check()
1315: {
1.13 mpech 1316: struct spc *spcp;
1.1 deraadt 1317:
1318: slc_start_reply();
1319: for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) {
1320: if (spcp->valp && spcp->val != *spcp->valp) {
1321: spcp->val = *spcp->valp;
1322: if (spcp->val == (cc_t)(_POSIX_VDISABLE))
1323: spcp->flags = SLC_NOSUPPORT;
1324: else
1325: spcp->flags = spcp->mylevel;
1326: slc_add_reply(spcp - spc_data, spcp->flags, spcp->val);
1327: }
1328: }
1329: slc_end_reply();
1330: setconnmode(1);
1331: }
1332:
1333:
1334: unsigned char slc_reply[128];
1335: unsigned char *slc_replyp;
1336:
1337: void
1338: slc_start_reply()
1339: {
1340: slc_replyp = slc_reply;
1341: *slc_replyp++ = IAC;
1342: *slc_replyp++ = SB;
1343: *slc_replyp++ = TELOPT_LINEMODE;
1344: *slc_replyp++ = LM_SLC;
1345: }
1346:
1347: void
1348: slc_add_reply(func, flags, value)
1349: unsigned char func;
1350: unsigned char flags;
1351: cc_t value;
1352: {
1353: if ((*slc_replyp++ = func) == IAC)
1354: *slc_replyp++ = IAC;
1355: if ((*slc_replyp++ = flags) == IAC)
1356: *slc_replyp++ = IAC;
1357: if ((*slc_replyp++ = (unsigned char)value) == IAC)
1358: *slc_replyp++ = IAC;
1359: }
1360:
1361: void
1362: slc_end_reply()
1363: {
1.13 mpech 1364: int len;
1.1 deraadt 1365:
1366: *slc_replyp++ = IAC;
1367: *slc_replyp++ = SE;
1368: len = slc_replyp - slc_reply;
1369: if (len <= 6)
1370: return;
1371: if (NETROOM() > len) {
1372: ring_supply_data(&netoring, slc_reply, slc_replyp - slc_reply);
1373: printsub('>', &slc_reply[2], slc_replyp - slc_reply - 2);
1374: }
1375: /*@*/else printf("slc_end_reply: not enough room\n");
1376: }
1377:
1378: int
1379: slc_update()
1380: {
1.13 mpech 1381: struct spc *spcp;
1.1 deraadt 1382: int need_update = 0;
1383:
1384: for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) {
1385: if (!(spcp->flags&SLC_ACK))
1386: continue;
1387: spcp->flags &= ~SLC_ACK;
1388: if (spcp->valp && (*spcp->valp != spcp->val)) {
1389: *spcp->valp = spcp->val;
1390: need_update = 1;
1391: }
1392: }
1393: return(need_update);
1394: }
1395:
1396: #ifdef OLD_ENVIRON
1397: # ifdef ENV_HACK
1398: /*
1399: * Earlier version of telnet/telnetd from the BSD code had
1400: * the definitions of VALUE and VAR reversed. To ensure
1401: * maximum interoperability, we assume that the server is
1402: * an older BSD server, until proven otherwise. The newer
1403: * BSD servers should be able to handle either definition,
1404: * so it is better to use the wrong values if we don't
1405: * know what type of server it is.
1406: */
1407: int env_auto = 1;
1408: int old_env_var = OLD_ENV_VAR;
1409: int old_env_value = OLD_ENV_VALUE;
1410: # else
1411: # define old_env_var OLD_ENV_VAR
1412: # define old_env_value OLD_ENV_VALUE
1413: # endif
1414: #endif
1415:
1416: void
1417: env_opt(buf, len)
1.13 mpech 1418: unsigned char *buf;
1419: int len;
1.1 deraadt 1420: {
1.13 mpech 1421: unsigned char *ep = 0, *epc = 0;
1422: int i;
1.1 deraadt 1423:
1424: switch(buf[0]&0xff) {
1425: case TELQUAL_SEND:
1426: env_opt_start();
1427: if (len == 1) {
1428: env_opt_add(NULL);
1429: } else for (i = 1; i < len; i++) {
1430: switch (buf[i]&0xff) {
1431: #ifdef OLD_ENVIRON
1432: case OLD_ENV_VAR:
1433: # ifdef ENV_HACK
1434: if (telopt_environ == TELOPT_OLD_ENVIRON
1435: && env_auto) {
1436: /* Server has the same definitions */
1437: old_env_var = OLD_ENV_VAR;
1438: old_env_value = OLD_ENV_VALUE;
1439: }
1440: /* FALL THROUGH */
1441: # endif
1442: case OLD_ENV_VALUE:
1443: /*
1444: * Although OLD_ENV_VALUE is not legal, we will
1445: * still recognize it, just in case it is an
1446: * old server that has VAR & VALUE mixed up...
1447: */
1448: /* FALL THROUGH */
1449: #else
1450: case NEW_ENV_VAR:
1451: #endif
1452: case ENV_USERVAR:
1453: if (ep) {
1454: *epc = 0;
1455: env_opt_add(ep);
1456: }
1457: ep = epc = &buf[i+1];
1458: break;
1459: case ENV_ESC:
1460: i++;
1461: /*FALL THROUGH*/
1462: default:
1463: if (epc)
1464: *epc++ = buf[i];
1465: break;
1466: }
1467: }
1468: if (ep) {
1469: *epc = 0;
1470: env_opt_add(ep);
1471: }
1472: env_opt_end(1);
1473: break;
1474:
1475: case TELQUAL_IS:
1476: case TELQUAL_INFO:
1477: /* Ignore for now. We shouldn't get it anyway. */
1478: break;
1479:
1480: default:
1481: break;
1482: }
1483: }
1484:
1485: #define OPT_REPLY_SIZE 256
1486: unsigned char *opt_reply;
1487: unsigned char *opt_replyp;
1488: unsigned char *opt_replyend;
1489:
1490: void
1491: env_opt_start()
1492: {
1.8 itojun 1493: unsigned char *p;
1494:
1495: if (opt_reply) {
1496: p = (unsigned char *)realloc(opt_reply, OPT_REPLY_SIZE);
1497: if (p == NULL)
1498: free(opt_reply);
1499: } else
1500: p = (unsigned char *)malloc(OPT_REPLY_SIZE);
1501: opt_reply = p;
1.1 deraadt 1502: if (opt_reply == NULL) {
1503: /*@*/ printf("env_opt_start: malloc()/realloc() failed!!!\n");
1504: opt_reply = opt_replyp = opt_replyend = NULL;
1505: return;
1506: }
1507: opt_replyp = opt_reply;
1508: opt_replyend = opt_reply + OPT_REPLY_SIZE;
1509: *opt_replyp++ = IAC;
1510: *opt_replyp++ = SB;
1511: *opt_replyp++ = telopt_environ;
1512: *opt_replyp++ = TELQUAL_IS;
1513: }
1514:
1515: void
1516: env_opt_start_info()
1517: {
1518: env_opt_start();
1519: if (opt_replyp)
1520: opt_replyp[-1] = TELQUAL_INFO;
1521: }
1522:
1523: void
1524: env_opt_add(ep)
1.13 mpech 1525: unsigned char *ep;
1.1 deraadt 1526: {
1.13 mpech 1527: unsigned char *vp, c;
1.1 deraadt 1528:
1529: if (opt_reply == NULL) /*XXX*/
1530: return; /*XXX*/
1531:
1532: if (ep == NULL || *ep == '\0') {
1533: /* Send user defined variables first. */
1534: env_default(1, 0);
1.4 art 1535: while ((ep = env_default(0, 0)))
1.1 deraadt 1536: env_opt_add(ep);
1537:
1538: /* Now add the list of well know variables. */
1539: env_default(1, 1);
1.4 art 1540: while ((ep = env_default(0, 1)))
1.1 deraadt 1541: env_opt_add(ep);
1542: return;
1543: }
1544: vp = env_getvalue(ep);
1545: if (opt_replyp + (vp ? strlen((char *)vp) : 0) +
1546: strlen((char *)ep) + 6 > opt_replyend)
1547: {
1.13 mpech 1548: int len;
1.8 itojun 1549: unsigned char *p;
1.1 deraadt 1550: opt_replyend += OPT_REPLY_SIZE;
1551: len = opt_replyend - opt_reply;
1.8 itojun 1552: p = (unsigned char *)realloc(opt_reply, len);
1553: if (p == NULL)
1554: free(opt_reply);
1555: opt_reply = p;
1.1 deraadt 1556: if (opt_reply == NULL) {
1557: /*@*/ printf("env_opt_add: realloc() failed!!!\n");
1558: opt_reply = opt_replyp = opt_replyend = NULL;
1559: return;
1560: }
1561: opt_replyp = opt_reply + len - (opt_replyend - opt_replyp);
1562: opt_replyend = opt_reply + len;
1563: }
1.4 art 1564: if (opt_welldefined((char *)ep))
1.1 deraadt 1565: #ifdef OLD_ENVIRON
1566: if (telopt_environ == TELOPT_OLD_ENVIRON)
1567: *opt_replyp++ = old_env_var;
1568: else
1569: #endif
1570: *opt_replyp++ = NEW_ENV_VAR;
1571: else
1572: *opt_replyp++ = ENV_USERVAR;
1573: for (;;) {
1.4 art 1574: while ((c = *ep++)) {
1.1 deraadt 1575: switch(c&0xff) {
1576: case IAC:
1577: *opt_replyp++ = IAC;
1578: break;
1579: case NEW_ENV_VAR:
1580: case NEW_ENV_VALUE:
1581: case ENV_ESC:
1582: case ENV_USERVAR:
1583: *opt_replyp++ = ENV_ESC;
1584: break;
1585: }
1586: *opt_replyp++ = c;
1587: }
1.4 art 1588: if ((ep = vp)) {
1.1 deraadt 1589: #ifdef OLD_ENVIRON
1590: if (telopt_environ == TELOPT_OLD_ENVIRON)
1591: *opt_replyp++ = old_env_value;
1592: else
1593: #endif
1594: *opt_replyp++ = NEW_ENV_VALUE;
1595: vp = NULL;
1596: } else
1597: break;
1598: }
1599: }
1600:
1601: int
1602: opt_welldefined(ep)
1603: char *ep;
1604: {
1605: if ((strcmp(ep, "USER") == 0) ||
1606: (strcmp(ep, "DISPLAY") == 0) ||
1607: (strcmp(ep, "PRINTER") == 0) ||
1608: (strcmp(ep, "SYSTEMTYPE") == 0) ||
1609: (strcmp(ep, "JOB") == 0) ||
1610: (strcmp(ep, "ACCT") == 0))
1611: return(1);
1612: return(0);
1613: }
1614: void
1615: env_opt_end(emptyok)
1.13 mpech 1616: int emptyok;
1.1 deraadt 1617: {
1.13 mpech 1618: int len;
1.1 deraadt 1619:
1620: len = opt_replyp - opt_reply + 2;
1621: if (emptyok || len > 6) {
1622: *opt_replyp++ = IAC;
1623: *opt_replyp++ = SE;
1624: if (NETROOM() > len) {
1625: ring_supply_data(&netoring, opt_reply, len);
1626: printsub('>', &opt_reply[2], len - 2);
1627: }
1628: /*@*/ else printf("slc_end_reply: not enough room\n");
1629: }
1630: if (opt_reply) {
1631: free(opt_reply);
1632: opt_reply = opt_replyp = opt_replyend = NULL;
1633: }
1634: }
1635:
1636:
1637:
1638: int
1639: telrcv()
1640: {
1.13 mpech 1641: int c;
1642: int scc;
1643: unsigned char *sbp;
1.1 deraadt 1644: int count;
1645: int returnValue = 0;
1646:
1647: scc = 0;
1648: count = 0;
1649: while (TTYROOM() > 2) {
1650: if (scc == 0) {
1651: if (count) {
1652: ring_consumed(&netiring, count);
1653: returnValue = 1;
1654: count = 0;
1655: }
1656: sbp = netiring.consume;
1657: scc = ring_full_consecutive(&netiring);
1658: if (scc == 0) {
1659: /* No more data coming in */
1660: break;
1661: }
1662: }
1663:
1664: c = *sbp++ & 0xff, scc--; count++;
1.4 art 1665: #if defined(ENCRYPTION)
1666: if (decrypt_input)
1667: c = (*decrypt_input)(c);
1668: #endif
1.1 deraadt 1669:
1670: switch (telrcv_state) {
1671:
1672: case TS_CR:
1673: telrcv_state = TS_DATA;
1674: if (c == '\0') {
1675: break; /* Ignore \0 after CR */
1676: }
1677: else if ((c == '\n') && my_want_state_is_dont(TELOPT_ECHO) && !crmod) {
1678: TTYADD(c);
1679: break;
1680: }
1681: /* Else, fall through */
1682:
1683: case TS_DATA:
1684: if (c == IAC) {
1685: telrcv_state = TS_IAC;
1686: break;
1687: }
1688: # if defined(TN3270)
1689: if (In3270) {
1690: *Ifrontp++ = c;
1691: while (scc > 0) {
1692: c = *sbp++ & 0377, scc--; count++;
1693: if (c == IAC) {
1694: telrcv_state = TS_IAC;
1695: break;
1696: }
1697: *Ifrontp++ = c;
1698: }
1699: } else
1700: # endif /* defined(TN3270) */
1701: /*
1702: * The 'crmod' hack (see following) is needed
1.4 art 1703: * since we can't set CRMOD on output only.
1.1 deraadt 1704: * Machines like MULTICS like to send \r without
1705: * \n; since we must turn off CRMOD to get proper
1706: * input, the mapping is done here (sigh).
1707: */
1708: if ((c == '\r') && my_want_state_is_dont(TELOPT_BINARY)) {
1709: if (scc > 0) {
1710: c = *sbp&0xff;
1.4 art 1711: #if defined(ENCRYPTION)
1712: if (decrypt_input)
1713: c = (*decrypt_input)(c);
1714: #endif
1.1 deraadt 1715: if (c == 0) {
1716: sbp++, scc--; count++;
1717: /* a "true" CR */
1718: TTYADD('\r');
1719: } else if (my_want_state_is_dont(TELOPT_ECHO) &&
1720: (c == '\n')) {
1721: sbp++, scc--; count++;
1722: TTYADD('\n');
1723: } else {
1.4 art 1724: #if defined(ENCRYPTION)
1725: if (decrypt_input)
1726: (*decrypt_input)(-1);
1727: #endif
1.1 deraadt 1728: TTYADD('\r');
1729: if (crmod) {
1730: TTYADD('\n');
1731: }
1732: }
1733: } else {
1734: telrcv_state = TS_CR;
1735: TTYADD('\r');
1736: if (crmod) {
1737: TTYADD('\n');
1738: }
1739: }
1740: } else {
1741: TTYADD(c);
1742: }
1743: continue;
1744:
1745: case TS_IAC:
1746: process_iac:
1747: switch (c) {
1.2 niklas 1748:
1.1 deraadt 1749: case WILL:
1750: telrcv_state = TS_WILL;
1751: continue;
1752:
1753: case WONT:
1754: telrcv_state = TS_WONT;
1755: continue;
1756:
1757: case DO:
1758: telrcv_state = TS_DO;
1759: continue;
1760:
1761: case DONT:
1762: telrcv_state = TS_DONT;
1763: continue;
1764:
1765: case DM:
1766: /*
1767: * We may have missed an urgent notification,
1768: * so make sure we flush whatever is in the
1769: * buffer currently.
1770: */
1771: printoption("RCVD", IAC, DM);
1772: SYNCHing = 1;
1773: (void) ttyflush(1);
1774: SYNCHing = stilloob();
1775: settimer(gotDM);
1776: break;
1777:
1778: case SB:
1779: SB_CLEAR();
1780: telrcv_state = TS_SB;
1781: continue;
1782:
1783: # if defined(TN3270)
1784: case EOR:
1785: if (In3270) {
1786: if (Ibackp == Ifrontp) {
1787: Ibackp = Ifrontp = Ibuf;
1788: ISend = 0; /* should have been! */
1789: } else {
1790: Ibackp += DataFromNetwork(Ibackp, Ifrontp-Ibackp, 1);
1791: ISend = 1;
1792: }
1793: }
1794: printoption("RCVD", IAC, EOR);
1795: break;
1796: # endif /* defined(TN3270) */
1797:
1798: case IAC:
1799: # if !defined(TN3270)
1800: TTYADD(IAC);
1801: # else /* !defined(TN3270) */
1802: if (In3270) {
1803: *Ifrontp++ = IAC;
1804: } else {
1805: TTYADD(IAC);
1806: }
1807: # endif /* !defined(TN3270) */
1808: break;
1809:
1810: case NOP:
1811: case GA:
1812: default:
1813: printoption("RCVD", IAC, c);
1814: break;
1815: }
1816: telrcv_state = TS_DATA;
1817: continue;
1818:
1819: case TS_WILL:
1820: printoption("RCVD", WILL, c);
1821: willoption(c);
1822: SetIn3270();
1823: telrcv_state = TS_DATA;
1824: continue;
1825:
1826: case TS_WONT:
1827: printoption("RCVD", WONT, c);
1828: wontoption(c);
1829: SetIn3270();
1830: telrcv_state = TS_DATA;
1831: continue;
1832:
1833: case TS_DO:
1834: printoption("RCVD", DO, c);
1835: dooption(c);
1836: SetIn3270();
1837: if (c == TELOPT_NAWS) {
1838: sendnaws();
1839: } else if (c == TELOPT_LFLOW) {
1840: localflow = 1;
1841: setcommandmode();
1842: setconnmode(0);
1843: }
1844: telrcv_state = TS_DATA;
1845: continue;
1846:
1847: case TS_DONT:
1848: printoption("RCVD", DONT, c);
1849: dontoption(c);
1850: flushline = 1;
1851: setconnmode(0); /* set new tty mode (maybe) */
1852: SetIn3270();
1853: telrcv_state = TS_DATA;
1854: continue;
1855:
1856: case TS_SB:
1857: if (c == IAC) {
1858: telrcv_state = TS_SE;
1859: } else {
1860: SB_ACCUM(c);
1861: }
1862: continue;
1863:
1864: case TS_SE:
1865: if (c != SE) {
1866: if (c != IAC) {
1867: /*
1868: * This is an error. We only expect to get
1869: * "IAC IAC" or "IAC SE". Several things may
1870: * have happend. An IAC was not doubled, the
1871: * IAC SE was left off, or another option got
1872: * inserted into the suboption are all possibilities.
1873: * If we assume that the IAC was not doubled,
1874: * and really the IAC SE was left off, we could
1875: * get into an infinate loop here. So, instead,
1876: * we terminate the suboption, and process the
1877: * partial suboption if we can.
1878: */
1879: SB_ACCUM(IAC);
1880: SB_ACCUM(c);
1881: subpointer -= 2;
1882: SB_TERM();
1883:
1884: printoption("In SUBOPTION processing, RCVD", IAC, c);
1885: suboption(); /* handle sub-option */
1886: SetIn3270();
1887: telrcv_state = TS_IAC;
1888: goto process_iac;
1889: }
1890: SB_ACCUM(c);
1891: telrcv_state = TS_SB;
1892: } else {
1893: SB_ACCUM(IAC);
1894: SB_ACCUM(SE);
1895: subpointer -= 2;
1896: SB_TERM();
1897: suboption(); /* handle sub-option */
1898: SetIn3270();
1899: telrcv_state = TS_DATA;
1900: }
1901: }
1902: }
1903: if (count)
1904: ring_consumed(&netiring, count);
1905: return returnValue||count;
1906: }
1907:
1908: static int bol = 1, local = 0;
1909:
1910: int
1911: rlogin_susp()
1912: {
1913: if (local) {
1914: local = 0;
1915: bol = 1;
1916: command(0, "z\n", 2);
1917: return(1);
1918: }
1919: return(0);
1920: }
1921:
1922: static int
1923: telsnd()
1924: {
1925: int tcc;
1926: int count;
1927: int returnValue = 0;
1928: unsigned char *tbp;
1929:
1930: tcc = 0;
1931: count = 0;
1932: while (NETROOM() > 2) {
1.13 mpech 1933: int sc;
1934: int c;
1.1 deraadt 1935:
1936: if (tcc == 0) {
1937: if (count) {
1938: ring_consumed(&ttyiring, count);
1939: returnValue = 1;
1940: count = 0;
1941: }
1942: tbp = ttyiring.consume;
1943: tcc = ring_full_consecutive(&ttyiring);
1944: if (tcc == 0) {
1945: break;
1946: }
1947: }
1948: c = *tbp++ & 0xff, sc = strip(c), tcc--; count++;
1949: if (rlogin != _POSIX_VDISABLE) {
1950: if (bol) {
1951: bol = 0;
1952: if (sc == rlogin) {
1953: local = 1;
1954: continue;
1955: }
1956: } else if (local) {
1957: local = 0;
1958: if (sc == '.' || c == termEofChar) {
1959: bol = 1;
1960: command(0, "close\n", 6);
1961: continue;
1962: }
1963: if (sc == termSuspChar) {
1964: bol = 1;
1965: command(0, "z\n", 2);
1966: continue;
1967: }
1968: if (sc == escape) {
1969: command(0, (char *)tbp, tcc);
1970: bol = 1;
1971: count += tcc;
1972: tcc = 0;
1973: flushline = 1;
1974: break;
1975: }
1976: if (sc != rlogin) {
1977: ++tcc;
1978: --tbp;
1979: --count;
1980: c = sc = rlogin;
1981: }
1982: }
1983: if ((sc == '\n') || (sc == '\r'))
1984: bol = 1;
1.7 aaron 1985: } else if (escape != _POSIX_VDISABLE && sc == escape) {
1.1 deraadt 1986: /*
1987: * Double escape is a pass through of a single escape character.
1988: */
1989: if (tcc && strip(*tbp) == escape) {
1990: tbp++;
1991: tcc--;
1992: count++;
1993: bol = 0;
1994: } else {
1995: command(0, (char *)tbp, tcc);
1996: bol = 1;
1997: count += tcc;
1998: tcc = 0;
1999: flushline = 1;
2000: break;
2001: }
2002: } else
2003: bol = 0;
2004: #ifdef KLUDGELINEMODE
2005: if (kludgelinemode && (globalmode&MODE_EDIT) && (sc == echoc)) {
2006: if (tcc > 0 && strip(*tbp) == echoc) {
2007: tcc--; tbp++; count++;
2008: } else {
2009: dontlecho = !dontlecho;
2010: settimer(echotoggle);
2011: setconnmode(0);
2012: flushline = 1;
2013: break;
2014: }
2015: }
2016: #endif
1.3 deraadt 2017: if (sc != _POSIX_VDISABLE && MODE_LOCAL_CHARS(globalmode)) {
1.1 deraadt 2018: if (TerminalSpecialChars(sc) == 0) {
2019: bol = 1;
2020: break;
2021: }
2022: }
2023: if (my_want_state_is_wont(TELOPT_BINARY)) {
2024: switch (c) {
2025: case '\n':
2026: /*
2027: * If we are in CRMOD mode (\r ==> \n)
2028: * on our local machine, then probably
2029: * a newline (unix) is CRLF (TELNET).
2030: */
2031: if (MODE_LOCAL_CHARS(globalmode)) {
2032: NETADD('\r');
2033: }
2034: NETADD('\n');
2035: bol = flushline = 1;
2036: break;
2037: case '\r':
2038: if (!crlf) {
2039: NET2ADD('\r', '\0');
2040: } else {
2041: NET2ADD('\r', '\n');
2042: }
2043: bol = flushline = 1;
2044: break;
2045: case IAC:
2046: NET2ADD(IAC, IAC);
2047: break;
2048: default:
2049: NETADD(c);
2050: break;
2051: }
2052: } else if (c == IAC) {
2053: NET2ADD(IAC, IAC);
2054: } else {
2055: NETADD(c);
2056: }
2057: }
2058: if (count)
2059: ring_consumed(&ttyiring, count);
2060: return returnValue||count; /* Non-zero if we did anything */
2061: }
2062:
2063: /*
2064: * Scheduler()
2065: *
2066: * Try to do something.
2067: *
2068: * If we do something useful, return 1; else return 0.
2069: *
2070: */
2071:
2072:
2073: int
2074: Scheduler(block)
2075: int block; /* should we block in the select ? */
2076: {
2077: /* One wants to be a bit careful about setting returnValue
2078: * to one, since a one implies we did some useful work,
2079: * and therefore probably won't be called to block next
2080: * time (TN3270 mode only).
2081: */
2082: int returnValue;
2083: int netin, netout, netex, ttyin, ttyout;
2084:
2085: /* Decide which rings should be processed */
2086:
2087: netout = ring_full_count(&netoring) &&
2088: (flushline ||
2089: (my_want_state_is_wont(TELOPT_LINEMODE)
2090: #ifdef KLUDGELINEMODE
2091: && (!kludgelinemode || my_want_state_is_do(TELOPT_SGA))
2092: #endif
2093: ) ||
2094: my_want_state_is_will(TELOPT_BINARY));
2095: ttyout = ring_full_count(&ttyoring);
2096:
2097: #if defined(TN3270)
2098: ttyin = ring_empty_count(&ttyiring) && (clienteof == 0) && (shell_active == 0);
2099: #else /* defined(TN3270) */
2100: ttyin = ring_empty_count(&ttyiring) && (clienteof == 0);
2101: #endif /* defined(TN3270) */
2102:
2103: #if defined(TN3270)
2104: netin = ring_empty_count(&netiring);
2105: # else /* !defined(TN3270) */
2106: netin = !ISend && ring_empty_count(&netiring);
2107: # endif /* !defined(TN3270) */
2108:
2109: netex = !SYNCHing;
2110:
2111: /* If we have seen a signal recently, reset things */
1.15 hin 2112:
2113: if (scheduler_lockout_tty) {
2114: ttyin = ttyout = 0;
2115: }
2116:
1.1 deraadt 2117: # if defined(TN3270) && defined(unix)
2118: if (HaveInput) {
2119: HaveInput = 0;
2120: (void) signal(SIGIO, inputAvailable);
2121: }
2122: #endif /* defined(TN3270) && defined(unix) */
2123:
2124: /* Call to system code to process rings */
2125:
2126: returnValue = process_rings(netin, netout, netex, ttyin, ttyout, !block);
2127:
2128: /* Now, look at the input rings, looking for work to do. */
2129:
2130: if (ring_full_count(&ttyiring)) {
2131: # if defined(TN3270)
2132: if (In3270) {
2133: int c;
2134:
2135: c = DataFromTerminal(ttyiring.consume,
2136: ring_full_consecutive(&ttyiring));
2137: if (c) {
2138: returnValue = 1;
1.2 niklas 2139: ring_consumed(&ttyiring, c);
1.1 deraadt 2140: }
2141: } else {
2142: # endif /* defined(TN3270) */
2143: returnValue |= telsnd();
2144: # if defined(TN3270)
2145: }
2146: # endif /* defined(TN3270) */
2147: }
2148:
2149: if (ring_full_count(&netiring)) {
2150: # if !defined(TN3270)
2151: returnValue |= telrcv();
2152: # else /* !defined(TN3270) */
2153: returnValue = Push3270();
2154: # endif /* !defined(TN3270) */
2155: }
2156: return returnValue;
2157: }
2158:
2159: /*
2160: * Select from tty and network...
2161: */
2162: void
2163: telnet(user)
2164: char *user;
2165: {
1.15 hin 2166: int printed_encrypt = 0;
2167:
1.1 deraadt 2168: sys_telnet_init();
2169:
1.4 art 2170: #if defined(AUTHENTICATION) || defined(ENCRYPTION)
1.1 deraadt 2171: {
2172: static char local_host[256] = { 0 };
2173:
2174: if (!local_host[0]) {
2175: gethostname(local_host, sizeof(local_host));
2176: local_host[sizeof(local_host)-1] = 0;
2177: }
2178: auth_encrypt_init(local_host, hostname, "TELNET", 0);
2179: auth_encrypt_user(user);
2180: }
1.4 art 2181: #endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */
1.1 deraadt 2182: # if !defined(TN3270)
2183: if (telnetport) {
2184: #if defined(AUTHENTICATION)
2185: if (autologin)
2186: send_will(TELOPT_AUTHENTICATION, 1);
2187: #endif
1.4 art 2188: #if defined(ENCRYPTION)
2189: send_do(TELOPT_ENCRYPT, 1);
2190: send_will(TELOPT_ENCRYPT, 1);
2191: #endif
1.1 deraadt 2192: send_do(TELOPT_SGA, 1);
2193: send_will(TELOPT_TTYPE, 1);
2194: send_will(TELOPT_NAWS, 1);
2195: send_will(TELOPT_TSPEED, 1);
2196: send_will(TELOPT_LFLOW, 1);
2197: send_will(TELOPT_LINEMODE, 1);
2198: send_will(TELOPT_NEW_ENVIRON, 1);
2199: send_do(TELOPT_STATUS, 1);
2200: if (env_getvalue((unsigned char *)"DISPLAY"))
2201: send_will(TELOPT_XDISPLOC, 1);
1.4 art 2202: if (binary)
2203: tel_enter_binary(binary);
1.1 deraadt 2204: }
2205: # endif /* !defined(TN3270) */
2206:
1.15 hin 2207: #ifdef ENCRYPTION
2208: /*
2209: * Note: we assume a tie to the authentication option here. This
2210: * is necessary so that authentication fails, we don't spin
2211: * forever.
2212: */
2213: if (wantencryption) {
2214: extern int auth_has_failed;
2215: time_t timeout = time(0) + 60;
2216:
2217: send_do(TELOPT_ENCRYPT, 1);
2218: send_will(TELOPT_ENCRYPT, 1);
2219: while (1) {
2220: if (my_want_state_is_wont(TELOPT_AUTHENTICATION)) {
2221: if (wantencryption == -1) {
2222: break;
2223: } else {
2224: printf("\nServer refused to negotiate authentication,");
2225: printf(" which is required for encryption.\n");
2226: Exit(1);
2227: }
2228: }
2229: if (auth_has_failed) {
2230: printf("\nAuthentication negotation has failed,");
2231: printf(" which is required for encryption.\n");
2232: Exit(1);
2233: }
2234: if (my_want_state_is_dont(TELOPT_ENCRYPT) ||
2235: my_want_state_is_wont(TELOPT_ENCRYPT)) {
2236: printf("\nServer refused to negotiate encryption.\n");
2237: Exit(1);
2238: }
2239: if (encrypt_is_encrypting())
2240: break;
2241: if (time(0) > timeout) {
2242: printf("\nEncryption could not be enabled.\n");
2243: Exit(1);
2244: }
2245: if (printed_encrypt == 0) {
2246: printed_encrypt = 1;
2247: printf("Waiting for encryption to be negotiated...\n");
2248: /*
2249: * Turn on MODE_TRAPSIG and then turn off localchars
2250: * so that ^C will cause telnet to exit.
2251: */
2252: TerminalNewMode(getconnmode()|MODE_TRAPSIG);
2253: intr_waiting = 1;
2254: }
2255: if (intr_happened) {
2256: printf("\nUser interrupt.\n");
2257: Exit(1);
2258: }
2259: telnet_spin();
2260: }
2261: if (printed_encrypt) {
2262: printf("Encryption negotiated.\n");
2263: intr_waiting = 0;
2264: setconnmode(0);
2265: }
2266: }
2267: #endif
2268:
1.1 deraadt 2269: # if !defined(TN3270)
2270: for (;;) {
2271: int schedValue;
2272:
2273: while ((schedValue = Scheduler(0)) != 0) {
2274: if (schedValue == -1) {
2275: setcommandmode();
2276: return;
2277: }
2278: }
2279:
2280: if (Scheduler(1) == -1) {
2281: setcommandmode();
2282: return;
2283: }
2284: }
2285: # else /* !defined(TN3270) */
2286: for (;;) {
2287: int schedValue;
2288:
2289: while (!In3270 && !shell_active) {
2290: if (Scheduler(1) == -1) {
2291: setcommandmode();
2292: return;
2293: }
2294: }
2295:
2296: while ((schedValue = Scheduler(0)) != 0) {
2297: if (schedValue == -1) {
2298: setcommandmode();
2299: return;
2300: }
2301: }
2302: /* If there is data waiting to go out to terminal, don't
2303: * schedule any more data for the terminal.
2304: */
2305: if (ring_full_count(&ttyoring)) {
2306: schedValue = 1;
2307: } else {
2308: if (shell_active) {
2309: if (shell_continue() == 0) {
2310: ConnectScreen();
2311: }
2312: } else if (In3270) {
2313: schedValue = DoTerminalOutput();
2314: }
2315: }
2316: if (schedValue && (shell_active == 0)) {
2317: if (Scheduler(1) == -1) {
2318: setcommandmode();
2319: return;
2320: }
2321: }
2322: }
2323: # endif /* !defined(TN3270) */
2324: }
2325:
2326: #if 0 /* XXX - this not being in is a bug */
2327: /*
2328: * nextitem()
2329: *
2330: * Return the address of the next "item" in the TELNET data
2331: * stream. This will be the address of the next character if
2332: * the current address is a user data character, or it will
2333: * be the address of the character following the TELNET command
2334: * if the current address is a TELNET IAC ("I Am a Command")
2335: * character.
2336: */
2337:
2338: static char *
2339: nextitem(current)
2340: char *current;
2341: {
2342: if ((*current&0xff) != IAC) {
2343: return current+1;
2344: }
2345: switch (*(current+1)&0xff) {
2346: case DO:
2347: case DONT:
2348: case WILL:
2349: case WONT:
2350: return current+3;
2351: case SB: /* loop forever looking for the SE */
2352: {
1.13 mpech 2353: char *look = current+2;
1.1 deraadt 2354:
2355: for (;;) {
2356: if ((*look++&0xff) == IAC) {
2357: if ((*look++&0xff) == SE) {
2358: return look;
2359: }
2360: }
2361: }
2362: }
2363: default:
2364: return current+2;
2365: }
2366: }
2367: #endif /* 0 */
2368:
2369: /*
2370: * netclear()
2371: *
2372: * We are about to do a TELNET SYNCH operation. Clear
2373: * the path to the network.
2374: *
2375: * Things are a bit tricky since we may have sent the first
2376: * byte or so of a previous TELNET command into the network.
2377: * So, we have to scan the network buffer from the beginning
2378: * until we are up to where we want to be.
2379: *
2380: * A side effect of what we do, just to keep things
2381: * simple, is to clear the urgent data pointer. The principal
2382: * caller should be setting the urgent data pointer AFTER calling
2383: * us in any case.
2384: */
2385:
2386: static void
2387: netclear()
2388: {
2389: #if 0 /* XXX */
1.13 mpech 2390: char *thisitem, *next;
1.1 deraadt 2391: char *good;
2392: #define wewant(p) ((nfrontp > p) && ((*p&0xff) == IAC) && \
2393: ((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL))
2394:
2395: thisitem = netobuf;
2396:
2397: while ((next = nextitem(thisitem)) <= netobuf.send) {
2398: thisitem = next;
2399: }
2400:
2401: /* Now, thisitem is first before/at boundary. */
2402:
2403: good = netobuf; /* where the good bytes go */
2404:
2405: while (netoring.add > thisitem) {
2406: if (wewant(thisitem)) {
2407: int length;
2408:
2409: next = thisitem;
2410: do {
2411: next = nextitem(next);
2412: } while (wewant(next) && (nfrontp > next));
2413: length = next-thisitem;
1.2 niklas 2414: memmove(good, thisitem, length);
1.1 deraadt 2415: good += length;
2416: thisitem = next;
2417: } else {
2418: thisitem = nextitem(thisitem);
2419: }
2420: }
2421:
2422: #endif /* 0 */
2423: }
2424:
2425: /*
2426: * These routines add various telnet commands to the data stream.
2427: */
2428:
2429: static void
2430: doflush()
2431: {
2432: NET2ADD(IAC, DO);
2433: NETADD(TELOPT_TM);
2434: flushline = 1;
2435: flushout = 1;
2436: (void) ttyflush(1); /* Flush/drop output */
2437: /* do printoption AFTER flush, otherwise the output gets tossed... */
2438: printoption("SENT", DO, TELOPT_TM);
2439: }
2440:
2441: void
2442: xmitAO()
2443: {
2444: NET2ADD(IAC, AO);
2445: printoption("SENT", IAC, AO);
2446: if (autoflush) {
2447: doflush();
2448: }
2449: }
2450:
2451:
2452: void
2453: xmitEL()
2454: {
2455: NET2ADD(IAC, EL);
2456: printoption("SENT", IAC, EL);
2457: }
2458:
2459: void
2460: xmitEC()
2461: {
2462: NET2ADD(IAC, EC);
2463: printoption("SENT", IAC, EC);
2464: }
2465:
2466:
2467: int
2468: dosynch()
2469: {
2470: netclear(); /* clear the path to the network */
2471: NETADD(IAC);
2472: setneturg();
2473: NETADD(DM);
2474: printoption("SENT", IAC, DM);
2475: return 1;
2476: }
2477:
2478: int want_status_response = 0;
2479:
2480: int
2481: get_status()
2482: {
2483: unsigned char tmp[16];
1.13 mpech 2484: unsigned char *cp;
1.1 deraadt 2485:
2486: if (my_want_state_is_dont(TELOPT_STATUS)) {
2487: printf("Remote side does not support STATUS option\n");
2488: return 0;
2489: }
2490: cp = tmp;
2491:
2492: *cp++ = IAC;
2493: *cp++ = SB;
2494: *cp++ = TELOPT_STATUS;
2495: *cp++ = TELQUAL_SEND;
2496: *cp++ = IAC;
2497: *cp++ = SE;
2498: if (NETROOM() >= cp - tmp) {
2499: ring_supply_data(&netoring, tmp, cp-tmp);
2500: printsub('>', tmp+2, cp - tmp - 2);
2501: }
2502: ++want_status_response;
2503: return 1;
2504: }
2505:
2506: void
2507: intp()
2508: {
2509: NET2ADD(IAC, IP);
2510: printoption("SENT", IAC, IP);
2511: flushline = 1;
2512: if (autoflush) {
2513: doflush();
2514: }
2515: if (autosynch) {
2516: dosynch();
2517: }
2518: }
2519:
2520: void
2521: sendbrk()
2522: {
2523: NET2ADD(IAC, BREAK);
2524: printoption("SENT", IAC, BREAK);
2525: flushline = 1;
2526: if (autoflush) {
2527: doflush();
2528: }
2529: if (autosynch) {
2530: dosynch();
2531: }
2532: }
2533:
2534: void
2535: sendabort()
2536: {
2537: NET2ADD(IAC, ABORT);
2538: printoption("SENT", IAC, ABORT);
2539: flushline = 1;
2540: if (autoflush) {
2541: doflush();
2542: }
2543: if (autosynch) {
2544: dosynch();
2545: }
2546: }
2547:
2548: void
2549: sendsusp()
2550: {
2551: NET2ADD(IAC, SUSP);
2552: printoption("SENT", IAC, SUSP);
2553: flushline = 1;
2554: if (autoflush) {
2555: doflush();
2556: }
2557: if (autosynch) {
2558: dosynch();
2559: }
2560: }
2561:
2562: void
2563: sendeof()
2564: {
2565: NET2ADD(IAC, xEOF);
2566: printoption("SENT", IAC, xEOF);
2567: }
2568:
2569: void
2570: sendayt()
2571: {
2572: NET2ADD(IAC, AYT);
2573: printoption("SENT", IAC, AYT);
2574: }
2575:
2576: /*
2577: * Send a window size update to the remote system.
2578: */
2579:
2580: void
2581: sendnaws()
2582: {
2583: long rows, cols;
2584: unsigned char tmp[16];
1.13 mpech 2585: unsigned char *cp;
1.1 deraadt 2586:
2587: if (my_state_is_wont(TELOPT_NAWS))
2588: return;
2589:
2590: #define PUTSHORT(cp, x) { if ((*cp++ = ((x)>>8)&0xff) == IAC) *cp++ = IAC; \
2591: if ((*cp++ = ((x))&0xff) == IAC) *cp++ = IAC; }
2592:
2593: if (TerminalWindowSize(&rows, &cols) == 0) { /* Failed */
2594: return;
2595: }
2596:
2597: cp = tmp;
2598:
2599: *cp++ = IAC;
2600: *cp++ = SB;
2601: *cp++ = TELOPT_NAWS;
2602: PUTSHORT(cp, cols);
2603: PUTSHORT(cp, rows);
2604: *cp++ = IAC;
2605: *cp++ = SE;
2606: if (NETROOM() >= cp - tmp) {
2607: ring_supply_data(&netoring, tmp, cp-tmp);
2608: printsub('>', tmp+2, cp - tmp - 2);
2609: }
2610: }
2611:
2612: void
2613: tel_enter_binary(rw)
2614: int rw;
2615: {
2616: if (rw&1)
2617: send_do(TELOPT_BINARY, 1);
2618: if (rw&2)
2619: send_will(TELOPT_BINARY, 1);
2620: }
2621:
2622: void
2623: tel_leave_binary(rw)
2624: int rw;
2625: {
2626: if (rw&1)
2627: send_dont(TELOPT_BINARY, 1);
2628: if (rw&2)
2629: send_wont(TELOPT_BINARY, 1);
2630: }