]>
git.saurik.com Git - apple/network_cmds.git/blob - telnet.tproj/telnet.c
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.0 (the 'License'). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
22 * @APPLE_LICENSE_HEADER_END@
25 * Copyright (c) 1988, 1990, 1993
26 * The Regents of the University of California. All rights reserved.
28 * Redistribution and use in source and binary forms, with or without
29 * modification, are permitted provided that the following conditions
31 * 1. Redistributions of source code must retain the above copyright
32 * notice, this list of conditions and the following disclaimer.
33 * 2. Redistributions in binary form must reproduce the above copyright
34 * notice, this list of conditions and the following disclaimer in the
35 * documentation and/or other materials provided with the distribution.
36 * 3. All advertising materials mentioning features or use of this software
37 * must display the following acknowledgement:
38 * This product includes software developed by the University of
39 * California, Berkeley and its contributors.
40 * 4. Neither the name of the University nor the names of its contributors
41 * may be used to endorse or promote products derived from this software
42 * without specific prior written permission.
44 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
45 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
47 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
48 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
49 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
50 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
51 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
52 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
53 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 static char sccsid
[] = "@(#)telnet.c 8.4 (Berkeley) 5/30/95";
61 #include <sys/types.h>
63 #if defined(unix) || defined(__APPLE__)
65 /* By the way, we need to include curses.h before telnet.h since,
66 * among other things, telnet.h #defines 'DO', which is a variable
67 * declared in curses.h.
69 #endif /* defined(unix) || defined(__APPLE__) */
71 #include <arpa/telnet.h>
83 #define strip(x) ((my_want_state_is_wont(TELOPT_BINARY)) ? ((x)&0x7f) : (x))
85 static unsigned char subbuffer
[SUBBUFSIZE
],
86 *subpointer
, *subend
; /* buffer for sub-options */
87 #define SB_CLEAR() subpointer = subbuffer;
88 #define SB_TERM() { subend = subpointer; SB_CLEAR(); }
89 #define SB_ACCUM(c) if (subpointer < (subbuffer+sizeof subbuffer)) { \
90 *subpointer++ = (c); \
93 #define SB_GET() ((*subpointer++)&0xff)
94 #define SB_PEEK() ((*subpointer)&0xff)
95 #define SB_EOF() (subpointer >= subend)
96 #define SB_LEN() (subend - subpointer)
98 char options
[256]; /* The combined options */
99 char do_dont_resp
[256];
100 char will_wont_resp
[256];
104 autologin
= 0, /* Autologin anyone? */
108 In3270
, /* Are we in 3270 mode? */
109 ISend
, /* trying to send network data in */
112 netdata
, /* Print out network data flow */
113 crlf
, /* Should '\r' be mapped to <CR><LF> (or <CR><NUL>)? */
115 noasynchtty
= 0,/* User specified "-noasynch" on command line */
116 noasynchnet
= 0,/* User specified "-noasynch" on command line */
117 askedSGA
= 0, /* We have talked about suppress go ahead */
118 #endif /* defined(TN3270) */
120 SYNCHing
, /* we are in TELNET SYNCH mode */
121 flushout
, /* flush output */
122 autoflush
= 0, /* flush output when interrupting? */
123 autosynch
, /* send interrupt characters with SYNCH? */
124 localflow
, /* we handle flow control locally */
125 restartany
, /* if flow control enabled, restart on any character */
126 localchars
, /* we recognize interrupt/quit */
127 donelclchars
, /* the user has set "localchars" */
128 donebinarytoggle
, /* the user has put us in binary */
129 dontlecho
, /* do we suppress local echoing right now? */
136 #ifdef KLUDGELINEMODE
141 * Telnet receiver states for fsm
150 #define TS_SB 7 /* sub-option collection */
151 #define TS_SE 8 /* looking for sub-option end */
153 static int telrcv_state
;
155 unsigned char telopt_environ
= TELOPT_NEW_ENVIRON
;
157 # define telopt_environ TELOPT_NEW_ENVIRON
160 jmp_buf toplevel
= { 0 };
166 #ifdef KLUDGELINEMODE
167 int kludgelinemode
= 1;
171 * The following are some clocks used to decide how to interpret
172 * the relationship between various variables.
178 Modelist modelist
[] = {
179 { "telnet command mode", COMMAND_LINE
},
180 { "character-at-a-time mode", 0 },
181 { "character-at-a-time mode (local echo)", LOCAL_ECHO
|LOCAL_CHARS
},
182 { "line-by-line mode (remote echo)", LINE
| LOCAL_CHARS
},
183 { "line-by-line mode", LINE
| LOCAL_ECHO
| LOCAL_CHARS
},
184 { "line-by-line mode (local echoing suppressed)", LINE
| LOCAL_CHARS
},
191 * Initialize telnet environment.
202 connected
= In3270
= ISend
= localflow
= donebinarytoggle
= 0;
203 #if defined(AUTHENTICATION) || defined(ENCRYPTION)
204 auth_encrypt_connect(connected
);
205 #endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */
210 /* Don't change NetTrace */
212 escape
= CONTROL(']');
213 rlogin
= _POSIX_VDISABLE
;
214 #ifdef KLUDGELINEMODE
215 echoc
= CONTROL('E');
219 telrcv_state
= TS_DATA
;
232 char buffer
[100]; /* where things go */
241 ring
= va_arg(ap
, Ring
*);
242 format
= va_arg(ap
, char *);
245 while ((i
= *format
++) != 0) {
250 *ptr
++ = va_arg(ap
, int);
253 string
= va_arg(ap
, char *);
254 ring_supply_data(ring
, buffer
, ptr
-buffer
);
255 ring_supply_data(ring
, string
, strlen(string
));
259 ExitString("printring: trailing %%.\n", 1);
262 ExitString("printring: unknown format character.\n", 1);
269 ring_supply_data(ring
, buffer
, ptr
-buffer
);
274 * These routines are in charge of sending option negotiations
277 * The basic idea is that we send the negotiation if either side
278 * is in disagreement as to what the current state should be.
283 register int c
, init
;
286 if (((do_dont_resp
[c
] == 0) && my_state_is_do(c
)) ||
287 my_want_state_is_do(c
))
289 set_my_want_state_do(c
);
294 printoption("SENT", DO
, c
);
299 register int c
, init
;
302 if (((do_dont_resp
[c
] == 0) && my_state_is_dont(c
)) ||
303 my_want_state_is_dont(c
))
305 set_my_want_state_dont(c
);
310 printoption("SENT", DONT
, c
);
315 register int c
, init
;
318 if (((will_wont_resp
[c
] == 0) && my_state_is_will(c
)) ||
319 my_want_state_is_will(c
))
321 set_my_want_state_will(c
);
326 printoption("SENT", WILL
, c
);
331 register int c
, init
;
334 if (((will_wont_resp
[c
] == 0) && my_state_is_wont(c
)) ||
335 my_want_state_is_wont(c
))
337 set_my_want_state_wont(c
);
342 printoption("SENT", WONT
, c
);
350 int new_state_ok
= 0;
352 if (do_dont_resp
[option
]) {
353 --do_dont_resp
[option
];
354 if (do_dont_resp
[option
] && my_state_is_do(option
))
355 --do_dont_resp
[option
];
358 if ((do_dont_resp
[option
] == 0) && my_want_state_is_dont(option
)) {
365 * The following is a pain in the rear-end.
366 * Various IBM servers (some versions of Wiscnet,
367 * possibly Fibronics/Spartacus, and who knows who
368 * else) will NOT allow us to send "DO SGA" too early
369 * in the setup proceedings. On the other hand,
370 * 4.2 servers (telnetd) won't set SGA correctly.
371 * So, we are stuck. Empirically (but, based on
372 * a VERY small sample), the IBM servers don't send
373 * out anything about ECHO, so we postpone our sending
374 * "DO SGA" until we see "WILL ECHO" (which 4.2 servers
380 if (my_want_state_is_dont(TELOPT_SGA
))
381 send_do(TELOPT_SGA
, 1);
386 #endif /* defined(TN3270) */
389 settimer(modenegotiated
);
392 #if defined(AUTHENTICATION)
393 case TELOPT_AUTHENTICATION
:
397 #endif /* ENCRYPTION */
405 * Special case for TM. If we get back a WILL,
406 * pretend we got back a WONT.
408 set_my_want_state_dont(option
);
409 set_my_state_dont(option
);
410 return; /* Never reply to TM will's/wont's */
412 case TELOPT_LINEMODE
:
418 set_my_want_state_do(option
);
420 setconnmode(0); /* possibly set new tty mode */
422 do_dont_resp
[option
]++;
423 send_dont(option
, 0);
426 set_my_state_do(option
);
428 if (option
== TELOPT_ENCRYPT
)
429 encrypt_send_support();
430 #endif /* ENCRYPTION */
437 if (do_dont_resp
[option
]) {
438 --do_dont_resp
[option
];
439 if (do_dont_resp
[option
] && my_state_is_dont(option
))
440 --do_dont_resp
[option
];
443 if ((do_dont_resp
[option
] == 0) && my_want_state_is_do(option
)) {
447 #ifdef KLUDGELINEMODE
454 settimer(modenegotiated
);
460 set_my_want_state_dont(option
);
461 set_my_state_dont(option
);
462 return; /* Never reply to TM will's/wont's */
467 set_my_want_state_dont(option
);
468 if (my_state_is_do(option
))
469 send_dont(option
, 0);
470 setconnmode(0); /* Set new tty mode */
471 } else if (option
== TELOPT_TM
) {
473 * Special case for TM.
477 set_my_want_state_dont(option
);
479 set_my_state_dont(option
);
486 int new_state_ok
= 0;
488 if (will_wont_resp
[option
]) {
489 --will_wont_resp
[option
];
490 if (will_wont_resp
[option
] && my_state_is_will(option
))
491 --will_wont_resp
[option
];
494 if (will_wont_resp
[option
] == 0) {
495 if (my_want_state_is_wont(option
)) {
501 * Special case for TM. We send a WILL, but pretend
504 send_will(option
, 0);
505 set_my_want_state_wont(TELOPT_TM
);
506 set_my_state_wont(TELOPT_TM
);
510 case TELOPT_EOR
: /* end of record */
511 # endif /* defined(TN3270) */
512 case TELOPT_BINARY
: /* binary mode */
513 case TELOPT_NAWS
: /* window size */
514 case TELOPT_TSPEED
: /* terminal speed */
515 case TELOPT_LFLOW
: /* local flow control */
516 case TELOPT_TTYPE
: /* terminal type option */
517 case TELOPT_SGA
: /* no big deal */
519 case TELOPT_ENCRYPT
: /* encryption variable option */
520 #endif /* ENCRYPTION */
524 case TELOPT_NEW_ENVIRON
: /* New environment variable option */
526 if (my_state_is_will(TELOPT_OLD_ENVIRON
))
527 send_wont(TELOPT_OLD_ENVIRON
, 1); /* turn off the old */
529 case TELOPT_OLD_ENVIRON
: /* Old environment variable option */
530 if (my_state_is_will(TELOPT_NEW_ENVIRON
))
531 break; /* Don't enable if new one is in use! */
533 telopt_environ
= option
;
538 #if defined(AUTHENTICATION)
539 case TELOPT_AUTHENTICATION
:
545 case TELOPT_XDISPLOC
: /* X Display location */
546 if (env_getvalue((unsigned char *)"DISPLAY"))
550 case TELOPT_LINEMODE
:
551 #ifdef KLUDGELINEMODE
553 send_do(TELOPT_SGA
, 1);
555 set_my_want_state_will(TELOPT_LINEMODE
);
556 send_will(option
, 0);
557 set_my_state_will(TELOPT_LINEMODE
);
561 case TELOPT_ECHO
: /* We're never going to echo... */
567 set_my_want_state_will(option
);
568 send_will(option
, 0);
569 setconnmode(0); /* Set new tty mode */
571 will_wont_resp
[option
]++;
572 send_wont(option
, 0);
576 * Handle options that need more things done after the
577 * other side has acknowledged the option.
580 case TELOPT_LINEMODE
:
581 #ifdef KLUDGELINEMODE
583 send_do(TELOPT_SGA
, 1);
585 set_my_state_will(option
);
587 send_do(TELOPT_SGA
, 0);
592 set_my_state_will(option
);
600 if (will_wont_resp
[option
]) {
601 --will_wont_resp
[option
];
602 if (will_wont_resp
[option
] && my_state_is_wont(option
))
603 --will_wont_resp
[option
];
606 if ((will_wont_resp
[option
] == 0) && my_want_state_is_will(option
)) {
608 case TELOPT_LINEMODE
:
609 linemode
= 0; /* put us back to the default state */
612 case TELOPT_NEW_ENVIRON
:
614 * The new environ option wasn't recognized, try
617 send_will(TELOPT_OLD_ENVIRON
, 1);
618 telopt_environ
= TELOPT_OLD_ENVIRON
;
622 /* we always accept a DONT */
623 set_my_want_state_wont(option
);
624 if (my_state_is_will(option
))
625 send_wont(option
, 0);
626 setconnmode(0); /* Set new tty mode */
628 set_my_state_wont(option
);
632 * Given a buffer returned by tgetent(), this routine will turn
633 * the pipe seperated list of names in the buffer into an array
634 * of pointers to null terminated names. We toss out any bad,
635 * duplicate, or verbose names (names with spaces).
638 static char *name_unknown
= "UNKNOWN";
639 static char *unknown
[] = { 0, 0 };
646 register char c
, *cp
, **argvp
, *cp2
, **argv
, **avt
;
649 if ((int)strlen(name
) > 40) {
651 unknown
[0] = name_unknown
;
657 unknown
[0] = name_unknown
;
659 * Count up the number of names.
661 for (n
= 1, cp
= buf
; *cp
&& *cp
!= ':'; cp
++) {
666 * Allocate an array to put the name pointers into
668 argv
= (char **)malloc((n
+3)*sizeof(char *));
673 * Fill up the array of pointers to names.
678 for (cp
= cp2
= buf
; (c
= *cp
); cp
++) {
679 if (c
== '|' || c
== ':') {
682 * Skip entries that have spaces or are over 40
683 * characters long. If this is our environment
684 * name, then put it up front. Otherwise, as
685 * long as this is not a duplicate name (case
686 * insensitive) add it to the list.
688 if (n
|| (cp
- cp2
> 41))
690 else if (name
&& (strncasecmp(name
, cp2
, cp
-cp2
) == 0))
692 else if (is_unique(cp2
, argv
+1, argvp
))
697 * Skip multiple delimiters. Reset cp2 to
698 * the beginning of the next name. Reset n,
699 * the flag for names with spaces.
701 while ((c
= *cp
) == '|')
707 * Skip entries with spaces or non-ascii values.
708 * Convert lower case letters to upper case.
710 if ((c
== ' ') || !isascii(c
))
717 * Check for an old V6 2 character name. If the second
718 * name points to the beginning of the buffer, and is
719 * only 2 characters long, move it to the end of the array.
721 if ((argv
[1] == buf
) && (strlen(argv
[1]) == 2)) {
723 for (avt
= &argv
[1]; avt
< argvp
; avt
++)
729 * Duplicate last name, for TTYPE option, and null
730 * terminate the array. If we didn't find a match on
731 * our terminal name, put that name at the beginning.
742 for (avt
= argv
; avt
< argvp
; avt
++)
753 is_unique(name
, as
, ae
)
754 register char *name
, **as
, **ae
;
759 n
= strlen(name
) + 1;
760 for (ap
= as
; ap
< ae
; ap
++)
761 if (strncasecmp(*ap
, name
, n
) == 0)
771 setupterm(tname
, fd
, errp
)
775 if (tgetent(termbuf
, tname
) == 1) {
776 termbuf
[1023] = '\0';
786 #define termbuf ttytype
787 extern char ttytype
[];
790 int resettermname
= 1;
796 static char **tnamep
= 0;
802 if (tnamep
&& tnamep
!= unknown
)
804 if ((tname
= (char *)env_getvalue((unsigned char *)"TERM")) &&
805 (setupterm(tname
, 1, &err
) == 0)) {
806 tnamep
= mklist(termbuf
, tname
);
808 if (tname
&& ((int)strlen(tname
) <= 40)) {
812 unknown
[0] = name_unknown
;
824 * Look at the sub-option buffer, and try to be helpful to the other
827 * Currently we recognize:
829 * Terminal type, send request.
830 * Terminal speed (send request).
831 * Local flow control (is request).
838 unsigned char subchar
;
840 printsub('<', subbuffer
, SB_LEN()+2);
841 switch (subchar
= SB_GET()) {
843 if (my_want_state_is_wont(TELOPT_TTYPE
))
845 if (SB_EOF() || SB_GET() != TELQUAL_SEND
) {
849 unsigned char temp
[50];
853 if (tn3270_ttype()) {
856 #endif /* defined(TN3270) */
857 name
= gettermname();
858 len
= strlen(name
) + 4 + 2;
859 if (len
< NETROOM()) {
860 sprintf((char *)temp
, "%c%c%c%c%s%c%c", IAC
, SB
, TELOPT_TTYPE
,
861 TELQUAL_IS
, name
, IAC
, SE
);
862 ring_supply_data(&netoring
, temp
, len
);
863 printsub('>', &temp
[2], len
-2);
865 ExitString("No room in buffer for terminal type.\n", 1);
871 if (my_want_state_is_wont(TELOPT_TSPEED
))
875 if (SB_GET() == TELQUAL_SEND
) {
877 unsigned char temp
[50];
880 TerminalSpeeds(&ispeed
, &ospeed
);
882 sprintf((char *)temp
, "%c%c%c%c%d,%d%c%c", IAC
, SB
, TELOPT_TSPEED
,
883 TELQUAL_IS
, ospeed
, ispeed
, IAC
, SE
);
884 len
= strlen((char *)temp
+4) + 4; /* temp[3] is 0 ... */
886 if (len
< NETROOM()) {
887 ring_supply_data(&netoring
, temp
, len
);
888 printsub('>', temp
+2, len
- 2);
890 /*@*/ else printf("lm_will: not enough room in buffer\n");
894 if (my_want_state_is_wont(TELOPT_LFLOW
))
899 case LFLOW_RESTART_ANY
:
902 case LFLOW_RESTART_XON
:
918 case TELOPT_LINEMODE
:
919 if (my_want_state_is_wont(TELOPT_LINEMODE
))
925 lm_will(subpointer
, SB_LEN());
928 lm_wont(subpointer
, SB_LEN());
931 lm_do(subpointer
, SB_LEN());
934 lm_dont(subpointer
, SB_LEN());
937 slc(subpointer
, SB_LEN());
940 lm_mode(subpointer
, SB_LEN(), 0);
948 case TELOPT_OLD_ENVIRON
:
950 case TELOPT_NEW_ENVIRON
:
956 if (my_want_state_is_dont(subchar
))
960 if (my_want_state_is_wont(subchar
)) {
967 env_opt(subpointer
, SB_LEN());
970 case TELOPT_XDISPLOC
:
971 if (my_want_state_is_wont(TELOPT_XDISPLOC
))
975 if (SB_GET() == TELQUAL_SEND
) {
976 unsigned char temp
[50], *dp
;
979 if ((dp
= env_getvalue((unsigned char *)"DISPLAY")) == NULL
) {
981 * Something happened, we no longer have a DISPLAY
982 * variable. So, turn off the option.
984 send_wont(TELOPT_XDISPLOC
, 1);
987 sprintf((char *)temp
, "%c%c%c%c%s%c%c", IAC
, SB
, TELOPT_XDISPLOC
,
988 TELQUAL_IS
, dp
, IAC
, SE
);
989 len
= strlen((char *)temp
+4) + 4; /* temp[3] is 0 ... */
991 if (len
< NETROOM()) {
992 ring_supply_data(&netoring
, temp
, len
);
993 printsub('>', temp
+2, len
- 2);
995 /*@*/ else printf("lm_will: not enough room in buffer\n");
999 #if defined(AUTHENTICATION)
1000 case TELOPT_AUTHENTICATION
: {
1007 if (my_want_state_is_dont(TELOPT_AUTHENTICATION
))
1009 auth_is(subpointer
, SB_LEN());
1012 if (my_want_state_is_wont(TELOPT_AUTHENTICATION
))
1014 auth_send(subpointer
, SB_LEN());
1017 if (my_want_state_is_wont(TELOPT_AUTHENTICATION
))
1019 auth_reply(subpointer
, SB_LEN());
1022 if (my_want_state_is_dont(TELOPT_AUTHENTICATION
))
1024 auth_name(subpointer
, SB_LEN());
1031 case TELOPT_ENCRYPT
:
1036 if (my_want_state_is_dont(TELOPT_ENCRYPT
))
1038 encrypt_start(subpointer
, SB_LEN());
1041 if (my_want_state_is_dont(TELOPT_ENCRYPT
))
1045 case ENCRYPT_SUPPORT
:
1046 if (my_want_state_is_wont(TELOPT_ENCRYPT
))
1048 encrypt_support(subpointer
, SB_LEN());
1050 case ENCRYPT_REQSTART
:
1051 if (my_want_state_is_wont(TELOPT_ENCRYPT
))
1053 encrypt_request_start(subpointer
, SB_LEN());
1055 case ENCRYPT_REQEND
:
1056 if (my_want_state_is_wont(TELOPT_ENCRYPT
))
1059 * We can always send an REQEND so that we cannot
1060 * get stuck encrypting. We should only get this
1061 * if we have been able to get in the correct mode
1064 encrypt_request_end();
1067 if (my_want_state_is_dont(TELOPT_ENCRYPT
))
1069 encrypt_is(subpointer
, SB_LEN());
1072 if (my_want_state_is_wont(TELOPT_ENCRYPT
))
1074 encrypt_reply(subpointer
, SB_LEN());
1076 case ENCRYPT_ENC_KEYID
:
1077 if (my_want_state_is_dont(TELOPT_ENCRYPT
))
1079 encrypt_enc_keyid(subpointer
, SB_LEN());
1081 case ENCRYPT_DEC_KEYID
:
1082 if (my_want_state_is_wont(TELOPT_ENCRYPT
))
1084 encrypt_dec_keyid(subpointer
, SB_LEN());
1090 #endif /* ENCRYPTION */
1096 static unsigned char str_lm
[] = { IAC
, SB
, TELOPT_LINEMODE
, 0, 0, IAC
, SE
};
1104 /*@*/ printf("lm_will: no command!!!\n"); /* Should not happen... */
1108 case LM_FORWARDMASK
: /* We shouldn't ever get this... */
1112 if (NETROOM() > sizeof(str_lm
)) {
1113 ring_supply_data(&netoring
, str_lm
, sizeof(str_lm
));
1114 printsub('>', &str_lm
[2], sizeof(str_lm
)-2);
1116 /*@*/ else printf("lm_will: not enough room in buffer\n");
1127 /*@*/ printf("lm_wont: no command!!!\n"); /* Should not happen... */
1131 case LM_FORWARDMASK
: /* We shouldn't ever get this... */
1133 /* We are always DONT, so don't respond */
1144 /*@*/ printf("lm_do: no command!!!\n"); /* Should not happen... */
1148 case LM_FORWARDMASK
:
1152 if (NETROOM() > sizeof(str_lm
)) {
1153 ring_supply_data(&netoring
, str_lm
, sizeof(str_lm
));
1154 printsub('>', &str_lm
[2], sizeof(str_lm
)-2);
1156 /*@*/ else printf("lm_do: not enough room in buffer\n");
1167 /*@*/ printf("lm_dont: no command!!!\n"); /* Should not happen... */
1171 case LM_FORWARDMASK
:
1173 /* we are always WONT, so don't respond */
1178 static unsigned char str_lm_mode
[] = {
1179 IAC
, SB
, TELOPT_LINEMODE
, LM_MODE
, 0, IAC
, SE
1183 lm_mode(cmd
, len
, init
)
1189 if ((linemode
&MODE_MASK
&~MODE_ACK
) == *cmd
)
1193 linemode
= *cmd
&(MODE_MASK
&~MODE_ACK
);
1194 str_lm_mode
[4] = linemode
;
1196 str_lm_mode
[4] |= MODE_ACK
;
1197 if (NETROOM() > sizeof(str_lm_mode
)) {
1198 ring_supply_data(&netoring
, str_lm_mode
, sizeof(str_lm_mode
));
1199 printsub('>', &str_lm_mode
[2], sizeof(str_lm_mode
)-2);
1201 /*@*/ else printf("lm_mode: not enough room in buffer\n");
1202 setconnmode(0); /* set changed mode */
1209 * Handle special character suboption of LINEMODE.
1215 char flags
; /* Current flags & level */
1216 char mylevel
; /* Maximum level & flags */
1219 #define SLC_IMPORT 0
1220 #define SLC_EXPORT 1
1221 #define SLC_RVALUE 2
1222 static int slc_mode
= SLC_EXPORT
;
1227 register struct spc
*spcp
;
1230 for (spcp
= spc_data
; spcp
< &spc_data
[NSLC
+1]; spcp
++) {
1233 spcp
->flags
= spcp
->mylevel
= SLC_NOSUPPORT
;
1236 #define initfunc(func, flags) { \
1237 spcp = &spc_data[func]; \
1238 if (spcp->valp = tcval(func)) { \
1239 spcp->val = *spcp->valp; \
1240 spcp->mylevel = SLC_VARIABLE|flags; \
1243 spcp->mylevel = SLC_DEFAULT; \
1247 initfunc(SLC_SYNCH
, 0);
1249 initfunc(SLC_AO
, 0);
1250 initfunc(SLC_AYT
, 0);
1252 initfunc(SLC_ABORT
, SLC_FLUSHIN
|SLC_FLUSHOUT
);
1253 initfunc(SLC_EOF
, 0);
1255 initfunc(SLC_SUSP
, SLC_FLUSHIN
);
1257 initfunc(SLC_EC
, 0);
1258 initfunc(SLC_EL
, 0);
1260 initfunc(SLC_EW
, 0);
1261 initfunc(SLC_RP
, 0);
1262 initfunc(SLC_LNEXT
, 0);
1264 initfunc(SLC_XON
, 0);
1265 initfunc(SLC_XOFF
, 0);
1267 spc_data
[SLC_XON
].mylevel
= SLC_CANTCHANGE
;
1268 spc_data
[SLC_XOFF
].mylevel
= SLC_CANTCHANGE
;
1270 initfunc(SLC_FORW1
, 0);
1272 initfunc(SLC_FORW2
, 0);
1276 initfunc(SLC_IP
, SLC_FLUSHIN
|SLC_FLUSHOUT
);
1279 if (slc_mode
== SLC_EXPORT
)
1289 printf("Special characters are %s values\n",
1290 slc_mode
== SLC_IMPORT
? "remote default" :
1291 slc_mode
== SLC_EXPORT
? "local" :
1298 slc_mode
= SLC_EXPORT
;
1299 if (my_state_is_will(TELOPT_LINEMODE
))
1304 slc_mode_import(def
)
1307 slc_mode
= def
? SLC_IMPORT
: SLC_RVALUE
;
1308 if (my_state_is_will(TELOPT_LINEMODE
))
1312 unsigned char slc_import_val
[] = {
1313 IAC
, SB
, TELOPT_LINEMODE
, LM_SLC
, 0, SLC_VARIABLE
, 0, IAC
, SE
1315 unsigned char slc_import_def
[] = {
1316 IAC
, SB
, TELOPT_LINEMODE
, LM_SLC
, 0, SLC_DEFAULT
, 0, IAC
, SE
1323 if (NETROOM() > sizeof(slc_import_val
)) {
1325 ring_supply_data(&netoring
, slc_import_def
, sizeof(slc_import_def
));
1326 printsub('>', &slc_import_def
[2], sizeof(slc_import_def
)-2);
1328 ring_supply_data(&netoring
, slc_import_val
, sizeof(slc_import_val
));
1329 printsub('>', &slc_import_val
[2], sizeof(slc_import_val
)-2);
1332 /*@*/ else printf("slc_import: not enough room\n");
1338 register struct spc
*spcp
;
1340 TerminalDefaultChars();
1343 for (spcp
= &spc_data
[1]; spcp
< &spc_data
[NSLC
+1]; spcp
++) {
1344 if (spcp
->mylevel
!= SLC_NOSUPPORT
) {
1345 if (spcp
->val
== (cc_t
)(_POSIX_VDISABLE
))
1346 spcp
->flags
= SLC_NOSUPPORT
;
1348 spcp
->flags
= spcp
->mylevel
;
1350 spcp
->val
= *spcp
->valp
;
1351 slc_add_reply(spcp
- spc_data
, spcp
->flags
, spcp
->val
);
1356 setconnmode(1); /* Make sure the character values are set */
1361 register unsigned char *cp
;
1364 register struct spc
*spcp
;
1365 register int func
,level
;
1369 for (; len
>= 3; len
-=3, cp
+=3) {
1371 func
= cp
[SLC_FUNC
];
1375 * Client side: always ignore 0 function.
1380 if ((cp
[SLC_FLAGS
] & SLC_LEVELBITS
) != SLC_NOSUPPORT
)
1381 slc_add_reply(func
, SLC_NOSUPPORT
, 0);
1385 spcp
= &spc_data
[func
];
1387 level
= cp
[SLC_FLAGS
]&(SLC_LEVELBITS
|SLC_ACK
);
1389 if ((cp
[SLC_VALUE
] == (unsigned char)spcp
->val
) &&
1390 ((level
&SLC_LEVELBITS
) == (spcp
->flags
&SLC_LEVELBITS
))) {
1394 if (level
== (SLC_DEFAULT
|SLC_ACK
)) {
1396 * This is an error condition, the SLC_ACK
1397 * bit should never be set for the SLC_DEFAULT
1398 * level. Our best guess to recover is to
1399 * ignore the SLC_ACK bit.
1401 cp
[SLC_FLAGS
] &= ~SLC_ACK
;
1404 if (level
== ((spcp
->flags
&SLC_LEVELBITS
)|SLC_ACK
)) {
1405 spcp
->val
= (cc_t
)cp
[SLC_VALUE
];
1406 spcp
->flags
= cp
[SLC_FLAGS
]; /* include SLC_ACK */
1412 if (level
<= (spcp
->mylevel
&SLC_LEVELBITS
)) {
1413 spcp
->flags
= cp
[SLC_FLAGS
]|SLC_ACK
;
1414 spcp
->val
= (cc_t
)cp
[SLC_VALUE
];
1416 if (level
== SLC_DEFAULT
) {
1417 if ((spcp
->mylevel
&SLC_LEVELBITS
) != SLC_DEFAULT
)
1418 spcp
->flags
= spcp
->mylevel
;
1420 spcp
->flags
= SLC_NOSUPPORT
;
1422 slc_add_reply(func
, spcp
->flags
, spcp
->val
);
1426 setconnmode(1); /* set the new character values */
1432 register struct spc
*spcp
;
1435 for (spcp
= &spc_data
[1]; spcp
< &spc_data
[NSLC
+1]; spcp
++) {
1436 if (spcp
->valp
&& spcp
->val
!= *spcp
->valp
) {
1437 spcp
->val
= *spcp
->valp
;
1438 if (spcp
->val
== (cc_t
)(_POSIX_VDISABLE
))
1439 spcp
->flags
= SLC_NOSUPPORT
;
1441 spcp
->flags
= spcp
->mylevel
;
1442 slc_add_reply(spcp
- spc_data
, spcp
->flags
, spcp
->val
);
1450 unsigned char slc_reply
[128];
1451 unsigned char *slc_replyp
;
1456 slc_replyp
= slc_reply
;
1457 *slc_replyp
++ = IAC
;
1459 *slc_replyp
++ = TELOPT_LINEMODE
;
1460 *slc_replyp
++ = LM_SLC
;
1464 slc_add_reply(func
, flags
, value
)
1466 unsigned char flags
;
1469 if ((*slc_replyp
++ = func
) == IAC
)
1470 *slc_replyp
++ = IAC
;
1471 if ((*slc_replyp
++ = flags
) == IAC
)
1472 *slc_replyp
++ = IAC
;
1473 if ((*slc_replyp
++ = (unsigned char)value
) == IAC
)
1474 *slc_replyp
++ = IAC
;
1482 *slc_replyp
++ = IAC
;
1484 len
= slc_replyp
- slc_reply
;
1487 if (NETROOM() > len
) {
1488 ring_supply_data(&netoring
, slc_reply
, slc_replyp
- slc_reply
);
1489 printsub('>', &slc_reply
[2], slc_replyp
- slc_reply
- 2);
1491 /*@*/else printf("slc_end_reply: not enough room\n");
1497 register struct spc
*spcp
;
1498 int need_update
= 0;
1500 for (spcp
= &spc_data
[1]; spcp
< &spc_data
[NSLC
+1]; spcp
++) {
1501 if (!(spcp
->flags
&SLC_ACK
))
1503 spcp
->flags
&= ~SLC_ACK
;
1504 if (spcp
->valp
&& (*spcp
->valp
!= spcp
->val
)) {
1505 *spcp
->valp
= spcp
->val
;
1509 return(need_update
);
1515 * Earlier version of telnet/telnetd from the BSD code had
1516 * the definitions of VALUE and VAR reversed. To ensure
1517 * maximum interoperability, we assume that the server is
1518 * an older BSD server, until proven otherwise. The newer
1519 * BSD servers should be able to handle either definition,
1520 * so it is better to use the wrong values if we don't
1521 * know what type of server it is.
1524 int old_env_var
= OLD_ENV_VAR
;
1525 int old_env_value
= OLD_ENV_VALUE
;
1527 # define old_env_var OLD_ENV_VAR
1528 # define old_env_value OLD_ENV_VALUE
1534 register unsigned char *buf
;
1537 register unsigned char *ep
= 0, *epc
= 0;
1540 switch(buf
[0]&0xff) {
1545 } else for (i
= 1; i
< len
; i
++) {
1546 switch (buf
[i
]&0xff) {
1550 if (telopt_environ
== TELOPT_OLD_ENVIRON
1552 /* Server has the same definitions */
1553 old_env_var
= OLD_ENV_VAR
;
1554 old_env_value
= OLD_ENV_VALUE
;
1560 * Although OLD_ENV_VALUE is not legal, we will
1561 * still recognize it, just in case it is an
1562 * old server that has VAR & VALUE mixed up...
1573 ep
= epc
= &buf
[i
+1];
1593 /* Ignore for now. We shouldn't get it anyway. */
1601 #define OPT_REPLY_SIZE 256
1602 unsigned char *opt_reply
;
1603 unsigned char *opt_replyp
;
1604 unsigned char *opt_replyend
;
1610 opt_reply
= (unsigned char *)realloc(opt_reply
, OPT_REPLY_SIZE
);
1612 opt_reply
= (unsigned char *)malloc(OPT_REPLY_SIZE
);
1613 if (opt_reply
== NULL
) {
1614 /*@*/ printf("env_opt_start: malloc()/realloc() failed!!!\n");
1615 opt_reply
= opt_replyp
= opt_replyend
= NULL
;
1618 opt_replyp
= opt_reply
;
1619 opt_replyend
= opt_reply
+ OPT_REPLY_SIZE
;
1620 *opt_replyp
++ = IAC
;
1622 *opt_replyp
++ = telopt_environ
;
1623 *opt_replyp
++ = TELQUAL_IS
;
1627 env_opt_start_info()
1631 opt_replyp
[-1] = TELQUAL_INFO
;
1636 register unsigned char *ep
;
1638 register unsigned char *vp
, c
;
1640 if (opt_reply
== NULL
) /*XXX*/
1643 if (ep
== NULL
|| *ep
== '\0') {
1644 /* Send user defined variables first. */
1646 while (ep
= env_default(0, 0))
1649 /* Now add the list of well know variables. */
1651 while (ep
= env_default(0, 1))
1655 vp
= env_getvalue(ep
);
1656 if (opt_replyp
+ (vp
? strlen((char *)vp
) : 0) +
1657 strlen((char *)ep
) + 6 > opt_replyend
)
1660 opt_replyend
+= OPT_REPLY_SIZE
;
1661 len
= opt_replyend
- opt_reply
;
1662 opt_reply
= (unsigned char *)realloc(opt_reply
, len
);
1663 if (opt_reply
== NULL
) {
1664 /*@*/ printf("env_opt_add: realloc() failed!!!\n");
1665 opt_reply
= opt_replyp
= opt_replyend
= NULL
;
1668 opt_replyp
= opt_reply
+ len
- (opt_replyend
- opt_replyp
);
1669 opt_replyend
= opt_reply
+ len
;
1671 if (opt_welldefined(ep
))
1673 if (telopt_environ
== TELOPT_OLD_ENVIRON
)
1674 *opt_replyp
++ = old_env_var
;
1677 *opt_replyp
++ = NEW_ENV_VAR
;
1679 *opt_replyp
++ = ENV_USERVAR
;
1684 *opt_replyp
++ = IAC
;
1690 *opt_replyp
++ = ENV_ESC
;
1697 if (telopt_environ
== TELOPT_OLD_ENVIRON
)
1698 *opt_replyp
++ = old_env_value
;
1701 *opt_replyp
++ = NEW_ENV_VALUE
;
1712 if ((strcmp(ep
, "USER") == 0) ||
1713 (strcmp(ep
, "DISPLAY") == 0) ||
1714 (strcmp(ep
, "PRINTER") == 0) ||
1715 (strcmp(ep
, "SYSTEMTYPE") == 0) ||
1716 (strcmp(ep
, "JOB") == 0) ||
1717 (strcmp(ep
, "ACCT") == 0))
1722 env_opt_end(emptyok
)
1723 register int emptyok
;
1727 len
= opt_replyp
- opt_reply
+ 2;
1728 if (emptyok
|| len
> 6) {
1729 *opt_replyp
++ = IAC
;
1731 if (NETROOM() > len
) {
1732 ring_supply_data(&netoring
, opt_reply
, len
);
1733 printsub('>', &opt_reply
[2], len
- 2);
1735 /*@*/ else printf("slc_end_reply: not enough room\n");
1739 opt_reply
= opt_replyp
= opt_replyend
= NULL
;
1750 register unsigned char *sbp
;
1752 int returnValue
= 0;
1756 while (TTYROOM() > 2) {
1759 ring_consumed(&netiring
, count
);
1763 sbp
= netiring
.consume
;
1764 scc
= ring_full_consecutive(&netiring
);
1766 /* No more data coming in */
1771 c
= *sbp
++ & 0xff, scc
--; count
++;
1774 c
= (*decrypt_input
)(c
);
1775 #endif /* ENCRYPTION */
1777 switch (telrcv_state
) {
1780 telrcv_state
= TS_DATA
;
1782 break; /* Ignore \0 after CR */
1784 else if ((c
== '\n') && my_want_state_is_dont(TELOPT_ECHO
) && !crmod
) {
1788 /* Else, fall through */
1792 telrcv_state
= TS_IAC
;
1795 # if defined(TN3270)
1799 c
= *sbp
++ & 0377, scc
--; count
++;
1802 c
= (*decrypt_input
)(c
);
1803 #endif /* ENCRYPTION */
1805 telrcv_state
= TS_IAC
;
1811 # endif /* defined(TN3270) */
1813 * The 'crmod' hack (see following) is needed
1814 * since we can't * set CRMOD on output only.
1815 * Machines like MULTICS like to send \r without
1816 * \n; since we must turn off CRMOD to get proper
1817 * input, the mapping is done here (sigh).
1819 if ((c
== '\r') && my_want_state_is_dont(TELOPT_BINARY
)) {
1824 c
= (*decrypt_input
)(c
);
1825 #endif /* ENCRYPTION */
1827 sbp
++, scc
--; count
++;
1830 } else if (my_want_state_is_dont(TELOPT_ECHO
) &&
1832 sbp
++, scc
--; count
++;
1837 (*decrypt_input
)(-1);
1838 #endif /* ENCRYPTION */
1846 telrcv_state
= TS_CR
;
1862 telrcv_state
= TS_WILL
;
1866 telrcv_state
= TS_WONT
;
1870 telrcv_state
= TS_DO
;
1874 telrcv_state
= TS_DONT
;
1879 * We may have missed an urgent notification,
1880 * so make sure we flush whatever is in the
1883 printoption("RCVD", IAC
, DM
);
1886 SYNCHing
= stilloob();
1892 telrcv_state
= TS_SB
;
1895 # if defined(TN3270)
1898 if (Ibackp
== Ifrontp
) {
1899 Ibackp
= Ifrontp
= Ibuf
;
1900 ISend
= 0; /* should have been! */
1902 Ibackp
+= DataFromNetwork(Ibackp
, Ifrontp
-Ibackp
, 1);
1906 printoption("RCVD", IAC
, EOR
);
1908 # endif /* defined(TN3270) */
1911 # if !defined(TN3270)
1913 # else /* !defined(TN3270) */
1919 # endif /* !defined(TN3270) */
1925 printoption("RCVD", IAC
, c
);
1928 telrcv_state
= TS_DATA
;
1932 printoption("RCVD", WILL
, c
);
1935 telrcv_state
= TS_DATA
;
1939 printoption("RCVD", WONT
, c
);
1942 telrcv_state
= TS_DATA
;
1946 printoption("RCVD", DO
, c
);
1949 if (c
== TELOPT_NAWS
) {
1951 } else if (c
== TELOPT_LFLOW
) {
1956 telrcv_state
= TS_DATA
;
1960 printoption("RCVD", DONT
, c
);
1963 setconnmode(0); /* set new tty mode (maybe) */
1965 telrcv_state
= TS_DATA
;
1970 telrcv_state
= TS_SE
;
1980 * This is an error. We only expect to get
1981 * "IAC IAC" or "IAC SE". Several things may
1982 * have happend. An IAC was not doubled, the
1983 * IAC SE was left off, or another option got
1984 * inserted into the suboption are all possibilities.
1985 * If we assume that the IAC was not doubled,
1986 * and really the IAC SE was left off, we could
1987 * get into an infinate loop here. So, instead,
1988 * we terminate the suboption, and process the
1989 * partial suboption if we can.
1996 printoption("In SUBOPTION processing, RCVD", IAC
, c
);
1997 suboption(); /* handle sub-option */
1999 telrcv_state
= TS_IAC
;
2003 telrcv_state
= TS_SB
;
2009 suboption(); /* handle sub-option */
2011 telrcv_state
= TS_DATA
;
2016 ring_consumed(&netiring
, count
);
2017 return returnValue
||count
;
2020 static int bol
= 1, local
= 0;
2028 command(0, "z\n", 2);
2039 int returnValue
= 0;
2044 while (NETROOM() > 2) {
2050 ring_consumed(&ttyiring
, count
);
2054 tbp
= ttyiring
.consume
;
2055 tcc
= ring_full_consecutive(&ttyiring
);
2060 c
= *tbp
++ & 0xff, sc
= strip(c
), tcc
--; count
++;
2061 if (rlogin
!= _POSIX_VDISABLE
) {
2070 if (sc
== '.' || c
== termEofChar
) {
2072 command(0, "close\n", 6);
2075 if (sc
== termSuspChar
) {
2077 command(0, "z\n", 2);
2081 command(0, (char *)tbp
, tcc
);
2095 if ((sc
== '\n') || (sc
== '\r'))
2097 } else if (sc
== escape
) {
2099 * Double escape is a pass through of a single escape character.
2101 if (tcc
&& strip(*tbp
) == escape
) {
2107 command(0, (char *)tbp
, tcc
);
2116 #ifdef KLUDGELINEMODE
2117 if (kludgelinemode
&& (globalmode
&MODE_EDIT
) && (sc
== echoc
)) {
2118 if (tcc
> 0 && strip(*tbp
) == echoc
) {
2119 tcc
--; tbp
++; count
++;
2121 dontlecho
= !dontlecho
;
2122 settimer(echotoggle
);
2129 if (MODE_LOCAL_CHARS(globalmode
)) {
2130 if (TerminalSpecialChars(sc
) == 0) {
2135 if (my_want_state_is_wont(TELOPT_BINARY
)) {
2139 * If we are in CRMOD mode (\r ==> \n)
2140 * on our local machine, then probably
2141 * a newline (unix) is CRLF (TELNET).
2143 if (MODE_LOCAL_CHARS(globalmode
)) {
2147 bol
= flushline
= 1;
2151 NET2ADD('\r', '\0');
2153 NET2ADD('\r', '\n');
2155 bol
= flushline
= 1;
2164 } else if (c
== IAC
) {
2171 ring_consumed(&ttyiring
, count
);
2172 return returnValue
||count
; /* Non-zero if we did anything */
2178 * Try to do something.
2180 * If we do something useful, return 1; else return 0.
2187 int block
; /* should we block in the select ? */
2189 /* One wants to be a bit careful about setting returnValue
2190 * to one, since a one implies we did some useful work,
2191 * and therefore probably won't be called to block next
2192 * time (TN3270 mode only).
2195 int netin
, netout
, netex
, ttyin
, ttyout
;
2197 /* Decide which rings should be processed */
2199 netout
= ring_full_count(&netoring
) &&
2201 (my_want_state_is_wont(TELOPT_LINEMODE
)
2202 #ifdef KLUDGELINEMODE
2203 && (!kludgelinemode
|| my_want_state_is_do(TELOPT_SGA
))
2206 my_want_state_is_will(TELOPT_BINARY
));
2207 ttyout
= ring_full_count(&ttyoring
);
2210 ttyin
= ring_empty_count(&ttyiring
) && (shell_active
== 0);
2211 #else /* defined(TN3270) */
2212 ttyin
= ring_empty_count(&ttyiring
);
2213 #endif /* defined(TN3270) */
2216 netin
= ring_empty_count(&netiring
);
2217 # else /* !defined(TN3270) */
2218 netin
= !ISend
&& ring_empty_count(&netiring
);
2219 # endif /* !defined(TN3270) */
2223 /* If we have seen a signal recently, reset things */
2224 # if defined(TN3270) && (defined(unix) || defined(__APPLE__))
2227 (void) signal(SIGIO
, inputAvailable
);
2229 #endif /* defined(TN3270) && (defined(unix) || defined(__APPLE__)) */
2231 /* Call to system code to process rings */
2233 returnValue
= process_rings(netin
, netout
, netex
, ttyin
, ttyout
, !block
);
2235 /* Now, look at the input rings, looking for work to do. */
2237 if (ring_full_count(&ttyiring
)) {
2238 # if defined(TN3270)
2242 c
= DataFromTerminal(ttyiring
.consume
,
2243 ring_full_consecutive(&ttyiring
));
2246 ring_consumed(&ttyiring
, c
);
2249 # endif /* defined(TN3270) */
2250 returnValue
|= telsnd();
2251 # if defined(TN3270)
2253 # endif /* defined(TN3270) */
2256 if (ring_full_count(&netiring
)) {
2257 # if !defined(TN3270)
2258 returnValue
|= telrcv();
2259 # else /* !defined(TN3270) */
2260 returnValue
= Push3270();
2261 # endif /* !defined(TN3270) */
2267 * Select from tty and network...
2275 #if defined(AUTHENTICATION) || defined(ENCRYPTION)
2277 static char local_host
[256] = { 0 };
2279 if (!local_host
[0]) {
2280 gethostname(local_host
, sizeof(local_host
));
2281 local_host
[sizeof(local_host
)-1] = 0;
2283 auth_encrypt_init(local_host
, hostname
, "TELNET", 0);
2284 auth_encrypt_user(user
);
2286 #endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */
2287 # if !defined(TN3270)
2289 #if defined(AUTHENTICATION)
2291 send_will(TELOPT_AUTHENTICATION
, 1);
2294 send_do(TELOPT_ENCRYPT
, 1);
2295 send_will(TELOPT_ENCRYPT
, 1);
2296 #endif /* ENCRYPTION */
2297 send_do(TELOPT_SGA
, 1);
2298 send_will(TELOPT_TTYPE
, 1);
2299 send_will(TELOPT_NAWS
, 1);
2300 send_will(TELOPT_TSPEED
, 1);
2301 send_will(TELOPT_LFLOW
, 1);
2302 send_will(TELOPT_LINEMODE
, 1);
2303 send_will(TELOPT_NEW_ENVIRON
, 1);
2304 send_do(TELOPT_STATUS
, 1);
2305 if (env_getvalue((unsigned char *)"DISPLAY"))
2306 send_will(TELOPT_XDISPLOC
, 1);
2308 tel_enter_binary(eight
);
2310 # endif /* !defined(TN3270) */
2312 # if !defined(TN3270)
2316 while ((schedValue
= Scheduler(0)) != 0) {
2317 if (schedValue
== -1) {
2323 if (Scheduler(1) == -1) {
2328 # else /* !defined(TN3270) */
2332 while (!In3270
&& !shell_active
) {
2333 if (Scheduler(1) == -1) {
2339 while ((schedValue
= Scheduler(0)) != 0) {
2340 if (schedValue
== -1) {
2345 /* If there is data waiting to go out to terminal, don't
2346 * schedule any more data for the terminal.
2348 if (ring_full_count(&ttyoring
)) {
2352 if (shell_continue() == 0) {
2355 } else if (In3270
) {
2356 schedValue
= DoTerminalOutput();
2359 if (schedValue
&& (shell_active
== 0)) {
2360 if (Scheduler(1) == -1) {
2366 # endif /* !defined(TN3270) */
2369 #if 0 /* XXX - this not being in is a bug */
2373 * Return the address of the next "item" in the TELNET data
2374 * stream. This will be the address of the next character if
2375 * the current address is a user data character, or it will
2376 * be the address of the character following the TELNET command
2377 * if the current address is a TELNET IAC ("I Am a Command")
2385 if ((*current
&0xff) != IAC
) {
2388 switch (*(current
+1)&0xff) {
2394 case SB
: /* loop forever looking for the SE */
2396 register char *look
= current
+2;
2399 if ((*look
++&0xff) == IAC
) {
2400 if ((*look
++&0xff) == SE
) {
2415 * We are about to do a TELNET SYNCH operation. Clear
2416 * the path to the network.
2418 * Things are a bit tricky since we may have sent the first
2419 * byte or so of a previous TELNET command into the network.
2420 * So, we have to scan the network buffer from the beginning
2421 * until we are up to where we want to be.
2423 * A side effect of what we do, just to keep things
2424 * simple, is to clear the urgent data pointer. The principal
2425 * caller should be setting the urgent data pointer AFTER calling
2433 register char *thisitem
, *next
;
2435 #define wewant(p) ((nfrontp > p) && ((*p&0xff) == IAC) && \
2436 ((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL))
2440 while ((next
= nextitem(thisitem
)) <= netobuf
.send
) {
2444 /* Now, thisitem is first before/at boundary. */
2446 good
= netobuf
; /* where the good bytes go */
2448 while (netoring
.add
> thisitem
) {
2449 if (wewant(thisitem
)) {
2454 next
= nextitem(next
);
2455 } while (wewant(next
) && (nfrontp
> next
));
2456 length
= next
-thisitem
;
2457 memmove(good
, thisitem
, length
);
2461 thisitem
= nextitem(thisitem
);
2469 * These routines add various telnet commands to the data stream.
2479 (void) ttyflush(1); /* Flush/drop output */
2480 /* do printoption AFTER flush, otherwise the output gets tossed... */
2481 printoption("SENT", DO
, TELOPT_TM
);
2488 printoption("SENT", IAC
, AO
);
2499 printoption("SENT", IAC
, EL
);
2506 printoption("SENT", IAC
, EC
);
2513 netclear(); /* clear the path to the network */
2517 printoption("SENT", IAC
, DM
);
2521 int want_status_response
= 0;
2526 unsigned char tmp
[16];
2527 register unsigned char *cp
;
2529 if (my_want_state_is_dont(TELOPT_STATUS
)) {
2530 printf("Remote side does not support STATUS option\n");
2537 *cp
++ = TELOPT_STATUS
;
2538 *cp
++ = TELQUAL_SEND
;
2541 if (NETROOM() >= cp
- tmp
) {
2542 ring_supply_data(&netoring
, tmp
, cp
-tmp
);
2543 printsub('>', tmp
+2, cp
- tmp
- 2);
2545 ++want_status_response
;
2553 printoption("SENT", IAC
, IP
);
2566 NET2ADD(IAC
, BREAK
);
2567 printoption("SENT", IAC
, BREAK
);
2580 NET2ADD(IAC
, ABORT
);
2581 printoption("SENT", IAC
, ABORT
);
2595 printoption("SENT", IAC
, SUSP
);
2609 printoption("SENT", IAC
, xEOF
);
2616 printoption("SENT", IAC
, AYT
);
2620 * Send a window size update to the remote system.
2627 unsigned char tmp
[16];
2628 register unsigned char *cp
;
2630 if (my_state_is_wont(TELOPT_NAWS
))
2633 #define PUTSHORT(cp, x) { if ((*cp++ = ((x)>>8)&0xff) == IAC) *cp++ = IAC; \
2634 if ((*cp++ = ((x))&0xff) == IAC) *cp++ = IAC; }
2636 if (TerminalWindowSize(&rows
, &cols
) == 0) { /* Failed */
2644 *cp
++ = TELOPT_NAWS
;
2649 if (NETROOM() >= cp
- tmp
) {
2650 ring_supply_data(&netoring
, tmp
, cp
-tmp
);
2651 printsub('>', tmp
+2, cp
- tmp
- 2);
2656 tel_enter_binary(rw
)
2660 send_do(TELOPT_BINARY
, 1);
2662 send_will(TELOPT_BINARY
, 1);
2666 tel_leave_binary(rw
)
2670 send_dont(TELOPT_BINARY
, 1);
2672 send_wont(TELOPT_BINARY
, 1);