Annotation of src/usr.bin/telnet/telnet.c, Revision 1.20
1.20 ! chl 1: /* $OpenBSD: telnet.c,v 1.19 2005/02/27 15:46:42 otto 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 */
1.19 otto 449: if (env_getvalue((unsigned char *)"DISPLAY", 0))
1.1 deraadt 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);
1.19 otto 685: if ((tname = (char *)env_getvalue((unsigned char *)"TERM", 0)) &&
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:
1.19 otto 862: if ((dp = env_getvalue((unsigned char *)"DISPLAY", 0)) == NULL) {
1.1 deraadt 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:
1.19 otto 1334: static unsigned char slc_reply[2 * SUBBUFSIZE];
1335: static unsigned char *slc_replyp;
1336:
1337: unsigned char
1338: slc_add(unsigned char ch)
1339: {
1340: if (slc_replyp == slc_reply + sizeof(slc_reply))
1341: return ch;
1342: return *slc_replyp++ = ch;
1343: }
1.1 deraadt 1344:
1345: void
1346: slc_start_reply()
1347: {
1348: slc_replyp = slc_reply;
1.19 otto 1349: slc_add(IAC);
1350: slc_add(SB);
1351: slc_add(TELOPT_LINEMODE);
1352: slc_add(LM_SLC);
1.1 deraadt 1353: }
1354:
1355: void
1356: slc_add_reply(func, flags, value)
1357: unsigned char func;
1358: unsigned char flags;
1359: cc_t value;
1360: {
1.19 otto 1361: if (slc_replyp + 6 >= slc_reply + sizeof(slc_reply)) {
1362: printf("slc_add_reply: not enough room\n");
1363: return;
1364: }
1365: if (slc_add(func) == IAC)
1366: slc_add(IAC);
1367: if (slc_add(flags) == IAC)
1368: slc_add(IAC);
1369: if (slc_add((unsigned char)value) == IAC)
1370: slc_add(IAC);
1.1 deraadt 1371: }
1372:
1373: void
1374: slc_end_reply()
1375: {
1.13 mpech 1376: int len;
1.1 deraadt 1377:
1.19 otto 1378: if (slc_replyp + 2 >= slc_reply + sizeof(slc_reply)) {
1379: printf("slc_end_reply: not enough room\n");
1380: return;
1381: }
1382:
1383: slc_add(IAC);
1384: slc_add(SE);
1.1 deraadt 1385: len = slc_replyp - slc_reply;
1386: if (len <= 6)
1387: return;
1388: if (NETROOM() > len) {
1389: ring_supply_data(&netoring, slc_reply, slc_replyp - slc_reply);
1390: printsub('>', &slc_reply[2], slc_replyp - slc_reply - 2);
1391: }
1392: /*@*/else printf("slc_end_reply: not enough room\n");
1393: }
1394:
1395: int
1396: slc_update()
1397: {
1.13 mpech 1398: struct spc *spcp;
1.1 deraadt 1399: int need_update = 0;
1400:
1401: for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) {
1402: if (!(spcp->flags&SLC_ACK))
1403: continue;
1404: spcp->flags &= ~SLC_ACK;
1405: if (spcp->valp && (*spcp->valp != spcp->val)) {
1406: *spcp->valp = spcp->val;
1407: need_update = 1;
1408: }
1409: }
1410: return(need_update);
1411: }
1412:
1413: #ifdef OLD_ENVIRON
1414: # ifdef ENV_HACK
1415: /*
1416: * Earlier version of telnet/telnetd from the BSD code had
1417: * the definitions of VALUE and VAR reversed. To ensure
1418: * maximum interoperability, we assume that the server is
1419: * an older BSD server, until proven otherwise. The newer
1420: * BSD servers should be able to handle either definition,
1421: * so it is better to use the wrong values if we don't
1422: * know what type of server it is.
1423: */
1424: int env_auto = 1;
1425: int old_env_var = OLD_ENV_VAR;
1426: int old_env_value = OLD_ENV_VALUE;
1427: # else
1428: # define old_env_var OLD_ENV_VAR
1429: # define old_env_value OLD_ENV_VALUE
1430: # endif
1431: #endif
1432:
1433: void
1434: env_opt(buf, len)
1.13 mpech 1435: unsigned char *buf;
1436: int len;
1.1 deraadt 1437: {
1.13 mpech 1438: unsigned char *ep = 0, *epc = 0;
1439: int i;
1.1 deraadt 1440:
1441: switch(buf[0]&0xff) {
1442: case TELQUAL_SEND:
1443: env_opt_start();
1444: if (len == 1) {
1445: env_opt_add(NULL);
1446: } else for (i = 1; i < len; i++) {
1447: switch (buf[i]&0xff) {
1448: #ifdef OLD_ENVIRON
1449: case OLD_ENV_VAR:
1450: # ifdef ENV_HACK
1451: if (telopt_environ == TELOPT_OLD_ENVIRON
1452: && env_auto) {
1453: /* Server has the same definitions */
1454: old_env_var = OLD_ENV_VAR;
1455: old_env_value = OLD_ENV_VALUE;
1456: }
1457: /* FALL THROUGH */
1458: # endif
1459: case OLD_ENV_VALUE:
1460: /*
1461: * Although OLD_ENV_VALUE is not legal, we will
1462: * still recognize it, just in case it is an
1463: * old server that has VAR & VALUE mixed up...
1464: */
1465: /* FALL THROUGH */
1466: #else
1467: case NEW_ENV_VAR:
1468: #endif
1469: case ENV_USERVAR:
1470: if (ep) {
1471: *epc = 0;
1472: env_opt_add(ep);
1473: }
1474: ep = epc = &buf[i+1];
1475: break;
1476: case ENV_ESC:
1477: i++;
1478: /*FALL THROUGH*/
1479: default:
1480: if (epc)
1481: *epc++ = buf[i];
1482: break;
1483: }
1484: }
1485: if (ep) {
1486: *epc = 0;
1487: env_opt_add(ep);
1488: }
1489: env_opt_end(1);
1490: break;
1491:
1492: case TELQUAL_IS:
1493: case TELQUAL_INFO:
1494: /* Ignore for now. We shouldn't get it anyway. */
1495: break;
1496:
1497: default:
1498: break;
1499: }
1500: }
1501:
1.19 otto 1502: #define OPT_REPLY_SIZE (2 * SUBBUFSIZE)
1503: static unsigned char *opt_reply;
1504: static unsigned char *opt_replyp;
1505: static unsigned char *opt_replyend;
1.1 deraadt 1506:
1507: void
1.19 otto 1508: opt_add(unsigned char ch)
1509: {
1510: if (opt_replyp == opt_replyend)
1511: return;
1512: *opt_replyp++ = ch;
1513: }
1514: void
1.1 deraadt 1515: env_opt_start()
1516: {
1.8 itojun 1517: unsigned char *p;
1518:
1.20 ! chl 1519: p = (unsigned char *)realloc(opt_reply, OPT_REPLY_SIZE);
! 1520: if (p == NULL)
! 1521: free(opt_reply);
1.8 itojun 1522: opt_reply = p;
1.1 deraadt 1523: if (opt_reply == NULL) {
1.20 ! chl 1524: /*@*/ printf("env_opt_start: realloc() failed!!!\n");
1.1 deraadt 1525: opt_reply = opt_replyp = opt_replyend = NULL;
1526: return;
1527: }
1528: opt_replyp = opt_reply;
1529: opt_replyend = opt_reply + OPT_REPLY_SIZE;
1.19 otto 1530: opt_add(IAC);
1531: opt_add(SB);
1532: opt_add(telopt_environ);
1533: opt_add(TELQUAL_IS);
1.1 deraadt 1534: }
1535:
1536: void
1537: env_opt_start_info()
1538: {
1539: env_opt_start();
1540: if (opt_replyp)
1541: opt_replyp[-1] = TELQUAL_INFO;
1542: }
1543:
1544: void
1545: env_opt_add(ep)
1.13 mpech 1546: unsigned char *ep;
1.1 deraadt 1547: {
1.13 mpech 1548: unsigned char *vp, c;
1.1 deraadt 1549:
1550: if (opt_reply == NULL) /*XXX*/
1551: return; /*XXX*/
1552:
1553: if (ep == NULL || *ep == '\0') {
1554: /* Send user defined variables first. */
1555: env_default(1, 0);
1.4 art 1556: while ((ep = env_default(0, 0)))
1.1 deraadt 1557: env_opt_add(ep);
1558:
1559: /* Now add the list of well know variables. */
1560: env_default(1, 1);
1.4 art 1561: while ((ep = env_default(0, 1)))
1.1 deraadt 1562: env_opt_add(ep);
1563: return;
1564: }
1.19 otto 1565: vp = env_getvalue(ep, 1);
1566: if (opt_replyp + 2 * (vp ? strlen((char *)vp) : 0) +
1567: 2 * strlen((char *)ep) + 6 > opt_replyend)
1.1 deraadt 1568: {
1.19 otto 1569: size_t len;
1.8 itojun 1570: unsigned char *p;
1.19 otto 1571:
1.1 deraadt 1572: len = opt_replyend - opt_reply;
1.19 otto 1573: len += OPT_REPLY_SIZE + 2 * strlen(ep);
1574: if (vp)
1575: len += 2 * strlen(vp);
1.8 itojun 1576: p = (unsigned char *)realloc(opt_reply, len);
1.19 otto 1577: if (p == NULL) {
1.8 itojun 1578: free(opt_reply);
1.1 deraadt 1579: /*@*/ printf("env_opt_add: realloc() failed!!!\n");
1580: opt_reply = opt_replyp = opt_replyend = NULL;
1581: return;
1582: }
1.19 otto 1583: opt_replyp = p + (opt_replyp - opt_reply);
1584: opt_replyend = p + len;
1585: opt_reply = p;
1.1 deraadt 1586: }
1.4 art 1587: if (opt_welldefined((char *)ep))
1.1 deraadt 1588: #ifdef OLD_ENVIRON
1589: if (telopt_environ == TELOPT_OLD_ENVIRON)
1.19 otto 1590: opt_add(old_env_var);
1.1 deraadt 1591: else
1592: #endif
1.19 otto 1593: opt_add(NEW_ENV_VAR);
1.1 deraadt 1594: else
1.19 otto 1595: opt_add(ENV_USERVAR);
1596:
1.1 deraadt 1597: for (;;) {
1.4 art 1598: while ((c = *ep++)) {
1.1 deraadt 1599: switch(c&0xff) {
1600: case IAC:
1.19 otto 1601: opt_add(IAC);
1.1 deraadt 1602: break;
1603: case NEW_ENV_VAR:
1604: case NEW_ENV_VALUE:
1605: case ENV_ESC:
1606: case ENV_USERVAR:
1.19 otto 1607: opt_add(ENV_ESC);
1.1 deraadt 1608: break;
1609: }
1.19 otto 1610: opt_add(c);
1.1 deraadt 1611: }
1.4 art 1612: if ((ep = vp)) {
1.1 deraadt 1613: #ifdef OLD_ENVIRON
1614: if (telopt_environ == TELOPT_OLD_ENVIRON)
1.19 otto 1615: opt_add(old_env_value);
1.1 deraadt 1616: else
1617: #endif
1.19 otto 1618: opt_add(NEW_ENV_VALUE);
1.1 deraadt 1619: vp = NULL;
1620: } else
1621: break;
1622: }
1623: }
1624:
1625: int
1626: opt_welldefined(ep)
1627: char *ep;
1628: {
1629: if ((strcmp(ep, "USER") == 0) ||
1630: (strcmp(ep, "DISPLAY") == 0) ||
1631: (strcmp(ep, "PRINTER") == 0) ||
1632: (strcmp(ep, "SYSTEMTYPE") == 0) ||
1633: (strcmp(ep, "JOB") == 0) ||
1634: (strcmp(ep, "ACCT") == 0))
1635: return(1);
1636: return(0);
1637: }
1638: void
1639: env_opt_end(emptyok)
1.13 mpech 1640: int emptyok;
1.1 deraadt 1641: {
1.13 mpech 1642: int len;
1.1 deraadt 1643:
1644: len = opt_replyp - opt_reply + 2;
1645: if (emptyok || len > 6) {
1.19 otto 1646: opt_add(IAC);
1647: opt_add(SE);
1.1 deraadt 1648: if (NETROOM() > len) {
1649: ring_supply_data(&netoring, opt_reply, len);
1650: printsub('>', &opt_reply[2], len - 2);
1651: }
1652: /*@*/ else printf("slc_end_reply: not enough room\n");
1653: }
1654: if (opt_reply) {
1655: free(opt_reply);
1656: opt_reply = opt_replyp = opt_replyend = NULL;
1657: }
1658: }
1659:
1660:
1661:
1662: int
1663: telrcv()
1664: {
1.13 mpech 1665: int c;
1666: int scc;
1667: unsigned char *sbp;
1.1 deraadt 1668: int count;
1669: int returnValue = 0;
1670:
1671: scc = 0;
1672: count = 0;
1673: while (TTYROOM() > 2) {
1674: if (scc == 0) {
1675: if (count) {
1676: ring_consumed(&netiring, count);
1677: returnValue = 1;
1678: count = 0;
1679: }
1680: sbp = netiring.consume;
1681: scc = ring_full_consecutive(&netiring);
1682: if (scc == 0) {
1683: /* No more data coming in */
1684: break;
1685: }
1686: }
1687:
1688: c = *sbp++ & 0xff, scc--; count++;
1.4 art 1689: #if defined(ENCRYPTION)
1690: if (decrypt_input)
1691: c = (*decrypt_input)(c);
1692: #endif
1.1 deraadt 1693:
1694: switch (telrcv_state) {
1695:
1696: case TS_CR:
1697: telrcv_state = TS_DATA;
1698: if (c == '\0') {
1699: break; /* Ignore \0 after CR */
1700: }
1701: else if ((c == '\n') && my_want_state_is_dont(TELOPT_ECHO) && !crmod) {
1702: TTYADD(c);
1703: break;
1704: }
1705: /* Else, fall through */
1706:
1707: case TS_DATA:
1708: if (c == IAC) {
1709: telrcv_state = TS_IAC;
1710: break;
1711: }
1712: # if defined(TN3270)
1713: if (In3270) {
1714: *Ifrontp++ = c;
1715: while (scc > 0) {
1716: c = *sbp++ & 0377, scc--; count++;
1717: if (c == IAC) {
1718: telrcv_state = TS_IAC;
1719: break;
1720: }
1721: *Ifrontp++ = c;
1722: }
1723: } else
1724: # endif /* defined(TN3270) */
1725: /*
1726: * The 'crmod' hack (see following) is needed
1.4 art 1727: * since we can't set CRMOD on output only.
1.1 deraadt 1728: * Machines like MULTICS like to send \r without
1729: * \n; since we must turn off CRMOD to get proper
1730: * input, the mapping is done here (sigh).
1731: */
1732: if ((c == '\r') && my_want_state_is_dont(TELOPT_BINARY)) {
1733: if (scc > 0) {
1734: c = *sbp&0xff;
1.4 art 1735: #if defined(ENCRYPTION)
1736: if (decrypt_input)
1737: c = (*decrypt_input)(c);
1738: #endif
1.1 deraadt 1739: if (c == 0) {
1740: sbp++, scc--; count++;
1741: /* a "true" CR */
1742: TTYADD('\r');
1743: } else if (my_want_state_is_dont(TELOPT_ECHO) &&
1744: (c == '\n')) {
1745: sbp++, scc--; count++;
1746: TTYADD('\n');
1747: } else {
1.4 art 1748: #if defined(ENCRYPTION)
1749: if (decrypt_input)
1750: (*decrypt_input)(-1);
1751: #endif
1.1 deraadt 1752: TTYADD('\r');
1753: if (crmod) {
1754: TTYADD('\n');
1755: }
1756: }
1757: } else {
1758: telrcv_state = TS_CR;
1759: TTYADD('\r');
1760: if (crmod) {
1761: TTYADD('\n');
1762: }
1763: }
1764: } else {
1765: TTYADD(c);
1766: }
1767: continue;
1768:
1769: case TS_IAC:
1770: process_iac:
1771: switch (c) {
1.2 niklas 1772:
1.1 deraadt 1773: case WILL:
1774: telrcv_state = TS_WILL;
1775: continue;
1776:
1777: case WONT:
1778: telrcv_state = TS_WONT;
1779: continue;
1780:
1781: case DO:
1782: telrcv_state = TS_DO;
1783: continue;
1784:
1785: case DONT:
1786: telrcv_state = TS_DONT;
1787: continue;
1788:
1789: case DM:
1790: /*
1791: * We may have missed an urgent notification,
1792: * so make sure we flush whatever is in the
1793: * buffer currently.
1794: */
1795: printoption("RCVD", IAC, DM);
1796: SYNCHing = 1;
1797: (void) ttyflush(1);
1798: SYNCHing = stilloob();
1799: settimer(gotDM);
1800: break;
1801:
1802: case SB:
1803: SB_CLEAR();
1804: telrcv_state = TS_SB;
1805: continue;
1806:
1807: # if defined(TN3270)
1808: case EOR:
1809: if (In3270) {
1810: if (Ibackp == Ifrontp) {
1811: Ibackp = Ifrontp = Ibuf;
1812: ISend = 0; /* should have been! */
1813: } else {
1814: Ibackp += DataFromNetwork(Ibackp, Ifrontp-Ibackp, 1);
1815: ISend = 1;
1816: }
1817: }
1818: printoption("RCVD", IAC, EOR);
1819: break;
1820: # endif /* defined(TN3270) */
1821:
1822: case IAC:
1823: # if !defined(TN3270)
1824: TTYADD(IAC);
1825: # else /* !defined(TN3270) */
1826: if (In3270) {
1827: *Ifrontp++ = IAC;
1828: } else {
1829: TTYADD(IAC);
1830: }
1831: # endif /* !defined(TN3270) */
1832: break;
1833:
1834: case NOP:
1835: case GA:
1836: default:
1837: printoption("RCVD", IAC, c);
1838: break;
1839: }
1840: telrcv_state = TS_DATA;
1841: continue;
1842:
1843: case TS_WILL:
1844: printoption("RCVD", WILL, c);
1845: willoption(c);
1846: SetIn3270();
1847: telrcv_state = TS_DATA;
1848: continue;
1849:
1850: case TS_WONT:
1851: printoption("RCVD", WONT, c);
1852: wontoption(c);
1853: SetIn3270();
1854: telrcv_state = TS_DATA;
1855: continue;
1856:
1857: case TS_DO:
1858: printoption("RCVD", DO, c);
1859: dooption(c);
1860: SetIn3270();
1861: if (c == TELOPT_NAWS) {
1862: sendnaws();
1863: } else if (c == TELOPT_LFLOW) {
1864: localflow = 1;
1865: setcommandmode();
1866: setconnmode(0);
1867: }
1868: telrcv_state = TS_DATA;
1869: continue;
1870:
1871: case TS_DONT:
1872: printoption("RCVD", DONT, c);
1873: dontoption(c);
1874: flushline = 1;
1875: setconnmode(0); /* set new tty mode (maybe) */
1876: SetIn3270();
1877: telrcv_state = TS_DATA;
1878: continue;
1879:
1880: case TS_SB:
1881: if (c == IAC) {
1882: telrcv_state = TS_SE;
1883: } else {
1884: SB_ACCUM(c);
1885: }
1886: continue;
1887:
1888: case TS_SE:
1889: if (c != SE) {
1890: if (c != IAC) {
1891: /*
1892: * This is an error. We only expect to get
1893: * "IAC IAC" or "IAC SE". Several things may
1.18 jmc 1894: * have happened. An IAC was not doubled, the
1.1 deraadt 1895: * IAC SE was left off, or another option got
1896: * inserted into the suboption are all possibilities.
1897: * If we assume that the IAC was not doubled,
1898: * and really the IAC SE was left off, we could
1899: * get into an infinate loop here. So, instead,
1900: * we terminate the suboption, and process the
1901: * partial suboption if we can.
1902: */
1903: SB_ACCUM(IAC);
1904: SB_ACCUM(c);
1905: subpointer -= 2;
1906: SB_TERM();
1907:
1908: printoption("In SUBOPTION processing, RCVD", IAC, c);
1909: suboption(); /* handle sub-option */
1910: SetIn3270();
1911: telrcv_state = TS_IAC;
1912: goto process_iac;
1913: }
1914: SB_ACCUM(c);
1915: telrcv_state = TS_SB;
1916: } else {
1917: SB_ACCUM(IAC);
1918: SB_ACCUM(SE);
1919: subpointer -= 2;
1920: SB_TERM();
1921: suboption(); /* handle sub-option */
1922: SetIn3270();
1923: telrcv_state = TS_DATA;
1924: }
1925: }
1926: }
1927: if (count)
1928: ring_consumed(&netiring, count);
1929: return returnValue||count;
1930: }
1931:
1932: static int bol = 1, local = 0;
1933:
1934: int
1935: rlogin_susp()
1936: {
1937: if (local) {
1938: local = 0;
1939: bol = 1;
1940: command(0, "z\n", 2);
1941: return(1);
1942: }
1943: return(0);
1944: }
1945:
1946: static int
1947: telsnd()
1948: {
1949: int tcc;
1950: int count;
1951: int returnValue = 0;
1952: unsigned char *tbp;
1953:
1954: tcc = 0;
1955: count = 0;
1956: while (NETROOM() > 2) {
1.13 mpech 1957: int sc;
1958: int c;
1.1 deraadt 1959:
1960: if (tcc == 0) {
1961: if (count) {
1962: ring_consumed(&ttyiring, count);
1963: returnValue = 1;
1964: count = 0;
1965: }
1966: tbp = ttyiring.consume;
1967: tcc = ring_full_consecutive(&ttyiring);
1968: if (tcc == 0) {
1969: break;
1970: }
1971: }
1972: c = *tbp++ & 0xff, sc = strip(c), tcc--; count++;
1973: if (rlogin != _POSIX_VDISABLE) {
1974: if (bol) {
1975: bol = 0;
1976: if (sc == rlogin) {
1977: local = 1;
1978: continue;
1979: }
1980: } else if (local) {
1981: local = 0;
1982: if (sc == '.' || c == termEofChar) {
1983: bol = 1;
1984: command(0, "close\n", 6);
1985: continue;
1986: }
1987: if (sc == termSuspChar) {
1988: bol = 1;
1989: command(0, "z\n", 2);
1990: continue;
1991: }
1992: if (sc == escape) {
1993: command(0, (char *)tbp, tcc);
1994: bol = 1;
1995: count += tcc;
1996: tcc = 0;
1997: flushline = 1;
1998: break;
1999: }
2000: if (sc != rlogin) {
2001: ++tcc;
2002: --tbp;
2003: --count;
2004: c = sc = rlogin;
2005: }
2006: }
2007: if ((sc == '\n') || (sc == '\r'))
2008: bol = 1;
1.7 aaron 2009: } else if (escape != _POSIX_VDISABLE && sc == escape) {
1.1 deraadt 2010: /*
2011: * Double escape is a pass through of a single escape character.
2012: */
2013: if (tcc && strip(*tbp) == escape) {
2014: tbp++;
2015: tcc--;
2016: count++;
2017: bol = 0;
2018: } else {
2019: command(0, (char *)tbp, tcc);
2020: bol = 1;
2021: count += tcc;
2022: tcc = 0;
2023: flushline = 1;
2024: break;
2025: }
2026: } else
2027: bol = 0;
2028: #ifdef KLUDGELINEMODE
2029: if (kludgelinemode && (globalmode&MODE_EDIT) && (sc == echoc)) {
2030: if (tcc > 0 && strip(*tbp) == echoc) {
2031: tcc--; tbp++; count++;
2032: } else {
2033: dontlecho = !dontlecho;
2034: settimer(echotoggle);
2035: setconnmode(0);
2036: flushline = 1;
2037: break;
2038: }
2039: }
2040: #endif
1.3 deraadt 2041: if (sc != _POSIX_VDISABLE && MODE_LOCAL_CHARS(globalmode)) {
1.1 deraadt 2042: if (TerminalSpecialChars(sc) == 0) {
2043: bol = 1;
2044: break;
2045: }
2046: }
2047: if (my_want_state_is_wont(TELOPT_BINARY)) {
2048: switch (c) {
2049: case '\n':
2050: /*
2051: * If we are in CRMOD mode (\r ==> \n)
2052: * on our local machine, then probably
2053: * a newline (unix) is CRLF (TELNET).
2054: */
2055: if (MODE_LOCAL_CHARS(globalmode)) {
2056: NETADD('\r');
2057: }
2058: NETADD('\n');
2059: bol = flushline = 1;
2060: break;
2061: case '\r':
2062: if (!crlf) {
2063: NET2ADD('\r', '\0');
2064: } else {
2065: NET2ADD('\r', '\n');
2066: }
2067: bol = flushline = 1;
2068: break;
2069: case IAC:
2070: NET2ADD(IAC, IAC);
2071: break;
2072: default:
2073: NETADD(c);
2074: break;
2075: }
2076: } else if (c == IAC) {
2077: NET2ADD(IAC, IAC);
2078: } else {
2079: NETADD(c);
2080: }
2081: }
2082: if (count)
2083: ring_consumed(&ttyiring, count);
2084: return returnValue||count; /* Non-zero if we did anything */
2085: }
2086:
2087: /*
2088: * Scheduler()
2089: *
2090: * Try to do something.
2091: *
2092: * If we do something useful, return 1; else return 0.
2093: *
2094: */
2095:
2096:
2097: int
2098: Scheduler(block)
2099: int block; /* should we block in the select ? */
2100: {
2101: /* One wants to be a bit careful about setting returnValue
2102: * to one, since a one implies we did some useful work,
2103: * and therefore probably won't be called to block next
2104: * time (TN3270 mode only).
2105: */
2106: int returnValue;
2107: int netin, netout, netex, ttyin, ttyout;
2108:
2109: /* Decide which rings should be processed */
2110:
2111: netout = ring_full_count(&netoring) &&
2112: (flushline ||
2113: (my_want_state_is_wont(TELOPT_LINEMODE)
2114: #ifdef KLUDGELINEMODE
2115: && (!kludgelinemode || my_want_state_is_do(TELOPT_SGA))
2116: #endif
2117: ) ||
2118: my_want_state_is_will(TELOPT_BINARY));
2119: ttyout = ring_full_count(&ttyoring);
2120:
2121: #if defined(TN3270)
2122: ttyin = ring_empty_count(&ttyiring) && (clienteof == 0) && (shell_active == 0);
2123: #else /* defined(TN3270) */
2124: ttyin = ring_empty_count(&ttyiring) && (clienteof == 0);
2125: #endif /* defined(TN3270) */
2126:
2127: #if defined(TN3270)
2128: netin = ring_empty_count(&netiring);
2129: # else /* !defined(TN3270) */
2130: netin = !ISend && ring_empty_count(&netiring);
2131: # endif /* !defined(TN3270) */
2132:
2133: netex = !SYNCHing;
2134:
2135: /* If we have seen a signal recently, reset things */
1.15 hin 2136:
2137: if (scheduler_lockout_tty) {
2138: ttyin = ttyout = 0;
2139: }
2140:
1.1 deraadt 2141: # if defined(TN3270) && defined(unix)
2142: if (HaveInput) {
2143: HaveInput = 0;
2144: (void) signal(SIGIO, inputAvailable);
2145: }
2146: #endif /* defined(TN3270) && defined(unix) */
2147:
2148: /* Call to system code to process rings */
2149:
2150: returnValue = process_rings(netin, netout, netex, ttyin, ttyout, !block);
2151:
2152: /* Now, look at the input rings, looking for work to do. */
2153:
2154: if (ring_full_count(&ttyiring)) {
2155: # if defined(TN3270)
2156: if (In3270) {
2157: int c;
2158:
2159: c = DataFromTerminal(ttyiring.consume,
2160: ring_full_consecutive(&ttyiring));
2161: if (c) {
2162: returnValue = 1;
1.2 niklas 2163: ring_consumed(&ttyiring, c);
1.1 deraadt 2164: }
2165: } else {
2166: # endif /* defined(TN3270) */
2167: returnValue |= telsnd();
2168: # if defined(TN3270)
2169: }
2170: # endif /* defined(TN3270) */
2171: }
2172:
2173: if (ring_full_count(&netiring)) {
2174: # if !defined(TN3270)
2175: returnValue |= telrcv();
2176: # else /* !defined(TN3270) */
2177: returnValue = Push3270();
2178: # endif /* !defined(TN3270) */
2179: }
2180: return returnValue;
2181: }
2182:
2183: /*
2184: * Select from tty and network...
2185: */
2186: void
2187: telnet(user)
2188: char *user;
2189: {
2190: sys_telnet_init();
2191:
1.4 art 2192: #if defined(AUTHENTICATION) || defined(ENCRYPTION)
1.1 deraadt 2193: {
2194: static char local_host[256] = { 0 };
2195:
2196: if (!local_host[0]) {
2197: gethostname(local_host, sizeof(local_host));
2198: local_host[sizeof(local_host)-1] = 0;
2199: }
2200: auth_encrypt_init(local_host, hostname, "TELNET", 0);
2201: auth_encrypt_user(user);
2202: }
1.4 art 2203: #endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */
1.1 deraadt 2204: # if !defined(TN3270)
2205: if (telnetport) {
2206: #if defined(AUTHENTICATION)
2207: if (autologin)
2208: send_will(TELOPT_AUTHENTICATION, 1);
2209: #endif
1.4 art 2210: #if defined(ENCRYPTION)
2211: send_do(TELOPT_ENCRYPT, 1);
2212: send_will(TELOPT_ENCRYPT, 1);
2213: #endif
1.1 deraadt 2214: send_do(TELOPT_SGA, 1);
2215: send_will(TELOPT_TTYPE, 1);
2216: send_will(TELOPT_NAWS, 1);
2217: send_will(TELOPT_TSPEED, 1);
2218: send_will(TELOPT_LFLOW, 1);
2219: send_will(TELOPT_LINEMODE, 1);
2220: send_will(TELOPT_NEW_ENVIRON, 1);
2221: send_do(TELOPT_STATUS, 1);
1.19 otto 2222: if (env_getvalue((unsigned char *)"DISPLAY", 0))
1.1 deraadt 2223: send_will(TELOPT_XDISPLOC, 1);
1.4 art 2224: if (binary)
2225: tel_enter_binary(binary);
1.1 deraadt 2226: }
2227: # endif /* !defined(TN3270) */
2228:
1.15 hin 2229: #ifdef ENCRYPTION
2230: /*
2231: * Note: we assume a tie to the authentication option here. This
2232: * is necessary so that authentication fails, we don't spin
2233: * forever.
2234: */
2235: if (wantencryption) {
2236: extern int auth_has_failed;
2237: time_t timeout = time(0) + 60;
1.20 ! chl 2238: int printed_encrypt = 0;
1.15 hin 2239:
2240: send_do(TELOPT_ENCRYPT, 1);
2241: send_will(TELOPT_ENCRYPT, 1);
2242: while (1) {
2243: if (my_want_state_is_wont(TELOPT_AUTHENTICATION)) {
2244: if (wantencryption == -1) {
2245: break;
2246: } else {
2247: printf("\nServer refused to negotiate authentication,");
2248: printf(" which is required for encryption.\n");
2249: Exit(1);
2250: }
2251: }
2252: if (auth_has_failed) {
1.17 jmc 2253: printf("\nAuthentication negotiation has failed,");
1.15 hin 2254: printf(" which is required for encryption.\n");
2255: Exit(1);
2256: }
2257: if (my_want_state_is_dont(TELOPT_ENCRYPT) ||
2258: my_want_state_is_wont(TELOPT_ENCRYPT)) {
2259: printf("\nServer refused to negotiate encryption.\n");
2260: Exit(1);
2261: }
2262: if (encrypt_is_encrypting())
2263: break;
2264: if (time(0) > timeout) {
2265: printf("\nEncryption could not be enabled.\n");
2266: Exit(1);
2267: }
2268: if (printed_encrypt == 0) {
2269: printed_encrypt = 1;
2270: printf("Waiting for encryption to be negotiated...\n");
2271: /*
2272: * Turn on MODE_TRAPSIG and then turn off localchars
2273: * so that ^C will cause telnet to exit.
2274: */
2275: TerminalNewMode(getconnmode()|MODE_TRAPSIG);
2276: intr_waiting = 1;
2277: }
2278: if (intr_happened) {
2279: printf("\nUser interrupt.\n");
2280: Exit(1);
2281: }
2282: telnet_spin();
2283: }
2284: if (printed_encrypt) {
2285: printf("Encryption negotiated.\n");
2286: intr_waiting = 0;
2287: setconnmode(0);
2288: }
2289: }
2290: #endif
2291:
1.1 deraadt 2292: # if !defined(TN3270)
2293: for (;;) {
2294: int schedValue;
2295:
2296: while ((schedValue = Scheduler(0)) != 0) {
2297: if (schedValue == -1) {
2298: setcommandmode();
2299: return;
2300: }
2301: }
2302:
2303: if (Scheduler(1) == -1) {
2304: setcommandmode();
2305: return;
2306: }
2307: }
2308: # else /* !defined(TN3270) */
2309: for (;;) {
2310: int schedValue;
2311:
2312: while (!In3270 && !shell_active) {
2313: if (Scheduler(1) == -1) {
2314: setcommandmode();
2315: return;
2316: }
2317: }
2318:
2319: while ((schedValue = Scheduler(0)) != 0) {
2320: if (schedValue == -1) {
2321: setcommandmode();
2322: return;
2323: }
2324: }
2325: /* If there is data waiting to go out to terminal, don't
2326: * schedule any more data for the terminal.
2327: */
2328: if (ring_full_count(&ttyoring)) {
2329: schedValue = 1;
2330: } else {
2331: if (shell_active) {
2332: if (shell_continue() == 0) {
2333: ConnectScreen();
2334: }
2335: } else if (In3270) {
2336: schedValue = DoTerminalOutput();
2337: }
2338: }
2339: if (schedValue && (shell_active == 0)) {
2340: if (Scheduler(1) == -1) {
2341: setcommandmode();
2342: return;
2343: }
2344: }
2345: }
2346: # endif /* !defined(TN3270) */
2347: }
2348:
2349: #if 0 /* XXX - this not being in is a bug */
2350: /*
2351: * nextitem()
2352: *
2353: * Return the address of the next "item" in the TELNET data
2354: * stream. This will be the address of the next character if
2355: * the current address is a user data character, or it will
2356: * be the address of the character following the TELNET command
2357: * if the current address is a TELNET IAC ("I Am a Command")
2358: * character.
2359: */
2360:
2361: static char *
2362: nextitem(current)
2363: char *current;
2364: {
2365: if ((*current&0xff) != IAC) {
2366: return current+1;
2367: }
2368: switch (*(current+1)&0xff) {
2369: case DO:
2370: case DONT:
2371: case WILL:
2372: case WONT:
2373: return current+3;
2374: case SB: /* loop forever looking for the SE */
2375: {
1.13 mpech 2376: char *look = current+2;
1.1 deraadt 2377:
2378: for (;;) {
2379: if ((*look++&0xff) == IAC) {
2380: if ((*look++&0xff) == SE) {
2381: return look;
2382: }
2383: }
2384: }
2385: }
2386: default:
2387: return current+2;
2388: }
2389: }
2390: #endif /* 0 */
2391:
2392: /*
2393: * netclear()
2394: *
2395: * We are about to do a TELNET SYNCH operation. Clear
2396: * the path to the network.
2397: *
2398: * Things are a bit tricky since we may have sent the first
2399: * byte or so of a previous TELNET command into the network.
2400: * So, we have to scan the network buffer from the beginning
2401: * until we are up to where we want to be.
2402: *
2403: * A side effect of what we do, just to keep things
2404: * simple, is to clear the urgent data pointer. The principal
2405: * caller should be setting the urgent data pointer AFTER calling
2406: * us in any case.
2407: */
2408:
2409: static void
2410: netclear()
2411: {
2412: #if 0 /* XXX */
1.13 mpech 2413: char *thisitem, *next;
1.1 deraadt 2414: char *good;
2415: #define wewant(p) ((nfrontp > p) && ((*p&0xff) == IAC) && \
2416: ((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL))
2417:
2418: thisitem = netobuf;
2419:
2420: while ((next = nextitem(thisitem)) <= netobuf.send) {
2421: thisitem = next;
2422: }
2423:
2424: /* Now, thisitem is first before/at boundary. */
2425:
2426: good = netobuf; /* where the good bytes go */
2427:
2428: while (netoring.add > thisitem) {
2429: if (wewant(thisitem)) {
2430: int length;
2431:
2432: next = thisitem;
2433: do {
2434: next = nextitem(next);
2435: } while (wewant(next) && (nfrontp > next));
2436: length = next-thisitem;
1.2 niklas 2437: memmove(good, thisitem, length);
1.1 deraadt 2438: good += length;
2439: thisitem = next;
2440: } else {
2441: thisitem = nextitem(thisitem);
2442: }
2443: }
2444:
2445: #endif /* 0 */
2446: }
2447:
2448: /*
2449: * These routines add various telnet commands to the data stream.
2450: */
2451:
2452: static void
2453: doflush()
2454: {
2455: NET2ADD(IAC, DO);
2456: NETADD(TELOPT_TM);
2457: flushline = 1;
2458: flushout = 1;
2459: (void) ttyflush(1); /* Flush/drop output */
2460: /* do printoption AFTER flush, otherwise the output gets tossed... */
2461: printoption("SENT", DO, TELOPT_TM);
2462: }
2463:
2464: void
2465: xmitAO()
2466: {
2467: NET2ADD(IAC, AO);
2468: printoption("SENT", IAC, AO);
2469: if (autoflush) {
2470: doflush();
2471: }
2472: }
2473:
2474:
2475: void
2476: xmitEL()
2477: {
2478: NET2ADD(IAC, EL);
2479: printoption("SENT", IAC, EL);
2480: }
2481:
2482: void
2483: xmitEC()
2484: {
2485: NET2ADD(IAC, EC);
2486: printoption("SENT", IAC, EC);
2487: }
2488:
2489:
2490: int
2491: dosynch()
2492: {
2493: netclear(); /* clear the path to the network */
2494: NETADD(IAC);
2495: setneturg();
2496: NETADD(DM);
2497: printoption("SENT", IAC, DM);
2498: return 1;
2499: }
2500:
2501: int want_status_response = 0;
2502:
2503: int
2504: get_status()
2505: {
2506: unsigned char tmp[16];
1.13 mpech 2507: unsigned char *cp;
1.1 deraadt 2508:
2509: if (my_want_state_is_dont(TELOPT_STATUS)) {
2510: printf("Remote side does not support STATUS option\n");
2511: return 0;
2512: }
2513: cp = tmp;
2514:
2515: *cp++ = IAC;
2516: *cp++ = SB;
2517: *cp++ = TELOPT_STATUS;
2518: *cp++ = TELQUAL_SEND;
2519: *cp++ = IAC;
2520: *cp++ = SE;
2521: if (NETROOM() >= cp - tmp) {
2522: ring_supply_data(&netoring, tmp, cp-tmp);
2523: printsub('>', tmp+2, cp - tmp - 2);
2524: }
2525: ++want_status_response;
2526: return 1;
2527: }
2528:
2529: void
2530: intp()
2531: {
2532: NET2ADD(IAC, IP);
2533: printoption("SENT", IAC, IP);
2534: flushline = 1;
2535: if (autoflush) {
2536: doflush();
2537: }
2538: if (autosynch) {
2539: dosynch();
2540: }
2541: }
2542:
2543: void
2544: sendbrk()
2545: {
2546: NET2ADD(IAC, BREAK);
2547: printoption("SENT", IAC, BREAK);
2548: flushline = 1;
2549: if (autoflush) {
2550: doflush();
2551: }
2552: if (autosynch) {
2553: dosynch();
2554: }
2555: }
2556:
2557: void
2558: sendabort()
2559: {
2560: NET2ADD(IAC, ABORT);
2561: printoption("SENT", IAC, ABORT);
2562: flushline = 1;
2563: if (autoflush) {
2564: doflush();
2565: }
2566: if (autosynch) {
2567: dosynch();
2568: }
2569: }
2570:
2571: void
2572: sendsusp()
2573: {
2574: NET2ADD(IAC, SUSP);
2575: printoption("SENT", IAC, SUSP);
2576: flushline = 1;
2577: if (autoflush) {
2578: doflush();
2579: }
2580: if (autosynch) {
2581: dosynch();
2582: }
2583: }
2584:
2585: void
2586: sendeof()
2587: {
2588: NET2ADD(IAC, xEOF);
2589: printoption("SENT", IAC, xEOF);
2590: }
2591:
2592: void
2593: sendayt()
2594: {
2595: NET2ADD(IAC, AYT);
2596: printoption("SENT", IAC, AYT);
2597: }
2598:
2599: /*
2600: * Send a window size update to the remote system.
2601: */
2602:
2603: void
2604: sendnaws()
2605: {
2606: long rows, cols;
2607: unsigned char tmp[16];
1.13 mpech 2608: unsigned char *cp;
1.1 deraadt 2609:
2610: if (my_state_is_wont(TELOPT_NAWS))
2611: return;
2612:
2613: #define PUTSHORT(cp, x) { if ((*cp++ = ((x)>>8)&0xff) == IAC) *cp++ = IAC; \
2614: if ((*cp++ = ((x))&0xff) == IAC) *cp++ = IAC; }
2615:
2616: if (TerminalWindowSize(&rows, &cols) == 0) { /* Failed */
2617: return;
2618: }
2619:
2620: cp = tmp;
2621:
2622: *cp++ = IAC;
2623: *cp++ = SB;
2624: *cp++ = TELOPT_NAWS;
2625: PUTSHORT(cp, cols);
2626: PUTSHORT(cp, rows);
2627: *cp++ = IAC;
2628: *cp++ = SE;
2629: if (NETROOM() >= cp - tmp) {
2630: ring_supply_data(&netoring, tmp, cp-tmp);
2631: printsub('>', tmp+2, cp - tmp - 2);
2632: }
2633: }
2634:
2635: void
2636: tel_enter_binary(rw)
2637: int rw;
2638: {
2639: if (rw&1)
2640: send_do(TELOPT_BINARY, 1);
2641: if (rw&2)
2642: send_will(TELOPT_BINARY, 1);
2643: }
2644:
2645: void
2646: tel_leave_binary(rw)
2647: int rw;
2648: {
2649: if (rw&1)
2650: send_dont(TELOPT_BINARY, 1);
2651: if (rw&2)
2652: send_wont(TELOPT_BINARY, 1);
2653: }