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