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