17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
37c478bd9Sstevel@tonic-gate * Use is subject to license terms.
47c478bd9Sstevel@tonic-gate */
57c478bd9Sstevel@tonic-gate
67c478bd9Sstevel@tonic-gate /*
77c478bd9Sstevel@tonic-gate * Copyright (c) 1988, 1990, 1993
87c478bd9Sstevel@tonic-gate * The Regents of the University of California. All rights reserved.
97c478bd9Sstevel@tonic-gate *
107c478bd9Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without
117c478bd9Sstevel@tonic-gate * modification, are permitted provided that the following conditions
127c478bd9Sstevel@tonic-gate * are met:
137c478bd9Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright
147c478bd9Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer.
157c478bd9Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright
167c478bd9Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the
177c478bd9Sstevel@tonic-gate * documentation and/or other materials provided with the distribution.
187c478bd9Sstevel@tonic-gate * 3. All advertising materials mentioning features or use of this software
197c478bd9Sstevel@tonic-gate * must display the following acknowledgement:
207c478bd9Sstevel@tonic-gate * This product includes software developed by the University of
217c478bd9Sstevel@tonic-gate * California, Berkeley and its contributors.
227c478bd9Sstevel@tonic-gate * 4. Neither the name of the University nor the names of its contributors
237c478bd9Sstevel@tonic-gate * may be used to endorse or promote products derived from this software
247c478bd9Sstevel@tonic-gate * without specific prior written permission.
257c478bd9Sstevel@tonic-gate *
267c478bd9Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
277c478bd9Sstevel@tonic-gate * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
287c478bd9Sstevel@tonic-gate * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
297c478bd9Sstevel@tonic-gate * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
307c478bd9Sstevel@tonic-gate * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
317c478bd9Sstevel@tonic-gate * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
327c478bd9Sstevel@tonic-gate * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
337c478bd9Sstevel@tonic-gate * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
347c478bd9Sstevel@tonic-gate * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
357c478bd9Sstevel@tonic-gate * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
367c478bd9Sstevel@tonic-gate * SUCH DAMAGE.
377c478bd9Sstevel@tonic-gate */
387c478bd9Sstevel@tonic-gate
397c478bd9Sstevel@tonic-gate #ifndef lint
407c478bd9Sstevel@tonic-gate static char sccsid[] = "@(#)telnet.c 8.1 (Berkeley) 6/6/93";
417c478bd9Sstevel@tonic-gate #endif /* not lint */
427c478bd9Sstevel@tonic-gate
437c478bd9Sstevel@tonic-gate #include <netdb.h>
447c478bd9Sstevel@tonic-gate #include <sys/types.h>
457c478bd9Sstevel@tonic-gate
467c478bd9Sstevel@tonic-gate #include <curses.h>
477c478bd9Sstevel@tonic-gate #include <signal.h>
487c478bd9Sstevel@tonic-gate /*
497c478bd9Sstevel@tonic-gate * By the way, we need to include curses.h before telnet.h since,
507c478bd9Sstevel@tonic-gate * among other things, telnet.h #defines 'DO', which is a variable
517c478bd9Sstevel@tonic-gate * declared in curses.h.
527c478bd9Sstevel@tonic-gate */
537c478bd9Sstevel@tonic-gate
547c478bd9Sstevel@tonic-gate #include <arpa/telnet.h>
557c478bd9Sstevel@tonic-gate
567c478bd9Sstevel@tonic-gate #include <ctype.h>
577c478bd9Sstevel@tonic-gate
587c478bd9Sstevel@tonic-gate #include "ring.h"
597c478bd9Sstevel@tonic-gate
607c478bd9Sstevel@tonic-gate #include "defines.h"
617c478bd9Sstevel@tonic-gate #include "externs.h"
627c478bd9Sstevel@tonic-gate #include "types.h"
637c478bd9Sstevel@tonic-gate #include "general.h"
647c478bd9Sstevel@tonic-gate
657c478bd9Sstevel@tonic-gate #include "auth.h"
667c478bd9Sstevel@tonic-gate #include "encrypt.h"
677c478bd9Sstevel@tonic-gate
687c478bd9Sstevel@tonic-gate #define strip(x) ((x)&0x7f)
697c478bd9Sstevel@tonic-gate
707c478bd9Sstevel@tonic-gate /* Buffer for sub-options */
717c478bd9Sstevel@tonic-gate static unsigned char subbuffer[SUBBUFSIZE];
727c478bd9Sstevel@tonic-gate static unsigned char *subpointer;
737c478bd9Sstevel@tonic-gate static unsigned char *subend;
747c478bd9Sstevel@tonic-gate
757c478bd9Sstevel@tonic-gate #define SB_CLEAR() subpointer = subbuffer;
767c478bd9Sstevel@tonic-gate #define SB_TERM() { subend = subpointer; SB_CLEAR(); }
777c478bd9Sstevel@tonic-gate #define SB_ACCUM(c) if (subpointer < (subbuffer+sizeof (subbuffer))) { \
787c478bd9Sstevel@tonic-gate *subpointer++ = (c); \
797c478bd9Sstevel@tonic-gate }
807c478bd9Sstevel@tonic-gate
817c478bd9Sstevel@tonic-gate #define SB_GET() ((*subpointer++)&0xff)
827c478bd9Sstevel@tonic-gate #define SB_PEEK() ((*subpointer)&0xff)
837c478bd9Sstevel@tonic-gate #define SB_EOF() (subpointer >= subend)
847c478bd9Sstevel@tonic-gate #define SB_LEN() (subend - subpointer)
857c478bd9Sstevel@tonic-gate
867c478bd9Sstevel@tonic-gate char options[SUBBUFSIZE]; /* The combined options */
877c478bd9Sstevel@tonic-gate char do_dont_resp[SUBBUFSIZE];
887c478bd9Sstevel@tonic-gate char will_wont_resp[SUBBUFSIZE];
897c478bd9Sstevel@tonic-gate
907c478bd9Sstevel@tonic-gate int eight = 0;
917c478bd9Sstevel@tonic-gate int autologin = 0; /* Autologin anyone? */
927c478bd9Sstevel@tonic-gate int skiprc = 0;
937c478bd9Sstevel@tonic-gate int connected;
947c478bd9Sstevel@tonic-gate int showoptions;
957c478bd9Sstevel@tonic-gate static int ISend; /* trying to send network data in */
967c478bd9Sstevel@tonic-gate int debug = 0;
977c478bd9Sstevel@tonic-gate int crmod;
987c478bd9Sstevel@tonic-gate int netdata; /* Print out network data flow */
997c478bd9Sstevel@tonic-gate int crlf; /* Should '\r' be mapped to <CR><LF> (or <CR><NUL>)? */
1007c478bd9Sstevel@tonic-gate int telnetport;
1017c478bd9Sstevel@tonic-gate int SYNCHing; /* we are in TELNET SYNCH mode */
1027c478bd9Sstevel@tonic-gate int flushout; /* flush output */
1037c478bd9Sstevel@tonic-gate int autoflush = 0; /* flush output when interrupting? */
1047c478bd9Sstevel@tonic-gate int autosynch; /* send interrupt characters with SYNCH? */
1057c478bd9Sstevel@tonic-gate int localflow; /* we handle flow control locally */
1067c478bd9Sstevel@tonic-gate int restartany; /* if flow control enabled, restart on any character */
1077c478bd9Sstevel@tonic-gate int localchars; /* we recognize interrupt/quit */
1087c478bd9Sstevel@tonic-gate int donelclchars; /* the user has set "localchars" */
1097c478bd9Sstevel@tonic-gate int donebinarytoggle; /* the user has put us in binary */
1107c478bd9Sstevel@tonic-gate int dontlecho; /* do we suppress local echoing right now? */
1117c478bd9Sstevel@tonic-gate int eof_pending = 0; /* we received a genuine EOF on input, send IAC-EOF */
1127c478bd9Sstevel@tonic-gate int globalmode;
1137c478bd9Sstevel@tonic-gate
1147c478bd9Sstevel@tonic-gate /* spin while waiting for authentication */
1157c478bd9Sstevel@tonic-gate boolean_t scheduler_lockout_tty = B_FALSE;
1167c478bd9Sstevel@tonic-gate int encrypt_flag = 0;
1177c478bd9Sstevel@tonic-gate int forwardable_flag = 0;
1187c478bd9Sstevel@tonic-gate int forward_flag = 0;
1197c478bd9Sstevel@tonic-gate boolean_t wantencryption = B_FALSE;
1207c478bd9Sstevel@tonic-gate
1217c478bd9Sstevel@tonic-gate char *prompt = 0;
1227c478bd9Sstevel@tonic-gate
1237c478bd9Sstevel@tonic-gate cc_t escape;
1247c478bd9Sstevel@tonic-gate cc_t rlogin;
1257c478bd9Sstevel@tonic-gate boolean_t escape_valid = B_TRUE;
1267c478bd9Sstevel@tonic-gate #ifdef KLUDGELINEMODE
1277c478bd9Sstevel@tonic-gate cc_t echoc;
1287c478bd9Sstevel@tonic-gate #endif
1297c478bd9Sstevel@tonic-gate
1307c478bd9Sstevel@tonic-gate /*
1317c478bd9Sstevel@tonic-gate * Telnet receiver states for fsm
1327c478bd9Sstevel@tonic-gate */
1337c478bd9Sstevel@tonic-gate #define TS_DATA 0
1347c478bd9Sstevel@tonic-gate #define TS_IAC 1
1357c478bd9Sstevel@tonic-gate #define TS_WILL 2
1367c478bd9Sstevel@tonic-gate #define TS_WONT 3
1377c478bd9Sstevel@tonic-gate #define TS_DO 4
1387c478bd9Sstevel@tonic-gate #define TS_DONT 5
1397c478bd9Sstevel@tonic-gate #define TS_CR 6
1407c478bd9Sstevel@tonic-gate #define TS_SB 7 /* sub-option collection */
1417c478bd9Sstevel@tonic-gate #define TS_SE 8 /* looking for sub-option end */
1427c478bd9Sstevel@tonic-gate
1437c478bd9Sstevel@tonic-gate static int telrcv_state;
1447c478bd9Sstevel@tonic-gate #ifdef OLD_ENVIRON
1457c478bd9Sstevel@tonic-gate static unsigned char telopt_environ = TELOPT_NEW_ENVIRON;
1467c478bd9Sstevel@tonic-gate #else
1477c478bd9Sstevel@tonic-gate #define telopt_environ TELOPT_NEW_ENVIRON
1487c478bd9Sstevel@tonic-gate #endif
1497c478bd9Sstevel@tonic-gate
1507c478bd9Sstevel@tonic-gate jmp_buf toplevel = { 0 };
1517c478bd9Sstevel@tonic-gate jmp_buf peerdied;
1527c478bd9Sstevel@tonic-gate
1537c478bd9Sstevel@tonic-gate static int flushline;
1547c478bd9Sstevel@tonic-gate int linemode;
1557c478bd9Sstevel@tonic-gate
1567c478bd9Sstevel@tonic-gate int reqd_linemode = 0; /* Set if either new or old line mode in */
1577c478bd9Sstevel@tonic-gate /* effect since before initial negotiations */
1587c478bd9Sstevel@tonic-gate
1597c478bd9Sstevel@tonic-gate #ifdef KLUDGELINEMODE
1607c478bd9Sstevel@tonic-gate int kludgelinemode = 1;
1617c478bd9Sstevel@tonic-gate #endif
1627c478bd9Sstevel@tonic-gate
1637c478bd9Sstevel@tonic-gate /*
1647c478bd9Sstevel@tonic-gate * The following are some clocks used to decide how to interpret
1657c478bd9Sstevel@tonic-gate * the relationship between various variables.
1667c478bd9Sstevel@tonic-gate */
1677c478bd9Sstevel@tonic-gate
1687c478bd9Sstevel@tonic-gate Clocks clocks;
1697c478bd9Sstevel@tonic-gate
1707c478bd9Sstevel@tonic-gate #ifdef notdef
1717c478bd9Sstevel@tonic-gate Modelist modelist[] = {
1727c478bd9Sstevel@tonic-gate { "telnet command mode", COMMAND_LINE },
1737c478bd9Sstevel@tonic-gate { "character-at-a-time mode", 0 },
1747c478bd9Sstevel@tonic-gate { "character-at-a-time mode (local echo)", LOCAL_ECHO|LOCAL_CHARS },
1757c478bd9Sstevel@tonic-gate { "line-by-line mode (remote echo)", LINE | LOCAL_CHARS },
1767c478bd9Sstevel@tonic-gate { "line-by-line mode", LINE | LOCAL_ECHO | LOCAL_CHARS },
1777c478bd9Sstevel@tonic-gate { "line-by-line mode (local echoing suppressed)", LINE | LOCAL_CHARS },
1787c478bd9Sstevel@tonic-gate { "3270 mode", 0 },
1797c478bd9Sstevel@tonic-gate };
1807c478bd9Sstevel@tonic-gate #endif
1817c478bd9Sstevel@tonic-gate
1827c478bd9Sstevel@tonic-gate static void willoption(int);
1837c478bd9Sstevel@tonic-gate static void wontoption(int);
1847c478bd9Sstevel@tonic-gate static void lm_will(unsigned char *, int);
1857c478bd9Sstevel@tonic-gate static void lm_wont(unsigned char *, int);
1867c478bd9Sstevel@tonic-gate static void lm_do(unsigned char *, int);
1877c478bd9Sstevel@tonic-gate static void lm_dont(unsigned char *, int);
1887c478bd9Sstevel@tonic-gate static void slc_init(void);
1897c478bd9Sstevel@tonic-gate static void slc_import(int);
1907c478bd9Sstevel@tonic-gate static void slc_export(void);
1917c478bd9Sstevel@tonic-gate static void slc_start_reply(size_t);
1927c478bd9Sstevel@tonic-gate static void slc_add_reply(unsigned char, unsigned char, cc_t);
1937c478bd9Sstevel@tonic-gate static void slc_end_reply(void);
1947c478bd9Sstevel@tonic-gate static void slc(unsigned char *, int);
1957c478bd9Sstevel@tonic-gate static int slc_update(void);
1967c478bd9Sstevel@tonic-gate static void env_opt(unsigned char *, int);
1977c478bd9Sstevel@tonic-gate static void env_opt_start(void);
1987c478bd9Sstevel@tonic-gate static void sendeof(void);
1997c478bd9Sstevel@tonic-gate static int is_unique(register char *, register char **, register char **);
2007c478bd9Sstevel@tonic-gate
2017c478bd9Sstevel@tonic-gate /*
2027c478bd9Sstevel@tonic-gate * Initialize telnet environment.
2037c478bd9Sstevel@tonic-gate */
2047c478bd9Sstevel@tonic-gate
2057c478bd9Sstevel@tonic-gate int
init_telnet()2067c478bd9Sstevel@tonic-gate init_telnet()
2077c478bd9Sstevel@tonic-gate {
2087c478bd9Sstevel@tonic-gate if (env_init() == 0)
2097c478bd9Sstevel@tonic-gate return (0);
2107c478bd9Sstevel@tonic-gate
2117c478bd9Sstevel@tonic-gate SB_CLEAR();
2127c478bd9Sstevel@tonic-gate ClearArray(options);
2137c478bd9Sstevel@tonic-gate
2147c478bd9Sstevel@tonic-gate connected = ISend = localflow = donebinarytoggle = 0;
2157c478bd9Sstevel@tonic-gate restartany = -1;
2167c478bd9Sstevel@tonic-gate
2177c478bd9Sstevel@tonic-gate SYNCHing = 0;
2187c478bd9Sstevel@tonic-gate
2197c478bd9Sstevel@tonic-gate /* Don't change NetTrace */
2207c478bd9Sstevel@tonic-gate
2217c478bd9Sstevel@tonic-gate escape = CONTROL(']');
2227c478bd9Sstevel@tonic-gate rlogin = _POSIX_VDISABLE;
2237c478bd9Sstevel@tonic-gate #ifdef KLUDGELINEMODE
2247c478bd9Sstevel@tonic-gate echoc = CONTROL('E');
2257c478bd9Sstevel@tonic-gate #endif
2267c478bd9Sstevel@tonic-gate
2277c478bd9Sstevel@tonic-gate flushline = 1;
2287c478bd9Sstevel@tonic-gate telrcv_state = TS_DATA;
2297c478bd9Sstevel@tonic-gate
2307c478bd9Sstevel@tonic-gate return (1);
2317c478bd9Sstevel@tonic-gate }
2327c478bd9Sstevel@tonic-gate
2337c478bd9Sstevel@tonic-gate
2347c478bd9Sstevel@tonic-gate #ifdef notdef
2357c478bd9Sstevel@tonic-gate #include <varargs.h>
2367c478bd9Sstevel@tonic-gate
2377c478bd9Sstevel@tonic-gate /*VARARGS*/
2387c478bd9Sstevel@tonic-gate static void
printring(va_alist)2397c478bd9Sstevel@tonic-gate printring(va_alist)
2407c478bd9Sstevel@tonic-gate va_dcl
2417c478bd9Sstevel@tonic-gate {
2427c478bd9Sstevel@tonic-gate va_list ap;
2437c478bd9Sstevel@tonic-gate char buffer[100]; /* where things go */
2447c478bd9Sstevel@tonic-gate char *ptr;
2457c478bd9Sstevel@tonic-gate char *format;
2467c478bd9Sstevel@tonic-gate char *string;
2477c478bd9Sstevel@tonic-gate Ring *ring;
2487c478bd9Sstevel@tonic-gate int i;
2497c478bd9Sstevel@tonic-gate
2507c478bd9Sstevel@tonic-gate va_start(ap);
2517c478bd9Sstevel@tonic-gate
2527c478bd9Sstevel@tonic-gate ring = va_arg(ap, Ring *);
2537c478bd9Sstevel@tonic-gate format = va_arg(ap, char *);
2547c478bd9Sstevel@tonic-gate ptr = buffer;
2557c478bd9Sstevel@tonic-gate
2567c478bd9Sstevel@tonic-gate while ((i = *format++) != 0) {
2577c478bd9Sstevel@tonic-gate if (i == '%') {
2587c478bd9Sstevel@tonic-gate i = *format++;
2597c478bd9Sstevel@tonic-gate switch (i) {
2607c478bd9Sstevel@tonic-gate case 'c':
2617c478bd9Sstevel@tonic-gate *ptr++ = va_arg(ap, int);
2627c478bd9Sstevel@tonic-gate break;
2637c478bd9Sstevel@tonic-gate case 's':
2647c478bd9Sstevel@tonic-gate string = va_arg(ap, char *);
2657c478bd9Sstevel@tonic-gate ring_supply_data(ring, buffer, ptr-buffer);
2667c478bd9Sstevel@tonic-gate ring_supply_data(ring, string, strlen(string));
2677c478bd9Sstevel@tonic-gate ptr = buffer;
2687c478bd9Sstevel@tonic-gate break;
2697c478bd9Sstevel@tonic-gate case 0:
2707c478bd9Sstevel@tonic-gate ExitString("printring: trailing %%.\n",
2717c478bd9Sstevel@tonic-gate EXIT_FAILURE);
2727c478bd9Sstevel@tonic-gate /*NOTREACHED*/
2737c478bd9Sstevel@tonic-gate default:
2747c478bd9Sstevel@tonic-gate ExitString("printring: unknown format "
2757c478bd9Sstevel@tonic-gate "character.\n", EXIT_FAILURE);
2767c478bd9Sstevel@tonic-gate /*NOTREACHED*/
2777c478bd9Sstevel@tonic-gate }
2787c478bd9Sstevel@tonic-gate } else {
2797c478bd9Sstevel@tonic-gate *ptr++ = i;
2807c478bd9Sstevel@tonic-gate }
2817c478bd9Sstevel@tonic-gate }
2827c478bd9Sstevel@tonic-gate ring_supply_data(ring, buffer, ptr-buffer);
2837c478bd9Sstevel@tonic-gate }
2847c478bd9Sstevel@tonic-gate #endif
2857c478bd9Sstevel@tonic-gate
2867c478bd9Sstevel@tonic-gate /*
2877c478bd9Sstevel@tonic-gate * These routines are in charge of sending option negotiations
2887c478bd9Sstevel@tonic-gate * to the other side.
2897c478bd9Sstevel@tonic-gate *
2907c478bd9Sstevel@tonic-gate * The basic idea is that we send the negotiation if either side
2917c478bd9Sstevel@tonic-gate * is in disagreement as to what the current state should be.
2927c478bd9Sstevel@tonic-gate */
2937c478bd9Sstevel@tonic-gate
2947c478bd9Sstevel@tonic-gate void
send_do(c,init)2957c478bd9Sstevel@tonic-gate send_do(c, init)
2967c478bd9Sstevel@tonic-gate register int c, init;
2977c478bd9Sstevel@tonic-gate {
2987c478bd9Sstevel@tonic-gate if (init) {
2997c478bd9Sstevel@tonic-gate if (((do_dont_resp[c] == 0) && my_state_is_do(c)) ||
3007c478bd9Sstevel@tonic-gate my_want_state_is_do(c))
3017c478bd9Sstevel@tonic-gate return;
3027c478bd9Sstevel@tonic-gate set_my_want_state_do(c);
3037c478bd9Sstevel@tonic-gate do_dont_resp[c]++;
3047c478bd9Sstevel@tonic-gate }
3057c478bd9Sstevel@tonic-gate NET2ADD(IAC, DO);
3067c478bd9Sstevel@tonic-gate NETADD(c);
3077c478bd9Sstevel@tonic-gate printoption("SENT", DO, c);
3087c478bd9Sstevel@tonic-gate }
3097c478bd9Sstevel@tonic-gate
3107c478bd9Sstevel@tonic-gate void
send_dont(c,init)3117c478bd9Sstevel@tonic-gate send_dont(c, init)
3127c478bd9Sstevel@tonic-gate register int c, init;
3137c478bd9Sstevel@tonic-gate {
3147c478bd9Sstevel@tonic-gate if (init) {
3157c478bd9Sstevel@tonic-gate if (((do_dont_resp[c] == 0) && my_state_is_dont(c)) ||
3167c478bd9Sstevel@tonic-gate my_want_state_is_dont(c))
3177c478bd9Sstevel@tonic-gate return;
3187c478bd9Sstevel@tonic-gate set_my_want_state_dont(c);
3197c478bd9Sstevel@tonic-gate do_dont_resp[c]++;
3207c478bd9Sstevel@tonic-gate }
3217c478bd9Sstevel@tonic-gate NET2ADD(IAC, DONT);
3227c478bd9Sstevel@tonic-gate NETADD(c);
3237c478bd9Sstevel@tonic-gate printoption("SENT", DONT, c);
3247c478bd9Sstevel@tonic-gate }
3257c478bd9Sstevel@tonic-gate
3267c478bd9Sstevel@tonic-gate void
send_will(c,init)3277c478bd9Sstevel@tonic-gate send_will(c, init)
3287c478bd9Sstevel@tonic-gate register int c, init;
3297c478bd9Sstevel@tonic-gate {
3307c478bd9Sstevel@tonic-gate if (init) {
3317c478bd9Sstevel@tonic-gate if (((will_wont_resp[c] == 0) && my_state_is_will(c)) ||
3327c478bd9Sstevel@tonic-gate my_want_state_is_will(c))
3337c478bd9Sstevel@tonic-gate return;
3347c478bd9Sstevel@tonic-gate set_my_want_state_will(c);
3357c478bd9Sstevel@tonic-gate will_wont_resp[c]++;
3367c478bd9Sstevel@tonic-gate }
3377c478bd9Sstevel@tonic-gate NET2ADD(IAC, WILL);
3387c478bd9Sstevel@tonic-gate NETADD(c);
3397c478bd9Sstevel@tonic-gate printoption("SENT", WILL, c);
3407c478bd9Sstevel@tonic-gate }
3417c478bd9Sstevel@tonic-gate
3427c478bd9Sstevel@tonic-gate void
send_wont(c,init)3437c478bd9Sstevel@tonic-gate send_wont(c, init)
3447c478bd9Sstevel@tonic-gate register int c, init;
3457c478bd9Sstevel@tonic-gate {
3467c478bd9Sstevel@tonic-gate if (init) {
3477c478bd9Sstevel@tonic-gate if (((will_wont_resp[c] == 0) && my_state_is_wont(c)) ||
3487c478bd9Sstevel@tonic-gate my_want_state_is_wont(c))
3497c478bd9Sstevel@tonic-gate return;
3507c478bd9Sstevel@tonic-gate set_my_want_state_wont(c);
3517c478bd9Sstevel@tonic-gate will_wont_resp[c]++;
3527c478bd9Sstevel@tonic-gate }
3537c478bd9Sstevel@tonic-gate NET2ADD(IAC, WONT);
3547c478bd9Sstevel@tonic-gate NETADD(c);
3557c478bd9Sstevel@tonic-gate printoption("SENT", WONT, c);
3567c478bd9Sstevel@tonic-gate }
3577c478bd9Sstevel@tonic-gate
3587c478bd9Sstevel@tonic-gate
3597c478bd9Sstevel@tonic-gate static void
willoption(option)3607c478bd9Sstevel@tonic-gate willoption(option)
3617c478bd9Sstevel@tonic-gate int option;
3627c478bd9Sstevel@tonic-gate {
3637c478bd9Sstevel@tonic-gate int new_state_ok = 0;
3647c478bd9Sstevel@tonic-gate
3657c478bd9Sstevel@tonic-gate if (do_dont_resp[option]) {
3667c478bd9Sstevel@tonic-gate --do_dont_resp[option];
3677c478bd9Sstevel@tonic-gate if (do_dont_resp[option] && my_state_is_do(option))
3687c478bd9Sstevel@tonic-gate --do_dont_resp[option];
3697c478bd9Sstevel@tonic-gate }
3707c478bd9Sstevel@tonic-gate
3717c478bd9Sstevel@tonic-gate if ((do_dont_resp[option] == 0) && my_want_state_is_dont(option)) {
3727c478bd9Sstevel@tonic-gate
3737c478bd9Sstevel@tonic-gate switch (option) {
3747c478bd9Sstevel@tonic-gate
3757c478bd9Sstevel@tonic-gate case TELOPT_ECHO:
3767c478bd9Sstevel@tonic-gate case TELOPT_SGA:
3777c478bd9Sstevel@tonic-gate if (reqd_linemode && my_state_is_dont(option)) {
3787c478bd9Sstevel@tonic-gate break;
3797c478bd9Sstevel@tonic-gate }
3807c478bd9Sstevel@tonic-gate /* FALLTHROUGH */
3817c478bd9Sstevel@tonic-gate case TELOPT_BINARY:
3827c478bd9Sstevel@tonic-gate settimer(modenegotiated);
3837c478bd9Sstevel@tonic-gate /* FALLTHROUGH */
3847c478bd9Sstevel@tonic-gate case TELOPT_STATUS:
3857c478bd9Sstevel@tonic-gate case TELOPT_AUTHENTICATION:
3867c478bd9Sstevel@tonic-gate /* FALLTHROUGH */
3877c478bd9Sstevel@tonic-gate case TELOPT_ENCRYPT:
3887c478bd9Sstevel@tonic-gate new_state_ok = 1;
3897c478bd9Sstevel@tonic-gate break;
3907c478bd9Sstevel@tonic-gate
3917c478bd9Sstevel@tonic-gate case TELOPT_TM:
3927c478bd9Sstevel@tonic-gate if (flushout)
3937c478bd9Sstevel@tonic-gate flushout = 0;
3947c478bd9Sstevel@tonic-gate /*
3957c478bd9Sstevel@tonic-gate * Special case for TM. If we get back a WILL,
3967c478bd9Sstevel@tonic-gate * pretend we got back a WONT.
3977c478bd9Sstevel@tonic-gate */
3987c478bd9Sstevel@tonic-gate set_my_want_state_dont(option);
3997c478bd9Sstevel@tonic-gate set_my_state_dont(option);
4007c478bd9Sstevel@tonic-gate return; /* Never reply to TM will's/wont's */
4017c478bd9Sstevel@tonic-gate
4027c478bd9Sstevel@tonic-gate case TELOPT_LINEMODE:
4037c478bd9Sstevel@tonic-gate default:
4047c478bd9Sstevel@tonic-gate break;
4057c478bd9Sstevel@tonic-gate }
4067c478bd9Sstevel@tonic-gate
4077c478bd9Sstevel@tonic-gate if (new_state_ok) {
4087c478bd9Sstevel@tonic-gate set_my_want_state_do(option);
4097c478bd9Sstevel@tonic-gate send_do(option, 0);
4107c478bd9Sstevel@tonic-gate setconnmode(0); /* possibly set new tty mode */
4117c478bd9Sstevel@tonic-gate } else {
4127c478bd9Sstevel@tonic-gate do_dont_resp[option]++;
4137c478bd9Sstevel@tonic-gate send_dont(option, 0);
4147c478bd9Sstevel@tonic-gate }
4157c478bd9Sstevel@tonic-gate }
4167c478bd9Sstevel@tonic-gate set_my_state_do(option);
4177c478bd9Sstevel@tonic-gate if (option == TELOPT_ENCRYPT)
4187c478bd9Sstevel@tonic-gate encrypt_send_support();
4197c478bd9Sstevel@tonic-gate }
4207c478bd9Sstevel@tonic-gate
4217c478bd9Sstevel@tonic-gate static void
wontoption(option)4227c478bd9Sstevel@tonic-gate wontoption(option)
4237c478bd9Sstevel@tonic-gate int option;
4247c478bd9Sstevel@tonic-gate {
4257c478bd9Sstevel@tonic-gate if (do_dont_resp[option]) {
4267c478bd9Sstevel@tonic-gate --do_dont_resp[option];
4277c478bd9Sstevel@tonic-gate if (do_dont_resp[option] && my_state_is_dont(option))
4287c478bd9Sstevel@tonic-gate --do_dont_resp[option];
4297c478bd9Sstevel@tonic-gate }
4307c478bd9Sstevel@tonic-gate
4317c478bd9Sstevel@tonic-gate if ((do_dont_resp[option] == 0) && my_want_state_is_do(option)) {
4327c478bd9Sstevel@tonic-gate
4337c478bd9Sstevel@tonic-gate switch (option) {
4347c478bd9Sstevel@tonic-gate
4357c478bd9Sstevel@tonic-gate #ifdef KLUDGELINEMODE
4367c478bd9Sstevel@tonic-gate case TELOPT_SGA:
4377c478bd9Sstevel@tonic-gate if (!kludgelinemode)
4387c478bd9Sstevel@tonic-gate break;
4397c478bd9Sstevel@tonic-gate /* FALLTHROUGH */
4407c478bd9Sstevel@tonic-gate #endif
4417c478bd9Sstevel@tonic-gate case TELOPT_ECHO:
4427c478bd9Sstevel@tonic-gate settimer(modenegotiated);
4437c478bd9Sstevel@tonic-gate break;
4447c478bd9Sstevel@tonic-gate
4457c478bd9Sstevel@tonic-gate case TELOPT_TM:
4467c478bd9Sstevel@tonic-gate if (flushout)
4477c478bd9Sstevel@tonic-gate flushout = 0;
4487c478bd9Sstevel@tonic-gate set_my_want_state_dont(option);
4497c478bd9Sstevel@tonic-gate set_my_state_dont(option);
4507c478bd9Sstevel@tonic-gate return; /* Never reply to TM will's/wont's */
4517c478bd9Sstevel@tonic-gate
4527c478bd9Sstevel@tonic-gate default:
4537c478bd9Sstevel@tonic-gate break;
4547c478bd9Sstevel@tonic-gate }
4557c478bd9Sstevel@tonic-gate set_my_want_state_dont(option);
4567c478bd9Sstevel@tonic-gate if (my_state_is_do(option))
4577c478bd9Sstevel@tonic-gate send_dont(option, 0);
4587c478bd9Sstevel@tonic-gate setconnmode(0); /* Set new tty mode */
4597c478bd9Sstevel@tonic-gate } else if (option == TELOPT_TM) {
4607c478bd9Sstevel@tonic-gate /*
4617c478bd9Sstevel@tonic-gate * Special case for TM.
4627c478bd9Sstevel@tonic-gate */
4637c478bd9Sstevel@tonic-gate if (flushout)
4647c478bd9Sstevel@tonic-gate flushout = 0;
4657c478bd9Sstevel@tonic-gate set_my_want_state_dont(option);
4667c478bd9Sstevel@tonic-gate }
4677c478bd9Sstevel@tonic-gate set_my_state_dont(option);
4687c478bd9Sstevel@tonic-gate }
4697c478bd9Sstevel@tonic-gate
4707c478bd9Sstevel@tonic-gate static void
dooption(option)4717c478bd9Sstevel@tonic-gate dooption(option)
4727c478bd9Sstevel@tonic-gate int option;
4737c478bd9Sstevel@tonic-gate {
4747c478bd9Sstevel@tonic-gate int new_state_ok = 0;
4757c478bd9Sstevel@tonic-gate
4767c478bd9Sstevel@tonic-gate if (will_wont_resp[option]) {
4777c478bd9Sstevel@tonic-gate --will_wont_resp[option];
4787c478bd9Sstevel@tonic-gate if (will_wont_resp[option] && my_state_is_will(option))
4797c478bd9Sstevel@tonic-gate --will_wont_resp[option];
4807c478bd9Sstevel@tonic-gate }
4817c478bd9Sstevel@tonic-gate
4827c478bd9Sstevel@tonic-gate if (will_wont_resp[option] == 0) {
4837c478bd9Sstevel@tonic-gate if (my_want_state_is_wont(option)) {
4847c478bd9Sstevel@tonic-gate
4857c478bd9Sstevel@tonic-gate switch (option) {
4867c478bd9Sstevel@tonic-gate
4877c478bd9Sstevel@tonic-gate case TELOPT_TM:
4887c478bd9Sstevel@tonic-gate /*
4897c478bd9Sstevel@tonic-gate * Special case for TM. We send a WILL,
4907c478bd9Sstevel@tonic-gate * but pretend we sent WONT.
4917c478bd9Sstevel@tonic-gate */
4927c478bd9Sstevel@tonic-gate send_will(option, 0);
4937c478bd9Sstevel@tonic-gate set_my_want_state_wont(TELOPT_TM);
4947c478bd9Sstevel@tonic-gate set_my_state_wont(TELOPT_TM);
4957c478bd9Sstevel@tonic-gate return;
4967c478bd9Sstevel@tonic-gate
4977c478bd9Sstevel@tonic-gate case TELOPT_BINARY: /* binary mode */
4987c478bd9Sstevel@tonic-gate case TELOPT_NAWS: /* window size */
4997c478bd9Sstevel@tonic-gate case TELOPT_TSPEED: /* terminal speed */
5007c478bd9Sstevel@tonic-gate case TELOPT_LFLOW: /* local flow control */
5017c478bd9Sstevel@tonic-gate case TELOPT_TTYPE: /* terminal type option */
5027c478bd9Sstevel@tonic-gate case TELOPT_SGA: /* no big deal */
5037c478bd9Sstevel@tonic-gate case TELOPT_ENCRYPT: /* encryption variable option */
5047c478bd9Sstevel@tonic-gate new_state_ok = 1;
5057c478bd9Sstevel@tonic-gate break;
5067c478bd9Sstevel@tonic-gate
5077c478bd9Sstevel@tonic-gate case TELOPT_NEW_ENVIRON:
5087c478bd9Sstevel@tonic-gate /* New environment variable option */
5097c478bd9Sstevel@tonic-gate #ifdef OLD_ENVIRON
5107c478bd9Sstevel@tonic-gate if (my_state_is_will(TELOPT_OLD_ENVIRON))
5117c478bd9Sstevel@tonic-gate /* turn off the old */
5127c478bd9Sstevel@tonic-gate send_wont(TELOPT_OLD_ENVIRON, 1);
5137c478bd9Sstevel@tonic-gate goto env_common;
5147c478bd9Sstevel@tonic-gate case TELOPT_OLD_ENVIRON:
5157c478bd9Sstevel@tonic-gate /* Old environment variable option */
5167c478bd9Sstevel@tonic-gate if (my_state_is_will(TELOPT_NEW_ENVIRON))
5177c478bd9Sstevel@tonic-gate /* Don't enable if new one is in use! */
5187c478bd9Sstevel@tonic-gate break;
5197c478bd9Sstevel@tonic-gate env_common:
5207c478bd9Sstevel@tonic-gate telopt_environ = option;
5217c478bd9Sstevel@tonic-gate #endif
5227c478bd9Sstevel@tonic-gate new_state_ok = 1;
5237c478bd9Sstevel@tonic-gate break;
5247c478bd9Sstevel@tonic-gate
5257c478bd9Sstevel@tonic-gate case TELOPT_AUTHENTICATION:
5267c478bd9Sstevel@tonic-gate if (autologin)
5277c478bd9Sstevel@tonic-gate new_state_ok = 1;
5287c478bd9Sstevel@tonic-gate break;
5297c478bd9Sstevel@tonic-gate
5307c478bd9Sstevel@tonic-gate case TELOPT_XDISPLOC: /* X Display location */
5317c478bd9Sstevel@tonic-gate if (env_getvalue((unsigned char *)"DISPLAY"))
5327c478bd9Sstevel@tonic-gate new_state_ok = 1;
5337c478bd9Sstevel@tonic-gate break;
5347c478bd9Sstevel@tonic-gate
5357c478bd9Sstevel@tonic-gate case TELOPT_LINEMODE:
5367c478bd9Sstevel@tonic-gate #ifdef KLUDGELINEMODE
5377c478bd9Sstevel@tonic-gate kludgelinemode = 0;
5387c478bd9Sstevel@tonic-gate send_do(TELOPT_SGA, 1);
5397c478bd9Sstevel@tonic-gate #endif
5407c478bd9Sstevel@tonic-gate set_my_want_state_will(TELOPT_LINEMODE);
5417c478bd9Sstevel@tonic-gate send_will(option, 0);
5427c478bd9Sstevel@tonic-gate set_my_state_will(TELOPT_LINEMODE);
5437c478bd9Sstevel@tonic-gate slc_init();
5447c478bd9Sstevel@tonic-gate return;
5457c478bd9Sstevel@tonic-gate
5467c478bd9Sstevel@tonic-gate case TELOPT_ECHO: /* We're never going to echo... */
5477c478bd9Sstevel@tonic-gate default:
5487c478bd9Sstevel@tonic-gate break;
5497c478bd9Sstevel@tonic-gate }
5507c478bd9Sstevel@tonic-gate
5517c478bd9Sstevel@tonic-gate if (new_state_ok) {
5527c478bd9Sstevel@tonic-gate set_my_want_state_will(option);
5537c478bd9Sstevel@tonic-gate send_will(option, 0);
5547c478bd9Sstevel@tonic-gate setconnmode(0); /* Set new tty mode */
5557c478bd9Sstevel@tonic-gate } else {
5567c478bd9Sstevel@tonic-gate will_wont_resp[option]++;
5577c478bd9Sstevel@tonic-gate send_wont(option, 0);
5587c478bd9Sstevel@tonic-gate }
5597c478bd9Sstevel@tonic-gate } else {
5607c478bd9Sstevel@tonic-gate /*
5617c478bd9Sstevel@tonic-gate * Handle options that need more things done after the
5627c478bd9Sstevel@tonic-gate * other side has acknowledged the option.
5637c478bd9Sstevel@tonic-gate */
5647c478bd9Sstevel@tonic-gate switch (option) {
5657c478bd9Sstevel@tonic-gate case TELOPT_LINEMODE:
5667c478bd9Sstevel@tonic-gate #ifdef KLUDGELINEMODE
5677c478bd9Sstevel@tonic-gate kludgelinemode = 0;
5687c478bd9Sstevel@tonic-gate send_do(TELOPT_SGA, 1);
5697c478bd9Sstevel@tonic-gate #endif
5707c478bd9Sstevel@tonic-gate set_my_state_will(option);
5717c478bd9Sstevel@tonic-gate slc_init();
5727c478bd9Sstevel@tonic-gate send_do(TELOPT_SGA, 0);
5737c478bd9Sstevel@tonic-gate return;
5747c478bd9Sstevel@tonic-gate }
5757c478bd9Sstevel@tonic-gate }
5767c478bd9Sstevel@tonic-gate }
5777c478bd9Sstevel@tonic-gate set_my_state_will(option);
5787c478bd9Sstevel@tonic-gate }
5797c478bd9Sstevel@tonic-gate
5807c478bd9Sstevel@tonic-gate static void
dontoption(option)5817c478bd9Sstevel@tonic-gate dontoption(option)
5827c478bd9Sstevel@tonic-gate int option;
5837c478bd9Sstevel@tonic-gate {
5847c478bd9Sstevel@tonic-gate
5857c478bd9Sstevel@tonic-gate if (will_wont_resp[option]) {
5867c478bd9Sstevel@tonic-gate --will_wont_resp[option];
5877c478bd9Sstevel@tonic-gate if (will_wont_resp[option] && my_state_is_wont(option))
5887c478bd9Sstevel@tonic-gate --will_wont_resp[option];
5897c478bd9Sstevel@tonic-gate }
5907c478bd9Sstevel@tonic-gate
5917c478bd9Sstevel@tonic-gate if ((will_wont_resp[option] == 0) && my_want_state_is_will(option)) {
5927c478bd9Sstevel@tonic-gate switch (option) {
5937c478bd9Sstevel@tonic-gate case TELOPT_LINEMODE:
5947c478bd9Sstevel@tonic-gate linemode = 0; /* put us back to the default state */
5957c478bd9Sstevel@tonic-gate break;
5967c478bd9Sstevel@tonic-gate #ifdef OLD_ENVIRON
5977c478bd9Sstevel@tonic-gate case TELOPT_NEW_ENVIRON:
5987c478bd9Sstevel@tonic-gate /*
5997c478bd9Sstevel@tonic-gate * The new environ option wasn't recognized, try
6007c478bd9Sstevel@tonic-gate * the old one.
6017c478bd9Sstevel@tonic-gate */
6027c478bd9Sstevel@tonic-gate send_will(TELOPT_OLD_ENVIRON, 1);
6037c478bd9Sstevel@tonic-gate telopt_environ = TELOPT_OLD_ENVIRON;
6047c478bd9Sstevel@tonic-gate break;
6057c478bd9Sstevel@tonic-gate #endif
6067c478bd9Sstevel@tonic-gate }
6077c478bd9Sstevel@tonic-gate /* we always accept a DONT */
6087c478bd9Sstevel@tonic-gate set_my_want_state_wont(option);
6097c478bd9Sstevel@tonic-gate if (my_state_is_will(option))
6107c478bd9Sstevel@tonic-gate send_wont(option, 0);
6117c478bd9Sstevel@tonic-gate setconnmode(0); /* Set new tty mode */
6127c478bd9Sstevel@tonic-gate }
6137c478bd9Sstevel@tonic-gate set_my_state_wont(option);
6147c478bd9Sstevel@tonic-gate }
6157c478bd9Sstevel@tonic-gate
6167c478bd9Sstevel@tonic-gate /*
6177c478bd9Sstevel@tonic-gate * Given a buffer returned by tgetent(), this routine will turn
6187c478bd9Sstevel@tonic-gate * the pipe seperated list of names in the buffer into an array
6197c478bd9Sstevel@tonic-gate * of pointers to null terminated names. We toss out any bad,
6207c478bd9Sstevel@tonic-gate * duplicate, or verbose names (names with spaces).
6217c478bd9Sstevel@tonic-gate */
6227c478bd9Sstevel@tonic-gate
6237c478bd9Sstevel@tonic-gate static char *name_unknown = "UNKNOWN";
6247c478bd9Sstevel@tonic-gate static char *unknown[] = { 0, 0 };
6257c478bd9Sstevel@tonic-gate
6267c478bd9Sstevel@tonic-gate static char **
mklist(buf,name)6277c478bd9Sstevel@tonic-gate mklist(buf, name)
6287c478bd9Sstevel@tonic-gate char *buf, *name;
6297c478bd9Sstevel@tonic-gate {
6307c478bd9Sstevel@tonic-gate register int n;
6317c478bd9Sstevel@tonic-gate register char c, *cp, **argvp, *cp2, **argv, **avt;
6327c478bd9Sstevel@tonic-gate
6337c478bd9Sstevel@tonic-gate if (name) {
6347c478bd9Sstevel@tonic-gate if (strlen(name) > 40u) {
6357c478bd9Sstevel@tonic-gate name = 0;
6367c478bd9Sstevel@tonic-gate unknown[0] = name_unknown;
6377c478bd9Sstevel@tonic-gate } else {
6387c478bd9Sstevel@tonic-gate unknown[0] = name;
6397c478bd9Sstevel@tonic-gate upcase(name);
6407c478bd9Sstevel@tonic-gate }
6417c478bd9Sstevel@tonic-gate } else
6427c478bd9Sstevel@tonic-gate unknown[0] = name_unknown;
6437c478bd9Sstevel@tonic-gate /*
6447c478bd9Sstevel@tonic-gate * Count up the number of names.
6457c478bd9Sstevel@tonic-gate */
6467c478bd9Sstevel@tonic-gate for (n = 1, cp = buf; *cp && *cp != ':'; cp++) {
6477c478bd9Sstevel@tonic-gate if (*cp == '|')
6487c478bd9Sstevel@tonic-gate n++;
6497c478bd9Sstevel@tonic-gate }
6507c478bd9Sstevel@tonic-gate /*
6517c478bd9Sstevel@tonic-gate * Allocate an array to put the name pointers into
6527c478bd9Sstevel@tonic-gate */
6537c478bd9Sstevel@tonic-gate argv = malloc((n+3)*sizeof (char *));
6547c478bd9Sstevel@tonic-gate if (argv == 0)
6557c478bd9Sstevel@tonic-gate return (unknown);
6567c478bd9Sstevel@tonic-gate
6577c478bd9Sstevel@tonic-gate /*
6587c478bd9Sstevel@tonic-gate * Fill up the array of pointers to names.
6597c478bd9Sstevel@tonic-gate */
6607c478bd9Sstevel@tonic-gate *argv = 0;
6617c478bd9Sstevel@tonic-gate argvp = argv+1;
6627c478bd9Sstevel@tonic-gate n = 0;
663*95c74518SToomas Soome for (cp = cp2 = buf; (c = *cp) != '\0'; cp++) {
6647c478bd9Sstevel@tonic-gate if (c == '|' || c == ':') {
6657c478bd9Sstevel@tonic-gate *cp++ = '\0';
6667c478bd9Sstevel@tonic-gate /*
6677c478bd9Sstevel@tonic-gate * Skip entries that have spaces or are over 40
6687c478bd9Sstevel@tonic-gate * characters long. If this is our environment
6697c478bd9Sstevel@tonic-gate * name, then put it up front. Otherwise, as
6707c478bd9Sstevel@tonic-gate * long as this is not a duplicate name (case
6717c478bd9Sstevel@tonic-gate * insensitive) add it to the list.
6727c478bd9Sstevel@tonic-gate */
6737c478bd9Sstevel@tonic-gate if (n || (cp - cp2 > 41))
6747c478bd9Sstevel@tonic-gate /* EMPTY */;
6757c478bd9Sstevel@tonic-gate else if (name && (strncasecmp(name, cp2, cp-cp2) == 0))
6767c478bd9Sstevel@tonic-gate *argv = cp2;
6777c478bd9Sstevel@tonic-gate else if (is_unique(cp2, argv+1, argvp))
6787c478bd9Sstevel@tonic-gate *argvp++ = cp2;
6797c478bd9Sstevel@tonic-gate if (c == ':')
6807c478bd9Sstevel@tonic-gate break;
6817c478bd9Sstevel@tonic-gate /*
6827c478bd9Sstevel@tonic-gate * Skip multiple delimiters. Reset cp2 to
6837c478bd9Sstevel@tonic-gate * the beginning of the next name. Reset n,
6847c478bd9Sstevel@tonic-gate * the flag for names with spaces.
6857c478bd9Sstevel@tonic-gate */
6867c478bd9Sstevel@tonic-gate while ((c = *cp) == '|')
6877c478bd9Sstevel@tonic-gate cp++;
6887c478bd9Sstevel@tonic-gate cp2 = cp;
6897c478bd9Sstevel@tonic-gate n = 0;
6907c478bd9Sstevel@tonic-gate }
6917c478bd9Sstevel@tonic-gate /*
6927c478bd9Sstevel@tonic-gate * Skip entries with spaces or non-ascii values.
6937c478bd9Sstevel@tonic-gate * Convert lower case letters to upper case.
6947c478bd9Sstevel@tonic-gate */
6957c478bd9Sstevel@tonic-gate if ((c == ' ') || !isascii(c))
6967c478bd9Sstevel@tonic-gate n = 1;
6977c478bd9Sstevel@tonic-gate else if (islower(c))
6987c478bd9Sstevel@tonic-gate *cp = toupper(c);
6997c478bd9Sstevel@tonic-gate }
7007c478bd9Sstevel@tonic-gate
7017c478bd9Sstevel@tonic-gate /*
7027c478bd9Sstevel@tonic-gate * Check for an old V6 2 character name. If the second
7037c478bd9Sstevel@tonic-gate * name points to the beginning of the buffer, and is
7047c478bd9Sstevel@tonic-gate * only 2 characters long, move it to the end of the array.
7057c478bd9Sstevel@tonic-gate */
7067c478bd9Sstevel@tonic-gate if ((argv[1] == buf) && (strlen(argv[1]) == 2)) {
7077c478bd9Sstevel@tonic-gate --argvp;
7087c478bd9Sstevel@tonic-gate for (avt = &argv[1]; avt < argvp; avt++)
7097c478bd9Sstevel@tonic-gate *avt = *(avt+1);
7107c478bd9Sstevel@tonic-gate *argvp++ = buf;
7117c478bd9Sstevel@tonic-gate }
7127c478bd9Sstevel@tonic-gate
7137c478bd9Sstevel@tonic-gate /*
7147c478bd9Sstevel@tonic-gate * Duplicate last name, for TTYPE option, and null
7157c478bd9Sstevel@tonic-gate * terminate the array. If we didn't find a match on
7167c478bd9Sstevel@tonic-gate * our terminal name, put that name at the beginning.
7177c478bd9Sstevel@tonic-gate */
7187c478bd9Sstevel@tonic-gate cp = *(argvp-1);
7197c478bd9Sstevel@tonic-gate *argvp++ = cp;
7207c478bd9Sstevel@tonic-gate *argvp = 0;
7217c478bd9Sstevel@tonic-gate
7227c478bd9Sstevel@tonic-gate if (*argv == 0) {
7237c478bd9Sstevel@tonic-gate if (name)
7247c478bd9Sstevel@tonic-gate *argv = name;
7257c478bd9Sstevel@tonic-gate else {
7267c478bd9Sstevel@tonic-gate --argvp;
7277c478bd9Sstevel@tonic-gate for (avt = argv; avt < argvp; avt++)
7287c478bd9Sstevel@tonic-gate *avt = *(avt+1);
7297c478bd9Sstevel@tonic-gate }
7307c478bd9Sstevel@tonic-gate }
7317c478bd9Sstevel@tonic-gate if (*argv)
7327c478bd9Sstevel@tonic-gate return (argv);
7337c478bd9Sstevel@tonic-gate else
7347c478bd9Sstevel@tonic-gate return (unknown);
7357c478bd9Sstevel@tonic-gate }
7367c478bd9Sstevel@tonic-gate
7377c478bd9Sstevel@tonic-gate static int
is_unique(name,as,ae)7387c478bd9Sstevel@tonic-gate is_unique(name, as, ae)
7397c478bd9Sstevel@tonic-gate register char *name, **as, **ae;
7407c478bd9Sstevel@tonic-gate {
7417c478bd9Sstevel@tonic-gate register char **ap;
7427c478bd9Sstevel@tonic-gate register int n;
7437c478bd9Sstevel@tonic-gate
7447c478bd9Sstevel@tonic-gate n = strlen(name) + 1;
7457c478bd9Sstevel@tonic-gate for (ap = as; ap < ae; ap++)
7467c478bd9Sstevel@tonic-gate if (strncasecmp(*ap, name, n) == 0)
7477c478bd9Sstevel@tonic-gate return (0);
7487c478bd9Sstevel@tonic-gate return (1);
7497c478bd9Sstevel@tonic-gate }
7507c478bd9Sstevel@tonic-gate
7517c478bd9Sstevel@tonic-gate #define termbuf ttytype
7527c478bd9Sstevel@tonic-gate extern char ttytype[];
7537c478bd9Sstevel@tonic-gate
7547c478bd9Sstevel@tonic-gate int resettermname = 1;
7557c478bd9Sstevel@tonic-gate
7567c478bd9Sstevel@tonic-gate static char *
gettermname(void)7577c478bd9Sstevel@tonic-gate gettermname(void)
7587c478bd9Sstevel@tonic-gate {
7597c478bd9Sstevel@tonic-gate char *tname;
7607c478bd9Sstevel@tonic-gate static char **tnamep = 0;
7617c478bd9Sstevel@tonic-gate static char **next;
7627c478bd9Sstevel@tonic-gate int err;
7637c478bd9Sstevel@tonic-gate
7647c478bd9Sstevel@tonic-gate if (resettermname) {
7657c478bd9Sstevel@tonic-gate resettermname = 0;
7667c478bd9Sstevel@tonic-gate if (tnamep && tnamep != unknown)
7677c478bd9Sstevel@tonic-gate free(tnamep);
7687c478bd9Sstevel@tonic-gate tname = (char *)env_getvalue((unsigned char *)"TERM");
7697c478bd9Sstevel@tonic-gate if ((tname != NULL) && (setupterm(tname, 1, &err) == 0)) {
7707c478bd9Sstevel@tonic-gate tnamep = mklist(termbuf, tname);
7717c478bd9Sstevel@tonic-gate } else {
7727c478bd9Sstevel@tonic-gate if (tname && (strlen(tname) <= 40u)) {
7737c478bd9Sstevel@tonic-gate unknown[0] = tname;
7747c478bd9Sstevel@tonic-gate upcase(tname);
7757c478bd9Sstevel@tonic-gate } else
7767c478bd9Sstevel@tonic-gate unknown[0] = name_unknown;
7777c478bd9Sstevel@tonic-gate tnamep = unknown;
7787c478bd9Sstevel@tonic-gate }
7797c478bd9Sstevel@tonic-gate next = tnamep;
7807c478bd9Sstevel@tonic-gate }
7817c478bd9Sstevel@tonic-gate if (*next == 0)
7827c478bd9Sstevel@tonic-gate next = tnamep;
7837c478bd9Sstevel@tonic-gate return (*next++);
7847c478bd9Sstevel@tonic-gate }
7857c478bd9Sstevel@tonic-gate /*
7867c478bd9Sstevel@tonic-gate * suboption()
7877c478bd9Sstevel@tonic-gate *
7887c478bd9Sstevel@tonic-gate * Look at the sub-option buffer, and try to be helpful to the other
7897c478bd9Sstevel@tonic-gate * side.
7907c478bd9Sstevel@tonic-gate *
7917c478bd9Sstevel@tonic-gate * Currently we recognize:
7927c478bd9Sstevel@tonic-gate *
7937c478bd9Sstevel@tonic-gate * Terminal type, send request.
7947c478bd9Sstevel@tonic-gate * Terminal speed (send request).
7957c478bd9Sstevel@tonic-gate * Local flow control (is request).
7967c478bd9Sstevel@tonic-gate * Linemode
7977c478bd9Sstevel@tonic-gate */
7987c478bd9Sstevel@tonic-gate
7997c478bd9Sstevel@tonic-gate static void
suboption()8007c478bd9Sstevel@tonic-gate suboption()
8017c478bd9Sstevel@tonic-gate {
8027c478bd9Sstevel@tonic-gate unsigned char subchar;
8037c478bd9Sstevel@tonic-gate
8047c478bd9Sstevel@tonic-gate printsub('<', subbuffer, SB_LEN()+2);
8057c478bd9Sstevel@tonic-gate switch (subchar = SB_GET()) {
8067c478bd9Sstevel@tonic-gate case TELOPT_TTYPE:
8077c478bd9Sstevel@tonic-gate if (my_want_state_is_wont(TELOPT_TTYPE))
8087c478bd9Sstevel@tonic-gate return;
8097c478bd9Sstevel@tonic-gate if (SB_EOF() || SB_GET() != TELQUAL_SEND) {
8107c478bd9Sstevel@tonic-gate return;
8117c478bd9Sstevel@tonic-gate } else {
8127c478bd9Sstevel@tonic-gate char *name;
8137c478bd9Sstevel@tonic-gate unsigned char temp[50];
8147c478bd9Sstevel@tonic-gate int len, bytes;
8157c478bd9Sstevel@tonic-gate
8167c478bd9Sstevel@tonic-gate name = gettermname();
8177c478bd9Sstevel@tonic-gate len = strlen(name) + 4 + 2;
8187c478bd9Sstevel@tonic-gate bytes = snprintf((char *)temp, sizeof (temp),
8197c478bd9Sstevel@tonic-gate "%c%c%c%c%s%c%c", IAC, SB,
8207c478bd9Sstevel@tonic-gate TELOPT_TTYPE, TELQUAL_IS, name, IAC, SE);
8217c478bd9Sstevel@tonic-gate if ((len < NETROOM()) && (bytes < sizeof (temp))) {
8227c478bd9Sstevel@tonic-gate ring_supply_data(&netoring, temp, len);
8237c478bd9Sstevel@tonic-gate printsub('>', &temp[2], len-2);
8247c478bd9Sstevel@tonic-gate } else {
8257c478bd9Sstevel@tonic-gate ExitString("No room in buffer for "
8267c478bd9Sstevel@tonic-gate "terminal type.\n", EXIT_FAILURE);
8277c478bd9Sstevel@tonic-gate /*NOTREACHED*/
8287c478bd9Sstevel@tonic-gate }
8297c478bd9Sstevel@tonic-gate }
8307c478bd9Sstevel@tonic-gate break;
8317c478bd9Sstevel@tonic-gate case TELOPT_TSPEED:
8327c478bd9Sstevel@tonic-gate if (my_want_state_is_wont(TELOPT_TSPEED))
8337c478bd9Sstevel@tonic-gate return;
8347c478bd9Sstevel@tonic-gate if (SB_EOF())
8357c478bd9Sstevel@tonic-gate return;
8367c478bd9Sstevel@tonic-gate if (SB_GET() == TELQUAL_SEND) {
8377c478bd9Sstevel@tonic-gate int ospeed, ispeed;
8387c478bd9Sstevel@tonic-gate unsigned char temp[50];
8397c478bd9Sstevel@tonic-gate int len, bytes;
8407c478bd9Sstevel@tonic-gate
8417c478bd9Sstevel@tonic-gate TerminalSpeeds(&ispeed, &ospeed);
8427c478bd9Sstevel@tonic-gate
8437c478bd9Sstevel@tonic-gate bytes = snprintf((char *)temp, sizeof (temp),
8447c478bd9Sstevel@tonic-gate "%c%c%c%c%d,%d%c%c", IAC, SB,
8457c478bd9Sstevel@tonic-gate TELOPT_TSPEED, TELQUAL_IS, ospeed, ispeed, IAC, SE);
8467c478bd9Sstevel@tonic-gate len = strlen((char *)temp+4) + 4; /* temp[3] is 0 ... */
8477c478bd9Sstevel@tonic-gate
8487c478bd9Sstevel@tonic-gate if ((len < NETROOM()) && (bytes < sizeof (temp))) {
8497c478bd9Sstevel@tonic-gate ring_supply_data(&netoring, temp, len);
8507c478bd9Sstevel@tonic-gate printsub('>', temp+2, len - 2);
8517c478bd9Sstevel@tonic-gate }
8527c478bd9Sstevel@tonic-gate else
8537c478bd9Sstevel@tonic-gate (void) printf(
8547c478bd9Sstevel@tonic-gate "telnet: not enough room in buffer "
8557c478bd9Sstevel@tonic-gate "for terminal speed option reply\n");
8567c478bd9Sstevel@tonic-gate }
8577c478bd9Sstevel@tonic-gate break;
8587c478bd9Sstevel@tonic-gate case TELOPT_LFLOW:
8597c478bd9Sstevel@tonic-gate if (my_want_state_is_wont(TELOPT_LFLOW))
8607c478bd9Sstevel@tonic-gate return;
8617c478bd9Sstevel@tonic-gate if (SB_EOF())
8627c478bd9Sstevel@tonic-gate return;
8637c478bd9Sstevel@tonic-gate switch (SB_GET()) {
8647c478bd9Sstevel@tonic-gate case LFLOW_RESTART_ANY:
8657c478bd9Sstevel@tonic-gate restartany = 1;
8667c478bd9Sstevel@tonic-gate break;
8677c478bd9Sstevel@tonic-gate case LFLOW_RESTART_XON:
8687c478bd9Sstevel@tonic-gate restartany = 0;
8697c478bd9Sstevel@tonic-gate break;
8707c478bd9Sstevel@tonic-gate case LFLOW_ON:
8717c478bd9Sstevel@tonic-gate localflow = 1;
8727c478bd9Sstevel@tonic-gate break;
8737c478bd9Sstevel@tonic-gate case LFLOW_OFF:
8747c478bd9Sstevel@tonic-gate localflow = 0;
8757c478bd9Sstevel@tonic-gate break;
8767c478bd9Sstevel@tonic-gate default:
8777c478bd9Sstevel@tonic-gate return;
8787c478bd9Sstevel@tonic-gate }
8797c478bd9Sstevel@tonic-gate setcommandmode();
8807c478bd9Sstevel@tonic-gate setconnmode(0);
8817c478bd9Sstevel@tonic-gate break;
8827c478bd9Sstevel@tonic-gate
8837c478bd9Sstevel@tonic-gate case TELOPT_LINEMODE:
8847c478bd9Sstevel@tonic-gate if (my_want_state_is_wont(TELOPT_LINEMODE))
8857c478bd9Sstevel@tonic-gate return;
8867c478bd9Sstevel@tonic-gate if (SB_EOF())
8877c478bd9Sstevel@tonic-gate return;
8887c478bd9Sstevel@tonic-gate switch (SB_GET()) {
8897c478bd9Sstevel@tonic-gate case WILL:
8907c478bd9Sstevel@tonic-gate lm_will(subpointer, SB_LEN());
8917c478bd9Sstevel@tonic-gate break;
8927c478bd9Sstevel@tonic-gate case WONT:
8937c478bd9Sstevel@tonic-gate lm_wont(subpointer, SB_LEN());
8947c478bd9Sstevel@tonic-gate break;
8957c478bd9Sstevel@tonic-gate case DO:
8967c478bd9Sstevel@tonic-gate lm_do(subpointer, SB_LEN());
8977c478bd9Sstevel@tonic-gate break;
8987c478bd9Sstevel@tonic-gate case DONT:
8997c478bd9Sstevel@tonic-gate lm_dont(subpointer, SB_LEN());
9007c478bd9Sstevel@tonic-gate break;
9017c478bd9Sstevel@tonic-gate case LM_SLC:
9027c478bd9Sstevel@tonic-gate slc(subpointer, SB_LEN());
9037c478bd9Sstevel@tonic-gate break;
9047c478bd9Sstevel@tonic-gate case LM_MODE:
9057c478bd9Sstevel@tonic-gate lm_mode(subpointer, SB_LEN(), 0);
9067c478bd9Sstevel@tonic-gate break;
9077c478bd9Sstevel@tonic-gate default:
9087c478bd9Sstevel@tonic-gate break;
9097c478bd9Sstevel@tonic-gate }
9107c478bd9Sstevel@tonic-gate break;
9117c478bd9Sstevel@tonic-gate
9127c478bd9Sstevel@tonic-gate #ifdef OLD_ENVIRON
9137c478bd9Sstevel@tonic-gate case TELOPT_OLD_ENVIRON:
9147c478bd9Sstevel@tonic-gate #endif
9157c478bd9Sstevel@tonic-gate case TELOPT_NEW_ENVIRON:
9167c478bd9Sstevel@tonic-gate if (SB_EOF())
9177c478bd9Sstevel@tonic-gate return;
9187c478bd9Sstevel@tonic-gate switch (SB_PEEK()) {
9197c478bd9Sstevel@tonic-gate case TELQUAL_IS:
9207c478bd9Sstevel@tonic-gate case TELQUAL_INFO:
9217c478bd9Sstevel@tonic-gate if (my_want_state_is_dont(subchar))
9227c478bd9Sstevel@tonic-gate return;
9237c478bd9Sstevel@tonic-gate break;
9247c478bd9Sstevel@tonic-gate case TELQUAL_SEND:
9257c478bd9Sstevel@tonic-gate if (my_want_state_is_wont(subchar)) {
9267c478bd9Sstevel@tonic-gate return;
9277c478bd9Sstevel@tonic-gate }
9287c478bd9Sstevel@tonic-gate break;
9297c478bd9Sstevel@tonic-gate default:
9307c478bd9Sstevel@tonic-gate return;
9317c478bd9Sstevel@tonic-gate }
9327c478bd9Sstevel@tonic-gate env_opt(subpointer, SB_LEN());
9337c478bd9Sstevel@tonic-gate break;
9347c478bd9Sstevel@tonic-gate
9357c478bd9Sstevel@tonic-gate case TELOPT_XDISPLOC:
9367c478bd9Sstevel@tonic-gate if (my_want_state_is_wont(TELOPT_XDISPLOC))
9377c478bd9Sstevel@tonic-gate return;
9387c478bd9Sstevel@tonic-gate if (SB_EOF())
9397c478bd9Sstevel@tonic-gate return;
9407c478bd9Sstevel@tonic-gate if (SB_GET() == TELQUAL_SEND) {
9417c478bd9Sstevel@tonic-gate unsigned char temp[50], *dp;
9427c478bd9Sstevel@tonic-gate int len, bytes;
9437c478bd9Sstevel@tonic-gate
9447c478bd9Sstevel@tonic-gate if ((dp = env_getvalue((unsigned char *)"DISPLAY")) ==
9457c478bd9Sstevel@tonic-gate NULL) {
9467c478bd9Sstevel@tonic-gate /*
9477c478bd9Sstevel@tonic-gate * Something happened, we no longer have a
9487c478bd9Sstevel@tonic-gate * DISPLAY variable. So, turn off the option.
9497c478bd9Sstevel@tonic-gate */
9507c478bd9Sstevel@tonic-gate send_wont(TELOPT_XDISPLOC, 1);
9517c478bd9Sstevel@tonic-gate break;
9527c478bd9Sstevel@tonic-gate }
9537c478bd9Sstevel@tonic-gate bytes = snprintf((char *)temp, sizeof (temp),
9547c478bd9Sstevel@tonic-gate "%c%c%c%c%s%c%c", IAC, SB,
9557c478bd9Sstevel@tonic-gate TELOPT_XDISPLOC, TELQUAL_IS, dp, IAC, SE);
9567c478bd9Sstevel@tonic-gate len = strlen((char *)temp+4) + 4; /* temp[3] is 0 ... */
9577c478bd9Sstevel@tonic-gate
9587c478bd9Sstevel@tonic-gate if ((len < NETROOM()) && (bytes < sizeof (temp))) {
9597c478bd9Sstevel@tonic-gate ring_supply_data(&netoring, temp, len);
9607c478bd9Sstevel@tonic-gate printsub('>', temp+2, len - 2);
9617c478bd9Sstevel@tonic-gate }
9627c478bd9Sstevel@tonic-gate else
9637c478bd9Sstevel@tonic-gate (void) printf(
9647c478bd9Sstevel@tonic-gate "telnet: not enough room in buffer"
9657c478bd9Sstevel@tonic-gate " for display location option reply\n");
9667c478bd9Sstevel@tonic-gate }
9677c478bd9Sstevel@tonic-gate break;
9687c478bd9Sstevel@tonic-gate
9697c478bd9Sstevel@tonic-gate case TELOPT_AUTHENTICATION: {
9707c478bd9Sstevel@tonic-gate if (!autologin)
9717c478bd9Sstevel@tonic-gate break;
9727c478bd9Sstevel@tonic-gate if (SB_EOF())
9737c478bd9Sstevel@tonic-gate return;
9747c478bd9Sstevel@tonic-gate switch (SB_GET()) {
9757c478bd9Sstevel@tonic-gate case TELQUAL_SEND:
9767c478bd9Sstevel@tonic-gate if (my_want_state_is_wont(TELOPT_AUTHENTICATION))
9777c478bd9Sstevel@tonic-gate return;
9787c478bd9Sstevel@tonic-gate auth_send(subpointer, SB_LEN());
9797c478bd9Sstevel@tonic-gate break;
9807c478bd9Sstevel@tonic-gate case TELQUAL_REPLY:
9817c478bd9Sstevel@tonic-gate if (my_want_state_is_wont(TELOPT_AUTHENTICATION))
9827c478bd9Sstevel@tonic-gate return;
9837c478bd9Sstevel@tonic-gate auth_reply(subpointer, SB_LEN());
9847c478bd9Sstevel@tonic-gate break;
9857c478bd9Sstevel@tonic-gate }
9867c478bd9Sstevel@tonic-gate }
9877c478bd9Sstevel@tonic-gate break;
9887c478bd9Sstevel@tonic-gate
9897c478bd9Sstevel@tonic-gate case TELOPT_ENCRYPT:
9907c478bd9Sstevel@tonic-gate if (SB_EOF())
9917c478bd9Sstevel@tonic-gate return;
9927c478bd9Sstevel@tonic-gate switch (SB_GET()) {
9937c478bd9Sstevel@tonic-gate case ENCRYPT_START:
9947c478bd9Sstevel@tonic-gate if (my_want_state_is_dont(TELOPT_ENCRYPT))
9957c478bd9Sstevel@tonic-gate return;
9967c478bd9Sstevel@tonic-gate encrypt_start(subpointer, SB_LEN());
9977c478bd9Sstevel@tonic-gate break;
9987c478bd9Sstevel@tonic-gate case ENCRYPT_END:
9997c478bd9Sstevel@tonic-gate if (my_want_state_is_dont(TELOPT_ENCRYPT))
10007c478bd9Sstevel@tonic-gate return;
10017c478bd9Sstevel@tonic-gate encrypt_end();
10027c478bd9Sstevel@tonic-gate break;
10037c478bd9Sstevel@tonic-gate case ENCRYPT_SUPPORT:
10047c478bd9Sstevel@tonic-gate if (my_want_state_is_wont(TELOPT_ENCRYPT))
10057c478bd9Sstevel@tonic-gate return;
10067c478bd9Sstevel@tonic-gate encrypt_support(subpointer, SB_LEN());
10077c478bd9Sstevel@tonic-gate break;
10087c478bd9Sstevel@tonic-gate case ENCRYPT_REQSTART:
10097c478bd9Sstevel@tonic-gate if (my_want_state_is_wont(TELOPT_ENCRYPT))
10107c478bd9Sstevel@tonic-gate return;
10117c478bd9Sstevel@tonic-gate encrypt_request_start(subpointer, SB_LEN());
10127c478bd9Sstevel@tonic-gate break;
10137c478bd9Sstevel@tonic-gate case ENCRYPT_REQEND:
10147c478bd9Sstevel@tonic-gate if (my_want_state_is_wont(TELOPT_ENCRYPT))
10157c478bd9Sstevel@tonic-gate return;
10167c478bd9Sstevel@tonic-gate /*
10177c478bd9Sstevel@tonic-gate * We can always send an REQEND so that we cannot
10187c478bd9Sstevel@tonic-gate * get stuck encrypting. We should only get this
10197c478bd9Sstevel@tonic-gate * if we have been able to get in the correct mode
10207c478bd9Sstevel@tonic-gate * anyhow.
10217c478bd9Sstevel@tonic-gate */
10227c478bd9Sstevel@tonic-gate encrypt_request_end();
10237c478bd9Sstevel@tonic-gate break;
10247c478bd9Sstevel@tonic-gate case ENCRYPT_IS:
10257c478bd9Sstevel@tonic-gate if (my_want_state_is_dont(TELOPT_ENCRYPT))
10267c478bd9Sstevel@tonic-gate return;
10277c478bd9Sstevel@tonic-gate encrypt_is(subpointer, SB_LEN());
10287c478bd9Sstevel@tonic-gate break;
10297c478bd9Sstevel@tonic-gate case ENCRYPT_REPLY:
10307c478bd9Sstevel@tonic-gate if (my_want_state_is_wont(TELOPT_ENCRYPT))
10317c478bd9Sstevel@tonic-gate return;
10327c478bd9Sstevel@tonic-gate encrypt_reply(subpointer, SB_LEN());
10337c478bd9Sstevel@tonic-gate break;
10347c478bd9Sstevel@tonic-gate case ENCRYPT_ENC_KEYID:
10357c478bd9Sstevel@tonic-gate if (my_want_state_is_dont(TELOPT_ENCRYPT))
10367c478bd9Sstevel@tonic-gate return;
10377c478bd9Sstevel@tonic-gate encrypt_enc_keyid(subpointer, SB_LEN());
10387c478bd9Sstevel@tonic-gate break;
10397c478bd9Sstevel@tonic-gate case ENCRYPT_DEC_KEYID:
10407c478bd9Sstevel@tonic-gate if (my_want_state_is_wont(TELOPT_ENCRYPT))
10417c478bd9Sstevel@tonic-gate return;
10427c478bd9Sstevel@tonic-gate encrypt_dec_keyid(subpointer, SB_LEN());
10437c478bd9Sstevel@tonic-gate break;
10447c478bd9Sstevel@tonic-gate default:
10457c478bd9Sstevel@tonic-gate break;
10467c478bd9Sstevel@tonic-gate }
10477c478bd9Sstevel@tonic-gate break;
10487c478bd9Sstevel@tonic-gate default:
10497c478bd9Sstevel@tonic-gate break;
10507c478bd9Sstevel@tonic-gate }
10517c478bd9Sstevel@tonic-gate }
10527c478bd9Sstevel@tonic-gate
10537c478bd9Sstevel@tonic-gate static unsigned char str_lm[] = { IAC, SB, TELOPT_LINEMODE, 0, 0, IAC, SE };
10547c478bd9Sstevel@tonic-gate
10557c478bd9Sstevel@tonic-gate static void
lm_will(cmd,len)10567c478bd9Sstevel@tonic-gate lm_will(cmd, len)
10577c478bd9Sstevel@tonic-gate unsigned char *cmd;
10587c478bd9Sstevel@tonic-gate int len;
10597c478bd9Sstevel@tonic-gate {
10607c478bd9Sstevel@tonic-gate if (len < 1) {
10617c478bd9Sstevel@tonic-gate /* Should not happen... */
10627c478bd9Sstevel@tonic-gate (void) printf(
10637c478bd9Sstevel@tonic-gate "telnet: command missing from linemode WILL request\n");
10647c478bd9Sstevel@tonic-gate return;
10657c478bd9Sstevel@tonic-gate }
10667c478bd9Sstevel@tonic-gate switch (cmd[0]) {
10677c478bd9Sstevel@tonic-gate case LM_FORWARDMASK: /* We shouldn't ever get this... */
10687c478bd9Sstevel@tonic-gate default:
10697c478bd9Sstevel@tonic-gate str_lm[3] = DONT;
10707c478bd9Sstevel@tonic-gate str_lm[4] = cmd[0];
10717c478bd9Sstevel@tonic-gate if (NETROOM() > sizeof (str_lm)) {
10727c478bd9Sstevel@tonic-gate ring_supply_data(&netoring, str_lm, sizeof (str_lm));
10737c478bd9Sstevel@tonic-gate printsub('>', &str_lm[2], sizeof (str_lm)-2);
10747c478bd9Sstevel@tonic-gate }
10757c478bd9Sstevel@tonic-gate else
10767c478bd9Sstevel@tonic-gate (void) printf("telnet: not enough room in buffer for"
10777c478bd9Sstevel@tonic-gate "reply to linemode WILL request\n");
10787c478bd9Sstevel@tonic-gate break;
10797c478bd9Sstevel@tonic-gate }
10807c478bd9Sstevel@tonic-gate }
10817c478bd9Sstevel@tonic-gate
10827c478bd9Sstevel@tonic-gate static void
lm_wont(cmd,len)10837c478bd9Sstevel@tonic-gate lm_wont(cmd, len)
10847c478bd9Sstevel@tonic-gate unsigned char *cmd;
10857c478bd9Sstevel@tonic-gate int len;
10867c478bd9Sstevel@tonic-gate {
10877c478bd9Sstevel@tonic-gate if (len < 1) {
10887c478bd9Sstevel@tonic-gate /* Should not happen... */
10897c478bd9Sstevel@tonic-gate (void) printf(
10907c478bd9Sstevel@tonic-gate "telnet: command missing from linemode WONT request\n");
10917c478bd9Sstevel@tonic-gate return;
10927c478bd9Sstevel@tonic-gate }
10937c478bd9Sstevel@tonic-gate switch (cmd[0]) {
10947c478bd9Sstevel@tonic-gate case LM_FORWARDMASK: /* We shouldn't ever get this... */
10957c478bd9Sstevel@tonic-gate default:
10967c478bd9Sstevel@tonic-gate /* We are always DONT, so don't respond */
10977c478bd9Sstevel@tonic-gate return;
10987c478bd9Sstevel@tonic-gate }
10997c478bd9Sstevel@tonic-gate }
11007c478bd9Sstevel@tonic-gate
11017c478bd9Sstevel@tonic-gate static void
lm_do(cmd,len)11027c478bd9Sstevel@tonic-gate lm_do(cmd, len)
11037c478bd9Sstevel@tonic-gate unsigned char *cmd;
11047c478bd9Sstevel@tonic-gate int len;
11057c478bd9Sstevel@tonic-gate {
11067c478bd9Sstevel@tonic-gate if (len < 1) {
11077c478bd9Sstevel@tonic-gate /* Should not happen... */
11087c478bd9Sstevel@tonic-gate (void) printf(
11097c478bd9Sstevel@tonic-gate "telnet: command missing from linemode DO request\n");
11107c478bd9Sstevel@tonic-gate return;
11117c478bd9Sstevel@tonic-gate }
11127c478bd9Sstevel@tonic-gate switch (cmd[0]) {
11137c478bd9Sstevel@tonic-gate case LM_FORWARDMASK:
11147c478bd9Sstevel@tonic-gate default:
11157c478bd9Sstevel@tonic-gate str_lm[3] = WONT;
11167c478bd9Sstevel@tonic-gate str_lm[4] = cmd[0];
11177c478bd9Sstevel@tonic-gate if (NETROOM() > sizeof (str_lm)) {
11187c478bd9Sstevel@tonic-gate ring_supply_data(&netoring, str_lm, sizeof (str_lm));
11197c478bd9Sstevel@tonic-gate printsub('>', &str_lm[2], sizeof (str_lm)-2);
11207c478bd9Sstevel@tonic-gate }
11217c478bd9Sstevel@tonic-gate else
11227c478bd9Sstevel@tonic-gate (void) printf("telnet: not enough room in buffer for"
11237c478bd9Sstevel@tonic-gate "reply to linemode DO request\n");
11247c478bd9Sstevel@tonic-gate break;
11257c478bd9Sstevel@tonic-gate }
11267c478bd9Sstevel@tonic-gate }
11277c478bd9Sstevel@tonic-gate
11287c478bd9Sstevel@tonic-gate static void
lm_dont(cmd,len)11297c478bd9Sstevel@tonic-gate lm_dont(cmd, len)
11307c478bd9Sstevel@tonic-gate unsigned char *cmd;
11317c478bd9Sstevel@tonic-gate int len;
11327c478bd9Sstevel@tonic-gate {
11337c478bd9Sstevel@tonic-gate if (len < 1) {
11347c478bd9Sstevel@tonic-gate /* Should not happen... */
11357c478bd9Sstevel@tonic-gate (void) printf(
11367c478bd9Sstevel@tonic-gate "telnet: command missing from linemode DONT request\n");
11377c478bd9Sstevel@tonic-gate return;
11387c478bd9Sstevel@tonic-gate }
11397c478bd9Sstevel@tonic-gate switch (cmd[0]) {
11407c478bd9Sstevel@tonic-gate case LM_FORWARDMASK:
11417c478bd9Sstevel@tonic-gate default:
11427c478bd9Sstevel@tonic-gate /* we are always WONT, so don't respond */
11437c478bd9Sstevel@tonic-gate break;
11447c478bd9Sstevel@tonic-gate }
11457c478bd9Sstevel@tonic-gate }
11467c478bd9Sstevel@tonic-gate
11477c478bd9Sstevel@tonic-gate static unsigned char str_lm_mode[] = {
11487c478bd9Sstevel@tonic-gate IAC, SB, TELOPT_LINEMODE, LM_MODE, 0, IAC, SE
11497c478bd9Sstevel@tonic-gate };
11507c478bd9Sstevel@tonic-gate
11517c478bd9Sstevel@tonic-gate void
lm_mode(cmd,len,init)11527c478bd9Sstevel@tonic-gate lm_mode(cmd, len, init)
11537c478bd9Sstevel@tonic-gate unsigned char *cmd;
11547c478bd9Sstevel@tonic-gate int len, init;
11557c478bd9Sstevel@tonic-gate {
11567c478bd9Sstevel@tonic-gate if (len != 1)
11577c478bd9Sstevel@tonic-gate return;
11587c478bd9Sstevel@tonic-gate if ((linemode&MODE_MASK&~MODE_ACK) == *cmd)
11597c478bd9Sstevel@tonic-gate return;
11607c478bd9Sstevel@tonic-gate linemode = *cmd&(MODE_MASK&~MODE_ACK);
11617c478bd9Sstevel@tonic-gate str_lm_mode[4] = linemode;
11627c478bd9Sstevel@tonic-gate if (!init)
11637c478bd9Sstevel@tonic-gate str_lm_mode[4] |= MODE_ACK;
11647c478bd9Sstevel@tonic-gate if (NETROOM() > sizeof (str_lm_mode)) {
11657c478bd9Sstevel@tonic-gate ring_supply_data(&netoring, str_lm_mode, sizeof (str_lm_mode));
11667c478bd9Sstevel@tonic-gate printsub('>', &str_lm_mode[2], sizeof (str_lm_mode)-2);
11677c478bd9Sstevel@tonic-gate }
11687c478bd9Sstevel@tonic-gate else
11697c478bd9Sstevel@tonic-gate (void) printf("telnet: not enough room in buffer for"
11707c478bd9Sstevel@tonic-gate "reply to linemode request\n");
11717c478bd9Sstevel@tonic-gate setconnmode(0); /* set changed mode */
11727c478bd9Sstevel@tonic-gate }
11737c478bd9Sstevel@tonic-gate
11747c478bd9Sstevel@tonic-gate
11757c478bd9Sstevel@tonic-gate
11767c478bd9Sstevel@tonic-gate /*
11777c478bd9Sstevel@tonic-gate * slc()
11787c478bd9Sstevel@tonic-gate * Handle special character suboption of LINEMODE.
11797c478bd9Sstevel@tonic-gate */
11807c478bd9Sstevel@tonic-gate
11817c478bd9Sstevel@tonic-gate static struct spc {
11827c478bd9Sstevel@tonic-gate cc_t val;
11837c478bd9Sstevel@tonic-gate cc_t *valp;
11847c478bd9Sstevel@tonic-gate char flags; /* Current flags & level */
11857c478bd9Sstevel@tonic-gate char mylevel; /* Maximum level & flags */
11867c478bd9Sstevel@tonic-gate } spc_data[NSLC+1];
11877c478bd9Sstevel@tonic-gate
11887c478bd9Sstevel@tonic-gate #define SLC_IMPORT 0
11897c478bd9Sstevel@tonic-gate #define SLC_EXPORT 1
11907c478bd9Sstevel@tonic-gate #define SLC_RVALUE 2
11917c478bd9Sstevel@tonic-gate static int slc_mode = SLC_EXPORT;
11927c478bd9Sstevel@tonic-gate
11937c478bd9Sstevel@tonic-gate static void
slc_init()11947c478bd9Sstevel@tonic-gate slc_init()
11957c478bd9Sstevel@tonic-gate {
11967c478bd9Sstevel@tonic-gate register struct spc *spcp;
11977c478bd9Sstevel@tonic-gate
11987c478bd9Sstevel@tonic-gate localchars = 1;
11997c478bd9Sstevel@tonic-gate for (spcp = spc_data; spcp < &spc_data[NSLC+1]; spcp++) {
12007c478bd9Sstevel@tonic-gate spcp->val = 0;
12017c478bd9Sstevel@tonic-gate spcp->valp = 0;
12027c478bd9Sstevel@tonic-gate spcp->flags = spcp->mylevel = SLC_NOSUPPORT;
12037c478bd9Sstevel@tonic-gate }
12047c478bd9Sstevel@tonic-gate
12057c478bd9Sstevel@tonic-gate #define initfunc(func, flags) { \
12067c478bd9Sstevel@tonic-gate spcp = &spc_data[func]; \
12077c478bd9Sstevel@tonic-gate if (spcp->valp = tcval(func)) { \
12087c478bd9Sstevel@tonic-gate spcp->val = *spcp->valp; \
12097c478bd9Sstevel@tonic-gate spcp->mylevel = SLC_VARIABLE|(flags);\
12107c478bd9Sstevel@tonic-gate } else { \
12117c478bd9Sstevel@tonic-gate spcp->val = 0; \
12127c478bd9Sstevel@tonic-gate spcp->mylevel = SLC_DEFAULT; \
12137c478bd9Sstevel@tonic-gate } \
12147c478bd9Sstevel@tonic-gate }
12157c478bd9Sstevel@tonic-gate
12167c478bd9Sstevel@tonic-gate initfunc(SLC_SYNCH, 0);
12177c478bd9Sstevel@tonic-gate /* No BRK */
12187c478bd9Sstevel@tonic-gate initfunc(SLC_AO, 0);
12197c478bd9Sstevel@tonic-gate initfunc(SLC_AYT, 0);
12207c478bd9Sstevel@tonic-gate /* No EOR */
12217c478bd9Sstevel@tonic-gate initfunc(SLC_ABORT, SLC_FLUSHIN|SLC_FLUSHOUT);
12227c478bd9Sstevel@tonic-gate initfunc(SLC_EOF, 0);
12237c478bd9Sstevel@tonic-gate initfunc(SLC_SUSP, SLC_FLUSHIN);
12247c478bd9Sstevel@tonic-gate initfunc(SLC_EC, 0);
12257c478bd9Sstevel@tonic-gate initfunc(SLC_EL, 0);
12267c478bd9Sstevel@tonic-gate initfunc(SLC_EW, 0);
12277c478bd9Sstevel@tonic-gate initfunc(SLC_RP, 0);
12287c478bd9Sstevel@tonic-gate initfunc(SLC_LNEXT, 0);
12297c478bd9Sstevel@tonic-gate initfunc(SLC_XON, 0);
12307c478bd9Sstevel@tonic-gate initfunc(SLC_XOFF, 0);
12317c478bd9Sstevel@tonic-gate initfunc(SLC_FORW1, 0);
12327c478bd9Sstevel@tonic-gate #ifdef USE_TERMIO
12337c478bd9Sstevel@tonic-gate initfunc(SLC_FORW2, 0);
12347c478bd9Sstevel@tonic-gate /* No FORW2 */
12357c478bd9Sstevel@tonic-gate #endif
12367c478bd9Sstevel@tonic-gate
12377c478bd9Sstevel@tonic-gate initfunc(SLC_IP, SLC_FLUSHIN|SLC_FLUSHOUT);
12387c478bd9Sstevel@tonic-gate #undef initfunc
12397c478bd9Sstevel@tonic-gate
12407c478bd9Sstevel@tonic-gate if (slc_mode == SLC_EXPORT)
12417c478bd9Sstevel@tonic-gate slc_export();
12427c478bd9Sstevel@tonic-gate else
12437c478bd9Sstevel@tonic-gate slc_import(1);
12447c478bd9Sstevel@tonic-gate
12457c478bd9Sstevel@tonic-gate }
12467c478bd9Sstevel@tonic-gate
12477c478bd9Sstevel@tonic-gate void
slcstate()12487c478bd9Sstevel@tonic-gate slcstate()
12497c478bd9Sstevel@tonic-gate {
12507c478bd9Sstevel@tonic-gate (void) printf("Special characters are %s values\n",
12517c478bd9Sstevel@tonic-gate slc_mode == SLC_IMPORT ? "remote default" :
12527c478bd9Sstevel@tonic-gate slc_mode == SLC_EXPORT ? "local" :
12537c478bd9Sstevel@tonic-gate "remote");
12547c478bd9Sstevel@tonic-gate }
12557c478bd9Sstevel@tonic-gate
12567c478bd9Sstevel@tonic-gate void
slc_mode_export()12577c478bd9Sstevel@tonic-gate slc_mode_export()
12587c478bd9Sstevel@tonic-gate {
12597c478bd9Sstevel@tonic-gate slc_mode = SLC_EXPORT;
12607c478bd9Sstevel@tonic-gate if (my_state_is_will(TELOPT_LINEMODE))
12617c478bd9Sstevel@tonic-gate slc_export();
12627c478bd9Sstevel@tonic-gate }
12637c478bd9Sstevel@tonic-gate
12647c478bd9Sstevel@tonic-gate void
slc_mode_import(def)12657c478bd9Sstevel@tonic-gate slc_mode_import(def)
12667c478bd9Sstevel@tonic-gate int def;
12677c478bd9Sstevel@tonic-gate {
12687c478bd9Sstevel@tonic-gate slc_mode = def ? SLC_IMPORT : SLC_RVALUE;
12697c478bd9Sstevel@tonic-gate if (my_state_is_will(TELOPT_LINEMODE))
12707c478bd9Sstevel@tonic-gate slc_import(def);
12717c478bd9Sstevel@tonic-gate }
12727c478bd9Sstevel@tonic-gate
12737c478bd9Sstevel@tonic-gate static unsigned char slc_import_val[] = {
12747c478bd9Sstevel@tonic-gate IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_VARIABLE, 0, IAC, SE
12757c478bd9Sstevel@tonic-gate };
12767c478bd9Sstevel@tonic-gate static unsigned char slc_import_def[] = {
12777c478bd9Sstevel@tonic-gate IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_DEFAULT, 0, IAC, SE
12787c478bd9Sstevel@tonic-gate };
12797c478bd9Sstevel@tonic-gate
12807c478bd9Sstevel@tonic-gate static void
slc_import(def)12817c478bd9Sstevel@tonic-gate slc_import(def)
12827c478bd9Sstevel@tonic-gate int def;
12837c478bd9Sstevel@tonic-gate {
12847c478bd9Sstevel@tonic-gate if (NETROOM() > sizeof (slc_import_val)) {
12857c478bd9Sstevel@tonic-gate if (def) {
12867c478bd9Sstevel@tonic-gate ring_supply_data(&netoring, slc_import_def,
12877c478bd9Sstevel@tonic-gate sizeof (slc_import_def));
12887c478bd9Sstevel@tonic-gate printsub('>', &slc_import_def[2],
12897c478bd9Sstevel@tonic-gate sizeof (slc_import_def)-2);
12907c478bd9Sstevel@tonic-gate } else {
12917c478bd9Sstevel@tonic-gate ring_supply_data(&netoring, slc_import_val,
12927c478bd9Sstevel@tonic-gate sizeof (slc_import_val));
12937c478bd9Sstevel@tonic-gate printsub('>', &slc_import_val[2],
12947c478bd9Sstevel@tonic-gate sizeof (slc_import_val)-2);
12957c478bd9Sstevel@tonic-gate }
12967c478bd9Sstevel@tonic-gate }
12977c478bd9Sstevel@tonic-gate else
12987c478bd9Sstevel@tonic-gate (void) printf(
12997c478bd9Sstevel@tonic-gate "telnet: not enough room in buffer for slc import"
13007c478bd9Sstevel@tonic-gate " request\n");
13017c478bd9Sstevel@tonic-gate }
13027c478bd9Sstevel@tonic-gate
13037c478bd9Sstevel@tonic-gate static uchar_t *slc_reply = NULL;
13047c478bd9Sstevel@tonic-gate static uchar_t *slc_replyp = NULL;
13057c478bd9Sstevel@tonic-gate /*
13067c478bd9Sstevel@tonic-gate * The SLC reply consists of: IAC, SB, TELOPT_LINEMODE, LM_SLC,
13077c478bd9Sstevel@tonic-gate * SLC triplets[], IAC, SE. i.e. it has a 'wrapper' of 6 control characters.
13087c478bd9Sstevel@tonic-gate */
13097c478bd9Sstevel@tonic-gate #define SLC_WRAPPER_SIZE 6
13107c478bd9Sstevel@tonic-gate
13117c478bd9Sstevel@tonic-gate static void
slc_export()13127c478bd9Sstevel@tonic-gate slc_export()
13137c478bd9Sstevel@tonic-gate {
13147c478bd9Sstevel@tonic-gate register struct spc *spcp;
13157c478bd9Sstevel@tonic-gate
13167c478bd9Sstevel@tonic-gate TerminalDefaultChars();
13177c478bd9Sstevel@tonic-gate
13187c478bd9Sstevel@tonic-gate slc_start_reply(NSLC * 3); /* 3 bytes needed per triplet */
13197c478bd9Sstevel@tonic-gate for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) {
13207c478bd9Sstevel@tonic-gate if (spcp->mylevel != SLC_NOSUPPORT) {
13217c478bd9Sstevel@tonic-gate if (spcp->val == (cc_t)(_POSIX_VDISABLE))
13227c478bd9Sstevel@tonic-gate spcp->flags = SLC_NOSUPPORT;
13237c478bd9Sstevel@tonic-gate else
13247c478bd9Sstevel@tonic-gate spcp->flags = spcp->mylevel;
13257c478bd9Sstevel@tonic-gate if (spcp->valp)
13267c478bd9Sstevel@tonic-gate spcp->val = *spcp->valp;
13277c478bd9Sstevel@tonic-gate slc_add_reply(spcp - spc_data, spcp->flags, spcp->val);
13287c478bd9Sstevel@tonic-gate }
13297c478bd9Sstevel@tonic-gate }
13307c478bd9Sstevel@tonic-gate slc_end_reply();
13317c478bd9Sstevel@tonic-gate (void) slc_update();
13327c478bd9Sstevel@tonic-gate setconnmode(1); /* Make sure the character values are set */
13337c478bd9Sstevel@tonic-gate }
13347c478bd9Sstevel@tonic-gate
13357c478bd9Sstevel@tonic-gate static void
slc(cp,len)13367c478bd9Sstevel@tonic-gate slc(cp, len)
13377c478bd9Sstevel@tonic-gate register unsigned char *cp;
13387c478bd9Sstevel@tonic-gate int len;
13397c478bd9Sstevel@tonic-gate {
13407c478bd9Sstevel@tonic-gate register struct spc *spcp;
13417c478bd9Sstevel@tonic-gate register int func, level;
13427c478bd9Sstevel@tonic-gate
13437c478bd9Sstevel@tonic-gate slc_start_reply(len);
13447c478bd9Sstevel@tonic-gate
13457c478bd9Sstevel@tonic-gate for (; len >= 3; len -= 3, cp += 3) {
13467c478bd9Sstevel@tonic-gate
13477c478bd9Sstevel@tonic-gate func = cp[SLC_FUNC];
13487c478bd9Sstevel@tonic-gate
13497c478bd9Sstevel@tonic-gate if (func == 0) {
13507c478bd9Sstevel@tonic-gate /*
13517c478bd9Sstevel@tonic-gate * Client side: always ignore 0 function.
13527c478bd9Sstevel@tonic-gate */
13537c478bd9Sstevel@tonic-gate continue;
13547c478bd9Sstevel@tonic-gate }
13557c478bd9Sstevel@tonic-gate if (func > NSLC) {
13567c478bd9Sstevel@tonic-gate if ((cp[SLC_FLAGS] & SLC_LEVELBITS) != SLC_NOSUPPORT)
13577c478bd9Sstevel@tonic-gate slc_add_reply(func, SLC_NOSUPPORT, 0);
13587c478bd9Sstevel@tonic-gate continue;
13597c478bd9Sstevel@tonic-gate }
13607c478bd9Sstevel@tonic-gate
13617c478bd9Sstevel@tonic-gate spcp = &spc_data[func];
13627c478bd9Sstevel@tonic-gate
13637c478bd9Sstevel@tonic-gate level = cp[SLC_FLAGS]&(SLC_LEVELBITS|SLC_ACK);
13647c478bd9Sstevel@tonic-gate
13657c478bd9Sstevel@tonic-gate if ((cp[SLC_VALUE] == (unsigned char)spcp->val) &&
13667c478bd9Sstevel@tonic-gate ((level&SLC_LEVELBITS) == (spcp->flags&SLC_LEVELBITS))) {
13677c478bd9Sstevel@tonic-gate continue;
13687c478bd9Sstevel@tonic-gate }
13697c478bd9Sstevel@tonic-gate
13707c478bd9Sstevel@tonic-gate if (level == (SLC_DEFAULT|SLC_ACK)) {
13717c478bd9Sstevel@tonic-gate /*
13727c478bd9Sstevel@tonic-gate * This is an error condition, the SLC_ACK
13737c478bd9Sstevel@tonic-gate * bit should never be set for the SLC_DEFAULT
13747c478bd9Sstevel@tonic-gate * level. Our best guess to recover is to
13757c478bd9Sstevel@tonic-gate * ignore the SLC_ACK bit.
13767c478bd9Sstevel@tonic-gate */
13777c478bd9Sstevel@tonic-gate cp[SLC_FLAGS] &= ~SLC_ACK;
13787c478bd9Sstevel@tonic-gate }
13797c478bd9Sstevel@tonic-gate
13807c478bd9Sstevel@tonic-gate if (level == ((spcp->flags&SLC_LEVELBITS)|SLC_ACK)) {
13817c478bd9Sstevel@tonic-gate spcp->val = (cc_t)cp[SLC_VALUE];
13827c478bd9Sstevel@tonic-gate spcp->flags = cp[SLC_FLAGS]; /* include SLC_ACK */
13837c478bd9Sstevel@tonic-gate continue;
13847c478bd9Sstevel@tonic-gate }
13857c478bd9Sstevel@tonic-gate
13867c478bd9Sstevel@tonic-gate level &= ~SLC_ACK;
13877c478bd9Sstevel@tonic-gate
13887c478bd9Sstevel@tonic-gate if (level <= (spcp->mylevel&SLC_LEVELBITS)) {
13897c478bd9Sstevel@tonic-gate spcp->flags = cp[SLC_FLAGS]|SLC_ACK;
13907c478bd9Sstevel@tonic-gate spcp->val = (cc_t)cp[SLC_VALUE];
13917c478bd9Sstevel@tonic-gate }
13927c478bd9Sstevel@tonic-gate if (level == SLC_DEFAULT) {
13937c478bd9Sstevel@tonic-gate if ((spcp->mylevel&SLC_LEVELBITS) != SLC_DEFAULT)
13947c478bd9Sstevel@tonic-gate spcp->flags = spcp->mylevel;
13957c478bd9Sstevel@tonic-gate else
13967c478bd9Sstevel@tonic-gate spcp->flags = SLC_NOSUPPORT;
13977c478bd9Sstevel@tonic-gate }
13987c478bd9Sstevel@tonic-gate slc_add_reply(func, spcp->flags, spcp->val);
13997c478bd9Sstevel@tonic-gate }
14007c478bd9Sstevel@tonic-gate slc_end_reply();
14017c478bd9Sstevel@tonic-gate if (slc_update())
14027c478bd9Sstevel@tonic-gate setconnmode(1); /* set the new character values */
14037c478bd9Sstevel@tonic-gate }
14047c478bd9Sstevel@tonic-gate
14057c478bd9Sstevel@tonic-gate void
slc_check()14067c478bd9Sstevel@tonic-gate slc_check()
14077c478bd9Sstevel@tonic-gate {
14087c478bd9Sstevel@tonic-gate register struct spc *spcp;
14097c478bd9Sstevel@tonic-gate
14107c478bd9Sstevel@tonic-gate slc_start_reply(NSLC * 3); /* 3 bytes needed per triplet */
14117c478bd9Sstevel@tonic-gate for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) {
14127c478bd9Sstevel@tonic-gate if (spcp->valp && spcp->val != *spcp->valp) {
14137c478bd9Sstevel@tonic-gate spcp->val = *spcp->valp;
14147c478bd9Sstevel@tonic-gate if (spcp->val == (cc_t)(_POSIX_VDISABLE))
14157c478bd9Sstevel@tonic-gate spcp->flags = SLC_NOSUPPORT;
14167c478bd9Sstevel@tonic-gate else
14177c478bd9Sstevel@tonic-gate spcp->flags = spcp->mylevel;
14187c478bd9Sstevel@tonic-gate slc_add_reply(spcp - spc_data, spcp->flags, spcp->val);
14197c478bd9Sstevel@tonic-gate }
14207c478bd9Sstevel@tonic-gate }
14217c478bd9Sstevel@tonic-gate slc_end_reply();
14227c478bd9Sstevel@tonic-gate setconnmode(1);
14237c478bd9Sstevel@tonic-gate }
14247c478bd9Sstevel@tonic-gate
14257c478bd9Sstevel@tonic-gate static void
slc_start_reply(size_t len)14267c478bd9Sstevel@tonic-gate slc_start_reply(size_t len)
14277c478bd9Sstevel@tonic-gate {
14287c478bd9Sstevel@tonic-gate /*
14297c478bd9Sstevel@tonic-gate * SLC triplets may contain escaped characters, allow for
14307c478bd9Sstevel@tonic-gate * worst case by allocating 2 bytes for every character.
14317c478bd9Sstevel@tonic-gate */
14327c478bd9Sstevel@tonic-gate slc_reply = realloc(slc_reply, (len * 2) + SLC_WRAPPER_SIZE);
14337c478bd9Sstevel@tonic-gate if (slc_reply == NULL) {
14347c478bd9Sstevel@tonic-gate fprintf(stderr, "telnet: error allocating SLC reply memory\n");
14357c478bd9Sstevel@tonic-gate return;
14367c478bd9Sstevel@tonic-gate }
14377c478bd9Sstevel@tonic-gate slc_replyp = slc_reply;
14387c478bd9Sstevel@tonic-gate *slc_replyp++ = IAC;
14397c478bd9Sstevel@tonic-gate *slc_replyp++ = SB;
14407c478bd9Sstevel@tonic-gate *slc_replyp++ = TELOPT_LINEMODE;
14417c478bd9Sstevel@tonic-gate *slc_replyp++ = LM_SLC;
14427c478bd9Sstevel@tonic-gate }
14437c478bd9Sstevel@tonic-gate
14447c478bd9Sstevel@tonic-gate static void
slc_add_reply(unsigned char func,unsigned char flags,cc_t value)14457c478bd9Sstevel@tonic-gate slc_add_reply(unsigned char func, unsigned char flags, cc_t value)
14467c478bd9Sstevel@tonic-gate {
14477c478bd9Sstevel@tonic-gate if ((*slc_replyp++ = func) == IAC)
14487c478bd9Sstevel@tonic-gate *slc_replyp++ = IAC;
14497c478bd9Sstevel@tonic-gate if ((*slc_replyp++ = flags) == IAC)
14507c478bd9Sstevel@tonic-gate *slc_replyp++ = IAC;
14517c478bd9Sstevel@tonic-gate if ((*slc_replyp++ = (unsigned char)value) == IAC)
14527c478bd9Sstevel@tonic-gate *slc_replyp++ = IAC;
14537c478bd9Sstevel@tonic-gate }
14547c478bd9Sstevel@tonic-gate
14557c478bd9Sstevel@tonic-gate static void
slc_end_reply()14567c478bd9Sstevel@tonic-gate slc_end_reply()
14577c478bd9Sstevel@tonic-gate {
14587c478bd9Sstevel@tonic-gate register int len;
14597c478bd9Sstevel@tonic-gate
14607c478bd9Sstevel@tonic-gate *slc_replyp++ = IAC;
14617c478bd9Sstevel@tonic-gate *slc_replyp++ = SE;
14627c478bd9Sstevel@tonic-gate len = slc_replyp - slc_reply;
14637c478bd9Sstevel@tonic-gate if (len <= SLC_WRAPPER_SIZE)
14647c478bd9Sstevel@tonic-gate return;
14657c478bd9Sstevel@tonic-gate if (NETROOM() > len) {
14667c478bd9Sstevel@tonic-gate ring_supply_data(&netoring, slc_reply, slc_replyp - slc_reply);
14677c478bd9Sstevel@tonic-gate printsub('>', &slc_reply[2], slc_replyp - slc_reply - 2);
14687c478bd9Sstevel@tonic-gate }
14697c478bd9Sstevel@tonic-gate else
14707c478bd9Sstevel@tonic-gate (void) printf("telnet: not enough room in buffer for slc end "
14717c478bd9Sstevel@tonic-gate "reply\n");
14727c478bd9Sstevel@tonic-gate }
14737c478bd9Sstevel@tonic-gate
14747c478bd9Sstevel@tonic-gate static int
slc_update()14757c478bd9Sstevel@tonic-gate slc_update()
14767c478bd9Sstevel@tonic-gate {
14777c478bd9Sstevel@tonic-gate register struct spc *spcp;
14787c478bd9Sstevel@tonic-gate int need_update = 0;
14797c478bd9Sstevel@tonic-gate
14807c478bd9Sstevel@tonic-gate for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) {
14817c478bd9Sstevel@tonic-gate if (!(spcp->flags&SLC_ACK))
14827c478bd9Sstevel@tonic-gate continue;
14837c478bd9Sstevel@tonic-gate spcp->flags &= ~SLC_ACK;
14847c478bd9Sstevel@tonic-gate if (spcp->valp && (*spcp->valp != spcp->val)) {
14857c478bd9Sstevel@tonic-gate *spcp->valp = spcp->val;
14867c478bd9Sstevel@tonic-gate need_update = 1;
14877c478bd9Sstevel@tonic-gate }
14887c478bd9Sstevel@tonic-gate }
14897c478bd9Sstevel@tonic-gate return (need_update);
14907c478bd9Sstevel@tonic-gate }
14917c478bd9Sstevel@tonic-gate
14927c478bd9Sstevel@tonic-gate #ifdef OLD_ENVIRON
14937c478bd9Sstevel@tonic-gate #ifdef ENV_HACK
14947c478bd9Sstevel@tonic-gate /*
14957c478bd9Sstevel@tonic-gate * Earlier version of telnet/telnetd from the BSD code had
14967c478bd9Sstevel@tonic-gate * the definitions of VALUE and VAR reversed. To ensure
14977c478bd9Sstevel@tonic-gate * maximum interoperability, we assume that the server is
14987c478bd9Sstevel@tonic-gate * an older BSD server, until proven otherwise. The newer
14997c478bd9Sstevel@tonic-gate * BSD servers should be able to handle either definition,
15007c478bd9Sstevel@tonic-gate * so it is better to use the wrong values if we don't
15017c478bd9Sstevel@tonic-gate * know what type of server it is.
15027c478bd9Sstevel@tonic-gate */
15037c478bd9Sstevel@tonic-gate int env_auto = 1;
15047c478bd9Sstevel@tonic-gate int old_env_var = OLD_ENV_VAR;
15057c478bd9Sstevel@tonic-gate int old_env_value = OLD_ENV_VALUE;
15067c478bd9Sstevel@tonic-gate #else
15077c478bd9Sstevel@tonic-gate #define old_env_var OLD_ENV_VAR
15087c478bd9Sstevel@tonic-gate #define old_env_value OLD_ENV_VALUE
15097c478bd9Sstevel@tonic-gate #endif
15107c478bd9Sstevel@tonic-gate #endif
15117c478bd9Sstevel@tonic-gate
15127c478bd9Sstevel@tonic-gate static void
env_opt(buf,len)15137c478bd9Sstevel@tonic-gate env_opt(buf, len)
15147c478bd9Sstevel@tonic-gate register unsigned char *buf;
15157c478bd9Sstevel@tonic-gate register int len;
15167c478bd9Sstevel@tonic-gate {
15177c478bd9Sstevel@tonic-gate register unsigned char *ep = 0, *epc = 0;
15187c478bd9Sstevel@tonic-gate register int i;
15197c478bd9Sstevel@tonic-gate
15207c478bd9Sstevel@tonic-gate switch (buf[0]&0xff) {
15217c478bd9Sstevel@tonic-gate case TELQUAL_SEND:
15227c478bd9Sstevel@tonic-gate env_opt_start();
15237c478bd9Sstevel@tonic-gate if (len == 1) {
15247c478bd9Sstevel@tonic-gate env_opt_add(NULL);
15257c478bd9Sstevel@tonic-gate } else for (i = 1; i < len; i++) {
15267c478bd9Sstevel@tonic-gate switch (buf[i]&0xff) {
15277c478bd9Sstevel@tonic-gate #ifdef OLD_ENVIRON
15287c478bd9Sstevel@tonic-gate case OLD_ENV_VAR:
15297c478bd9Sstevel@tonic-gate #ifdef ENV_HACK
15307c478bd9Sstevel@tonic-gate if (telopt_environ == TELOPT_OLD_ENVIRON &&
15317c478bd9Sstevel@tonic-gate env_auto) {
15327c478bd9Sstevel@tonic-gate /* Server has the same definitions */
15337c478bd9Sstevel@tonic-gate old_env_var = OLD_ENV_VAR;
15347c478bd9Sstevel@tonic-gate old_env_value = OLD_ENV_VALUE;
15357c478bd9Sstevel@tonic-gate }
15367c478bd9Sstevel@tonic-gate /* FALLTHROUGH */
15377c478bd9Sstevel@tonic-gate #endif
15387c478bd9Sstevel@tonic-gate case OLD_ENV_VALUE:
15397c478bd9Sstevel@tonic-gate /*
15407c478bd9Sstevel@tonic-gate * Although OLD_ENV_VALUE is not legal, we will
15417c478bd9Sstevel@tonic-gate * still recognize it, just in case it is an
15427c478bd9Sstevel@tonic-gate * old server that has VAR & VALUE mixed up...
15437c478bd9Sstevel@tonic-gate */
15447c478bd9Sstevel@tonic-gate /* FALLTHROUGH */
15457c478bd9Sstevel@tonic-gate #else
15467c478bd9Sstevel@tonic-gate case NEW_ENV_VAR:
15477c478bd9Sstevel@tonic-gate #endif
15487c478bd9Sstevel@tonic-gate case ENV_USERVAR:
15497c478bd9Sstevel@tonic-gate if (ep) {
15507c478bd9Sstevel@tonic-gate *epc = 0;
15517c478bd9Sstevel@tonic-gate env_opt_add(ep);
15527c478bd9Sstevel@tonic-gate }
15537c478bd9Sstevel@tonic-gate ep = epc = &buf[i+1];
15547c478bd9Sstevel@tonic-gate break;
15557c478bd9Sstevel@tonic-gate case ENV_ESC:
15567c478bd9Sstevel@tonic-gate i++;
15577c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/
15587c478bd9Sstevel@tonic-gate default:
15597c478bd9Sstevel@tonic-gate if (epc)
15607c478bd9Sstevel@tonic-gate *epc++ = buf[i];
15617c478bd9Sstevel@tonic-gate break;
15627c478bd9Sstevel@tonic-gate }
15637c478bd9Sstevel@tonic-gate }
15647c478bd9Sstevel@tonic-gate if (ep) {
15657c478bd9Sstevel@tonic-gate *epc = 0;
15667c478bd9Sstevel@tonic-gate env_opt_add(ep);
15677c478bd9Sstevel@tonic-gate }
15687c478bd9Sstevel@tonic-gate env_opt_end(1);
15697c478bd9Sstevel@tonic-gate break;
15707c478bd9Sstevel@tonic-gate
15717c478bd9Sstevel@tonic-gate case TELQUAL_IS:
15727c478bd9Sstevel@tonic-gate case TELQUAL_INFO:
15737c478bd9Sstevel@tonic-gate /* Ignore for now. We shouldn't get it anyway. */
15747c478bd9Sstevel@tonic-gate break;
15757c478bd9Sstevel@tonic-gate
15767c478bd9Sstevel@tonic-gate default:
15777c478bd9Sstevel@tonic-gate break;
15787c478bd9Sstevel@tonic-gate }
15797c478bd9Sstevel@tonic-gate }
15807c478bd9Sstevel@tonic-gate
15817c478bd9Sstevel@tonic-gate static unsigned char *opt_reply;
15827c478bd9Sstevel@tonic-gate static unsigned char *opt_replyp;
15837c478bd9Sstevel@tonic-gate static unsigned char *opt_replyend;
15847c478bd9Sstevel@tonic-gate #define OPT_REPLY_INITIAL_SIZE 256
15857c478bd9Sstevel@tonic-gate /*
15867c478bd9Sstevel@tonic-gate * The opt reply consists of: IAC, SB, telopt_environ, TELQUAL_IS,
15877c478bd9Sstevel@tonic-gate * value, IAC, SE. i.e. it has a 'wrapper' of 6 control characters.
15887c478bd9Sstevel@tonic-gate */
15897c478bd9Sstevel@tonic-gate #define OPT_WRAPPER_SIZE 6
15907c478bd9Sstevel@tonic-gate
15917c478bd9Sstevel@tonic-gate static void
env_opt_start()15927c478bd9Sstevel@tonic-gate env_opt_start()
15937c478bd9Sstevel@tonic-gate {
15947c478bd9Sstevel@tonic-gate opt_reply = realloc(opt_reply, OPT_REPLY_INITIAL_SIZE);
15957c478bd9Sstevel@tonic-gate if (opt_reply == NULL) {
15967c478bd9Sstevel@tonic-gate (void) printf(
15977c478bd9Sstevel@tonic-gate "telnet: error allocating environment option memory\n");
15987c478bd9Sstevel@tonic-gate opt_reply = opt_replyp = opt_replyend = NULL;
15997c478bd9Sstevel@tonic-gate return;
16007c478bd9Sstevel@tonic-gate }
16017c478bd9Sstevel@tonic-gate opt_replyp = opt_reply;
16027c478bd9Sstevel@tonic-gate opt_replyend = opt_reply + OPT_REPLY_INITIAL_SIZE;
16037c478bd9Sstevel@tonic-gate *opt_replyp++ = IAC;
16047c478bd9Sstevel@tonic-gate *opt_replyp++ = SB;
16057c478bd9Sstevel@tonic-gate *opt_replyp++ = telopt_environ;
16067c478bd9Sstevel@tonic-gate *opt_replyp++ = TELQUAL_IS;
16077c478bd9Sstevel@tonic-gate }
16087c478bd9Sstevel@tonic-gate
16097c478bd9Sstevel@tonic-gate void
env_opt_start_info()16107c478bd9Sstevel@tonic-gate env_opt_start_info()
16117c478bd9Sstevel@tonic-gate {
16127c478bd9Sstevel@tonic-gate env_opt_start();
16137c478bd9Sstevel@tonic-gate if (opt_replyp)
16147c478bd9Sstevel@tonic-gate opt_replyp[-1] = TELQUAL_INFO;
16157c478bd9Sstevel@tonic-gate }
16167c478bd9Sstevel@tonic-gate
16177c478bd9Sstevel@tonic-gate void
env_opt_add(ep)16187c478bd9Sstevel@tonic-gate env_opt_add(ep)
16197c478bd9Sstevel@tonic-gate register unsigned char *ep;
16207c478bd9Sstevel@tonic-gate {
16217c478bd9Sstevel@tonic-gate register unsigned char *vp, c;
16227c478bd9Sstevel@tonic-gate int opt_reply_size;
16237c478bd9Sstevel@tonic-gate int opt_reply_used;
16247c478bd9Sstevel@tonic-gate
16257c478bd9Sstevel@tonic-gate if (opt_reply == NULL) /* XXX */
16267c478bd9Sstevel@tonic-gate return; /* XXX */
16277c478bd9Sstevel@tonic-gate
16287c478bd9Sstevel@tonic-gate if (ep == NULL || *ep == '\0') {
16297c478bd9Sstevel@tonic-gate /* Send user defined variables first. */
16307c478bd9Sstevel@tonic-gate (void) env_default(1, 0);
16317c478bd9Sstevel@tonic-gate while (ep = env_default(0, 0))
16327c478bd9Sstevel@tonic-gate env_opt_add(ep);
16337c478bd9Sstevel@tonic-gate
16347c478bd9Sstevel@tonic-gate /* Now add the list of well know variables. */
16357c478bd9Sstevel@tonic-gate (void) env_default(1, 1);
16367c478bd9Sstevel@tonic-gate while (ep = env_default(0, 1))
16377c478bd9Sstevel@tonic-gate env_opt_add(ep);
16387c478bd9Sstevel@tonic-gate return;
16397c478bd9Sstevel@tonic-gate }
16407c478bd9Sstevel@tonic-gate vp = env_getvalue(ep);
16417c478bd9Sstevel@tonic-gate
16427c478bd9Sstevel@tonic-gate /*
16437c478bd9Sstevel@tonic-gate * Calculate space required for opt_reply and allocate more if required.
16447c478bd9Sstevel@tonic-gate * Assume worst case that every character is escaped, so needs 2 bytes.
16457c478bd9Sstevel@tonic-gate */
16467c478bd9Sstevel@tonic-gate opt_reply_used = opt_replyp - opt_reply; /* existing contents */
16477c478bd9Sstevel@tonic-gate opt_reply_size = opt_reply_used + OPT_WRAPPER_SIZE +
16487c478bd9Sstevel@tonic-gate (2 * (strlen((char *)ep))) +
16497c478bd9Sstevel@tonic-gate (vp == NULL ? 0 : (2 * strlen((char *)vp)));
16507c478bd9Sstevel@tonic-gate
16517c478bd9Sstevel@tonic-gate if (opt_reply_size > (opt_replyend - opt_reply)) {
16527c478bd9Sstevel@tonic-gate opt_reply = realloc(opt_reply, opt_reply_size);
16537c478bd9Sstevel@tonic-gate if (opt_reply == NULL) {
16547c478bd9Sstevel@tonic-gate (void) printf(
16557c478bd9Sstevel@tonic-gate "telnet: can't allocate environment option "
16567c478bd9Sstevel@tonic-gate "reply\n");
16577c478bd9Sstevel@tonic-gate opt_reply = opt_replyp = opt_replyend = NULL;
16587c478bd9Sstevel@tonic-gate return;
16597c478bd9Sstevel@tonic-gate }
16607c478bd9Sstevel@tonic-gate opt_replyp = opt_reply + opt_reply_used;
16617c478bd9Sstevel@tonic-gate opt_replyend = opt_reply + opt_reply_size;
16627c478bd9Sstevel@tonic-gate }
16637c478bd9Sstevel@tonic-gate
16647c478bd9Sstevel@tonic-gate if (opt_welldefined((char *)ep))
16657c478bd9Sstevel@tonic-gate #ifdef OLD_ENVIRON
16667c478bd9Sstevel@tonic-gate if (telopt_environ == TELOPT_OLD_ENVIRON)
16677c478bd9Sstevel@tonic-gate *opt_replyp++ = old_env_var;
16687c478bd9Sstevel@tonic-gate else
16697c478bd9Sstevel@tonic-gate #endif
16707c478bd9Sstevel@tonic-gate *opt_replyp++ = NEW_ENV_VAR;
16717c478bd9Sstevel@tonic-gate else
16727c478bd9Sstevel@tonic-gate *opt_replyp++ = ENV_USERVAR;
16737c478bd9Sstevel@tonic-gate for (;;) {
1674*95c74518SToomas Soome while ((c = *ep++) != '\0') {
16757c478bd9Sstevel@tonic-gate switch (c&0xff) {
16767c478bd9Sstevel@tonic-gate case IAC:
16777c478bd9Sstevel@tonic-gate *opt_replyp++ = IAC;
16787c478bd9Sstevel@tonic-gate break;
16797c478bd9Sstevel@tonic-gate case NEW_ENV_VAR:
16807c478bd9Sstevel@tonic-gate case NEW_ENV_VALUE:
16817c478bd9Sstevel@tonic-gate case ENV_ESC:
16827c478bd9Sstevel@tonic-gate case ENV_USERVAR:
16837c478bd9Sstevel@tonic-gate *opt_replyp++ = ENV_ESC;
16847c478bd9Sstevel@tonic-gate break;
16857c478bd9Sstevel@tonic-gate }
16867c478bd9Sstevel@tonic-gate *opt_replyp++ = c;
16877c478bd9Sstevel@tonic-gate }
16887c478bd9Sstevel@tonic-gate if ((ep = vp) != NULL) {
16897c478bd9Sstevel@tonic-gate #ifdef OLD_ENVIRON
16907c478bd9Sstevel@tonic-gate if (telopt_environ == TELOPT_OLD_ENVIRON)
16917c478bd9Sstevel@tonic-gate *opt_replyp++ = old_env_value;
16927c478bd9Sstevel@tonic-gate else
16937c478bd9Sstevel@tonic-gate #endif
16947c478bd9Sstevel@tonic-gate *opt_replyp++ = NEW_ENV_VALUE;
16957c478bd9Sstevel@tonic-gate vp = NULL;
16967c478bd9Sstevel@tonic-gate } else
16977c478bd9Sstevel@tonic-gate break;
16987c478bd9Sstevel@tonic-gate }
16997c478bd9Sstevel@tonic-gate }
17007c478bd9Sstevel@tonic-gate
17017c478bd9Sstevel@tonic-gate int
opt_welldefined(ep)17027c478bd9Sstevel@tonic-gate opt_welldefined(ep)
17037c478bd9Sstevel@tonic-gate char *ep;
17047c478bd9Sstevel@tonic-gate {
17057c478bd9Sstevel@tonic-gate if ((strcmp(ep, "USER") == 0) ||
17067c478bd9Sstevel@tonic-gate (strcmp(ep, "DISPLAY") == 0) ||
17077c478bd9Sstevel@tonic-gate (strcmp(ep, "PRINTER") == 0) ||
17087c478bd9Sstevel@tonic-gate (strcmp(ep, "SYSTEMTYPE") == 0) ||
17097c478bd9Sstevel@tonic-gate (strcmp(ep, "JOB") == 0) ||
17107c478bd9Sstevel@tonic-gate (strcmp(ep, "ACCT") == 0))
17117c478bd9Sstevel@tonic-gate return (1);
17127c478bd9Sstevel@tonic-gate return (0);
17137c478bd9Sstevel@tonic-gate }
17147c478bd9Sstevel@tonic-gate void
env_opt_end(emptyok)17157c478bd9Sstevel@tonic-gate env_opt_end(emptyok)
17167c478bd9Sstevel@tonic-gate register int emptyok;
17177c478bd9Sstevel@tonic-gate {
17187c478bd9Sstevel@tonic-gate register int len;
17197c478bd9Sstevel@tonic-gate
17207c478bd9Sstevel@tonic-gate len = opt_replyp - opt_reply + 2;
17217c478bd9Sstevel@tonic-gate if (emptyok || len > OPT_WRAPPER_SIZE) {
17227c478bd9Sstevel@tonic-gate *opt_replyp++ = IAC;
17237c478bd9Sstevel@tonic-gate *opt_replyp++ = SE;
17247c478bd9Sstevel@tonic-gate if (NETROOM() > len) {
17257c478bd9Sstevel@tonic-gate ring_supply_data(&netoring, opt_reply, len);
17267c478bd9Sstevel@tonic-gate printsub('>', &opt_reply[2], len - 2);
17277c478bd9Sstevel@tonic-gate }
17287c478bd9Sstevel@tonic-gate else
17297c478bd9Sstevel@tonic-gate (void) printf("telnet: not enough room in buffer for "
17307c478bd9Sstevel@tonic-gate "environment option end reply\n");
17317c478bd9Sstevel@tonic-gate }
17327c478bd9Sstevel@tonic-gate if (opt_reply) {
17337c478bd9Sstevel@tonic-gate free(opt_reply);
17347c478bd9Sstevel@tonic-gate opt_reply = opt_replyp = opt_replyend = NULL;
17357c478bd9Sstevel@tonic-gate }
17367c478bd9Sstevel@tonic-gate }
17377c478bd9Sstevel@tonic-gate
17387c478bd9Sstevel@tonic-gate
17397c478bd9Sstevel@tonic-gate
17407c478bd9Sstevel@tonic-gate int
telrcv()17417c478bd9Sstevel@tonic-gate telrcv()
17427c478bd9Sstevel@tonic-gate {
17437c478bd9Sstevel@tonic-gate register int c;
17447c478bd9Sstevel@tonic-gate register int scc;
17457c478bd9Sstevel@tonic-gate register unsigned char *sbp;
17467c478bd9Sstevel@tonic-gate int count;
17477c478bd9Sstevel@tonic-gate int returnValue = 0;
17487c478bd9Sstevel@tonic-gate int min_room = 0;
17497c478bd9Sstevel@tonic-gate
17507c478bd9Sstevel@tonic-gate scc = 0;
17517c478bd9Sstevel@tonic-gate count = 0;
17527c478bd9Sstevel@tonic-gate while (--min_room > 2 || (min_room = TTYROOM()) > 2) {
17537c478bd9Sstevel@tonic-gate if (scc == 0) {
17547c478bd9Sstevel@tonic-gate if (count) {
17557c478bd9Sstevel@tonic-gate ring_consumed(&netiring, count);
17567c478bd9Sstevel@tonic-gate returnValue = 1;
17577c478bd9Sstevel@tonic-gate count = 0;
17587c478bd9Sstevel@tonic-gate }
17597c478bd9Sstevel@tonic-gate sbp = netiring.consume;
17607c478bd9Sstevel@tonic-gate scc = ring_full_consecutive(&netiring);
17617c478bd9Sstevel@tonic-gate if (scc == 0) {
17627c478bd9Sstevel@tonic-gate /* No more data coming in */
17637c478bd9Sstevel@tonic-gate break;
17647c478bd9Sstevel@tonic-gate }
17657c478bd9Sstevel@tonic-gate }
17667c478bd9Sstevel@tonic-gate
17677c478bd9Sstevel@tonic-gate c = *sbp++ & 0xff, scc--; count++;
17687c478bd9Sstevel@tonic-gate
17697c478bd9Sstevel@tonic-gate if (decrypt_input)
17707c478bd9Sstevel@tonic-gate c = (*decrypt_input)(c);
17717c478bd9Sstevel@tonic-gate
17727c478bd9Sstevel@tonic-gate switch (telrcv_state) {
17737c478bd9Sstevel@tonic-gate
17747c478bd9Sstevel@tonic-gate case TS_CR:
17757c478bd9Sstevel@tonic-gate telrcv_state = TS_DATA;
17767c478bd9Sstevel@tonic-gate if (c == '\0') {
17777c478bd9Sstevel@tonic-gate break; /* Ignore \0 after CR */
17787c478bd9Sstevel@tonic-gate } else if ((c == '\n') &&
17797c478bd9Sstevel@tonic-gate my_want_state_is_dont(TELOPT_ECHO) && !crmod) {
17807c478bd9Sstevel@tonic-gate TTYADD(c);
17817c478bd9Sstevel@tonic-gate break;
17827c478bd9Sstevel@tonic-gate }
17837c478bd9Sstevel@tonic-gate /* FALLTHROUGH */
17847c478bd9Sstevel@tonic-gate
17857c478bd9Sstevel@tonic-gate case TS_DATA:
17867c478bd9Sstevel@tonic-gate if (c == IAC) {
17877c478bd9Sstevel@tonic-gate telrcv_state = TS_IAC;
17887c478bd9Sstevel@tonic-gate break;
17897c478bd9Sstevel@tonic-gate }
17907c478bd9Sstevel@tonic-gate /*
17917c478bd9Sstevel@tonic-gate * The 'crmod' hack (see following) is needed
17927c478bd9Sstevel@tonic-gate * since we can't * set CRMOD on output only.
17937c478bd9Sstevel@tonic-gate * Machines like MULTICS like to send \r without
17947c478bd9Sstevel@tonic-gate * \n; since we must turn off CRMOD to get proper
17957c478bd9Sstevel@tonic-gate * input, the mapping is done here (sigh).
17967c478bd9Sstevel@tonic-gate */
17977c478bd9Sstevel@tonic-gate if ((c == '\r') &&
17987c478bd9Sstevel@tonic-gate my_want_state_is_dont(TELOPT_BINARY)) {
17997c478bd9Sstevel@tonic-gate if (scc > 0) {
18007c478bd9Sstevel@tonic-gate c = *sbp&0xff;
18017c478bd9Sstevel@tonic-gate
18027c478bd9Sstevel@tonic-gate if (decrypt_input)
18037c478bd9Sstevel@tonic-gate c = (*decrypt_input)(c);
18047c478bd9Sstevel@tonic-gate
18057c478bd9Sstevel@tonic-gate if (c == 0) {
18067c478bd9Sstevel@tonic-gate sbp++, scc--; count++;
18077c478bd9Sstevel@tonic-gate /* a "true" CR */
18087c478bd9Sstevel@tonic-gate TTYADD('\r');
18097c478bd9Sstevel@tonic-gate } else if (my_want_state_is_dont(
18107c478bd9Sstevel@tonic-gate TELOPT_ECHO) && (c == '\n')) {
18117c478bd9Sstevel@tonic-gate sbp++, scc--; count++;
18127c478bd9Sstevel@tonic-gate TTYADD('\n');
18137c478bd9Sstevel@tonic-gate } else {
18147c478bd9Sstevel@tonic-gate
18157c478bd9Sstevel@tonic-gate if (decrypt_input)
18167c478bd9Sstevel@tonic-gate (*decrypt_input)(-1);
18177c478bd9Sstevel@tonic-gate
18187c478bd9Sstevel@tonic-gate TTYADD('\r');
18197c478bd9Sstevel@tonic-gate if (crmod) {
18207c478bd9Sstevel@tonic-gate TTYADD('\n');
18217c478bd9Sstevel@tonic-gate }
18227c478bd9Sstevel@tonic-gate }
18237c478bd9Sstevel@tonic-gate } else {
18247c478bd9Sstevel@tonic-gate telrcv_state = TS_CR;
18257c478bd9Sstevel@tonic-gate TTYADD('\r');
18267c478bd9Sstevel@tonic-gate if (crmod) {
18277c478bd9Sstevel@tonic-gate TTYADD('\n');
18287c478bd9Sstevel@tonic-gate }
18297c478bd9Sstevel@tonic-gate }
18307c478bd9Sstevel@tonic-gate } else {
18317c478bd9Sstevel@tonic-gate TTYADD(c);
18327c478bd9Sstevel@tonic-gate }
18337c478bd9Sstevel@tonic-gate continue;
18347c478bd9Sstevel@tonic-gate
18357c478bd9Sstevel@tonic-gate case TS_IAC:
18367c478bd9Sstevel@tonic-gate process_iac:
18377c478bd9Sstevel@tonic-gate switch (c) {
18387c478bd9Sstevel@tonic-gate
18397c478bd9Sstevel@tonic-gate case WILL:
18407c478bd9Sstevel@tonic-gate telrcv_state = TS_WILL;
18417c478bd9Sstevel@tonic-gate continue;
18427c478bd9Sstevel@tonic-gate
18437c478bd9Sstevel@tonic-gate case WONT:
18447c478bd9Sstevel@tonic-gate telrcv_state = TS_WONT;
18457c478bd9Sstevel@tonic-gate continue;
18467c478bd9Sstevel@tonic-gate
18477c478bd9Sstevel@tonic-gate case DO:
18487c478bd9Sstevel@tonic-gate telrcv_state = TS_DO;
18497c478bd9Sstevel@tonic-gate continue;
18507c478bd9Sstevel@tonic-gate
18517c478bd9Sstevel@tonic-gate case DONT:
18527c478bd9Sstevel@tonic-gate telrcv_state = TS_DONT;
18537c478bd9Sstevel@tonic-gate continue;
18547c478bd9Sstevel@tonic-gate
18557c478bd9Sstevel@tonic-gate case DM:
18567c478bd9Sstevel@tonic-gate /*
18577c478bd9Sstevel@tonic-gate * We may have missed an urgent notification,
18587c478bd9Sstevel@tonic-gate * so make sure we flush whatever is in the
18597c478bd9Sstevel@tonic-gate * buffer currently.
18607c478bd9Sstevel@tonic-gate */
18617c478bd9Sstevel@tonic-gate printoption("RCVD", IAC, DM);
18627c478bd9Sstevel@tonic-gate SYNCHing = 1;
18637c478bd9Sstevel@tonic-gate if (ttyflush(1) == -2) {
18647c478bd9Sstevel@tonic-gate /* This will not return. */
18657c478bd9Sstevel@tonic-gate fatal_tty_error("write");
18667c478bd9Sstevel@tonic-gate }
18677c478bd9Sstevel@tonic-gate SYNCHing = stilloob();
18687c478bd9Sstevel@tonic-gate settimer(gotDM);
18697c478bd9Sstevel@tonic-gate break;
18707c478bd9Sstevel@tonic-gate
18717c478bd9Sstevel@tonic-gate case SB:
18727c478bd9Sstevel@tonic-gate SB_CLEAR();
18737c478bd9Sstevel@tonic-gate telrcv_state = TS_SB;
18747c478bd9Sstevel@tonic-gate continue;
18757c478bd9Sstevel@tonic-gate
18767c478bd9Sstevel@tonic-gate case IAC:
18777c478bd9Sstevel@tonic-gate TTYADD(IAC);
18787c478bd9Sstevel@tonic-gate break;
18797c478bd9Sstevel@tonic-gate
18807c478bd9Sstevel@tonic-gate case NOP:
18817c478bd9Sstevel@tonic-gate case GA:
18827c478bd9Sstevel@tonic-gate default:
18837c478bd9Sstevel@tonic-gate printoption("RCVD", IAC, c);
18847c478bd9Sstevel@tonic-gate break;
18857c478bd9Sstevel@tonic-gate }
18867c478bd9Sstevel@tonic-gate telrcv_state = TS_DATA;
18877c478bd9Sstevel@tonic-gate continue;
18887c478bd9Sstevel@tonic-gate
18897c478bd9Sstevel@tonic-gate case TS_WILL:
18907c478bd9Sstevel@tonic-gate printoption("RCVD", WILL, c);
18917c478bd9Sstevel@tonic-gate willoption(c);
18927c478bd9Sstevel@tonic-gate telrcv_state = TS_DATA;
18937c478bd9Sstevel@tonic-gate continue;
18947c478bd9Sstevel@tonic-gate
18957c478bd9Sstevel@tonic-gate case TS_WONT:
18967c478bd9Sstevel@tonic-gate printoption("RCVD", WONT, c);
18977c478bd9Sstevel@tonic-gate wontoption(c);
18987c478bd9Sstevel@tonic-gate telrcv_state = TS_DATA;
18997c478bd9Sstevel@tonic-gate continue;
19007c478bd9Sstevel@tonic-gate
19017c478bd9Sstevel@tonic-gate case TS_DO:
19027c478bd9Sstevel@tonic-gate printoption("RCVD", DO, c);
19037c478bd9Sstevel@tonic-gate dooption(c);
19047c478bd9Sstevel@tonic-gate if (c == TELOPT_NAWS) {
19057c478bd9Sstevel@tonic-gate sendnaws();
19067c478bd9Sstevel@tonic-gate } else if (c == TELOPT_LFLOW) {
19077c478bd9Sstevel@tonic-gate localflow = 1;
19087c478bd9Sstevel@tonic-gate setcommandmode();
19097c478bd9Sstevel@tonic-gate setconnmode(0);
19107c478bd9Sstevel@tonic-gate }
19117c478bd9Sstevel@tonic-gate telrcv_state = TS_DATA;
19127c478bd9Sstevel@tonic-gate continue;
19137c478bd9Sstevel@tonic-gate
19147c478bd9Sstevel@tonic-gate case TS_DONT:
19157c478bd9Sstevel@tonic-gate printoption("RCVD", DONT, c);
19167c478bd9Sstevel@tonic-gate dontoption(c);
19177c478bd9Sstevel@tonic-gate flushline = 1;
19187c478bd9Sstevel@tonic-gate setconnmode(0); /* set new tty mode (maybe) */
19197c478bd9Sstevel@tonic-gate telrcv_state = TS_DATA;
19207c478bd9Sstevel@tonic-gate continue;
19217c478bd9Sstevel@tonic-gate
19227c478bd9Sstevel@tonic-gate case TS_SB:
19237c478bd9Sstevel@tonic-gate if (c == IAC) {
19247c478bd9Sstevel@tonic-gate telrcv_state = TS_SE;
19257c478bd9Sstevel@tonic-gate } else {
19267c478bd9Sstevel@tonic-gate SB_ACCUM(c);
19277c478bd9Sstevel@tonic-gate }
19287c478bd9Sstevel@tonic-gate continue;
19297c478bd9Sstevel@tonic-gate
19307c478bd9Sstevel@tonic-gate case TS_SE:
19317c478bd9Sstevel@tonic-gate if (c != SE) {
19327c478bd9Sstevel@tonic-gate if (c != IAC) {
19337c478bd9Sstevel@tonic-gate /*
19347c478bd9Sstevel@tonic-gate * This is an error. We only expect to get
19357c478bd9Sstevel@tonic-gate * "IAC IAC" or "IAC SE". Several things may
19367c478bd9Sstevel@tonic-gate * have happend. An IAC was not doubled, the
19377c478bd9Sstevel@tonic-gate * IAC SE was left off, or another option got
19387c478bd9Sstevel@tonic-gate * inserted into the suboption are all possibilities.
19397c478bd9Sstevel@tonic-gate * If we assume that the IAC was not doubled,
19407c478bd9Sstevel@tonic-gate * and really the IAC SE was left off, we could
19417c478bd9Sstevel@tonic-gate * get into an infinate loop here. So, instead,
19427c478bd9Sstevel@tonic-gate * we terminate the suboption, and process the
19437c478bd9Sstevel@tonic-gate * partial suboption if we can.
19447c478bd9Sstevel@tonic-gate */
19457c478bd9Sstevel@tonic-gate SB_ACCUM(IAC);
19467c478bd9Sstevel@tonic-gate SB_ACCUM(c);
19477c478bd9Sstevel@tonic-gate subpointer -= 2;
19487c478bd9Sstevel@tonic-gate SB_TERM();
19497c478bd9Sstevel@tonic-gate
19507c478bd9Sstevel@tonic-gate printoption("In SUBOPTION processing, "
19517c478bd9Sstevel@tonic-gate "RCVD", IAC, c);
19527c478bd9Sstevel@tonic-gate suboption(); /* handle sub-option */
19537c478bd9Sstevel@tonic-gate telrcv_state = TS_IAC;
19547c478bd9Sstevel@tonic-gate goto process_iac;
19557c478bd9Sstevel@tonic-gate }
19567c478bd9Sstevel@tonic-gate SB_ACCUM(c);
19577c478bd9Sstevel@tonic-gate telrcv_state = TS_SB;
19587c478bd9Sstevel@tonic-gate } else {
19597c478bd9Sstevel@tonic-gate SB_ACCUM(IAC);
19607c478bd9Sstevel@tonic-gate SB_ACCUM(SE);
19617c478bd9Sstevel@tonic-gate subpointer -= 2;
19627c478bd9Sstevel@tonic-gate SB_TERM();
19637c478bd9Sstevel@tonic-gate suboption(); /* handle sub-option */
19647c478bd9Sstevel@tonic-gate telrcv_state = TS_DATA;
19657c478bd9Sstevel@tonic-gate }
19667c478bd9Sstevel@tonic-gate }
19677c478bd9Sstevel@tonic-gate }
19687c478bd9Sstevel@tonic-gate if (count)
19697c478bd9Sstevel@tonic-gate ring_consumed(&netiring, count);
19707c478bd9Sstevel@tonic-gate return (returnValue||count);
19717c478bd9Sstevel@tonic-gate }
19727c478bd9Sstevel@tonic-gate
19737c478bd9Sstevel@tonic-gate static int bol = 1, local = 0;
19747c478bd9Sstevel@tonic-gate
19757c478bd9Sstevel@tonic-gate int
rlogin_susp()19767c478bd9Sstevel@tonic-gate rlogin_susp()
19777c478bd9Sstevel@tonic-gate {
19787c478bd9Sstevel@tonic-gate if (local) {
19797c478bd9Sstevel@tonic-gate local = 0;
19807c478bd9Sstevel@tonic-gate bol = 1;
19817c478bd9Sstevel@tonic-gate command(0, "z\n", 2);
19827c478bd9Sstevel@tonic-gate return (1);
19837c478bd9Sstevel@tonic-gate }
19847c478bd9Sstevel@tonic-gate return (0);
19857c478bd9Sstevel@tonic-gate }
19867c478bd9Sstevel@tonic-gate
19877c478bd9Sstevel@tonic-gate static int
telsnd()19887c478bd9Sstevel@tonic-gate telsnd()
19897c478bd9Sstevel@tonic-gate {
19907c478bd9Sstevel@tonic-gate int tcc;
19917c478bd9Sstevel@tonic-gate int count;
19927c478bd9Sstevel@tonic-gate int returnValue = 0;
19937c478bd9Sstevel@tonic-gate unsigned char *tbp;
19947c478bd9Sstevel@tonic-gate
19957c478bd9Sstevel@tonic-gate tcc = 0;
19967c478bd9Sstevel@tonic-gate count = 0;
19977c478bd9Sstevel@tonic-gate while (NETROOM() > 2) {
19987c478bd9Sstevel@tonic-gate register int sc;
19997c478bd9Sstevel@tonic-gate register int c;
20007c478bd9Sstevel@tonic-gate
20017c478bd9Sstevel@tonic-gate if (tcc == 0) {
20027c478bd9Sstevel@tonic-gate if (count) {
20037c478bd9Sstevel@tonic-gate ring_consumed(&ttyiring, count);
20047c478bd9Sstevel@tonic-gate returnValue = 1;
20057c478bd9Sstevel@tonic-gate count = 0;
20067c478bd9Sstevel@tonic-gate }
20077c478bd9Sstevel@tonic-gate tbp = ttyiring.consume;
20087c478bd9Sstevel@tonic-gate tcc = ring_full_consecutive(&ttyiring);
20097c478bd9Sstevel@tonic-gate if (tcc == 0) {
20107c478bd9Sstevel@tonic-gate break;
20117c478bd9Sstevel@tonic-gate }
20127c478bd9Sstevel@tonic-gate }
20137c478bd9Sstevel@tonic-gate c = *tbp++ & 0xff, sc = strip(c), tcc--; count++;
20147c478bd9Sstevel@tonic-gate if (rlogin != _POSIX_VDISABLE) {
20157c478bd9Sstevel@tonic-gate if (bol) {
20167c478bd9Sstevel@tonic-gate bol = 0;
20177c478bd9Sstevel@tonic-gate if (sc == rlogin) {
20187c478bd9Sstevel@tonic-gate local = 1;
20197c478bd9Sstevel@tonic-gate continue;
20207c478bd9Sstevel@tonic-gate }
20217c478bd9Sstevel@tonic-gate } else if (local) {
20227c478bd9Sstevel@tonic-gate local = 0;
20237c478bd9Sstevel@tonic-gate if (sc == '.' || c == termEofChar) {
20247c478bd9Sstevel@tonic-gate bol = 1;
20257c478bd9Sstevel@tonic-gate command(0, "close\n", 6);
20267c478bd9Sstevel@tonic-gate continue;
20277c478bd9Sstevel@tonic-gate }
20287c478bd9Sstevel@tonic-gate if (sc == termSuspChar) {
20297c478bd9Sstevel@tonic-gate bol = 1;
20307c478bd9Sstevel@tonic-gate command(0, "z\n", 2);
20317c478bd9Sstevel@tonic-gate continue;
20327c478bd9Sstevel@tonic-gate }
20337c478bd9Sstevel@tonic-gate if (sc == escape) {
20347c478bd9Sstevel@tonic-gate command(0, (char *)tbp, tcc);
20357c478bd9Sstevel@tonic-gate bol = 1;
20367c478bd9Sstevel@tonic-gate count += tcc;
20377c478bd9Sstevel@tonic-gate tcc = 0;
20387c478bd9Sstevel@tonic-gate flushline = 1;
20397c478bd9Sstevel@tonic-gate break;
20407c478bd9Sstevel@tonic-gate }
20417c478bd9Sstevel@tonic-gate if (sc != rlogin) {
20427c478bd9Sstevel@tonic-gate ++tcc;
20437c478bd9Sstevel@tonic-gate --tbp;
20447c478bd9Sstevel@tonic-gate --count;
20457c478bd9Sstevel@tonic-gate c = sc = rlogin;
20467c478bd9Sstevel@tonic-gate }
20477c478bd9Sstevel@tonic-gate }
20487c478bd9Sstevel@tonic-gate if ((sc == '\n') || (sc == '\r'))
20497c478bd9Sstevel@tonic-gate bol = 1;
20507c478bd9Sstevel@tonic-gate } else if (sc == escape && escape_valid) {
20517c478bd9Sstevel@tonic-gate /*
20527c478bd9Sstevel@tonic-gate * Double escape is a pass through of a single
20537c478bd9Sstevel@tonic-gate * escape character.
20547c478bd9Sstevel@tonic-gate */
20557c478bd9Sstevel@tonic-gate if (tcc && strip(*tbp) == escape) {
20567c478bd9Sstevel@tonic-gate tbp++;
20577c478bd9Sstevel@tonic-gate tcc--;
20587c478bd9Sstevel@tonic-gate count++;
20597c478bd9Sstevel@tonic-gate bol = 0;
20607c478bd9Sstevel@tonic-gate } else {
20617c478bd9Sstevel@tonic-gate command(0, (char *)tbp, tcc);
20627c478bd9Sstevel@tonic-gate bol = 1;
20637c478bd9Sstevel@tonic-gate count += tcc;
20647c478bd9Sstevel@tonic-gate tcc = 0;
20657c478bd9Sstevel@tonic-gate flushline = 1;
20667c478bd9Sstevel@tonic-gate break;
20677c478bd9Sstevel@tonic-gate }
20687c478bd9Sstevel@tonic-gate } else
20697c478bd9Sstevel@tonic-gate bol = 0;
20707c478bd9Sstevel@tonic-gate #ifdef KLUDGELINEMODE
20717c478bd9Sstevel@tonic-gate if (kludgelinemode && (globalmode&MODE_EDIT) && (sc == echoc)) {
20727c478bd9Sstevel@tonic-gate if (tcc > 0 && strip(*tbp) == echoc) {
20737c478bd9Sstevel@tonic-gate tcc--; tbp++; count++;
20747c478bd9Sstevel@tonic-gate } else {
20757c478bd9Sstevel@tonic-gate dontlecho = !dontlecho;
20767c478bd9Sstevel@tonic-gate settimer(echotoggle);
20777c478bd9Sstevel@tonic-gate setconnmode(0);
20787c478bd9Sstevel@tonic-gate flushline = 1;
20797c478bd9Sstevel@tonic-gate break;
20807c478bd9Sstevel@tonic-gate }
20817c478bd9Sstevel@tonic-gate }
20827c478bd9Sstevel@tonic-gate #endif
20837c478bd9Sstevel@tonic-gate if (MODE_LOCAL_CHARS(globalmode)) {
20847c478bd9Sstevel@tonic-gate if (TerminalSpecialChars(sc) == 0) {
20857c478bd9Sstevel@tonic-gate bol = 1;
20867c478bd9Sstevel@tonic-gate break;
20877c478bd9Sstevel@tonic-gate }
20887c478bd9Sstevel@tonic-gate }
20897c478bd9Sstevel@tonic-gate if (my_want_state_is_wont(TELOPT_BINARY)) {
20907c478bd9Sstevel@tonic-gate switch (c) {
20917c478bd9Sstevel@tonic-gate case '\n':
20927c478bd9Sstevel@tonic-gate /*
20937c478bd9Sstevel@tonic-gate * If we are in CRMOD mode (\r ==> \n)
20947c478bd9Sstevel@tonic-gate * on our local machine, then probably
20957c478bd9Sstevel@tonic-gate * a newline (unix) is CRLF (TELNET).
20967c478bd9Sstevel@tonic-gate */
20977c478bd9Sstevel@tonic-gate if (MODE_LOCAL_CHARS(globalmode)) {
20987c478bd9Sstevel@tonic-gate NETADD('\r');
20997c478bd9Sstevel@tonic-gate }
21007c478bd9Sstevel@tonic-gate NETADD('\n');
21017c478bd9Sstevel@tonic-gate bol = flushline = 1;
21027c478bd9Sstevel@tonic-gate break;
21037c478bd9Sstevel@tonic-gate case '\r':
21047c478bd9Sstevel@tonic-gate if (!crlf) {
21057c478bd9Sstevel@tonic-gate NET2ADD('\r', '\0');
21067c478bd9Sstevel@tonic-gate } else {
21077c478bd9Sstevel@tonic-gate NET2ADD('\r', '\n');
21087c478bd9Sstevel@tonic-gate }
21097c478bd9Sstevel@tonic-gate bol = flushline = 1;
21107c478bd9Sstevel@tonic-gate break;
21117c478bd9Sstevel@tonic-gate case IAC:
21127c478bd9Sstevel@tonic-gate NET2ADD(IAC, IAC);
21137c478bd9Sstevel@tonic-gate break;
21147c478bd9Sstevel@tonic-gate default:
21157c478bd9Sstevel@tonic-gate NETADD(c);
21167c478bd9Sstevel@tonic-gate break;
21177c478bd9Sstevel@tonic-gate }
21187c478bd9Sstevel@tonic-gate } else if (c == IAC) {
21197c478bd9Sstevel@tonic-gate NET2ADD(IAC, IAC);
21207c478bd9Sstevel@tonic-gate } else {
21217c478bd9Sstevel@tonic-gate NETADD(c);
21227c478bd9Sstevel@tonic-gate }
21237c478bd9Sstevel@tonic-gate }
21247c478bd9Sstevel@tonic-gate if (count)
21257c478bd9Sstevel@tonic-gate ring_consumed(&ttyiring, count);
21267c478bd9Sstevel@tonic-gate return (returnValue||count); /* Non-zero if we did anything */
21277c478bd9Sstevel@tonic-gate }
21287c478bd9Sstevel@tonic-gate
21297c478bd9Sstevel@tonic-gate /*
21307c478bd9Sstevel@tonic-gate * Scheduler()
21317c478bd9Sstevel@tonic-gate *
21327c478bd9Sstevel@tonic-gate * Try to do something.
21337c478bd9Sstevel@tonic-gate *
21347c478bd9Sstevel@tonic-gate * If we do something useful, return 1; else return 0.
21357c478bd9Sstevel@tonic-gate *
21367c478bd9Sstevel@tonic-gate */
21377c478bd9Sstevel@tonic-gate
21387c478bd9Sstevel@tonic-gate
21397c478bd9Sstevel@tonic-gate int
Scheduler(block)21407c478bd9Sstevel@tonic-gate Scheduler(block)
21417c478bd9Sstevel@tonic-gate int block; /* should we block in the select ? */
21427c478bd9Sstevel@tonic-gate {
21437c478bd9Sstevel@tonic-gate /*
21447c478bd9Sstevel@tonic-gate * One wants to be a bit careful about setting returnValue
21457c478bd9Sstevel@tonic-gate * to one, since a one implies we did some useful work,
21467c478bd9Sstevel@tonic-gate * and therefore probably won't be called to block next
21477c478bd9Sstevel@tonic-gate * time (TN3270 mode only).
21487c478bd9Sstevel@tonic-gate */
21497c478bd9Sstevel@tonic-gate int returnValue;
21507c478bd9Sstevel@tonic-gate int netin, netout, netex, ttyin, ttyout;
21517c478bd9Sstevel@tonic-gate
21527c478bd9Sstevel@tonic-gate /* Decide which rings should be processed */
21537c478bd9Sstevel@tonic-gate
21547c478bd9Sstevel@tonic-gate netout = ring_full_count(&netoring) &&
21557c478bd9Sstevel@tonic-gate (flushline ||
21567c478bd9Sstevel@tonic-gate (my_want_state_is_wont(TELOPT_LINEMODE)
21577c478bd9Sstevel@tonic-gate #ifdef KLUDGELINEMODE
21587c478bd9Sstevel@tonic-gate /* X */ && (!kludgelinemode || my_want_state_is_do(TELOPT_SGA))
21597c478bd9Sstevel@tonic-gate #endif
21607c478bd9Sstevel@tonic-gate /* XXX */) ||
21617c478bd9Sstevel@tonic-gate my_want_state_is_will(TELOPT_BINARY));
21627c478bd9Sstevel@tonic-gate ttyout = ring_full_count(&ttyoring);
21637c478bd9Sstevel@tonic-gate
21647c478bd9Sstevel@tonic-gate ttyin = (ring_empty_count(&ttyiring) && !eof_pending);
21657c478bd9Sstevel@tonic-gate
21667c478bd9Sstevel@tonic-gate netin = !ISend && ring_empty_count(&netiring);
21677c478bd9Sstevel@tonic-gate
21687c478bd9Sstevel@tonic-gate netex = !SYNCHing;
21697c478bd9Sstevel@tonic-gate
21707c478bd9Sstevel@tonic-gate if (scheduler_lockout_tty) {
21717c478bd9Sstevel@tonic-gate ttyin = ttyout = 0;
21727c478bd9Sstevel@tonic-gate }
21737c478bd9Sstevel@tonic-gate
21747c478bd9Sstevel@tonic-gate /* Call to system code to process rings */
21757c478bd9Sstevel@tonic-gate
21767c478bd9Sstevel@tonic-gate returnValue = process_rings(netin, netout, netex, ttyin, ttyout,
21777c478bd9Sstevel@tonic-gate !block);
21787c478bd9Sstevel@tonic-gate
21797c478bd9Sstevel@tonic-gate /* Now, look at the input rings, looking for work to do. */
21807c478bd9Sstevel@tonic-gate
21817c478bd9Sstevel@tonic-gate if (ring_full_count(&ttyiring)) {
21827c478bd9Sstevel@tonic-gate returnValue |= telsnd();
21837c478bd9Sstevel@tonic-gate } else {
21847c478bd9Sstevel@tonic-gate /*
21857c478bd9Sstevel@tonic-gate * If ttyiring is empty, check to see if there is a real EOF
21867c478bd9Sstevel@tonic-gate * pending. If so, we can maybe do the EOF write now.
21877c478bd9Sstevel@tonic-gate */
21887c478bd9Sstevel@tonic-gate if (eof_pending) {
21897c478bd9Sstevel@tonic-gate eof_pending = 0;
21907c478bd9Sstevel@tonic-gate sendeof();
21917c478bd9Sstevel@tonic-gate }
21927c478bd9Sstevel@tonic-gate }
21937c478bd9Sstevel@tonic-gate
21947c478bd9Sstevel@tonic-gate if (ring_full_count(&netiring)) {
21957c478bd9Sstevel@tonic-gate returnValue |= telrcv();
21967c478bd9Sstevel@tonic-gate }
21977c478bd9Sstevel@tonic-gate return (returnValue);
21987c478bd9Sstevel@tonic-gate }
21997c478bd9Sstevel@tonic-gate
22007c478bd9Sstevel@tonic-gate /*
22017c478bd9Sstevel@tonic-gate * Select from tty and network...
22027c478bd9Sstevel@tonic-gate */
22037c478bd9Sstevel@tonic-gate void
telnet(user)22047c478bd9Sstevel@tonic-gate telnet(user)
22057c478bd9Sstevel@tonic-gate char *user;
22067c478bd9Sstevel@tonic-gate {
22077c478bd9Sstevel@tonic-gate sys_telnet_init();
22087c478bd9Sstevel@tonic-gate
22097c478bd9Sstevel@tonic-gate {
22107c478bd9Sstevel@tonic-gate static char local_host[MAXHOSTNAMELEN] = { 0 };
22117c478bd9Sstevel@tonic-gate
22127c478bd9Sstevel@tonic-gate if (!local_host[0]) {
22137c478bd9Sstevel@tonic-gate (void) gethostname(local_host, sizeof (local_host));
22147c478bd9Sstevel@tonic-gate local_host[sizeof (local_host)-1] = 0;
22157c478bd9Sstevel@tonic-gate }
22167c478bd9Sstevel@tonic-gate auth_encrypt_init(local_host, hostname, "TELNET");
22177c478bd9Sstevel@tonic-gate auth_encrypt_user(user);
22187c478bd9Sstevel@tonic-gate }
22197c478bd9Sstevel@tonic-gate
22207c478bd9Sstevel@tonic-gate if (autologin)
22217c478bd9Sstevel@tonic-gate send_will(TELOPT_AUTHENTICATION, 1);
22227c478bd9Sstevel@tonic-gate
22237c478bd9Sstevel@tonic-gate if (telnetport || wantencryption) {
22247c478bd9Sstevel@tonic-gate send_do(TELOPT_ENCRYPT, 1);
22257c478bd9Sstevel@tonic-gate send_will(TELOPT_ENCRYPT, 1);
22267c478bd9Sstevel@tonic-gate }
22277c478bd9Sstevel@tonic-gate
22287c478bd9Sstevel@tonic-gate if (telnetport) {
22297c478bd9Sstevel@tonic-gate if (!reqd_linemode)
22307c478bd9Sstevel@tonic-gate send_do(TELOPT_SGA, 1);
22317c478bd9Sstevel@tonic-gate send_will(TELOPT_TTYPE, 1);
22327c478bd9Sstevel@tonic-gate send_will(TELOPT_NAWS, 1);
22337c478bd9Sstevel@tonic-gate send_will(TELOPT_TSPEED, 1);
22347c478bd9Sstevel@tonic-gate send_will(TELOPT_LFLOW, 1);
22357c478bd9Sstevel@tonic-gate if (!reqd_linemode)
22367c478bd9Sstevel@tonic-gate send_will(TELOPT_LINEMODE, 1);
22377c478bd9Sstevel@tonic-gate send_will(TELOPT_NEW_ENVIRON, 1);
22387c478bd9Sstevel@tonic-gate send_do(TELOPT_STATUS, 1);
22397c478bd9Sstevel@tonic-gate if (env_getvalue((unsigned char *)"DISPLAY"))
22407c478bd9Sstevel@tonic-gate send_will(TELOPT_XDISPLOC, 1);
22417c478bd9Sstevel@tonic-gate if (eight)
22427c478bd9Sstevel@tonic-gate tel_enter_binary(eight);
22437c478bd9Sstevel@tonic-gate }
22447c478bd9Sstevel@tonic-gate
22457c478bd9Sstevel@tonic-gate /*
22467c478bd9Sstevel@tonic-gate * Note: we assume a tie to the authentication option here. This
22477c478bd9Sstevel@tonic-gate * is necessary so that authentication fails, we don't spin
22487c478bd9Sstevel@tonic-gate * forever.
22497c478bd9Sstevel@tonic-gate */
22507c478bd9Sstevel@tonic-gate if (wantencryption) {
22517c478bd9Sstevel@tonic-gate boolean_t printed_encrypt = B_FALSE;
22527c478bd9Sstevel@tonic-gate extern boolean_t auth_has_failed;
22537c478bd9Sstevel@tonic-gate time_t timeout = time(0) + 60;
22547c478bd9Sstevel@tonic-gate
22557c478bd9Sstevel@tonic-gate send_do(TELOPT_ENCRYPT, 1);
22567c478bd9Sstevel@tonic-gate send_will(TELOPT_ENCRYPT, 1);
22577c478bd9Sstevel@tonic-gate for (;;) {
22587c478bd9Sstevel@tonic-gate if (my_want_state_is_wont(TELOPT_AUTHENTICATION)) {
22597c478bd9Sstevel@tonic-gate (void) printf(gettext(
22607c478bd9Sstevel@tonic-gate "\nServer refused to negotiate "
22617c478bd9Sstevel@tonic-gate "authentication, which is required\n"
22627c478bd9Sstevel@tonic-gate "for encryption. Good-bye.\n\r"));
22637c478bd9Sstevel@tonic-gate Exit(EXIT_FAILURE);
22647c478bd9Sstevel@tonic-gate }
22657c478bd9Sstevel@tonic-gate if (auth_has_failed) {
22667c478bd9Sstevel@tonic-gate (void) printf(gettext(
22677c478bd9Sstevel@tonic-gate "\nAuthentication negotation has failed, "
22687c478bd9Sstevel@tonic-gate "which is required for\n"
22697c478bd9Sstevel@tonic-gate "encryption. Good-bye.\n\r"));
22707c478bd9Sstevel@tonic-gate Exit(EXIT_FAILURE);
22717c478bd9Sstevel@tonic-gate }
22727c478bd9Sstevel@tonic-gate if (my_want_state_is_dont(TELOPT_ENCRYPT) ||
22737c478bd9Sstevel@tonic-gate my_want_state_is_wont(TELOPT_ENCRYPT)) {
22747c478bd9Sstevel@tonic-gate (void) printf(gettext(
22757c478bd9Sstevel@tonic-gate "\nServer refused to negotiate encryption. "
22767c478bd9Sstevel@tonic-gate "Good-bye.\n\r"));
22777c478bd9Sstevel@tonic-gate Exit(EXIT_FAILURE);
22787c478bd9Sstevel@tonic-gate }
22797c478bd9Sstevel@tonic-gate if (encrypt_is_encrypting())
22807c478bd9Sstevel@tonic-gate break;
22817c478bd9Sstevel@tonic-gate
22827c478bd9Sstevel@tonic-gate if (time(0) > timeout) {
22837c478bd9Sstevel@tonic-gate (void) printf(gettext(
22847c478bd9Sstevel@tonic-gate "\nEncryption could not be enabled. "
22857c478bd9Sstevel@tonic-gate "Good-bye.\n\r"));
22867c478bd9Sstevel@tonic-gate Exit(EXIT_FAILURE);
22877c478bd9Sstevel@tonic-gate }
22887c478bd9Sstevel@tonic-gate if (printed_encrypt == B_FALSE) {
22897c478bd9Sstevel@tonic-gate printed_encrypt = B_TRUE;
22907c478bd9Sstevel@tonic-gate (void) printf(gettext(
22917c478bd9Sstevel@tonic-gate "Waiting for encryption to be negotiated...\n"));
22927c478bd9Sstevel@tonic-gate /*
22937c478bd9Sstevel@tonic-gate * Turn on MODE_TRAPSIG and then turn off localchars
22947c478bd9Sstevel@tonic-gate * so that ^C will cause telnet to exit.
22957c478bd9Sstevel@tonic-gate */
22967c478bd9Sstevel@tonic-gate TerminalNewMode(getconnmode()|MODE_TRAPSIG);
22977c478bd9Sstevel@tonic-gate intr_waiting = 1;
22987c478bd9Sstevel@tonic-gate }
22997c478bd9Sstevel@tonic-gate if (intr_happened) {
23007c478bd9Sstevel@tonic-gate (void) printf(gettext(
23017c478bd9Sstevel@tonic-gate "\nUser requested an interrupt. Good-bye.\n\r"));
23027c478bd9Sstevel@tonic-gate Exit(EXIT_FAILURE);
23037c478bd9Sstevel@tonic-gate }
23047c478bd9Sstevel@tonic-gate telnet_spin();
23057c478bd9Sstevel@tonic-gate }
23067c478bd9Sstevel@tonic-gate if (printed_encrypt) {
23077c478bd9Sstevel@tonic-gate (void) printf(gettext("done.\n"));
23087c478bd9Sstevel@tonic-gate intr_waiting = 0;
23097c478bd9Sstevel@tonic-gate setconnmode(0);
23107c478bd9Sstevel@tonic-gate }
23117c478bd9Sstevel@tonic-gate }
23127c478bd9Sstevel@tonic-gate
23137c478bd9Sstevel@tonic-gate for (;;) {
23147c478bd9Sstevel@tonic-gate int schedValue;
23157c478bd9Sstevel@tonic-gate
23167c478bd9Sstevel@tonic-gate while ((schedValue = Scheduler(0)) != 0) {
23177c478bd9Sstevel@tonic-gate if (schedValue == -1) {
23187c478bd9Sstevel@tonic-gate setcommandmode();
23197c478bd9Sstevel@tonic-gate return;
23207c478bd9Sstevel@tonic-gate }
23217c478bd9Sstevel@tonic-gate }
23227c478bd9Sstevel@tonic-gate
23237c478bd9Sstevel@tonic-gate if (Scheduler(1) == -1) {
23247c478bd9Sstevel@tonic-gate setcommandmode();
23257c478bd9Sstevel@tonic-gate return;
23267c478bd9Sstevel@tonic-gate }
23277c478bd9Sstevel@tonic-gate }
23287c478bd9Sstevel@tonic-gate }
23297c478bd9Sstevel@tonic-gate
23307c478bd9Sstevel@tonic-gate #if 0 /* XXX - this not being in is a bug */
23317c478bd9Sstevel@tonic-gate /*
23327c478bd9Sstevel@tonic-gate * nextitem()
23337c478bd9Sstevel@tonic-gate *
23347c478bd9Sstevel@tonic-gate * Return the address of the next "item" in the TELNET data
23357c478bd9Sstevel@tonic-gate * stream. This will be the address of the next character if
23367c478bd9Sstevel@tonic-gate * the current address is a user data character, or it will
23377c478bd9Sstevel@tonic-gate * be the address of the character following the TELNET command
23387c478bd9Sstevel@tonic-gate * if the current address is a TELNET IAC ("I Am a Command")
23397c478bd9Sstevel@tonic-gate * character.
23407c478bd9Sstevel@tonic-gate */
23417c478bd9Sstevel@tonic-gate
23427c478bd9Sstevel@tonic-gate static char *
23437c478bd9Sstevel@tonic-gate nextitem(current)
23447c478bd9Sstevel@tonic-gate char *current;
23457c478bd9Sstevel@tonic-gate {
23467c478bd9Sstevel@tonic-gate if ((*current&0xff) != IAC) {
23477c478bd9Sstevel@tonic-gate return (current+1);
23487c478bd9Sstevel@tonic-gate }
23497c478bd9Sstevel@tonic-gate switch (*(current+1)&0xff) {
23507c478bd9Sstevel@tonic-gate case DO:
23517c478bd9Sstevel@tonic-gate case DONT:
23527c478bd9Sstevel@tonic-gate case WILL:
23537c478bd9Sstevel@tonic-gate case WONT:
23547c478bd9Sstevel@tonic-gate return (current+3);
23557c478bd9Sstevel@tonic-gate case SB: /* loop forever looking for the SE */
23567c478bd9Sstevel@tonic-gate {
23577c478bd9Sstevel@tonic-gate register char *look = current+2;
23587c478bd9Sstevel@tonic-gate
23597c478bd9Sstevel@tonic-gate for (;;) {
23607c478bd9Sstevel@tonic-gate if ((*look++&0xff) == IAC) {
23617c478bd9Sstevel@tonic-gate if ((*look++&0xff) == SE) {
23627c478bd9Sstevel@tonic-gate return (look);
23637c478bd9Sstevel@tonic-gate }
23647c478bd9Sstevel@tonic-gate }
23657c478bd9Sstevel@tonic-gate }
23667c478bd9Sstevel@tonic-gate }
23677c478bd9Sstevel@tonic-gate default:
23687c478bd9Sstevel@tonic-gate return (current+2);
23697c478bd9Sstevel@tonic-gate }
23707c478bd9Sstevel@tonic-gate }
23717c478bd9Sstevel@tonic-gate #endif /* 0 */
23727c478bd9Sstevel@tonic-gate
23737c478bd9Sstevel@tonic-gate /*
23747c478bd9Sstevel@tonic-gate * netclear()
23757c478bd9Sstevel@tonic-gate *
23767c478bd9Sstevel@tonic-gate * We are about to do a TELNET SYNCH operation. Clear
23777c478bd9Sstevel@tonic-gate * the path to the network.
23787c478bd9Sstevel@tonic-gate *
23797c478bd9Sstevel@tonic-gate * Things are a bit tricky since we may have sent the first
23807c478bd9Sstevel@tonic-gate * byte or so of a previous TELNET command into the network.
23817c478bd9Sstevel@tonic-gate * So, we have to scan the network buffer from the beginning
23827c478bd9Sstevel@tonic-gate * until we are up to where we want to be.
23837c478bd9Sstevel@tonic-gate *
23847c478bd9Sstevel@tonic-gate * A side effect of what we do, just to keep things
23857c478bd9Sstevel@tonic-gate * simple, is to clear the urgent data pointer. The principal
23867c478bd9Sstevel@tonic-gate * caller should be setting the urgent data pointer AFTER calling
23877c478bd9Sstevel@tonic-gate * us in any case.
23887c478bd9Sstevel@tonic-gate */
23897c478bd9Sstevel@tonic-gate
23907c478bd9Sstevel@tonic-gate static void
netclear()23917c478bd9Sstevel@tonic-gate netclear()
23927c478bd9Sstevel@tonic-gate {
23937c478bd9Sstevel@tonic-gate #if 0 /* XXX */
23947c478bd9Sstevel@tonic-gate register char *thisitem, *next;
23957c478bd9Sstevel@tonic-gate char *good;
23967c478bd9Sstevel@tonic-gate #define wewant(p) ((nfrontp > p) && ((*p&0xff) == IAC) && \
23977c478bd9Sstevel@tonic-gate ((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL))
23987c478bd9Sstevel@tonic-gate
23997c478bd9Sstevel@tonic-gate thisitem = netobuf;
24007c478bd9Sstevel@tonic-gate
24017c478bd9Sstevel@tonic-gate while ((next = nextitem(thisitem)) <= netobuf.send) {
24027c478bd9Sstevel@tonic-gate thisitem = next;
24037c478bd9Sstevel@tonic-gate }
24047c478bd9Sstevel@tonic-gate
24057c478bd9Sstevel@tonic-gate /* Now, thisitem is first before/at boundary. */
24067c478bd9Sstevel@tonic-gate
24077c478bd9Sstevel@tonic-gate good = netobuf; /* where the good bytes go */
24087c478bd9Sstevel@tonic-gate
24097c478bd9Sstevel@tonic-gate while (netoring.add > thisitem) {
24107c478bd9Sstevel@tonic-gate if (wewant(thisitem)) {
24117c478bd9Sstevel@tonic-gate int length;
24127c478bd9Sstevel@tonic-gate
24137c478bd9Sstevel@tonic-gate next = thisitem;
24147c478bd9Sstevel@tonic-gate do {
24157c478bd9Sstevel@tonic-gate next = nextitem(next);
24167c478bd9Sstevel@tonic-gate } while (wewant(next) && (nfrontp > next));
24177c478bd9Sstevel@tonic-gate length = next-thisitem;
24187c478bd9Sstevel@tonic-gate memcpy(good, thisitem, length);
24197c478bd9Sstevel@tonic-gate good += length;
24207c478bd9Sstevel@tonic-gate thisitem = next;
24217c478bd9Sstevel@tonic-gate } else {
24227c478bd9Sstevel@tonic-gate thisitem = nextitem(thisitem);
24237c478bd9Sstevel@tonic-gate }
24247c478bd9Sstevel@tonic-gate }
24257c478bd9Sstevel@tonic-gate
24267c478bd9Sstevel@tonic-gate #endif /* 0 */
24277c478bd9Sstevel@tonic-gate }
24287c478bd9Sstevel@tonic-gate
24297c478bd9Sstevel@tonic-gate /*
24307c478bd9Sstevel@tonic-gate * These routines add various telnet commands to the data stream.
24317c478bd9Sstevel@tonic-gate */
24327c478bd9Sstevel@tonic-gate
24337c478bd9Sstevel@tonic-gate /*
24347c478bd9Sstevel@tonic-gate * doflush - Send do timing mark (for network connection flush) & then
24357c478bd9Sstevel@tonic-gate * get rid of anything in the output buffer. Return -1 if there was a
24367c478bd9Sstevel@tonic-gate * non-EWOULDBLOCK error on the tty flush, and otherwise return 0.
24377c478bd9Sstevel@tonic-gate */
24387c478bd9Sstevel@tonic-gate static int
doflush()24397c478bd9Sstevel@tonic-gate doflush()
24407c478bd9Sstevel@tonic-gate {
24417c478bd9Sstevel@tonic-gate NET2ADD(IAC, DO);
24427c478bd9Sstevel@tonic-gate NETADD(TELOPT_TM);
24437c478bd9Sstevel@tonic-gate flushline = 1;
24447c478bd9Sstevel@tonic-gate flushout = 1;
24457c478bd9Sstevel@tonic-gate
24467c478bd9Sstevel@tonic-gate /* Drop pending tty output */
24477c478bd9Sstevel@tonic-gate if (ttyflush(1) == -2)
24487c478bd9Sstevel@tonic-gate return (-1);
24497c478bd9Sstevel@tonic-gate
24507c478bd9Sstevel@tonic-gate /* do printoption AFTER flush, otherwise the output gets tossed... */
24517c478bd9Sstevel@tonic-gate printoption("SENT", DO, TELOPT_TM);
24527c478bd9Sstevel@tonic-gate return (0);
24537c478bd9Sstevel@tonic-gate }
24547c478bd9Sstevel@tonic-gate
24557c478bd9Sstevel@tonic-gate int
xmitAO()24567c478bd9Sstevel@tonic-gate xmitAO()
24577c478bd9Sstevel@tonic-gate {
24587c478bd9Sstevel@tonic-gate NET2ADD(IAC, AO);
24597c478bd9Sstevel@tonic-gate printoption("SENT", IAC, AO);
24607c478bd9Sstevel@tonic-gate if (autoflush) {
24617c478bd9Sstevel@tonic-gate if (doflush() == -1)
24627c478bd9Sstevel@tonic-gate return (-1);
24637c478bd9Sstevel@tonic-gate }
24647c478bd9Sstevel@tonic-gate return (0);
24657c478bd9Sstevel@tonic-gate }
24667c478bd9Sstevel@tonic-gate
24677c478bd9Sstevel@tonic-gate
24687c478bd9Sstevel@tonic-gate void
xmitEL()24697c478bd9Sstevel@tonic-gate xmitEL()
24707c478bd9Sstevel@tonic-gate {
24717c478bd9Sstevel@tonic-gate NET2ADD(IAC, EL);
24727c478bd9Sstevel@tonic-gate printoption("SENT", IAC, EL);
24737c478bd9Sstevel@tonic-gate }
24747c478bd9Sstevel@tonic-gate
24757c478bd9Sstevel@tonic-gate void
xmitEC()24767c478bd9Sstevel@tonic-gate xmitEC()
24777c478bd9Sstevel@tonic-gate {
24787c478bd9Sstevel@tonic-gate NET2ADD(IAC, EC);
24797c478bd9Sstevel@tonic-gate printoption("SENT", IAC, EC);
24807c478bd9Sstevel@tonic-gate }
24817c478bd9Sstevel@tonic-gate
24827c478bd9Sstevel@tonic-gate
24837c478bd9Sstevel@tonic-gate int
dosynch()24847c478bd9Sstevel@tonic-gate dosynch()
24857c478bd9Sstevel@tonic-gate {
24867c478bd9Sstevel@tonic-gate netclear(); /* clear the path to the network */
24877c478bd9Sstevel@tonic-gate NETADD(IAC);
24887c478bd9Sstevel@tonic-gate setneturg();
24897c478bd9Sstevel@tonic-gate NETADD(DM);
24907c478bd9Sstevel@tonic-gate printoption("SENT", IAC, DM);
24917c478bd9Sstevel@tonic-gate return (1);
24927c478bd9Sstevel@tonic-gate }
24937c478bd9Sstevel@tonic-gate
24947c478bd9Sstevel@tonic-gate int want_status_response = 0;
24957c478bd9Sstevel@tonic-gate
24967c478bd9Sstevel@tonic-gate int
get_status()24977c478bd9Sstevel@tonic-gate get_status()
24987c478bd9Sstevel@tonic-gate {
24997c478bd9Sstevel@tonic-gate unsigned char tmp[16];
25007c478bd9Sstevel@tonic-gate register unsigned char *cp;
25017c478bd9Sstevel@tonic-gate
25027c478bd9Sstevel@tonic-gate if (my_want_state_is_dont(TELOPT_STATUS)) {
25037c478bd9Sstevel@tonic-gate (void) printf("Remote side does not support STATUS option\n");
25047c478bd9Sstevel@tonic-gate return (0);
25057c478bd9Sstevel@tonic-gate }
25067c478bd9Sstevel@tonic-gate cp = tmp;
25077c478bd9Sstevel@tonic-gate
25087c478bd9Sstevel@tonic-gate *cp++ = IAC;
25097c478bd9Sstevel@tonic-gate *cp++ = SB;
25107c478bd9Sstevel@tonic-gate *cp++ = TELOPT_STATUS;
25117c478bd9Sstevel@tonic-gate *cp++ = TELQUAL_SEND;
25127c478bd9Sstevel@tonic-gate *cp++ = IAC;
25137c478bd9Sstevel@tonic-gate *cp++ = SE;
25147c478bd9Sstevel@tonic-gate if (NETROOM() >= cp - tmp) {
25157c478bd9Sstevel@tonic-gate ring_supply_data(&netoring, tmp, cp-tmp);
25167c478bd9Sstevel@tonic-gate printsub('>', tmp+2, cp - tmp - 2);
25177c478bd9Sstevel@tonic-gate }
25187c478bd9Sstevel@tonic-gate ++want_status_response;
25197c478bd9Sstevel@tonic-gate return (1);
25207c478bd9Sstevel@tonic-gate }
25217c478bd9Sstevel@tonic-gate
25227c478bd9Sstevel@tonic-gate void
intp()25237c478bd9Sstevel@tonic-gate intp()
25247c478bd9Sstevel@tonic-gate {
25257c478bd9Sstevel@tonic-gate NET2ADD(IAC, IP);
25267c478bd9Sstevel@tonic-gate printoption("SENT", IAC, IP);
25277c478bd9Sstevel@tonic-gate flushline = 1;
25287c478bd9Sstevel@tonic-gate if (autoflush) {
25297c478bd9Sstevel@tonic-gate /* Ignore return as we're ending off anyway. */
25307c478bd9Sstevel@tonic-gate (void) doflush();
25317c478bd9Sstevel@tonic-gate }
25327c478bd9Sstevel@tonic-gate if (autosynch) {
25337c478bd9Sstevel@tonic-gate (void) dosynch();
25347c478bd9Sstevel@tonic-gate }
25357c478bd9Sstevel@tonic-gate }
25367c478bd9Sstevel@tonic-gate
25377c478bd9Sstevel@tonic-gate int
sendbrk()25387c478bd9Sstevel@tonic-gate sendbrk()
25397c478bd9Sstevel@tonic-gate {
25407c478bd9Sstevel@tonic-gate NET2ADD(IAC, BREAK);
25417c478bd9Sstevel@tonic-gate printoption("SENT", IAC, BREAK);
25427c478bd9Sstevel@tonic-gate flushline = 1;
25437c478bd9Sstevel@tonic-gate if (autoflush) {
25447c478bd9Sstevel@tonic-gate if (doflush() == -1)
25457c478bd9Sstevel@tonic-gate return (-1);
25467c478bd9Sstevel@tonic-gate }
25477c478bd9Sstevel@tonic-gate if (autosynch) {
25487c478bd9Sstevel@tonic-gate (void) dosynch();
25497c478bd9Sstevel@tonic-gate }
25507c478bd9Sstevel@tonic-gate return (0);
25517c478bd9Sstevel@tonic-gate }
25527c478bd9Sstevel@tonic-gate
25537c478bd9Sstevel@tonic-gate void
sendabort()25547c478bd9Sstevel@tonic-gate sendabort()
25557c478bd9Sstevel@tonic-gate {
25567c478bd9Sstevel@tonic-gate NET2ADD(IAC, ABORT);
25577c478bd9Sstevel@tonic-gate printoption("SENT", IAC, ABORT);
25587c478bd9Sstevel@tonic-gate flushline = 1;
25597c478bd9Sstevel@tonic-gate if (autoflush) {
25607c478bd9Sstevel@tonic-gate /*
25617c478bd9Sstevel@tonic-gate * Since sendabort() gets called while aborting,
25627c478bd9Sstevel@tonic-gate * ignore the doflush() return
25637c478bd9Sstevel@tonic-gate */
25647c478bd9Sstevel@tonic-gate (void) doflush();
25657c478bd9Sstevel@tonic-gate }
25667c478bd9Sstevel@tonic-gate if (autosynch) {
25677c478bd9Sstevel@tonic-gate (void) dosynch();
25687c478bd9Sstevel@tonic-gate }
25697c478bd9Sstevel@tonic-gate }
25707c478bd9Sstevel@tonic-gate
25717c478bd9Sstevel@tonic-gate void
sendsusp()25727c478bd9Sstevel@tonic-gate sendsusp()
25737c478bd9Sstevel@tonic-gate {
25747c478bd9Sstevel@tonic-gate NET2ADD(IAC, SUSP);
25757c478bd9Sstevel@tonic-gate printoption("SENT", IAC, SUSP);
25767c478bd9Sstevel@tonic-gate flushline = 1;
25777c478bd9Sstevel@tonic-gate if (autoflush) {
25787c478bd9Sstevel@tonic-gate if (doflush() == -1) {
25797c478bd9Sstevel@tonic-gate /* The following will not return. */
25807c478bd9Sstevel@tonic-gate fatal_tty_error("write");
25817c478bd9Sstevel@tonic-gate }
25827c478bd9Sstevel@tonic-gate }
25837c478bd9Sstevel@tonic-gate if (autosynch) {
25847c478bd9Sstevel@tonic-gate (void) dosynch();
25857c478bd9Sstevel@tonic-gate }
25867c478bd9Sstevel@tonic-gate }
25877c478bd9Sstevel@tonic-gate
25887c478bd9Sstevel@tonic-gate static void
sendeof()25897c478bd9Sstevel@tonic-gate sendeof()
25907c478bd9Sstevel@tonic-gate {
25917c478bd9Sstevel@tonic-gate NET2ADD(IAC, xEOF);
25927c478bd9Sstevel@tonic-gate printoption("SENT", IAC, xEOF);
25937c478bd9Sstevel@tonic-gate }
25947c478bd9Sstevel@tonic-gate
25957c478bd9Sstevel@tonic-gate /*
25967c478bd9Sstevel@tonic-gate * Send a window size update to the remote system.
25977c478bd9Sstevel@tonic-gate */
25987c478bd9Sstevel@tonic-gate
25997c478bd9Sstevel@tonic-gate void
sendnaws()26007c478bd9Sstevel@tonic-gate sendnaws()
26017c478bd9Sstevel@tonic-gate {
26027c478bd9Sstevel@tonic-gate unsigned short rows, cols;
26037c478bd9Sstevel@tonic-gate unsigned char tmp[16];
26047c478bd9Sstevel@tonic-gate register unsigned char *cp;
26057c478bd9Sstevel@tonic-gate
26067c478bd9Sstevel@tonic-gate if (my_state_is_wont(TELOPT_NAWS))
26077c478bd9Sstevel@tonic-gate return;
26087c478bd9Sstevel@tonic-gate
26097c478bd9Sstevel@tonic-gate #define PUTSHORT(cp, x) { if ((*cp++ = ((x)>>8)&0xff) == IAC) *cp++ = IAC; \
26107c478bd9Sstevel@tonic-gate if ((*cp++ = ((x))&0xff) == IAC) *cp++ = IAC; }
26117c478bd9Sstevel@tonic-gate
26127c478bd9Sstevel@tonic-gate if (TerminalWindowSize(&rows, &cols) == 0) { /* Failed */
26137c478bd9Sstevel@tonic-gate return;
26147c478bd9Sstevel@tonic-gate }
26157c478bd9Sstevel@tonic-gate
26167c478bd9Sstevel@tonic-gate cp = tmp;
26177c478bd9Sstevel@tonic-gate
26187c478bd9Sstevel@tonic-gate *cp++ = IAC;
26197c478bd9Sstevel@tonic-gate *cp++ = SB;
26207c478bd9Sstevel@tonic-gate *cp++ = TELOPT_NAWS;
26217c478bd9Sstevel@tonic-gate PUTSHORT(cp, cols);
26227c478bd9Sstevel@tonic-gate PUTSHORT(cp, rows);
26237c478bd9Sstevel@tonic-gate *cp++ = IAC;
26247c478bd9Sstevel@tonic-gate *cp++ = SE;
26257c478bd9Sstevel@tonic-gate if (NETROOM() >= cp - tmp) {
26267c478bd9Sstevel@tonic-gate ring_supply_data(&netoring, tmp, cp-tmp);
26277c478bd9Sstevel@tonic-gate printsub('>', tmp+2, cp - tmp - 2);
26287c478bd9Sstevel@tonic-gate }
26297c478bd9Sstevel@tonic-gate }
26307c478bd9Sstevel@tonic-gate
26317c478bd9Sstevel@tonic-gate void
tel_enter_binary(rw)26327c478bd9Sstevel@tonic-gate tel_enter_binary(rw)
26337c478bd9Sstevel@tonic-gate int rw;
26347c478bd9Sstevel@tonic-gate {
26357c478bd9Sstevel@tonic-gate if (rw&1)
26367c478bd9Sstevel@tonic-gate send_do(TELOPT_BINARY, 1);
26377c478bd9Sstevel@tonic-gate if (rw&2)
26387c478bd9Sstevel@tonic-gate send_will(TELOPT_BINARY, 1);
26397c478bd9Sstevel@tonic-gate }
26407c478bd9Sstevel@tonic-gate
26417c478bd9Sstevel@tonic-gate void
tel_leave_binary(rw)26427c478bd9Sstevel@tonic-gate tel_leave_binary(rw)
26437c478bd9Sstevel@tonic-gate int rw;
26447c478bd9Sstevel@tonic-gate {
26457c478bd9Sstevel@tonic-gate if (rw&1)
26467c478bd9Sstevel@tonic-gate send_dont(TELOPT_BINARY, 1);
26477c478bd9Sstevel@tonic-gate if (rw&2)
26487c478bd9Sstevel@tonic-gate send_wont(TELOPT_BINARY, 1);
26497c478bd9Sstevel@tonic-gate }
2650