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