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