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