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