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