2 * Copyright (c) 1988, 1990, 1993
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
34 #include "telnet_locl.h"
36 RCSID("$Id: telnet.c 16285 2005-11-03 18:38:57Z lha $");
38 #define strip(x) (eight ? (x) : ((x) & 0x7f))
40 static unsigned char subbuffer[SUBBUFSIZE],
41 *subpointer, *subend; /* buffer for sub-options */
42 #define SB_CLEAR() subpointer = subbuffer;
43 #define SB_TERM() { subend = subpointer; SB_CLEAR(); }
44 #define SB_ACCUM(c) if (subpointer < (subbuffer+sizeof subbuffer)) { \
45 *subpointer++ = (c); \
48 #define SB_GET() ((*subpointer++)&0xff)
49 #define SB_PEEK() ((*subpointer)&0xff)
50 #define SB_EOF() (subpointer >= subend)
51 #define SB_LEN() (subend - subpointer)
53 char options[256]; /* The combined options */
54 char do_dont_resp[256];
55 char will_wont_resp[256];
60 autologin = 0, /* Autologin anyone? */
64 ISend, /* trying to send network data in */
67 netdata, /* Print out network data flow */
68 crlf, /* Should '\r' be mapped to <CR><LF> (or <CR><NUL>)? */
71 SYNCHing, /* we are in TELNET SYNCH mode */
72 flushout, /* flush output */
73 autoflush = 0, /* flush output when interrupting? */
74 autosynch, /* send interrupt characters with SYNCH? */
75 localflow, /* we handle flow control locally */
76 restartany, /* if flow control enabled, restart on any character */
77 localchars, /* we recognize interrupt/quit */
78 donelclchars, /* the user has set "localchars" */
79 donebinarytoggle, /* the user has put us in binary */
80 dontlecho, /* do we suppress local echoing right now? */
85 int scheduler_lockout_tty = 0;
94 * Telnet receiver states for fsm
103 #define TS_SB 7 /* sub-option collection */
104 #define TS_SE 8 /* looking for sub-option end */
106 static int telrcv_state;
108 unsigned char telopt_environ = TELOPT_NEW_ENVIRON;
110 # define telopt_environ TELOPT_NEW_ENVIRON
119 #ifdef KLUDGELINEMODE
120 int kludgelinemode = 1;
124 * The following are some clocks used to decide how to interpret
125 * the relationship between various variables.
130 static int is_unique(char *name, char **as, char **ae);
134 * Initialize telnet environment.
143 memset(options, 0, sizeof options);
145 connected = ISend = localflow = donebinarytoggle = 0;
146 #if defined(AUTHENTICATION) || defined(ENCRYPTION)
147 auth_encrypt_connect(connected);
148 #endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */
153 /* Don't change NetTrace */
155 escape = CONTROL(']');
156 rlogin = _POSIX_VDISABLE;
157 #ifdef KLUDGELINEMODE
158 echoc = CONTROL('E');
162 telrcv_state = TS_DATA;
167 * These routines are in charge of sending option negotiations
170 * The basic idea is that we send the negotiation if either side
171 * is in disagreement as to what the current state should be.
175 send_do(int c, int init)
178 if (((do_dont_resp[c] == 0) && my_state_is_do(c)) ||
179 my_want_state_is_do(c))
181 set_my_want_state_do(c);
186 printoption("SENT", DO, c);
190 send_dont(int c, int init)
193 if (((do_dont_resp[c] == 0) && my_state_is_dont(c)) ||
194 my_want_state_is_dont(c))
196 set_my_want_state_dont(c);
201 printoption("SENT", DONT, c);
205 send_will(int c, int init)
208 if (((will_wont_resp[c] == 0) && my_state_is_will(c)) ||
209 my_want_state_is_will(c))
211 set_my_want_state_will(c);
216 printoption("SENT", WILL, c);
220 send_wont(int c, int init)
223 if (((will_wont_resp[c] == 0) && my_state_is_wont(c)) ||
224 my_want_state_is_wont(c))
226 set_my_want_state_wont(c);
231 printoption("SENT", WONT, c);
236 willoption(int option)
238 int new_state_ok = 0;
240 if (do_dont_resp[option]) {
241 --do_dont_resp[option];
242 if (do_dont_resp[option] && my_state_is_do(option))
243 --do_dont_resp[option];
246 if ((do_dont_resp[option] == 0) && my_want_state_is_dont(option)) {
253 settimer(modenegotiated);
256 #if defined(AUTHENTICATION)
257 case TELOPT_AUTHENTICATION:
259 #if defined(ENCRYPTION)
269 * Special case for TM. If we get back a WILL,
270 * pretend we got back a WONT.
272 set_my_want_state_dont(option);
273 set_my_state_dont(option);
274 return; /* Never reply to TM will's/wont's */
276 case TELOPT_LINEMODE:
282 set_my_want_state_do(option);
284 setconnmode(0); /* possibly set new tty mode */
286 do_dont_resp[option]++;
287 send_dont(option, 0);
290 set_my_state_do(option);
291 #if defined(ENCRYPTION)
292 if (option == TELOPT_ENCRYPT)
293 encrypt_send_support();
298 wontoption(int option)
300 if (do_dont_resp[option]) {
301 --do_dont_resp[option];
302 if (do_dont_resp[option] && my_state_is_dont(option))
303 --do_dont_resp[option];
306 if ((do_dont_resp[option] == 0) && my_want_state_is_do(option)) {
310 #ifdef KLUDGELINEMODE
317 settimer(modenegotiated);
323 set_my_want_state_dont(option);
324 set_my_state_dont(option);
325 return; /* Never reply to TM will's/wont's */
335 set_my_want_state_dont(option);
336 if (my_state_is_do(option))
337 send_dont(option, 0);
338 setconnmode(0); /* Set new tty mode */
339 } else if (option == TELOPT_TM) {
341 * Special case for TM.
345 set_my_want_state_dont(option);
347 set_my_state_dont(option);
353 int new_state_ok = 0;
355 if (will_wont_resp[option]) {
356 --will_wont_resp[option];
357 if (will_wont_resp[option] && my_state_is_will(option))
358 --will_wont_resp[option];
361 if (will_wont_resp[option] == 0) {
362 if (my_want_state_is_wont(option)) {
368 * Special case for TM. We send a WILL, but pretend
371 send_will(option, 0);
372 set_my_want_state_wont(TELOPT_TM);
373 set_my_state_wont(TELOPT_TM);
376 case TELOPT_BINARY: /* binary mode */
377 case TELOPT_NAWS: /* window size */
378 case TELOPT_TSPEED: /* terminal speed */
379 case TELOPT_LFLOW: /* local flow control */
380 case TELOPT_TTYPE: /* terminal type option */
381 case TELOPT_SGA: /* no big deal */
382 #if defined(ENCRYPTION)
383 case TELOPT_ENCRYPT: /* encryption variable option */
388 case TELOPT_NEW_ENVIRON: /* New environment variable option */
390 if (my_state_is_will(TELOPT_OLD_ENVIRON))
391 send_wont(TELOPT_OLD_ENVIRON, 1); /* turn off the old */
393 case TELOPT_OLD_ENVIRON: /* Old environment variable option */
394 if (my_state_is_will(TELOPT_NEW_ENVIRON))
395 break; /* Don't enable if new one is in use! */
397 telopt_environ = option;
402 #if defined(AUTHENTICATION)
403 case TELOPT_AUTHENTICATION:
409 case TELOPT_XDISPLOC: /* X Display location */
410 if (env_getvalue((unsigned char *)"DISPLAY"))
414 case TELOPT_LINEMODE:
415 #ifdef KLUDGELINEMODE
417 send_do(TELOPT_SGA, 1);
419 set_my_want_state_will(TELOPT_LINEMODE);
420 send_will(option, 0);
421 set_my_state_will(TELOPT_LINEMODE);
425 case TELOPT_ECHO: /* We're never going to echo... */
431 set_my_want_state_will(option);
432 send_will(option, 0);
433 setconnmode(0); /* Set new tty mode */
435 will_wont_resp[option]++;
436 send_wont(option, 0);
440 * Handle options that need more things done after the
441 * other side has acknowledged the option.
444 case TELOPT_LINEMODE:
445 #ifdef KLUDGELINEMODE
447 send_do(TELOPT_SGA, 1);
449 set_my_state_will(option);
451 send_do(TELOPT_SGA, 0);
456 set_my_state_will(option);
460 dontoption(int option)
463 if (will_wont_resp[option]) {
464 --will_wont_resp[option];
465 if (will_wont_resp[option] && my_state_is_wont(option))
466 --will_wont_resp[option];
469 if ((will_wont_resp[option] == 0) && my_want_state_is_will(option)) {
471 case TELOPT_LINEMODE:
472 linemode = 0; /* put us back to the default state */
475 case TELOPT_NEW_ENVIRON:
477 * The new environ option wasn't recognized, try
480 send_will(TELOPT_OLD_ENVIRON, 1);
481 telopt_environ = TELOPT_OLD_ENVIRON;
492 /* we always accept a DONT */
493 set_my_want_state_wont(option);
494 if (my_state_is_will(option))
495 send_wont(option, 0);
496 setconnmode(0); /* Set new tty mode */
498 set_my_state_wont(option);
502 * Given a buffer returned by tgetent(), this routine will turn
503 * the pipe separated list of names in the buffer into an array
504 * of pointers to null terminated names. We toss out any bad,
505 * duplicate, or verbose names (names with spaces).
508 static char *name_unknown = "UNKNOWN";
509 static char *unknown[] = { 0, 0 };
512 mklist(char *buf, char *name)
515 char c, *cp, **argvp, *cp2, **argv, **avt;
518 if ((int)strlen(name) > 40) {
520 unknown[0] = name_unknown;
526 unknown[0] = name_unknown;
528 * Count up the number of names.
530 for (n = 1, cp = buf; *cp && *cp != ':'; cp++) {
535 * Allocate an array to put the name pointers into
537 argv = (char **)malloc((n+3)*sizeof(char *));
542 * Fill up the array of pointers to names.
547 for (cp = cp2 = buf; (c = *cp); cp++) {
548 if (c == '|' || c == ':') {
551 * Skip entries that have spaces or are over 40
552 * characters long. If this is our environment
553 * name, then put it up front. Otherwise, as
554 * long as this is not a duplicate name (case
555 * insensitive) add it to the list.
557 if (n || (cp - cp2 > 41))
559 else if (name && (strncasecmp(name, cp2, cp-cp2) == 0))
561 else if (is_unique(cp2, argv+1, argvp))
566 * Skip multiple delimiters. Reset cp2 to
567 * the beginning of the next name. Reset n,
568 * the flag for names with spaces.
570 while ((c = *cp) == '|')
576 * Skip entries with spaces or non-ascii values.
577 * Convert lower case letters to upper case.
580 #define ISASCII(c) (!((c)&0x80))
581 if ((c == ' ') || !ISASCII(c))
583 else if (islower((unsigned char)c))
584 *cp = toupper((unsigned char)c);
588 * Check for an old V6 2 character name. If the second
589 * name points to the beginning of the buffer, and is
590 * only 2 characters long, move it to the end of the array.
592 if ((argv[1] == buf) && (strlen(argv[1]) == 2)) {
594 for (avt = &argv[1]; avt < argvp; avt++)
600 * Duplicate last name, for TTYPE option, and null
601 * terminate the array. If we didn't find a match on
602 * our terminal name, put that name at the beginning.
613 for (avt = argv; avt < argvp; avt++)
624 is_unique(char *name, char **as, char **ae)
629 n = strlen(name) + 1;
630 for (ap = as; ap < ae; ap++)
631 if (strncasecmp(*ap, name, n) == 0)
636 static char termbuf[1024];
639 telnet_setupterm(const char *tname, int fd, int *errp)
642 if (tgetent(termbuf, tname) == 1) {
643 termbuf[1023] = '\0';
652 strlcpy(termbuf, tname, sizeof(termbuf));
658 int resettermname = 1;
664 static char **tnamep = 0;
670 if (tnamep && tnamep != unknown)
672 if ((tname = (char *)env_getvalue((unsigned char *)"TERM")) &&
673 telnet_setupterm(tname, 1, &err) == 0) {
674 tnamep = mklist(termbuf, tname);
676 if (tname && ((int)strlen(tname) <= 40)) {
680 unknown[0] = name_unknown;
692 * Look at the sub-option buffer, and try to be helpful to the other
695 * Currently we recognize:
697 * Terminal type, send request.
698 * Terminal speed (send request).
699 * Local flow control (is request).
706 unsigned char subchar;
708 printsub('<', subbuffer, SB_LEN()+2);
709 switch (subchar = SB_GET()) {
711 if (my_want_state_is_wont(TELOPT_TTYPE))
713 if (SB_EOF() || SB_GET() != TELQUAL_SEND) {
717 unsigned char temp[50];
720 name = gettermname();
721 len = strlen(name) + 4 + 2;
722 if (len < NETROOM()) {
723 snprintf((char *)temp, sizeof(temp),
724 "%c%c%c%c%s%c%c", IAC, SB, TELOPT_TTYPE,
725 TELQUAL_IS, name, IAC, SE);
726 ring_supply_data(&netoring, temp, len);
727 printsub('>', &temp[2], len-2);
729 ExitString("No room in buffer for terminal type.\n", 1);
735 if (my_want_state_is_wont(TELOPT_TSPEED))
739 if (SB_GET() == TELQUAL_SEND) {
740 long output_speed, input_speed;
741 unsigned char temp[50];
744 TerminalSpeeds(&input_speed, &output_speed);
746 snprintf((char *)temp, sizeof(temp),
747 "%c%c%c%c%u,%u%c%c", IAC, SB, TELOPT_TSPEED,
749 (unsigned)output_speed,
750 (unsigned)input_speed, IAC, SE);
751 len = strlen((char *)temp+4) + 4; /* temp[3] is 0 ... */
753 if (len < NETROOM()) {
754 ring_supply_data(&netoring, temp, len);
755 printsub('>', temp+2, len - 2);
757 /*@*/ else printf("lm_will: not enough room in buffer\n");
761 if (my_want_state_is_wont(TELOPT_LFLOW))
766 case LFLOW_RESTART_ANY:
769 case LFLOW_RESTART_XON:
785 case TELOPT_LINEMODE:
786 if (my_want_state_is_wont(TELOPT_LINEMODE))
792 lm_will(subpointer, SB_LEN());
795 lm_wont(subpointer, SB_LEN());
798 lm_do(subpointer, SB_LEN());
801 lm_dont(subpointer, SB_LEN());
804 slc(subpointer, SB_LEN());
807 lm_mode(subpointer, SB_LEN(), 0);
815 case TELOPT_OLD_ENVIRON:
817 case TELOPT_NEW_ENVIRON:
823 if (my_want_state_is_dont(subchar))
827 if (my_want_state_is_wont(subchar)) {
834 env_opt(subpointer, SB_LEN());
837 case TELOPT_XDISPLOC:
838 if (my_want_state_is_wont(TELOPT_XDISPLOC))
842 if (SB_GET() == TELQUAL_SEND) {
843 unsigned char temp[50], *dp;
846 if ((dp = env_getvalue((unsigned char *)"DISPLAY")) == NULL) {
848 * Something happened, we no longer have a DISPLAY
849 * variable. So, turn off the option.
851 send_wont(TELOPT_XDISPLOC, 1);
854 snprintf((char *)temp, sizeof(temp),
855 "%c%c%c%c%s%c%c", IAC, SB, TELOPT_XDISPLOC,
856 TELQUAL_IS, dp, IAC, SE);
857 len = strlen((char *)temp+4) + 4; /* temp[3] is 0 ... */
859 if (len < NETROOM()) {
860 ring_supply_data(&netoring, temp, len);
861 printsub('>', temp+2, len - 2);
863 /*@*/ else printf("lm_will: not enough room in buffer\n");
867 #if defined(AUTHENTICATION)
868 case TELOPT_AUTHENTICATION: {
875 if (my_want_state_is_dont(TELOPT_AUTHENTICATION))
877 auth_is(subpointer, SB_LEN());
880 if (my_want_state_is_wont(TELOPT_AUTHENTICATION))
882 auth_send(subpointer, SB_LEN());
885 if (my_want_state_is_wont(TELOPT_AUTHENTICATION))
887 auth_reply(subpointer, SB_LEN());
890 if (my_want_state_is_dont(TELOPT_AUTHENTICATION))
892 auth_name(subpointer, SB_LEN());
898 #if defined(ENCRYPTION)
904 if (my_want_state_is_dont(TELOPT_ENCRYPT))
906 encrypt_start(subpointer, SB_LEN());
909 if (my_want_state_is_dont(TELOPT_ENCRYPT))
913 case ENCRYPT_SUPPORT:
914 if (my_want_state_is_wont(TELOPT_ENCRYPT))
916 encrypt_support(subpointer, SB_LEN());
918 case ENCRYPT_REQSTART:
919 if (my_want_state_is_wont(TELOPT_ENCRYPT))
921 encrypt_request_start(subpointer, SB_LEN());
924 if (my_want_state_is_wont(TELOPT_ENCRYPT))
927 * We can always send an REQEND so that we cannot
928 * get stuck encrypting. We should only get this
929 * if we have been able to get in the correct mode
932 encrypt_request_end();
935 if (my_want_state_is_dont(TELOPT_ENCRYPT))
937 encrypt_is(subpointer, SB_LEN());
940 if (my_want_state_is_wont(TELOPT_ENCRYPT))
942 encrypt_reply(subpointer, SB_LEN());
944 case ENCRYPT_ENC_KEYID:
945 if (my_want_state_is_dont(TELOPT_ENCRYPT))
947 encrypt_enc_keyid(subpointer, SB_LEN());
949 case ENCRYPT_DEC_KEYID:
950 if (my_want_state_is_wont(TELOPT_ENCRYPT))
952 encrypt_dec_keyid(subpointer, SB_LEN());
964 static unsigned char str_lm[] = { IAC, SB, TELOPT_LINEMODE, 0, 0, IAC, SE };
967 lm_will(unsigned char *cmd, int len)
970 /*@*/ printf("lm_will: no command!!!\n"); /* Should not happen... */
974 case LM_FORWARDMASK: /* We shouldn't ever get this... */
978 if (NETROOM() > sizeof(str_lm)) {
979 ring_supply_data(&netoring, str_lm, sizeof(str_lm));
980 printsub('>', &str_lm[2], sizeof(str_lm)-2);
982 /*@*/ else printf("lm_will: not enough room in buffer\n");
988 lm_wont(unsigned char *cmd, int len)
991 /*@*/ printf("lm_wont: no command!!!\n"); /* Should not happen... */
995 case LM_FORWARDMASK: /* We shouldn't ever get this... */
997 /* We are always DONT, so don't respond */
1003 lm_do(unsigned char *cmd, int len)
1006 /*@*/ printf("lm_do: no command!!!\n"); /* Should not happen... */
1010 case LM_FORWARDMASK:
1014 if (NETROOM() > sizeof(str_lm)) {
1015 ring_supply_data(&netoring, str_lm, sizeof(str_lm));
1016 printsub('>', &str_lm[2], sizeof(str_lm)-2);
1018 /*@*/ else printf("lm_do: not enough room in buffer\n");
1024 lm_dont(unsigned char *cmd, int len)
1027 /*@*/ printf("lm_dont: no command!!!\n"); /* Should not happen... */
1031 case LM_FORWARDMASK:
1033 /* we are always WONT, so don't respond */
1038 static unsigned char str_lm_mode[] = {
1039 IAC, SB, TELOPT_LINEMODE, LM_MODE, 0, IAC, SE
1043 lm_mode(unsigned char *cmd, int len, int init)
1047 if ((linemode&MODE_MASK&~MODE_ACK) == *cmd)
1051 linemode = *cmd&(MODE_MASK&~MODE_ACK);
1052 str_lm_mode[4] = linemode;
1054 str_lm_mode[4] |= MODE_ACK;
1055 if (NETROOM() > sizeof(str_lm_mode)) {
1056 ring_supply_data(&netoring, str_lm_mode, sizeof(str_lm_mode));
1057 printsub('>', &str_lm_mode[2], sizeof(str_lm_mode)-2);
1059 /*@*/ else printf("lm_mode: not enough room in buffer\n");
1060 setconnmode(0); /* set changed mode */
1067 * Handle special character suboption of LINEMODE.
1073 char flags; /* Current flags & level */
1074 char mylevel; /* Maximum level & flags */
1077 #define SLC_IMPORT 0
1078 #define SLC_EXPORT 1
1079 #define SLC_RVALUE 2
1080 static int slc_mode = SLC_EXPORT;
1088 for (spcp = spc_data; spcp < &spc_data[NSLC+1]; spcp++) {
1091 spcp->flags = spcp->mylevel = SLC_NOSUPPORT;
1094 #define initfunc(func, flags) { \
1095 spcp = &spc_data[func]; \
1096 if ((spcp->valp = tcval(func))) { \
1097 spcp->val = *spcp->valp; \
1098 spcp->mylevel = SLC_VARIABLE|flags; \
1101 spcp->mylevel = SLC_DEFAULT; \
1105 initfunc(SLC_SYNCH, 0);
1107 initfunc(SLC_AO, 0);
1108 initfunc(SLC_AYT, 0);
1110 initfunc(SLC_ABORT, SLC_FLUSHIN|SLC_FLUSHOUT);
1111 initfunc(SLC_EOF, 0);
1112 initfunc(SLC_SUSP, SLC_FLUSHIN);
1113 initfunc(SLC_EC, 0);
1114 initfunc(SLC_EL, 0);
1115 initfunc(SLC_EW, 0);
1116 initfunc(SLC_RP, 0);
1117 initfunc(SLC_LNEXT, 0);
1118 initfunc(SLC_XON, 0);
1119 initfunc(SLC_XOFF, 0);
1120 initfunc(SLC_FORW1, 0);
1121 initfunc(SLC_FORW2, 0);
1124 initfunc(SLC_IP, SLC_FLUSHIN|SLC_FLUSHOUT);
1127 if (slc_mode == SLC_EXPORT)
1137 printf("Special characters are %s values\n",
1138 slc_mode == SLC_IMPORT ? "remote default" :
1139 slc_mode == SLC_EXPORT ? "local" :
1146 slc_mode = SLC_EXPORT;
1147 if (my_state_is_will(TELOPT_LINEMODE))
1152 slc_mode_import(int def)
1154 slc_mode = def ? SLC_IMPORT : SLC_RVALUE;
1155 if (my_state_is_will(TELOPT_LINEMODE))
1159 unsigned char slc_import_val[] = {
1160 IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_VARIABLE, 0, IAC, SE
1162 unsigned char slc_import_def[] = {
1163 IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_DEFAULT, 0, IAC, SE
1169 if (NETROOM() > sizeof(slc_import_val)) {
1171 ring_supply_data(&netoring, slc_import_def, sizeof(slc_import_def));
1172 printsub('>', &slc_import_def[2], sizeof(slc_import_def)-2);
1174 ring_supply_data(&netoring, slc_import_val, sizeof(slc_import_val));
1175 printsub('>', &slc_import_val[2], sizeof(slc_import_val)-2);
1178 /*@*/ else printf("slc_import: not enough room\n");
1186 TerminalDefaultChars();
1189 for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) {
1190 if (spcp->mylevel != SLC_NOSUPPORT) {
1191 if (spcp->val == (cc_t)(_POSIX_VDISABLE))
1192 spcp->flags = SLC_NOSUPPORT;
1194 spcp->flags = spcp->mylevel;
1196 spcp->val = *spcp->valp;
1197 slc_add_reply(spcp - spc_data, spcp->flags, spcp->val);
1202 setconnmode(1); /* Make sure the character values are set */
1206 slc(unsigned char *cp, int len)
1213 for (; len >= 3; len -=3, cp +=3) {
1215 func = cp[SLC_FUNC];
1219 * Client side: always ignore 0 function.
1224 if ((cp[SLC_FLAGS] & SLC_LEVELBITS) != SLC_NOSUPPORT)
1225 slc_add_reply(func, SLC_NOSUPPORT, 0);
1229 spcp = &spc_data[func];
1231 level = cp[SLC_FLAGS]&(SLC_LEVELBITS|SLC_ACK);
1233 if ((cp[SLC_VALUE] == (unsigned char)spcp->val) &&
1234 ((level&SLC_LEVELBITS) == (spcp->flags&SLC_LEVELBITS))) {
1238 if (level == (SLC_DEFAULT|SLC_ACK)) {
1240 * This is an error condition, the SLC_ACK
1241 * bit should never be set for the SLC_DEFAULT
1242 * level. Our best guess to recover is to
1243 * ignore the SLC_ACK bit.
1245 cp[SLC_FLAGS] &= ~SLC_ACK;
1248 if (level == ((spcp->flags&SLC_LEVELBITS)|SLC_ACK)) {
1249 spcp->val = (cc_t)cp[SLC_VALUE];
1250 spcp->flags = cp[SLC_FLAGS]; /* include SLC_ACK */
1256 if (level <= (spcp->mylevel&SLC_LEVELBITS)) {
1257 spcp->flags = cp[SLC_FLAGS]|SLC_ACK;
1258 spcp->val = (cc_t)cp[SLC_VALUE];
1260 if (level == SLC_DEFAULT) {
1261 if ((spcp->mylevel&SLC_LEVELBITS) != SLC_DEFAULT)
1262 spcp->flags = spcp->mylevel;
1264 spcp->flags = SLC_NOSUPPORT;
1266 slc_add_reply(func, spcp->flags, spcp->val);
1270 setconnmode(1); /* set the new character values */
1279 for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) {
1280 if (spcp->valp && spcp->val != *spcp->valp) {
1281 spcp->val = *spcp->valp;
1282 if (spcp->val == (cc_t)(_POSIX_VDISABLE))
1283 spcp->flags = SLC_NOSUPPORT;
1285 spcp->flags = spcp->mylevel;
1286 slc_add_reply(spcp - spc_data, spcp->flags, spcp->val);
1294 unsigned char slc_reply[128];
1295 unsigned char const * const slc_reply_eom = &slc_reply[sizeof(slc_reply)];
1296 unsigned char *slc_replyp;
1301 slc_replyp = slc_reply;
1302 *slc_replyp++ = IAC;
1304 *slc_replyp++ = TELOPT_LINEMODE;
1305 *slc_replyp++ = LM_SLC;
1309 slc_add_reply(unsigned char func, unsigned char flags, cc_t value)
1311 /* A sequence of up to 6 bytes my be written for this member of the SLC
1312 * suboption list by this function. The end of negotiation command,
1313 * which is written by slc_end_reply(), will require 2 additional
1314 * bytes. Do not proceed unless there is sufficient space for these
1317 if (&slc_replyp[6+2] > slc_reply_eom)
1319 if ((*slc_replyp++ = func) == IAC)
1320 *slc_replyp++ = IAC;
1321 if ((*slc_replyp++ = flags) == IAC)
1322 *slc_replyp++ = IAC;
1323 if ((*slc_replyp++ = (unsigned char)value) == IAC)
1324 *slc_replyp++ = IAC;
1332 /* The end of negotiation command requires 2 bytes. */
1333 if (&slc_replyp[2] > slc_reply_eom)
1335 *slc_replyp++ = IAC;
1337 len = slc_replyp - slc_reply;
1340 if (NETROOM() > len) {
1341 ring_supply_data(&netoring, slc_reply, slc_replyp - slc_reply);
1342 printsub('>', &slc_reply[2], slc_replyp - slc_reply - 2);
1344 /*@*/else printf("slc_end_reply: not enough room\n");
1351 int need_update = 0;
1353 for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) {
1354 if (!(spcp->flags&SLC_ACK))
1356 spcp->flags &= ~SLC_ACK;
1357 if (spcp->valp && (*spcp->valp != spcp->val)) {
1358 *spcp->valp = spcp->val;
1362 return(need_update);
1366 # define old_env_var OLD_ENV_VAR
1367 # define old_env_value OLD_ENV_VALUE
1371 env_opt(unsigned char *buf, int len)
1373 unsigned char *ep = 0, *epc = 0;
1376 switch(buf[0]&0xff) {
1381 } else for (i = 1; i < len; i++) {
1382 switch (buf[i]&0xff) {
1387 * Although OLD_ENV_VALUE is not legal, we will
1388 * still recognize it, just in case it is an
1389 * old server that has VAR & VALUE mixed up...
1400 ep = epc = &buf[i+1];
1420 /* Ignore for now. We shouldn't get it anyway. */
1428 #define OPT_REPLY_SIZE (2 * SUBBUFSIZE)
1429 unsigned char *opt_reply;
1430 unsigned char *opt_replyp;
1431 unsigned char *opt_replyend;
1437 void *tmp = realloc (opt_reply, OPT_REPLY_SIZE);
1445 opt_reply = (unsigned char *)malloc(OPT_REPLY_SIZE);
1446 if (opt_reply == NULL) {
1447 /*@*/ printf("env_opt_start: malloc()/realloc() failed!!!\n");
1448 opt_reply = opt_replyp = opt_replyend = NULL;
1451 opt_replyp = opt_reply;
1452 opt_replyend = opt_reply + OPT_REPLY_SIZE;
1453 *opt_replyp++ = IAC;
1455 *opt_replyp++ = telopt_environ;
1456 *opt_replyp++ = TELQUAL_IS;
1460 env_opt_start_info()
1464 opt_replyp[-1] = TELQUAL_INFO;
1468 env_opt_add(unsigned char *ep)
1470 unsigned char *vp, c;
1472 if (opt_reply == NULL) /*XXX*/
1475 if (ep == NULL || *ep == '\0') {
1476 /* Send user defined variables first. */
1478 while ((ep = env_default(0, 0)))
1481 /* Now add the list of well know variables. */
1483 while ((ep = env_default(0, 1)))
1487 vp = env_getvalue(ep);
1488 if (opt_replyp + (vp ? 2 * strlen((char *)vp) : 0) +
1489 2 * strlen((char *)ep) + 6 > opt_replyend)
1493 opt_replyend += OPT_REPLY_SIZE;
1494 len = opt_replyend - opt_reply;
1495 tmp = realloc(opt_reply, len);
1497 /*@*/ printf("env_opt_add: realloc() failed!!!\n");
1498 opt_reply = opt_replyp = opt_replyend = NULL;
1502 opt_replyp = opt_reply + len - (opt_replyend - opt_replyp);
1503 opt_replyend = opt_reply + len;
1505 if (opt_welldefined((char *)ep)) {
1507 if (telopt_environ == TELOPT_OLD_ENVIRON)
1508 *opt_replyp++ = old_env_var;
1511 *opt_replyp++ = NEW_ENV_VAR;
1513 *opt_replyp++ = ENV_USERVAR;
1515 while ((c = *ep++)) {
1516 if (opt_replyp + (2 + 2) > opt_replyend)
1520 *opt_replyp++ = IAC;
1526 *opt_replyp++ = ENV_ESC;
1532 if (opt_replyp + (1 + 2 + 2) > opt_replyend)
1535 if (telopt_environ == TELOPT_OLD_ENVIRON)
1536 *opt_replyp++ = old_env_value;
1539 *opt_replyp++ = NEW_ENV_VALUE;
1547 opt_welldefined(char *ep)
1549 if ((strcmp(ep, "USER") == 0) ||
1550 (strcmp(ep, "DISPLAY") == 0) ||
1551 (strcmp(ep, "PRINTER") == 0) ||
1552 (strcmp(ep, "SYSTEMTYPE") == 0) ||
1553 (strcmp(ep, "JOB") == 0) ||
1554 (strcmp(ep, "ACCT") == 0))
1560 env_opt_end(int emptyok)
1564 if (opt_replyp + 2 > opt_replyend)
1566 len = opt_replyp + 2 - opt_reply;
1567 if (emptyok || len > 6) {
1568 *opt_replyp++ = IAC;
1570 if (NETROOM() > len) {
1571 ring_supply_data(&netoring, opt_reply, len);
1572 printsub('>', &opt_reply[2], len - 2);
1574 /*@*/ else printf("slc_end_reply: not enough room\n");
1578 opt_reply = opt_replyp = opt_replyend = NULL;
1589 unsigned char *sbp = NULL;
1591 int returnValue = 0;
1595 while (TTYROOM() > 2) {
1598 ring_consumed(&netiring, count);
1602 sbp = netiring.consume;
1603 scc = ring_full_consecutive(&netiring);
1605 /* No more data coming in */
1610 c = *sbp++ & 0xff, scc--; count++;
1611 #if defined(ENCRYPTION)
1613 c = (*decrypt_input)(c);
1616 switch (telrcv_state) {
1619 telrcv_state = TS_DATA;
1621 break; /* Ignore \0 after CR */
1623 else if ((c == '\n') && my_want_state_is_dont(TELOPT_ECHO) && !crmod) {
1627 /* Else, fall through */
1631 telrcv_state = TS_IAC;
1635 * The 'crmod' hack (see following) is needed
1636 * since we can't set CRMOD on output only.
1637 * Machines like MULTICS like to send \r without
1638 * \n; since we must turn off CRMOD to get proper
1639 * input, the mapping is done here (sigh).
1641 if ((c == '\r') && my_want_state_is_dont(TELOPT_BINARY)) {
1644 #if defined(ENCRYPTION)
1646 c = (*decrypt_input)(c);
1649 sbp++, scc--; count++;
1652 } else if (my_want_state_is_dont(TELOPT_ECHO) &&
1654 sbp++, scc--; count++;
1657 #if defined(ENCRYPTION)
1659 (*decrypt_input)(-1);
1668 telrcv_state = TS_CR;
1684 telrcv_state = TS_WILL;
1688 telrcv_state = TS_WONT;
1692 telrcv_state = TS_DO;
1696 telrcv_state = TS_DONT;
1701 * We may have missed an urgent notification,
1702 * so make sure we flush whatever is in the
1705 printoption("RCVD", IAC, DM);
1708 SYNCHing = stilloob();
1714 telrcv_state = TS_SB;
1725 printoption("RCVD", IAC, c);
1728 telrcv_state = TS_DATA;
1732 printoption("RCVD", WILL, c);
1734 telrcv_state = TS_DATA;
1738 printoption("RCVD", WONT, c);
1740 telrcv_state = TS_DATA;
1744 printoption("RCVD", DO, c);
1746 if (c == TELOPT_NAWS) {
1748 } else if (c == TELOPT_LFLOW) {
1753 telrcv_state = TS_DATA;
1757 printoption("RCVD", DONT, c);
1760 setconnmode(0); /* set new tty mode (maybe) */
1761 telrcv_state = TS_DATA;
1766 telrcv_state = TS_SE;
1776 * This is an error. We only expect to get
1777 * "IAC IAC" or "IAC SE". Several things may
1778 * have happened. An IAC was not doubled, the
1779 * IAC SE was left off, or another option got
1780 * inserted into the suboption are all possibilities.
1781 * If we assume that the IAC was not doubled,
1782 * and really the IAC SE was left off, we could
1783 * get into an infinite loop here. So, instead,
1784 * we terminate the suboption, and process the
1785 * partial suboption if we can.
1792 printoption("In SUBOPTION processing, RCVD", IAC, c);
1793 suboption(); /* handle sub-option */
1794 telrcv_state = TS_IAC;
1798 telrcv_state = TS_SB;
1804 suboption(); /* handle sub-option */
1805 telrcv_state = TS_DATA;
1810 ring_consumed(&netiring, count);
1811 return returnValue||count;
1814 static int bol = 1, local = 0;
1822 command(0, "z\n", 2);
1833 int returnValue = 0;
1834 unsigned char *tbp = NULL;
1838 while (NETROOM() > 2) {
1844 ring_consumed(&ttyiring, count);
1848 tbp = ttyiring.consume;
1849 tcc = ring_full_consecutive(&ttyiring);
1854 c = *tbp++ & 0xff, sc = strip(c), tcc--; count++;
1855 if (rlogin != _POSIX_VDISABLE) {
1864 if (sc == '.' || c == termEofChar) {
1866 command(0, "close\n", 6);
1869 if (sc == termSuspChar) {
1871 command(0, "z\n", 2);
1875 command(0, (char *)tbp, tcc);
1889 if ((sc == '\n') || (sc == '\r'))
1891 } else if (sc == escape) {
1893 * Double escape is a pass through of a single escape character.
1895 if (tcc && strip(*tbp) == escape) {
1901 command(0, (char *)tbp, tcc);
1910 #ifdef KLUDGELINEMODE
1911 if (kludgelinemode && (globalmode&MODE_EDIT) && (sc == echoc)) {
1912 if (tcc > 0 && strip(*tbp) == echoc) {
1913 tcc--; tbp++; count++;
1915 dontlecho = !dontlecho;
1916 settimer(echotoggle);
1923 if (MODE_LOCAL_CHARS(globalmode)) {
1924 if (TerminalSpecialChars(sc) == 0) {
1929 if (my_want_state_is_wont(TELOPT_BINARY)) {
1933 * If we are in CRMOD mode (\r ==> \n)
1934 * on our local machine, then probably
1935 * a newline (unix) is CRLF (TELNET).
1937 if (MODE_LOCAL_CHARS(globalmode)) {
1941 bol = flushline = 1;
1945 NET2ADD('\r', '\0');
1947 NET2ADD('\r', '\n');
1949 bol = flushline = 1;
1958 } else if (c == IAC) {
1965 ring_consumed(&ttyiring, count);
1966 return returnValue||count; /* Non-zero if we did anything */
1972 * Try to do something.
1974 * If we do something useful, return 1; else return 0.
1980 Scheduler(int block) /* should we block in the select ? */
1982 /* One wants to be a bit careful about setting returnValue
1983 * to one, since a one implies we did some useful work,
1984 * and therefore probably won't be called to block next
1985 * time (TN3270 mode only).
1988 int netin, netout, netex, ttyin, ttyout;
1990 /* Decide which rings should be processed */
1992 netout = ring_full_count(&netoring) &&
1994 (my_want_state_is_wont(TELOPT_LINEMODE)
1995 #ifdef KLUDGELINEMODE
1996 && (!kludgelinemode || my_want_state_is_do(TELOPT_SGA))
1999 my_want_state_is_will(TELOPT_BINARY));
2000 ttyout = ring_full_count(&ttyoring);
2002 ttyin = ring_empty_count(&ttyiring);
2004 netin = !ISend && ring_empty_count(&netiring);
2008 /* If we have seen a signal recently, reset things */
2010 if (scheduler_lockout_tty) {
2014 /* Call to system code to process rings */
2016 returnValue = process_rings(netin, netout, netex, ttyin, ttyout, !block);
2018 /* Now, look at the input rings, looking for work to do. */
2020 if (ring_full_count(&ttyiring)) {
2021 returnValue |= telsnd();
2024 if (ring_full_count(&netiring)) {
2025 returnValue |= telrcv();
2030 extern int auth_has_failed; /* XXX should be somewhere else */
2033 * Select from tty and network...
2036 my_telnet(char *user)
2038 int printed_encrypt = 0;
2042 #if defined(AUTHENTICATION) || defined(ENCRYPTION)
2044 static char local_host[256] = { 0 };
2046 if (!local_host[0]) {
2047 /* XXX - should be k_gethostname? */
2048 gethostname(local_host, sizeof(local_host));
2049 local_host[sizeof(local_host)-1] = 0;
2051 auth_encrypt_init(local_host, hostname, "TELNET", 0);
2052 auth_encrypt_user(user);
2056 #if defined(AUTHENTICATION)
2058 send_will(TELOPT_AUTHENTICATION, 1);
2060 #if defined(ENCRYPTION)
2061 send_do(TELOPT_ENCRYPT, 1);
2062 send_will(TELOPT_ENCRYPT, 1);
2064 send_do(TELOPT_SGA, 1);
2065 send_will(TELOPT_TTYPE, 1);
2066 send_will(TELOPT_NAWS, 1);
2067 send_will(TELOPT_TSPEED, 1);
2068 send_will(TELOPT_LFLOW, 1);
2069 send_will(TELOPT_LINEMODE, 1);
2070 send_will(TELOPT_NEW_ENVIRON, 1);
2071 send_do(TELOPT_STATUS, 1);
2072 if (env_getvalue((unsigned char *)"DISPLAY"))
2073 send_will(TELOPT_XDISPLOC, 1);
2075 tel_enter_binary(binary);
2080 * Note: we assume a tie to the authentication option here. This
2081 * is necessary so that authentication fails, we don't spin
2084 if (telnetport && wantencryption) {
2085 time_t timeout = time(0) + 60;
2087 send_do(TELOPT_ENCRYPT, 1);
2088 send_will(TELOPT_ENCRYPT, 1);
2090 if (my_want_state_is_wont(TELOPT_AUTHENTICATION)) {
2091 if (wantencryption == -1) {
2094 printf("\nServer refused to negotiate authentication,\n");
2095 printf("which is required for encryption.\n");
2099 if (auth_has_failed) {
2100 printf("\nAuthentication negotiation has failed,\n");
2101 printf("which is required for encryption.\n");
2104 if (my_want_state_is_dont(TELOPT_ENCRYPT) ||
2105 my_want_state_is_wont(TELOPT_ENCRYPT)) {
2106 printf("\nServer refused to negotiate encryption.\n");
2109 if (encrypt_is_encrypting())
2111 if (time(0) > timeout) {
2112 printf("\nEncryption could not be enabled.\n");
2115 if (printed_encrypt == 0) {
2116 printed_encrypt = 1;
2117 printf("Waiting for encryption to be negotiated...\n");
2119 * Turn on MODE_TRAPSIG and then turn off localchars
2120 * so that ^C will cause telnet to exit.
2122 TerminalNewMode(getconnmode()|MODE_TRAPSIG);
2125 if (intr_happened) {
2126 printf("\nUser interrupt.\n");
2129 if (telnet_spin()) {
2130 printf("\nServer disconnected.\n");
2135 if (printed_encrypt) {
2136 printf("Encryption negotiated.\n");
2146 while ((schedValue = Scheduler(0)) != 0) {
2147 if (schedValue == -1) {
2153 if (Scheduler(1) == -1) {
2163 * We are about to do a TELNET SYNCH operation. Clear
2164 * the path to the network.
2166 * Things are a bit tricky since we may have sent the first
2167 * byte or so of a previous TELNET command into the network.
2168 * So, we have to scan the network buffer from the beginning
2169 * until we are up to where we want to be.
2171 * A side effect of what we do, just to keep things
2172 * simple, is to clear the urgent data pointer. The principal
2173 * caller should be setting the urgent data pointer AFTER calling
2181 char *thisitem, *next;
2183 #define wewant(p) ((nfrontp > p) && ((*p&0xff) == IAC) && \
2184 ((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL))
2188 while ((next = nextitem(thisitem)) <= netobuf.send) {
2192 /* Now, thisitem is first before/at boundary. */
2194 good = netobuf; /* where the good bytes go */
2196 while (netoring.add > thisitem) {
2197 if (wewant(thisitem)) {
2202 next = nextitem(next);
2203 } while (wewant(next) && (nfrontp > next));
2204 length = next-thisitem;
2205 memmove(good, thisitem, length);
2209 thisitem = nextitem(thisitem);
2217 * These routines add various telnet commands to the data stream.
2227 ttyflush(1); /* Flush/drop output */
2228 /* do printoption AFTER flush, otherwise the output gets tossed... */
2229 printoption("SENT", DO, TELOPT_TM);
2236 printoption("SENT", IAC, AO);
2247 printoption("SENT", IAC, EL);
2254 printoption("SENT", IAC, EC);
2261 netclear(); /* clear the path to the network */
2265 printoption("SENT", IAC, DM);
2269 int want_status_response = 0;
2274 unsigned char tmp[16];
2277 if (my_want_state_is_dont(TELOPT_STATUS)) {
2278 printf("Remote side does not support STATUS option\n");
2285 *cp++ = TELOPT_STATUS;
2286 *cp++ = TELQUAL_SEND;
2289 if (NETROOM() >= cp - tmp) {
2290 ring_supply_data(&netoring, tmp, cp-tmp);
2291 printsub('>', tmp+2, cp - tmp - 2);
2293 ++want_status_response;
2301 printoption("SENT", IAC, IP);
2314 NET2ADD(IAC, BREAK);
2315 printoption("SENT", IAC, BREAK);
2328 NET2ADD(IAC, ABORT);
2329 printoption("SENT", IAC, ABORT);
2343 printoption("SENT", IAC, SUSP);
2357 printoption("SENT", IAC, xEOF);
2364 printoption("SENT", IAC, AYT);
2368 * Send a window size update to the remote system.
2375 unsigned char tmp[16];
2378 if (my_state_is_wont(TELOPT_NAWS))
2382 #define PUTSHORT(cp, x) { if ((*cp++ = ((x)>>8)&0xff) == IAC) *cp++ = IAC; \
2383 if ((*cp++ = ((x))&0xff) == IAC) *cp++ = IAC; }
2385 if (TerminalWindowSize(&rows, &cols) == 0) { /* Failed */
2393 *cp++ = TELOPT_NAWS;
2398 if (NETROOM() >= cp - tmp) {
2399 ring_supply_data(&netoring, tmp, cp-tmp);
2400 printsub('>', tmp+2, cp - tmp - 2);
2405 tel_enter_binary(int rw)
2408 send_do(TELOPT_BINARY, 1);
2410 send_will(TELOPT_BINARY, 1);
2414 tel_leave_binary(int rw)
2417 send_dont(TELOPT_BINARY, 1);
2419 send_wont(TELOPT_BINARY, 1);