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