181cb6ddcSMark Murray /* 281cb6ddcSMark Murray * Copyright (c) 1988, 1990, 1993 381cb6ddcSMark Murray * The Regents of the University of California. All rights reserved. 481cb6ddcSMark Murray * 581cb6ddcSMark Murray * Redistribution and use in source and binary forms, with or without 681cb6ddcSMark Murray * modification, are permitted provided that the following conditions 781cb6ddcSMark Murray * are met: 881cb6ddcSMark Murray * 1. Redistributions of source code must retain the above copyright 981cb6ddcSMark Murray * notice, this list of conditions and the following disclaimer. 1081cb6ddcSMark Murray * 2. Redistributions in binary form must reproduce the above copyright 1181cb6ddcSMark Murray * notice, this list of conditions and the following disclaimer in the 1281cb6ddcSMark Murray * documentation and/or other materials provided with the distribution. 1381cb6ddcSMark Murray * 3. All advertising materials mentioning features or use of this software 1481cb6ddcSMark Murray * must display the following acknowledgement: 1581cb6ddcSMark Murray * This product includes software developed by the University of 1681cb6ddcSMark Murray * California, Berkeley and its contributors. 1781cb6ddcSMark Murray * 4. Neither the name of the University nor the names of its contributors 1881cb6ddcSMark Murray * may be used to endorse or promote products derived from this software 1981cb6ddcSMark Murray * without specific prior written permission. 2081cb6ddcSMark Murray * 2181cb6ddcSMark Murray * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2281cb6ddcSMark Murray * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2381cb6ddcSMark Murray * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2481cb6ddcSMark Murray * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2581cb6ddcSMark Murray * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2681cb6ddcSMark Murray * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2781cb6ddcSMark Murray * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2881cb6ddcSMark Murray * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2981cb6ddcSMark Murray * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3081cb6ddcSMark Murray * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3181cb6ddcSMark Murray * SUCH DAMAGE. 32579c78c7SKris Kennaway * 33579c78c7SKris Kennaway * $FreeBSD$ 3481cb6ddcSMark Murray */ 3581cb6ddcSMark Murray 3681cb6ddcSMark Murray #ifndef lint 37ecece7e3SPeter Wemm #if 0 3804c426ccSMark Murray static const char sccsid[] = "@(#)telnet.c 8.4 (Berkeley) 5/30/95"; 39ecece7e3SPeter Wemm #else 40ecece7e3SPeter Wemm static const char rcsid[] = 41ecece7e3SPeter Wemm "$FreeBSD$"; 42ecece7e3SPeter Wemm #endif 4381cb6ddcSMark Murray #endif /* not lint */ 4481cb6ddcSMark Murray 4581cb6ddcSMark Murray #include <sys/types.h> 4681cb6ddcSMark Murray 4781cb6ddcSMark Murray #if defined(unix) 4881cb6ddcSMark Murray #include <signal.h> 4981cb6ddcSMark Murray /* By the way, we need to include curses.h before telnet.h since, 5081cb6ddcSMark Murray * among other things, telnet.h #defines 'DO', which is a variable 5181cb6ddcSMark Murray * declared in curses.h. 5281cb6ddcSMark Murray */ 5381cb6ddcSMark Murray #endif /* defined(unix) */ 5481cb6ddcSMark Murray 5581cb6ddcSMark Murray #include <arpa/telnet.h> 5681cb6ddcSMark Murray #include <ctype.h> 5704c426ccSMark Murray #include <stdlib.h> 5804c426ccSMark Murray #include <unistd.h> 5904c426ccSMark Murray 6081cb6ddcSMark Murray #include "ring.h" 6181cb6ddcSMark Murray 6281cb6ddcSMark Murray #include "defines.h" 6381cb6ddcSMark Murray #include "externs.h" 6481cb6ddcSMark Murray #include "types.h" 6581cb6ddcSMark Murray #include "general.h" 6681cb6ddcSMark Murray 6704c426ccSMark Murray #if defined(AUTHENTICATION) 6804c426ccSMark Murray #include <libtelnet/auth.h> 6904c426ccSMark Murray #endif 7004c426ccSMark Murray #if defined(ENCRYPTION) 7104c426ccSMark Murray #include <libtelnet/encrypt.h> 7204c426ccSMark Murray #endif 7304c426ccSMark Murray #include <libtelnet/misc.h> 7481cb6ddcSMark Murray 7581cb6ddcSMark Murray #define strip(x) ((my_want_state_is_wont(TELOPT_BINARY)) ? ((x)&0x7f) : (x)) 7681cb6ddcSMark Murray 7781cb6ddcSMark Murray static unsigned char subbuffer[SUBBUFSIZE], 7881cb6ddcSMark Murray *subpointer, *subend; /* buffer for sub-options */ 7981cb6ddcSMark Murray #define SB_CLEAR() subpointer = subbuffer; 8081cb6ddcSMark Murray #define SB_TERM() { subend = subpointer; SB_CLEAR(); } 8181cb6ddcSMark Murray #define SB_ACCUM(c) if (subpointer < (subbuffer+sizeof subbuffer)) { \ 8281cb6ddcSMark Murray *subpointer++ = (c); \ 8381cb6ddcSMark Murray } 8481cb6ddcSMark Murray 8581cb6ddcSMark Murray #define SB_GET() ((*subpointer++)&0xff) 8681cb6ddcSMark Murray #define SB_PEEK() ((*subpointer)&0xff) 8781cb6ddcSMark Murray #define SB_EOF() (subpointer >= subend) 8881cb6ddcSMark Murray #define SB_LEN() (subend - subpointer) 8981cb6ddcSMark Murray 9081cb6ddcSMark Murray char options[256]; /* The combined options */ 9181cb6ddcSMark Murray char do_dont_resp[256]; 9281cb6ddcSMark Murray char will_wont_resp[256]; 9381cb6ddcSMark Murray 9481cb6ddcSMark Murray int 9581cb6ddcSMark Murray eight = 0, 9681cb6ddcSMark Murray autologin = 0, /* Autologin anyone? */ 9781cb6ddcSMark Murray skiprc = 0, 9881cb6ddcSMark Murray connected, 9981cb6ddcSMark Murray showoptions, 10081cb6ddcSMark Murray In3270, /* Are we in 3270 mode? */ 10181cb6ddcSMark Murray ISend, /* trying to send network data in */ 10281cb6ddcSMark Murray debug = 0, 10381cb6ddcSMark Murray crmod, 10481cb6ddcSMark Murray netdata, /* Print out network data flow */ 10581cb6ddcSMark Murray crlf, /* Should '\r' be mapped to <CR><LF> (or <CR><NUL>)? */ 10681cb6ddcSMark Murray #if defined(TN3270) 10781cb6ddcSMark Murray noasynchtty = 0,/* User specified "-noasynch" on command line */ 10881cb6ddcSMark Murray noasynchnet = 0,/* User specified "-noasynch" on command line */ 10981cb6ddcSMark Murray askedSGA = 0, /* We have talked about suppress go ahead */ 11081cb6ddcSMark Murray #endif /* defined(TN3270) */ 11181cb6ddcSMark Murray telnetport, 11281cb6ddcSMark Murray SYNCHing, /* we are in TELNET SYNCH mode */ 11381cb6ddcSMark Murray flushout, /* flush output */ 11481cb6ddcSMark Murray autoflush = 0, /* flush output when interrupting? */ 11581cb6ddcSMark Murray autosynch, /* send interrupt characters with SYNCH? */ 11681cb6ddcSMark Murray localflow, /* we handle flow control locally */ 11781cb6ddcSMark Murray restartany, /* if flow control enabled, restart on any character */ 11881cb6ddcSMark Murray localchars, /* we recognize interrupt/quit */ 11981cb6ddcSMark Murray donelclchars, /* the user has set "localchars" */ 12081cb6ddcSMark Murray donebinarytoggle, /* the user has put us in binary */ 12181cb6ddcSMark Murray dontlecho, /* do we suppress local echoing right now? */ 12204c426ccSMark Murray globalmode, 12342cf8219SRuslan Ermilov doaddrlookup = 1, /* do a reverse address lookup? */ 12404c426ccSMark Murray clienteof = 0; 12581cb6ddcSMark Murray 12681cb6ddcSMark Murray char *prompt = 0; 12721f083c0SMark Murray #ifdef ENCRYPTION 128cd189e11SPeter Wemm char *line; /* hack around breakage in sra.c :-( !! */ 12921f083c0SMark Murray #endif 13081cb6ddcSMark Murray 13181cb6ddcSMark Murray cc_t escape; 13281cb6ddcSMark Murray cc_t rlogin; 13381cb6ddcSMark Murray #ifdef KLUDGELINEMODE 13481cb6ddcSMark Murray cc_t echoc; 13581cb6ddcSMark Murray #endif 13681cb6ddcSMark Murray 13781cb6ddcSMark Murray /* 13881cb6ddcSMark Murray * Telnet receiver states for fsm 13981cb6ddcSMark Murray */ 14081cb6ddcSMark Murray #define TS_DATA 0 14181cb6ddcSMark Murray #define TS_IAC 1 14281cb6ddcSMark Murray #define TS_WILL 2 14381cb6ddcSMark Murray #define TS_WONT 3 14481cb6ddcSMark Murray #define TS_DO 4 14581cb6ddcSMark Murray #define TS_DONT 5 14681cb6ddcSMark Murray #define TS_CR 6 14781cb6ddcSMark Murray #define TS_SB 7 /* sub-option collection */ 14881cb6ddcSMark Murray #define TS_SE 8 /* looking for sub-option end */ 14981cb6ddcSMark Murray 15081cb6ddcSMark Murray static int telrcv_state; 15181cb6ddcSMark Murray #ifdef OLD_ENVIRON 15281cb6ddcSMark Murray unsigned char telopt_environ = TELOPT_NEW_ENVIRON; 15381cb6ddcSMark Murray #else 15481cb6ddcSMark Murray # define telopt_environ TELOPT_NEW_ENVIRON 15581cb6ddcSMark Murray #endif 15681cb6ddcSMark Murray 15781cb6ddcSMark Murray jmp_buf toplevel = { 0 }; 15881cb6ddcSMark Murray jmp_buf peerdied; 15981cb6ddcSMark Murray 16081cb6ddcSMark Murray int flushline; 16181cb6ddcSMark Murray int linemode; 16281cb6ddcSMark Murray 16381cb6ddcSMark Murray #ifdef KLUDGELINEMODE 16481cb6ddcSMark Murray int kludgelinemode = 1; 16581cb6ddcSMark Murray #endif 16681cb6ddcSMark Murray 16781cb6ddcSMark Murray /* 16881cb6ddcSMark Murray * The following are some clocks used to decide how to interpret 16981cb6ddcSMark Murray * the relationship between various variables. 17081cb6ddcSMark Murray */ 17181cb6ddcSMark Murray 17281cb6ddcSMark Murray Clocks clocks; 17381cb6ddcSMark Murray 17481cb6ddcSMark Murray #ifdef notdef 17581cb6ddcSMark Murray Modelist modelist[] = { 17681cb6ddcSMark Murray { "telnet command mode", COMMAND_LINE }, 17781cb6ddcSMark Murray { "character-at-a-time mode", 0 }, 17881cb6ddcSMark Murray { "character-at-a-time mode (local echo)", LOCAL_ECHO|LOCAL_CHARS }, 17981cb6ddcSMark Murray { "line-by-line mode (remote echo)", LINE | LOCAL_CHARS }, 18081cb6ddcSMark Murray { "line-by-line mode", LINE | LOCAL_ECHO | LOCAL_CHARS }, 18181cb6ddcSMark Murray { "line-by-line mode (local echoing suppressed)", LINE | LOCAL_CHARS }, 18281cb6ddcSMark Murray { "3270 mode", 0 }, 18381cb6ddcSMark Murray }; 18481cb6ddcSMark Murray #endif 18581cb6ddcSMark Murray 18681cb6ddcSMark Murray 18781cb6ddcSMark Murray /* 18881cb6ddcSMark Murray * Initialize telnet environment. 18981cb6ddcSMark Murray */ 19081cb6ddcSMark Murray 19181cb6ddcSMark Murray void 19281cb6ddcSMark Murray init_telnet() 19381cb6ddcSMark Murray { 19481cb6ddcSMark Murray env_init(); 19581cb6ddcSMark Murray 19681cb6ddcSMark Murray SB_CLEAR(); 19781cb6ddcSMark Murray ClearArray(options); 19881cb6ddcSMark Murray 19981cb6ddcSMark Murray connected = In3270 = ISend = localflow = donebinarytoggle = 0; 20081cb6ddcSMark Murray #if defined(AUTHENTICATION) || defined(ENCRYPTION) 20181cb6ddcSMark Murray auth_encrypt_connect(connected); 20281cb6ddcSMark Murray #endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */ 20381cb6ddcSMark Murray restartany = -1; 20481cb6ddcSMark Murray 20581cb6ddcSMark Murray SYNCHing = 0; 20681cb6ddcSMark Murray 20781cb6ddcSMark Murray /* Don't change NetTrace */ 20881cb6ddcSMark Murray 20981cb6ddcSMark Murray escape = CONTROL(']'); 21081cb6ddcSMark Murray rlogin = _POSIX_VDISABLE; 21181cb6ddcSMark Murray #ifdef KLUDGELINEMODE 21281cb6ddcSMark Murray echoc = CONTROL('E'); 21381cb6ddcSMark Murray #endif 21481cb6ddcSMark Murray 21581cb6ddcSMark Murray flushline = 1; 21681cb6ddcSMark Murray telrcv_state = TS_DATA; 21781cb6ddcSMark Murray } 21881cb6ddcSMark Murray 21981cb6ddcSMark Murray 22081cb6ddcSMark Murray #ifdef notdef 22181cb6ddcSMark Murray #include <varargs.h> 22281cb6ddcSMark Murray 22381cb6ddcSMark Murray /*VARARGS*/ 22481cb6ddcSMark Murray static void 22581cb6ddcSMark Murray printring(va_alist) 22681cb6ddcSMark Murray va_dcl 22781cb6ddcSMark Murray { 22881cb6ddcSMark Murray va_list ap; 22981cb6ddcSMark Murray char buffer[100]; /* where things go */ 23081cb6ddcSMark Murray char *ptr; 23181cb6ddcSMark Murray char *format; 23281cb6ddcSMark Murray char *string; 23381cb6ddcSMark Murray Ring *ring; 23481cb6ddcSMark Murray int i; 23581cb6ddcSMark Murray 23681cb6ddcSMark Murray va_start(ap); 23781cb6ddcSMark Murray 23881cb6ddcSMark Murray ring = va_arg(ap, Ring *); 23981cb6ddcSMark Murray format = va_arg(ap, char *); 24081cb6ddcSMark Murray ptr = buffer; 24181cb6ddcSMark Murray 24281cb6ddcSMark Murray while ((i = *format++) != 0) { 24381cb6ddcSMark Murray if (i == '%') { 24481cb6ddcSMark Murray i = *format++; 24581cb6ddcSMark Murray switch (i) { 24681cb6ddcSMark Murray case 'c': 24781cb6ddcSMark Murray *ptr++ = va_arg(ap, int); 24881cb6ddcSMark Murray break; 24981cb6ddcSMark Murray case 's': 25081cb6ddcSMark Murray string = va_arg(ap, char *); 25181cb6ddcSMark Murray ring_supply_data(ring, buffer, ptr-buffer); 25281cb6ddcSMark Murray ring_supply_data(ring, string, strlen(string)); 25381cb6ddcSMark Murray ptr = buffer; 25481cb6ddcSMark Murray break; 25581cb6ddcSMark Murray case 0: 25681cb6ddcSMark Murray ExitString("printring: trailing %%.\n", 1); 25781cb6ddcSMark Murray /*NOTREACHED*/ 25881cb6ddcSMark Murray default: 25981cb6ddcSMark Murray ExitString("printring: unknown format character.\n", 1); 26081cb6ddcSMark Murray /*NOTREACHED*/ 26181cb6ddcSMark Murray } 26281cb6ddcSMark Murray } else { 26381cb6ddcSMark Murray *ptr++ = i; 26481cb6ddcSMark Murray } 26581cb6ddcSMark Murray } 26681cb6ddcSMark Murray ring_supply_data(ring, buffer, ptr-buffer); 26781cb6ddcSMark Murray } 26881cb6ddcSMark Murray #endif 26981cb6ddcSMark Murray 27081cb6ddcSMark Murray /* 27181cb6ddcSMark Murray * These routines are in charge of sending option negotiations 27281cb6ddcSMark Murray * to the other side. 27381cb6ddcSMark Murray * 27481cb6ddcSMark Murray * The basic idea is that we send the negotiation if either side 27581cb6ddcSMark Murray * is in disagreement as to what the current state should be. 27681cb6ddcSMark Murray */ 27781cb6ddcSMark Murray 27881cb6ddcSMark Murray void 27981cb6ddcSMark Murray send_do(c, init) 28081cb6ddcSMark Murray register int c, init; 28181cb6ddcSMark Murray { 28281cb6ddcSMark Murray if (init) { 28381cb6ddcSMark Murray if (((do_dont_resp[c] == 0) && my_state_is_do(c)) || 28481cb6ddcSMark Murray my_want_state_is_do(c)) 28581cb6ddcSMark Murray return; 28681cb6ddcSMark Murray set_my_want_state_do(c); 28781cb6ddcSMark Murray do_dont_resp[c]++; 28881cb6ddcSMark Murray } 28981cb6ddcSMark Murray NET2ADD(IAC, DO); 29081cb6ddcSMark Murray NETADD(c); 29181cb6ddcSMark Murray printoption("SENT", DO, c); 29281cb6ddcSMark Murray } 29381cb6ddcSMark Murray 29481cb6ddcSMark Murray void 29581cb6ddcSMark Murray send_dont(c, init) 29681cb6ddcSMark Murray register int c, init; 29781cb6ddcSMark Murray { 29881cb6ddcSMark Murray if (init) { 29981cb6ddcSMark Murray if (((do_dont_resp[c] == 0) && my_state_is_dont(c)) || 30081cb6ddcSMark Murray my_want_state_is_dont(c)) 30181cb6ddcSMark Murray return; 30281cb6ddcSMark Murray set_my_want_state_dont(c); 30381cb6ddcSMark Murray do_dont_resp[c]++; 30481cb6ddcSMark Murray } 30581cb6ddcSMark Murray NET2ADD(IAC, DONT); 30681cb6ddcSMark Murray NETADD(c); 30781cb6ddcSMark Murray printoption("SENT", DONT, c); 30881cb6ddcSMark Murray } 30981cb6ddcSMark Murray 31081cb6ddcSMark Murray void 31181cb6ddcSMark Murray send_will(c, init) 31281cb6ddcSMark Murray register int c, init; 31381cb6ddcSMark Murray { 31481cb6ddcSMark Murray if (init) { 31581cb6ddcSMark Murray if (((will_wont_resp[c] == 0) && my_state_is_will(c)) || 31681cb6ddcSMark Murray my_want_state_is_will(c)) 31781cb6ddcSMark Murray return; 31881cb6ddcSMark Murray set_my_want_state_will(c); 31981cb6ddcSMark Murray will_wont_resp[c]++; 32081cb6ddcSMark Murray } 32181cb6ddcSMark Murray NET2ADD(IAC, WILL); 32281cb6ddcSMark Murray NETADD(c); 32381cb6ddcSMark Murray printoption("SENT", WILL, c); 32481cb6ddcSMark Murray } 32581cb6ddcSMark Murray 32681cb6ddcSMark Murray void 32781cb6ddcSMark Murray send_wont(c, init) 32881cb6ddcSMark Murray register int c, init; 32981cb6ddcSMark Murray { 33081cb6ddcSMark Murray if (init) { 33181cb6ddcSMark Murray if (((will_wont_resp[c] == 0) && my_state_is_wont(c)) || 33281cb6ddcSMark Murray my_want_state_is_wont(c)) 33381cb6ddcSMark Murray return; 33481cb6ddcSMark Murray set_my_want_state_wont(c); 33581cb6ddcSMark Murray will_wont_resp[c]++; 33681cb6ddcSMark Murray } 33781cb6ddcSMark Murray NET2ADD(IAC, WONT); 33881cb6ddcSMark Murray NETADD(c); 33981cb6ddcSMark Murray printoption("SENT", WONT, c); 34081cb6ddcSMark Murray } 34181cb6ddcSMark Murray 34281cb6ddcSMark Murray 34381cb6ddcSMark Murray void 34481cb6ddcSMark Murray willoption(option) 34581cb6ddcSMark Murray int option; 34681cb6ddcSMark Murray { 34781cb6ddcSMark Murray int new_state_ok = 0; 34881cb6ddcSMark Murray 34981cb6ddcSMark Murray if (do_dont_resp[option]) { 35081cb6ddcSMark Murray --do_dont_resp[option]; 35181cb6ddcSMark Murray if (do_dont_resp[option] && my_state_is_do(option)) 35281cb6ddcSMark Murray --do_dont_resp[option]; 35381cb6ddcSMark Murray } 35481cb6ddcSMark Murray 35581cb6ddcSMark Murray if ((do_dont_resp[option] == 0) && my_want_state_is_dont(option)) { 35681cb6ddcSMark Murray 35781cb6ddcSMark Murray switch (option) { 35881cb6ddcSMark Murray 35981cb6ddcSMark Murray case TELOPT_ECHO: 36081cb6ddcSMark Murray # if defined(TN3270) 36181cb6ddcSMark Murray /* 36281cb6ddcSMark Murray * The following is a pain in the rear-end. 36381cb6ddcSMark Murray * Various IBM servers (some versions of Wiscnet, 36481cb6ddcSMark Murray * possibly Fibronics/Spartacus, and who knows who 36581cb6ddcSMark Murray * else) will NOT allow us to send "DO SGA" too early 36681cb6ddcSMark Murray * in the setup proceedings. On the other hand, 36781cb6ddcSMark Murray * 4.2 servers (telnetd) won't set SGA correctly. 36881cb6ddcSMark Murray * So, we are stuck. Empirically (but, based on 36981cb6ddcSMark Murray * a VERY small sample), the IBM servers don't send 37081cb6ddcSMark Murray * out anything about ECHO, so we postpone our sending 37181cb6ddcSMark Murray * "DO SGA" until we see "WILL ECHO" (which 4.2 servers 37281cb6ddcSMark Murray * DO send). 37381cb6ddcSMark Murray */ 37481cb6ddcSMark Murray { 37581cb6ddcSMark Murray if (askedSGA == 0) { 37681cb6ddcSMark Murray askedSGA = 1; 37781cb6ddcSMark Murray if (my_want_state_is_dont(TELOPT_SGA)) 37881cb6ddcSMark Murray send_do(TELOPT_SGA, 1); 37981cb6ddcSMark Murray } 38081cb6ddcSMark Murray } 38181cb6ddcSMark Murray /* Fall through */ 38281cb6ddcSMark Murray case TELOPT_EOR: 38381cb6ddcSMark Murray #endif /* defined(TN3270) */ 38481cb6ddcSMark Murray case TELOPT_BINARY: 38581cb6ddcSMark Murray case TELOPT_SGA: 38681cb6ddcSMark Murray settimer(modenegotiated); 38781cb6ddcSMark Murray /* FALL THROUGH */ 38881cb6ddcSMark Murray case TELOPT_STATUS: 38981cb6ddcSMark Murray #if defined(AUTHENTICATION) 39081cb6ddcSMark Murray case TELOPT_AUTHENTICATION: 39181cb6ddcSMark Murray #endif 39281cb6ddcSMark Murray #ifdef ENCRYPTION 39381cb6ddcSMark Murray case TELOPT_ENCRYPT: 39481cb6ddcSMark Murray #endif /* ENCRYPTION */ 39581cb6ddcSMark Murray new_state_ok = 1; 39681cb6ddcSMark Murray break; 39781cb6ddcSMark Murray 39881cb6ddcSMark Murray case TELOPT_TM: 39981cb6ddcSMark Murray if (flushout) 40081cb6ddcSMark Murray flushout = 0; 40181cb6ddcSMark Murray /* 40281cb6ddcSMark Murray * Special case for TM. If we get back a WILL, 40381cb6ddcSMark Murray * pretend we got back a WONT. 40481cb6ddcSMark Murray */ 40581cb6ddcSMark Murray set_my_want_state_dont(option); 40681cb6ddcSMark Murray set_my_state_dont(option); 40781cb6ddcSMark Murray return; /* Never reply to TM will's/wont's */ 40881cb6ddcSMark Murray 40981cb6ddcSMark Murray case TELOPT_LINEMODE: 41081cb6ddcSMark Murray default: 41181cb6ddcSMark Murray break; 41281cb6ddcSMark Murray } 41381cb6ddcSMark Murray 41481cb6ddcSMark Murray if (new_state_ok) { 41581cb6ddcSMark Murray set_my_want_state_do(option); 41681cb6ddcSMark Murray send_do(option, 0); 41781cb6ddcSMark Murray setconnmode(0); /* possibly set new tty mode */ 41881cb6ddcSMark Murray } else { 41981cb6ddcSMark Murray do_dont_resp[option]++; 42081cb6ddcSMark Murray send_dont(option, 0); 42181cb6ddcSMark Murray } 42281cb6ddcSMark Murray } 42381cb6ddcSMark Murray set_my_state_do(option); 42481cb6ddcSMark Murray #ifdef ENCRYPTION 42581cb6ddcSMark Murray if (option == TELOPT_ENCRYPT) 42681cb6ddcSMark Murray encrypt_send_support(); 42781cb6ddcSMark Murray #endif /* ENCRYPTION */ 42881cb6ddcSMark Murray } 42981cb6ddcSMark Murray 43081cb6ddcSMark Murray void 43181cb6ddcSMark Murray wontoption(option) 43281cb6ddcSMark Murray int option; 43381cb6ddcSMark Murray { 43481cb6ddcSMark Murray if (do_dont_resp[option]) { 43581cb6ddcSMark Murray --do_dont_resp[option]; 43681cb6ddcSMark Murray if (do_dont_resp[option] && my_state_is_dont(option)) 43781cb6ddcSMark Murray --do_dont_resp[option]; 43881cb6ddcSMark Murray } 43981cb6ddcSMark Murray 44081cb6ddcSMark Murray if ((do_dont_resp[option] == 0) && my_want_state_is_do(option)) { 44181cb6ddcSMark Murray 44281cb6ddcSMark Murray switch (option) { 44381cb6ddcSMark Murray 44481cb6ddcSMark Murray #ifdef KLUDGELINEMODE 44581cb6ddcSMark Murray case TELOPT_SGA: 44681cb6ddcSMark Murray if (!kludgelinemode) 44781cb6ddcSMark Murray break; 44881cb6ddcSMark Murray /* FALL THROUGH */ 44981cb6ddcSMark Murray #endif 45081cb6ddcSMark Murray case TELOPT_ECHO: 45181cb6ddcSMark Murray settimer(modenegotiated); 45281cb6ddcSMark Murray break; 45381cb6ddcSMark Murray 45481cb6ddcSMark Murray case TELOPT_TM: 45581cb6ddcSMark Murray if (flushout) 45681cb6ddcSMark Murray flushout = 0; 45781cb6ddcSMark Murray set_my_want_state_dont(option); 45881cb6ddcSMark Murray set_my_state_dont(option); 45981cb6ddcSMark Murray return; /* Never reply to TM will's/wont's */ 46081cb6ddcSMark Murray 46181cb6ddcSMark Murray default: 46281cb6ddcSMark Murray break; 46381cb6ddcSMark Murray } 46481cb6ddcSMark Murray set_my_want_state_dont(option); 46581cb6ddcSMark Murray if (my_state_is_do(option)) 46681cb6ddcSMark Murray send_dont(option, 0); 46781cb6ddcSMark Murray setconnmode(0); /* Set new tty mode */ 46881cb6ddcSMark Murray } else if (option == TELOPT_TM) { 46981cb6ddcSMark Murray /* 47081cb6ddcSMark Murray * Special case for TM. 47181cb6ddcSMark Murray */ 47281cb6ddcSMark Murray if (flushout) 47381cb6ddcSMark Murray flushout = 0; 47481cb6ddcSMark Murray set_my_want_state_dont(option); 47581cb6ddcSMark Murray } 47681cb6ddcSMark Murray set_my_state_dont(option); 47781cb6ddcSMark Murray } 47881cb6ddcSMark Murray 47981cb6ddcSMark Murray static void 48081cb6ddcSMark Murray dooption(option) 48181cb6ddcSMark Murray int option; 48281cb6ddcSMark Murray { 48381cb6ddcSMark Murray int new_state_ok = 0; 48481cb6ddcSMark Murray 48581cb6ddcSMark Murray if (will_wont_resp[option]) { 48681cb6ddcSMark Murray --will_wont_resp[option]; 48781cb6ddcSMark Murray if (will_wont_resp[option] && my_state_is_will(option)) 48881cb6ddcSMark Murray --will_wont_resp[option]; 48981cb6ddcSMark Murray } 49081cb6ddcSMark Murray 49181cb6ddcSMark Murray if (will_wont_resp[option] == 0) { 49281cb6ddcSMark Murray if (my_want_state_is_wont(option)) { 49381cb6ddcSMark Murray 49481cb6ddcSMark Murray switch (option) { 49581cb6ddcSMark Murray 49681cb6ddcSMark Murray case TELOPT_TM: 49781cb6ddcSMark Murray /* 49881cb6ddcSMark Murray * Special case for TM. We send a WILL, but pretend 49981cb6ddcSMark Murray * we sent WONT. 50081cb6ddcSMark Murray */ 50181cb6ddcSMark Murray send_will(option, 0); 50281cb6ddcSMark Murray set_my_want_state_wont(TELOPT_TM); 50381cb6ddcSMark Murray set_my_state_wont(TELOPT_TM); 50481cb6ddcSMark Murray return; 50581cb6ddcSMark Murray 50681cb6ddcSMark Murray # if defined(TN3270) 50781cb6ddcSMark Murray case TELOPT_EOR: /* end of record */ 50881cb6ddcSMark Murray # endif /* defined(TN3270) */ 50981cb6ddcSMark Murray case TELOPT_BINARY: /* binary mode */ 51081cb6ddcSMark Murray case TELOPT_NAWS: /* window size */ 51181cb6ddcSMark Murray case TELOPT_TSPEED: /* terminal speed */ 51281cb6ddcSMark Murray case TELOPT_LFLOW: /* local flow control */ 51381cb6ddcSMark Murray case TELOPT_TTYPE: /* terminal type option */ 51481cb6ddcSMark Murray case TELOPT_SGA: /* no big deal */ 51581cb6ddcSMark Murray #ifdef ENCRYPTION 51681cb6ddcSMark Murray case TELOPT_ENCRYPT: /* encryption variable option */ 51781cb6ddcSMark Murray #endif /* ENCRYPTION */ 51881cb6ddcSMark Murray new_state_ok = 1; 51981cb6ddcSMark Murray break; 52081cb6ddcSMark Murray 52181cb6ddcSMark Murray case TELOPT_NEW_ENVIRON: /* New environment variable option */ 52281cb6ddcSMark Murray #ifdef OLD_ENVIRON 52381cb6ddcSMark Murray if (my_state_is_will(TELOPT_OLD_ENVIRON)) 52481cb6ddcSMark Murray send_wont(TELOPT_OLD_ENVIRON, 1); /* turn off the old */ 52581cb6ddcSMark Murray goto env_common; 52681cb6ddcSMark Murray case TELOPT_OLD_ENVIRON: /* Old environment variable option */ 52781cb6ddcSMark Murray if (my_state_is_will(TELOPT_NEW_ENVIRON)) 52881cb6ddcSMark Murray break; /* Don't enable if new one is in use! */ 52981cb6ddcSMark Murray env_common: 53081cb6ddcSMark Murray telopt_environ = option; 53181cb6ddcSMark Murray #endif 53281cb6ddcSMark Murray new_state_ok = 1; 53381cb6ddcSMark Murray break; 53481cb6ddcSMark Murray 53581cb6ddcSMark Murray #if defined(AUTHENTICATION) 53681cb6ddcSMark Murray case TELOPT_AUTHENTICATION: 53781cb6ddcSMark Murray if (autologin) 53881cb6ddcSMark Murray new_state_ok = 1; 53981cb6ddcSMark Murray break; 54081cb6ddcSMark Murray #endif 54181cb6ddcSMark Murray 54281cb6ddcSMark Murray case TELOPT_XDISPLOC: /* X Display location */ 54381cb6ddcSMark Murray if (env_getvalue((unsigned char *)"DISPLAY")) 54481cb6ddcSMark Murray new_state_ok = 1; 54581cb6ddcSMark Murray break; 54681cb6ddcSMark Murray 54781cb6ddcSMark Murray case TELOPT_LINEMODE: 54881cb6ddcSMark Murray #ifdef KLUDGELINEMODE 54981cb6ddcSMark Murray kludgelinemode = 0; 55081cb6ddcSMark Murray send_do(TELOPT_SGA, 1); 55181cb6ddcSMark Murray #endif 55281cb6ddcSMark Murray set_my_want_state_will(TELOPT_LINEMODE); 55381cb6ddcSMark Murray send_will(option, 0); 55481cb6ddcSMark Murray set_my_state_will(TELOPT_LINEMODE); 55581cb6ddcSMark Murray slc_init(); 55681cb6ddcSMark Murray return; 55781cb6ddcSMark Murray 55881cb6ddcSMark Murray case TELOPT_ECHO: /* We're never going to echo... */ 55981cb6ddcSMark Murray default: 56081cb6ddcSMark Murray break; 56181cb6ddcSMark Murray } 56281cb6ddcSMark Murray 56381cb6ddcSMark Murray if (new_state_ok) { 56481cb6ddcSMark Murray set_my_want_state_will(option); 56581cb6ddcSMark Murray send_will(option, 0); 56681cb6ddcSMark Murray setconnmode(0); /* Set new tty mode */ 56781cb6ddcSMark Murray } else { 56881cb6ddcSMark Murray will_wont_resp[option]++; 56981cb6ddcSMark Murray send_wont(option, 0); 57081cb6ddcSMark Murray } 57181cb6ddcSMark Murray } else { 57281cb6ddcSMark Murray /* 57381cb6ddcSMark Murray * Handle options that need more things done after the 57481cb6ddcSMark Murray * other side has acknowledged the option. 57581cb6ddcSMark Murray */ 57681cb6ddcSMark Murray switch (option) { 57781cb6ddcSMark Murray case TELOPT_LINEMODE: 57881cb6ddcSMark Murray #ifdef KLUDGELINEMODE 57981cb6ddcSMark Murray kludgelinemode = 0; 58081cb6ddcSMark Murray send_do(TELOPT_SGA, 1); 58181cb6ddcSMark Murray #endif 58281cb6ddcSMark Murray set_my_state_will(option); 58381cb6ddcSMark Murray slc_init(); 58481cb6ddcSMark Murray send_do(TELOPT_SGA, 0); 58581cb6ddcSMark Murray return; 58681cb6ddcSMark Murray } 58781cb6ddcSMark Murray } 58881cb6ddcSMark Murray } 58981cb6ddcSMark Murray set_my_state_will(option); 59081cb6ddcSMark Murray } 59181cb6ddcSMark Murray 59281cb6ddcSMark Murray static void 59381cb6ddcSMark Murray dontoption(option) 59481cb6ddcSMark Murray int option; 59581cb6ddcSMark Murray { 59681cb6ddcSMark Murray 59781cb6ddcSMark Murray if (will_wont_resp[option]) { 59881cb6ddcSMark Murray --will_wont_resp[option]; 59981cb6ddcSMark Murray if (will_wont_resp[option] && my_state_is_wont(option)) 60081cb6ddcSMark Murray --will_wont_resp[option]; 60181cb6ddcSMark Murray } 60281cb6ddcSMark Murray 60381cb6ddcSMark Murray if ((will_wont_resp[option] == 0) && my_want_state_is_will(option)) { 60481cb6ddcSMark Murray switch (option) { 60581cb6ddcSMark Murray case TELOPT_LINEMODE: 60681cb6ddcSMark Murray linemode = 0; /* put us back to the default state */ 60781cb6ddcSMark Murray break; 60881cb6ddcSMark Murray #ifdef OLD_ENVIRON 60981cb6ddcSMark Murray case TELOPT_NEW_ENVIRON: 61081cb6ddcSMark Murray /* 61181cb6ddcSMark Murray * The new environ option wasn't recognized, try 61281cb6ddcSMark Murray * the old one. 61381cb6ddcSMark Murray */ 61481cb6ddcSMark Murray send_will(TELOPT_OLD_ENVIRON, 1); 61581cb6ddcSMark Murray telopt_environ = TELOPT_OLD_ENVIRON; 61681cb6ddcSMark Murray break; 61781cb6ddcSMark Murray #endif 61881cb6ddcSMark Murray } 61981cb6ddcSMark Murray /* we always accept a DONT */ 62081cb6ddcSMark Murray set_my_want_state_wont(option); 62181cb6ddcSMark Murray if (my_state_is_will(option)) 62281cb6ddcSMark Murray send_wont(option, 0); 62381cb6ddcSMark Murray setconnmode(0); /* Set new tty mode */ 62481cb6ddcSMark Murray } 62581cb6ddcSMark Murray set_my_state_wont(option); 62681cb6ddcSMark Murray } 62781cb6ddcSMark Murray 62881cb6ddcSMark Murray /* 62981cb6ddcSMark Murray * Given a buffer returned by tgetent(), this routine will turn 6309a01d32bSJeroen Ruigrok van der Werven * the pipe separated list of names in the buffer into an array 63181cb6ddcSMark Murray * of pointers to null terminated names. We toss out any bad, 63281cb6ddcSMark Murray * duplicate, or verbose names (names with spaces). 63381cb6ddcSMark Murray */ 63481cb6ddcSMark Murray 63581cb6ddcSMark Murray static char *name_unknown = "UNKNOWN"; 63681cb6ddcSMark Murray static char *unknown[] = { 0, 0 }; 63781cb6ddcSMark Murray 63881cb6ddcSMark Murray char ** 63981cb6ddcSMark Murray mklist(buf, name) 64081cb6ddcSMark Murray char *buf, *name; 64181cb6ddcSMark Murray { 64281cb6ddcSMark Murray register int n; 64381cb6ddcSMark Murray register char c, *cp, **argvp, *cp2, **argv, **avt; 64481cb6ddcSMark Murray 64581cb6ddcSMark Murray if (name) { 64621f083c0SMark Murray if (strlen(name) > 40) { 64781cb6ddcSMark Murray name = 0; 64881cb6ddcSMark Murray unknown[0] = name_unknown; 64981cb6ddcSMark Murray } else { 65081cb6ddcSMark Murray unknown[0] = name; 65181cb6ddcSMark Murray upcase(name); 65281cb6ddcSMark Murray } 65381cb6ddcSMark Murray } else 65481cb6ddcSMark Murray unknown[0] = name_unknown; 65581cb6ddcSMark Murray /* 65681cb6ddcSMark Murray * Count up the number of names. 65781cb6ddcSMark Murray */ 65881cb6ddcSMark Murray for (n = 1, cp = buf; *cp && *cp != ':'; cp++) { 65981cb6ddcSMark Murray if (*cp == '|') 66081cb6ddcSMark Murray n++; 66181cb6ddcSMark Murray } 66281cb6ddcSMark Murray /* 66381cb6ddcSMark Murray * Allocate an array to put the name pointers into 66481cb6ddcSMark Murray */ 66581cb6ddcSMark Murray argv = (char **)malloc((n+3)*sizeof(char *)); 66681cb6ddcSMark Murray if (argv == 0) 66781cb6ddcSMark Murray return(unknown); 66881cb6ddcSMark Murray 66981cb6ddcSMark Murray /* 67081cb6ddcSMark Murray * Fill up the array of pointers to names. 67181cb6ddcSMark Murray */ 67281cb6ddcSMark Murray *argv = 0; 67381cb6ddcSMark Murray argvp = argv+1; 67481cb6ddcSMark Murray n = 0; 67581cb6ddcSMark Murray for (cp = cp2 = buf; (c = *cp); cp++) { 67681cb6ddcSMark Murray if (c == '|' || c == ':') { 67781cb6ddcSMark Murray *cp++ = '\0'; 67881cb6ddcSMark Murray /* 67981cb6ddcSMark Murray * Skip entries that have spaces or are over 40 68081cb6ddcSMark Murray * characters long. If this is our environment 68181cb6ddcSMark Murray * name, then put it up front. Otherwise, as 68281cb6ddcSMark Murray * long as this is not a duplicate name (case 68381cb6ddcSMark Murray * insensitive) add it to the list. 68481cb6ddcSMark Murray */ 68581cb6ddcSMark Murray if (n || (cp - cp2 > 41)) 68681cb6ddcSMark Murray ; 68781cb6ddcSMark Murray else if (name && (strncasecmp(name, cp2, cp-cp2) == 0)) 68881cb6ddcSMark Murray *argv = cp2; 68981cb6ddcSMark Murray else if (is_unique(cp2, argv+1, argvp)) 69081cb6ddcSMark Murray *argvp++ = cp2; 69181cb6ddcSMark Murray if (c == ':') 69281cb6ddcSMark Murray break; 69381cb6ddcSMark Murray /* 69481cb6ddcSMark Murray * Skip multiple delimiters. Reset cp2 to 69581cb6ddcSMark Murray * the beginning of the next name. Reset n, 69681cb6ddcSMark Murray * the flag for names with spaces. 69781cb6ddcSMark Murray */ 69881cb6ddcSMark Murray while ((c = *cp) == '|') 69981cb6ddcSMark Murray cp++; 70081cb6ddcSMark Murray cp2 = cp; 70181cb6ddcSMark Murray n = 0; 70281cb6ddcSMark Murray } 70381cb6ddcSMark Murray /* 70481cb6ddcSMark Murray * Skip entries with spaces or non-ascii values. 70581cb6ddcSMark Murray * Convert lower case letters to upper case. 70681cb6ddcSMark Murray */ 70781cb6ddcSMark Murray if ((c == ' ') || !isascii(c)) 70881cb6ddcSMark Murray n = 1; 70981cb6ddcSMark Murray else if (islower(c)) 71081cb6ddcSMark Murray *cp = toupper(c); 71181cb6ddcSMark Murray } 71281cb6ddcSMark Murray 71381cb6ddcSMark Murray /* 71481cb6ddcSMark Murray * Check for an old V6 2 character name. If the second 71581cb6ddcSMark Murray * name points to the beginning of the buffer, and is 71681cb6ddcSMark Murray * only 2 characters long, move it to the end of the array. 71781cb6ddcSMark Murray */ 71881cb6ddcSMark Murray if ((argv[1] == buf) && (strlen(argv[1]) == 2)) { 71981cb6ddcSMark Murray --argvp; 72081cb6ddcSMark Murray for (avt = &argv[1]; avt < argvp; avt++) 72181cb6ddcSMark Murray *avt = *(avt+1); 72281cb6ddcSMark Murray *argvp++ = buf; 72381cb6ddcSMark Murray } 72481cb6ddcSMark Murray 72581cb6ddcSMark Murray /* 72681cb6ddcSMark Murray * Duplicate last name, for TTYPE option, and null 72781cb6ddcSMark Murray * terminate the array. If we didn't find a match on 72881cb6ddcSMark Murray * our terminal name, put that name at the beginning. 72981cb6ddcSMark Murray */ 73081cb6ddcSMark Murray cp = *(argvp-1); 73181cb6ddcSMark Murray *argvp++ = cp; 73281cb6ddcSMark Murray *argvp = 0; 73381cb6ddcSMark Murray 73481cb6ddcSMark Murray if (*argv == 0) { 73581cb6ddcSMark Murray if (name) 73681cb6ddcSMark Murray *argv = name; 73781cb6ddcSMark Murray else { 73881cb6ddcSMark Murray --argvp; 73981cb6ddcSMark Murray for (avt = argv; avt < argvp; avt++) 74081cb6ddcSMark Murray *avt = *(avt+1); 74181cb6ddcSMark Murray } 74281cb6ddcSMark Murray } 74381cb6ddcSMark Murray if (*argv) 74481cb6ddcSMark Murray return(argv); 74581cb6ddcSMark Murray else 74681cb6ddcSMark Murray return(unknown); 74781cb6ddcSMark Murray } 74881cb6ddcSMark Murray 74981cb6ddcSMark Murray int 75081cb6ddcSMark Murray is_unique(name, as, ae) 75181cb6ddcSMark Murray register char *name, **as, **ae; 75281cb6ddcSMark Murray { 75381cb6ddcSMark Murray register char **ap; 75481cb6ddcSMark Murray register int n; 75581cb6ddcSMark Murray 75681cb6ddcSMark Murray n = strlen(name) + 1; 75781cb6ddcSMark Murray for (ap = as; ap < ae; ap++) 75881cb6ddcSMark Murray if (strncasecmp(*ap, name, n) == 0) 75981cb6ddcSMark Murray return(0); 76081cb6ddcSMark Murray return (1); 76181cb6ddcSMark Murray } 76281cb6ddcSMark Murray 76381cb6ddcSMark Murray #ifdef TERMCAP 76481cb6ddcSMark Murray char termbuf[1024]; 76581cb6ddcSMark Murray 76681cb6ddcSMark Murray /*ARGSUSED*/ 76781cb6ddcSMark Murray int 76881cb6ddcSMark Murray setupterm(tname, fd, errp) 76981cb6ddcSMark Murray char *tname; 77081cb6ddcSMark Murray int fd, *errp; 77181cb6ddcSMark Murray { 77281cb6ddcSMark Murray if (tgetent(termbuf, tname) == 1) { 77381cb6ddcSMark Murray termbuf[1023] = '\0'; 77481cb6ddcSMark Murray if (errp) 77581cb6ddcSMark Murray *errp = 1; 77681cb6ddcSMark Murray return(0); 77781cb6ddcSMark Murray } 77881cb6ddcSMark Murray if (errp) 77981cb6ddcSMark Murray *errp = 0; 78081cb6ddcSMark Murray return(-1); 78181cb6ddcSMark Murray } 78281cb6ddcSMark Murray #else 78381cb6ddcSMark Murray #define termbuf ttytype 78481cb6ddcSMark Murray extern char ttytype[]; 78581cb6ddcSMark Murray #endif 78681cb6ddcSMark Murray 78781cb6ddcSMark Murray int resettermname = 1; 78881cb6ddcSMark Murray 78981cb6ddcSMark Murray char * 79081cb6ddcSMark Murray gettermname() 79181cb6ddcSMark Murray { 79281cb6ddcSMark Murray char *tname; 79381cb6ddcSMark Murray static char **tnamep = 0; 79481cb6ddcSMark Murray static char **next; 79581cb6ddcSMark Murray int err; 79681cb6ddcSMark Murray 79781cb6ddcSMark Murray if (resettermname) { 79881cb6ddcSMark Murray resettermname = 0; 79981cb6ddcSMark Murray if (tnamep && tnamep != unknown) 80081cb6ddcSMark Murray free(tnamep); 80181cb6ddcSMark Murray if ((tname = (char *)env_getvalue((unsigned char *)"TERM")) && 80281cb6ddcSMark Murray (setupterm(tname, 1, &err) == 0)) { 80381cb6ddcSMark Murray tnamep = mklist(termbuf, tname); 80481cb6ddcSMark Murray } else { 80521f083c0SMark Murray if (tname && (strlen(tname) <= 40)) { 80681cb6ddcSMark Murray unknown[0] = tname; 80781cb6ddcSMark Murray upcase(tname); 80881cb6ddcSMark Murray } else 80981cb6ddcSMark Murray unknown[0] = name_unknown; 81081cb6ddcSMark Murray tnamep = unknown; 81181cb6ddcSMark Murray } 81281cb6ddcSMark Murray next = tnamep; 81381cb6ddcSMark Murray } 81481cb6ddcSMark Murray if (*next == 0) 81581cb6ddcSMark Murray next = tnamep; 81681cb6ddcSMark Murray return(*next++); 81781cb6ddcSMark Murray } 81881cb6ddcSMark Murray /* 81981cb6ddcSMark Murray * suboption() 82081cb6ddcSMark Murray * 82181cb6ddcSMark Murray * Look at the sub-option buffer, and try to be helpful to the other 82281cb6ddcSMark Murray * side. 82381cb6ddcSMark Murray * 82481cb6ddcSMark Murray * Currently we recognize: 82581cb6ddcSMark Murray * 82681cb6ddcSMark Murray * Terminal type, send request. 82781cb6ddcSMark Murray * Terminal speed (send request). 82881cb6ddcSMark Murray * Local flow control (is request). 82981cb6ddcSMark Murray * Linemode 83081cb6ddcSMark Murray */ 83181cb6ddcSMark Murray 83281cb6ddcSMark Murray static void 83381cb6ddcSMark Murray suboption() 83481cb6ddcSMark Murray { 83581cb6ddcSMark Murray unsigned char subchar; 83681cb6ddcSMark Murray 83781cb6ddcSMark Murray printsub('<', subbuffer, SB_LEN()+2); 83881cb6ddcSMark Murray switch (subchar = SB_GET()) { 83981cb6ddcSMark Murray case TELOPT_TTYPE: 84081cb6ddcSMark Murray if (my_want_state_is_wont(TELOPT_TTYPE)) 84181cb6ddcSMark Murray return; 84281cb6ddcSMark Murray if (SB_EOF() || SB_GET() != TELQUAL_SEND) { 84381cb6ddcSMark Murray return; 84481cb6ddcSMark Murray } else { 84581cb6ddcSMark Murray char *name; 84681cb6ddcSMark Murray unsigned char temp[50]; 84781cb6ddcSMark Murray int len; 84881cb6ddcSMark Murray 84981cb6ddcSMark Murray #if defined(TN3270) 85081cb6ddcSMark Murray if (tn3270_ttype()) { 85181cb6ddcSMark Murray return; 85281cb6ddcSMark Murray } 85381cb6ddcSMark Murray #endif /* defined(TN3270) */ 85481cb6ddcSMark Murray name = gettermname(); 85581cb6ddcSMark Murray len = strlen(name) + 4 + 2; 85681cb6ddcSMark Murray if (len < NETROOM()) { 85781cb6ddcSMark Murray sprintf((char *)temp, "%c%c%c%c%s%c%c", IAC, SB, TELOPT_TTYPE, 85881cb6ddcSMark Murray TELQUAL_IS, name, IAC, SE); 85981cb6ddcSMark Murray ring_supply_data(&netoring, temp, len); 86081cb6ddcSMark Murray printsub('>', &temp[2], len-2); 86181cb6ddcSMark Murray } else { 86281cb6ddcSMark Murray ExitString("No room in buffer for terminal type.\n", 1); 86381cb6ddcSMark Murray /*NOTREACHED*/ 86481cb6ddcSMark Murray } 86581cb6ddcSMark Murray } 86681cb6ddcSMark Murray break; 86781cb6ddcSMark Murray case TELOPT_TSPEED: 86881cb6ddcSMark Murray if (my_want_state_is_wont(TELOPT_TSPEED)) 86981cb6ddcSMark Murray return; 87081cb6ddcSMark Murray if (SB_EOF()) 87181cb6ddcSMark Murray return; 87281cb6ddcSMark Murray if (SB_GET() == TELQUAL_SEND) { 87381cb6ddcSMark Murray long ospeed, ispeed; 87481cb6ddcSMark Murray unsigned char temp[50]; 87581cb6ddcSMark Murray int len; 87681cb6ddcSMark Murray 87781cb6ddcSMark Murray TerminalSpeeds(&ispeed, &ospeed); 87881cb6ddcSMark Murray 87904c426ccSMark Murray sprintf((char *)temp, "%c%c%c%c%ld,%ld%c%c", IAC, SB, TELOPT_TSPEED, 88081cb6ddcSMark Murray TELQUAL_IS, ospeed, ispeed, IAC, SE); 88181cb6ddcSMark Murray len = strlen((char *)temp+4) + 4; /* temp[3] is 0 ... */ 88281cb6ddcSMark Murray 88381cb6ddcSMark Murray if (len < NETROOM()) { 88481cb6ddcSMark Murray ring_supply_data(&netoring, temp, len); 88581cb6ddcSMark Murray printsub('>', temp+2, len - 2); 88681cb6ddcSMark Murray } 88781cb6ddcSMark Murray /*@*/ else printf("lm_will: not enough room in buffer\n"); 88881cb6ddcSMark Murray } 88981cb6ddcSMark Murray break; 89081cb6ddcSMark Murray case TELOPT_LFLOW: 89181cb6ddcSMark Murray if (my_want_state_is_wont(TELOPT_LFLOW)) 89281cb6ddcSMark Murray return; 89381cb6ddcSMark Murray if (SB_EOF()) 89481cb6ddcSMark Murray return; 89581cb6ddcSMark Murray switch(SB_GET()) { 89681cb6ddcSMark Murray case LFLOW_RESTART_ANY: 89781cb6ddcSMark Murray restartany = 1; 89881cb6ddcSMark Murray break; 89981cb6ddcSMark Murray case LFLOW_RESTART_XON: 90081cb6ddcSMark Murray restartany = 0; 90181cb6ddcSMark Murray break; 90281cb6ddcSMark Murray case LFLOW_ON: 90381cb6ddcSMark Murray localflow = 1; 90481cb6ddcSMark Murray break; 90581cb6ddcSMark Murray case LFLOW_OFF: 90681cb6ddcSMark Murray localflow = 0; 90781cb6ddcSMark Murray break; 90881cb6ddcSMark Murray default: 90981cb6ddcSMark Murray return; 91081cb6ddcSMark Murray } 91181cb6ddcSMark Murray setcommandmode(); 91281cb6ddcSMark Murray setconnmode(0); 91381cb6ddcSMark Murray break; 91481cb6ddcSMark Murray 91581cb6ddcSMark Murray case TELOPT_LINEMODE: 91681cb6ddcSMark Murray if (my_want_state_is_wont(TELOPT_LINEMODE)) 91781cb6ddcSMark Murray return; 91881cb6ddcSMark Murray if (SB_EOF()) 91981cb6ddcSMark Murray return; 92081cb6ddcSMark Murray switch (SB_GET()) { 92181cb6ddcSMark Murray case WILL: 92281cb6ddcSMark Murray lm_will(subpointer, SB_LEN()); 92381cb6ddcSMark Murray break; 92481cb6ddcSMark Murray case WONT: 92581cb6ddcSMark Murray lm_wont(subpointer, SB_LEN()); 92681cb6ddcSMark Murray break; 92781cb6ddcSMark Murray case DO: 92881cb6ddcSMark Murray lm_do(subpointer, SB_LEN()); 92981cb6ddcSMark Murray break; 93081cb6ddcSMark Murray case DONT: 93181cb6ddcSMark Murray lm_dont(subpointer, SB_LEN()); 93281cb6ddcSMark Murray break; 93381cb6ddcSMark Murray case LM_SLC: 93481cb6ddcSMark Murray slc(subpointer, SB_LEN()); 93581cb6ddcSMark Murray break; 93681cb6ddcSMark Murray case LM_MODE: 93781cb6ddcSMark Murray lm_mode(subpointer, SB_LEN(), 0); 93881cb6ddcSMark Murray break; 93981cb6ddcSMark Murray default: 94081cb6ddcSMark Murray break; 94181cb6ddcSMark Murray } 94281cb6ddcSMark Murray break; 94381cb6ddcSMark Murray 94481cb6ddcSMark Murray #ifdef OLD_ENVIRON 94581cb6ddcSMark Murray case TELOPT_OLD_ENVIRON: 94681cb6ddcSMark Murray #endif 94781cb6ddcSMark Murray case TELOPT_NEW_ENVIRON: 94881cb6ddcSMark Murray if (SB_EOF()) 94981cb6ddcSMark Murray return; 95081cb6ddcSMark Murray switch(SB_PEEK()) { 95181cb6ddcSMark Murray case TELQUAL_IS: 95281cb6ddcSMark Murray case TELQUAL_INFO: 95381cb6ddcSMark Murray if (my_want_state_is_dont(subchar)) 95481cb6ddcSMark Murray return; 95581cb6ddcSMark Murray break; 95681cb6ddcSMark Murray case TELQUAL_SEND: 95781cb6ddcSMark Murray if (my_want_state_is_wont(subchar)) { 95881cb6ddcSMark Murray return; 95981cb6ddcSMark Murray } 96081cb6ddcSMark Murray break; 96181cb6ddcSMark Murray default: 96281cb6ddcSMark Murray return; 96381cb6ddcSMark Murray } 96481cb6ddcSMark Murray env_opt(subpointer, SB_LEN()); 96581cb6ddcSMark Murray break; 96681cb6ddcSMark Murray 96781cb6ddcSMark Murray case TELOPT_XDISPLOC: 96881cb6ddcSMark Murray if (my_want_state_is_wont(TELOPT_XDISPLOC)) 96981cb6ddcSMark Murray return; 97081cb6ddcSMark Murray if (SB_EOF()) 97181cb6ddcSMark Murray return; 97281cb6ddcSMark Murray if (SB_GET() == TELQUAL_SEND) { 97381cb6ddcSMark Murray unsigned char temp[50], *dp; 97481cb6ddcSMark Murray int len; 97581cb6ddcSMark Murray 976579c78c7SKris Kennaway if ((dp = env_getvalue((unsigned char *)"DISPLAY")) == NULL || 977579c78c7SKris Kennaway strlen(dp) > sizeof(temp) - 7) { 97881cb6ddcSMark Murray /* 97981cb6ddcSMark Murray * Something happened, we no longer have a DISPLAY 980579c78c7SKris Kennaway * variable. Or it is too long. So, turn off the option. 98181cb6ddcSMark Murray */ 98281cb6ddcSMark Murray send_wont(TELOPT_XDISPLOC, 1); 98381cb6ddcSMark Murray break; 98481cb6ddcSMark Murray } 985579c78c7SKris Kennaway snprintf((char *)temp, sizeof(temp), "%c%c%c%c%s%c%c", IAC, SB, 986579c78c7SKris Kennaway TELOPT_XDISPLOC, TELQUAL_IS, dp, IAC, SE); 98781cb6ddcSMark Murray len = strlen((char *)temp+4) + 4; /* temp[3] is 0 ... */ 98881cb6ddcSMark Murray 98981cb6ddcSMark Murray if (len < NETROOM()) { 99081cb6ddcSMark Murray ring_supply_data(&netoring, temp, len); 99181cb6ddcSMark Murray printsub('>', temp+2, len - 2); 99281cb6ddcSMark Murray } 99381cb6ddcSMark Murray /*@*/ else printf("lm_will: not enough room in buffer\n"); 99481cb6ddcSMark Murray } 99581cb6ddcSMark Murray break; 99681cb6ddcSMark Murray 99781cb6ddcSMark Murray #if defined(AUTHENTICATION) 99881cb6ddcSMark Murray case TELOPT_AUTHENTICATION: { 99981cb6ddcSMark Murray if (!autologin) 100081cb6ddcSMark Murray break; 100181cb6ddcSMark Murray if (SB_EOF()) 100281cb6ddcSMark Murray return; 100381cb6ddcSMark Murray switch(SB_GET()) { 100481cb6ddcSMark Murray case TELQUAL_IS: 100581cb6ddcSMark Murray if (my_want_state_is_dont(TELOPT_AUTHENTICATION)) 100681cb6ddcSMark Murray return; 100781cb6ddcSMark Murray auth_is(subpointer, SB_LEN()); 100881cb6ddcSMark Murray break; 100981cb6ddcSMark Murray case TELQUAL_SEND: 101081cb6ddcSMark Murray if (my_want_state_is_wont(TELOPT_AUTHENTICATION)) 101181cb6ddcSMark Murray return; 101281cb6ddcSMark Murray auth_send(subpointer, SB_LEN()); 101381cb6ddcSMark Murray break; 101481cb6ddcSMark Murray case TELQUAL_REPLY: 101581cb6ddcSMark Murray if (my_want_state_is_wont(TELOPT_AUTHENTICATION)) 101681cb6ddcSMark Murray return; 101781cb6ddcSMark Murray auth_reply(subpointer, SB_LEN()); 101881cb6ddcSMark Murray break; 101981cb6ddcSMark Murray case TELQUAL_NAME: 102081cb6ddcSMark Murray if (my_want_state_is_dont(TELOPT_AUTHENTICATION)) 102181cb6ddcSMark Murray return; 102281cb6ddcSMark Murray auth_name(subpointer, SB_LEN()); 102381cb6ddcSMark Murray break; 102481cb6ddcSMark Murray } 102581cb6ddcSMark Murray } 102681cb6ddcSMark Murray break; 102781cb6ddcSMark Murray #endif 102881cb6ddcSMark Murray #ifdef ENCRYPTION 102981cb6ddcSMark Murray case TELOPT_ENCRYPT: 103081cb6ddcSMark Murray if (SB_EOF()) 103181cb6ddcSMark Murray return; 103281cb6ddcSMark Murray switch(SB_GET()) { 103381cb6ddcSMark Murray case ENCRYPT_START: 103481cb6ddcSMark Murray if (my_want_state_is_dont(TELOPT_ENCRYPT)) 103581cb6ddcSMark Murray return; 103681cb6ddcSMark Murray encrypt_start(subpointer, SB_LEN()); 103781cb6ddcSMark Murray break; 103881cb6ddcSMark Murray case ENCRYPT_END: 103981cb6ddcSMark Murray if (my_want_state_is_dont(TELOPT_ENCRYPT)) 104081cb6ddcSMark Murray return; 104181cb6ddcSMark Murray encrypt_end(); 104281cb6ddcSMark Murray break; 104381cb6ddcSMark Murray case ENCRYPT_SUPPORT: 104481cb6ddcSMark Murray if (my_want_state_is_wont(TELOPT_ENCRYPT)) 104581cb6ddcSMark Murray return; 104681cb6ddcSMark Murray encrypt_support(subpointer, SB_LEN()); 104781cb6ddcSMark Murray break; 104881cb6ddcSMark Murray case ENCRYPT_REQSTART: 104981cb6ddcSMark Murray if (my_want_state_is_wont(TELOPT_ENCRYPT)) 105081cb6ddcSMark Murray return; 105181cb6ddcSMark Murray encrypt_request_start(subpointer, SB_LEN()); 105281cb6ddcSMark Murray break; 105381cb6ddcSMark Murray case ENCRYPT_REQEND: 105481cb6ddcSMark Murray if (my_want_state_is_wont(TELOPT_ENCRYPT)) 105581cb6ddcSMark Murray return; 105681cb6ddcSMark Murray /* 105781cb6ddcSMark Murray * We can always send an REQEND so that we cannot 105881cb6ddcSMark Murray * get stuck encrypting. We should only get this 105981cb6ddcSMark Murray * if we have been able to get in the correct mode 106081cb6ddcSMark Murray * anyhow. 106181cb6ddcSMark Murray */ 106281cb6ddcSMark Murray encrypt_request_end(); 106381cb6ddcSMark Murray break; 106481cb6ddcSMark Murray case ENCRYPT_IS: 106581cb6ddcSMark Murray if (my_want_state_is_dont(TELOPT_ENCRYPT)) 106681cb6ddcSMark Murray return; 106781cb6ddcSMark Murray encrypt_is(subpointer, SB_LEN()); 106881cb6ddcSMark Murray break; 106981cb6ddcSMark Murray case ENCRYPT_REPLY: 107081cb6ddcSMark Murray if (my_want_state_is_wont(TELOPT_ENCRYPT)) 107181cb6ddcSMark Murray return; 107281cb6ddcSMark Murray encrypt_reply(subpointer, SB_LEN()); 107381cb6ddcSMark Murray break; 107481cb6ddcSMark Murray case ENCRYPT_ENC_KEYID: 107581cb6ddcSMark Murray if (my_want_state_is_dont(TELOPT_ENCRYPT)) 107681cb6ddcSMark Murray return; 107781cb6ddcSMark Murray encrypt_enc_keyid(subpointer, SB_LEN()); 107881cb6ddcSMark Murray break; 107981cb6ddcSMark Murray case ENCRYPT_DEC_KEYID: 108081cb6ddcSMark Murray if (my_want_state_is_wont(TELOPT_ENCRYPT)) 108181cb6ddcSMark Murray return; 108281cb6ddcSMark Murray encrypt_dec_keyid(subpointer, SB_LEN()); 108381cb6ddcSMark Murray break; 108481cb6ddcSMark Murray default: 108581cb6ddcSMark Murray break; 108681cb6ddcSMark Murray } 108781cb6ddcSMark Murray break; 108881cb6ddcSMark Murray #endif /* ENCRYPTION */ 108981cb6ddcSMark Murray default: 109081cb6ddcSMark Murray break; 109181cb6ddcSMark Murray } 109281cb6ddcSMark Murray } 109381cb6ddcSMark Murray 109481cb6ddcSMark Murray static unsigned char str_lm[] = { IAC, SB, TELOPT_LINEMODE, 0, 0, IAC, SE }; 109581cb6ddcSMark Murray 109681cb6ddcSMark Murray void 109781cb6ddcSMark Murray lm_will(cmd, len) 109881cb6ddcSMark Murray unsigned char *cmd; 109981cb6ddcSMark Murray int len; 110081cb6ddcSMark Murray { 110181cb6ddcSMark Murray if (len < 1) { 110281cb6ddcSMark Murray /*@*/ printf("lm_will: no command!!!\n"); /* Should not happen... */ 110381cb6ddcSMark Murray return; 110481cb6ddcSMark Murray } 110581cb6ddcSMark Murray switch(cmd[0]) { 110681cb6ddcSMark Murray case LM_FORWARDMASK: /* We shouldn't ever get this... */ 110781cb6ddcSMark Murray default: 110881cb6ddcSMark Murray str_lm[3] = DONT; 110981cb6ddcSMark Murray str_lm[4] = cmd[0]; 111081cb6ddcSMark Murray if (NETROOM() > sizeof(str_lm)) { 111181cb6ddcSMark Murray ring_supply_data(&netoring, str_lm, sizeof(str_lm)); 111281cb6ddcSMark Murray printsub('>', &str_lm[2], sizeof(str_lm)-2); 111381cb6ddcSMark Murray } 111481cb6ddcSMark Murray /*@*/ else printf("lm_will: not enough room in buffer\n"); 111581cb6ddcSMark Murray break; 111681cb6ddcSMark Murray } 111781cb6ddcSMark Murray } 111881cb6ddcSMark Murray 111981cb6ddcSMark Murray void 112081cb6ddcSMark Murray lm_wont(cmd, len) 112181cb6ddcSMark Murray unsigned char *cmd; 112281cb6ddcSMark Murray int len; 112381cb6ddcSMark Murray { 112481cb6ddcSMark Murray if (len < 1) { 112581cb6ddcSMark Murray /*@*/ printf("lm_wont: no command!!!\n"); /* Should not happen... */ 112681cb6ddcSMark Murray return; 112781cb6ddcSMark Murray } 112881cb6ddcSMark Murray switch(cmd[0]) { 112981cb6ddcSMark Murray case LM_FORWARDMASK: /* We shouldn't ever get this... */ 113081cb6ddcSMark Murray default: 113181cb6ddcSMark Murray /* We are always DONT, so don't respond */ 113281cb6ddcSMark Murray return; 113381cb6ddcSMark Murray } 113481cb6ddcSMark Murray } 113581cb6ddcSMark Murray 113681cb6ddcSMark Murray void 113781cb6ddcSMark Murray lm_do(cmd, len) 113881cb6ddcSMark Murray unsigned char *cmd; 113981cb6ddcSMark Murray int len; 114081cb6ddcSMark Murray { 114181cb6ddcSMark Murray if (len < 1) { 114281cb6ddcSMark Murray /*@*/ printf("lm_do: no command!!!\n"); /* Should not happen... */ 114381cb6ddcSMark Murray return; 114481cb6ddcSMark Murray } 114581cb6ddcSMark Murray switch(cmd[0]) { 114681cb6ddcSMark Murray case LM_FORWARDMASK: 114781cb6ddcSMark Murray default: 114881cb6ddcSMark Murray str_lm[3] = WONT; 114981cb6ddcSMark Murray str_lm[4] = cmd[0]; 115081cb6ddcSMark Murray if (NETROOM() > sizeof(str_lm)) { 115181cb6ddcSMark Murray ring_supply_data(&netoring, str_lm, sizeof(str_lm)); 115281cb6ddcSMark Murray printsub('>', &str_lm[2], sizeof(str_lm)-2); 115381cb6ddcSMark Murray } 115481cb6ddcSMark Murray /*@*/ else printf("lm_do: not enough room in buffer\n"); 115581cb6ddcSMark Murray break; 115681cb6ddcSMark Murray } 115781cb6ddcSMark Murray } 115881cb6ddcSMark Murray 115981cb6ddcSMark Murray void 116081cb6ddcSMark Murray lm_dont(cmd, len) 116181cb6ddcSMark Murray unsigned char *cmd; 116281cb6ddcSMark Murray int len; 116381cb6ddcSMark Murray { 116481cb6ddcSMark Murray if (len < 1) { 116581cb6ddcSMark Murray /*@*/ printf("lm_dont: no command!!!\n"); /* Should not happen... */ 116681cb6ddcSMark Murray return; 116781cb6ddcSMark Murray } 116881cb6ddcSMark Murray switch(cmd[0]) { 116981cb6ddcSMark Murray case LM_FORWARDMASK: 117081cb6ddcSMark Murray default: 117181cb6ddcSMark Murray /* we are always WONT, so don't respond */ 117281cb6ddcSMark Murray break; 117381cb6ddcSMark Murray } 117481cb6ddcSMark Murray } 117581cb6ddcSMark Murray 117681cb6ddcSMark Murray static unsigned char str_lm_mode[] = { 117781cb6ddcSMark Murray IAC, SB, TELOPT_LINEMODE, LM_MODE, 0, IAC, SE 117881cb6ddcSMark Murray }; 117981cb6ddcSMark Murray 118081cb6ddcSMark Murray void 118181cb6ddcSMark Murray lm_mode(cmd, len, init) 118281cb6ddcSMark Murray unsigned char *cmd; 118381cb6ddcSMark Murray int len, init; 118481cb6ddcSMark Murray { 118581cb6ddcSMark Murray if (len != 1) 118681cb6ddcSMark Murray return; 118781cb6ddcSMark Murray if ((linemode&MODE_MASK&~MODE_ACK) == *cmd) 118881cb6ddcSMark Murray return; 118981cb6ddcSMark Murray if (*cmd&MODE_ACK) 119081cb6ddcSMark Murray return; 119181cb6ddcSMark Murray linemode = *cmd&(MODE_MASK&~MODE_ACK); 119281cb6ddcSMark Murray str_lm_mode[4] = linemode; 119381cb6ddcSMark Murray if (!init) 119481cb6ddcSMark Murray str_lm_mode[4] |= MODE_ACK; 119581cb6ddcSMark Murray if (NETROOM() > sizeof(str_lm_mode)) { 119681cb6ddcSMark Murray ring_supply_data(&netoring, str_lm_mode, sizeof(str_lm_mode)); 119781cb6ddcSMark Murray printsub('>', &str_lm_mode[2], sizeof(str_lm_mode)-2); 119881cb6ddcSMark Murray } 119981cb6ddcSMark Murray /*@*/ else printf("lm_mode: not enough room in buffer\n"); 120081cb6ddcSMark Murray setconnmode(0); /* set changed mode */ 120181cb6ddcSMark Murray } 120281cb6ddcSMark Murray 120381cb6ddcSMark Murray 120481cb6ddcSMark Murray 120581cb6ddcSMark Murray /* 120681cb6ddcSMark Murray * slc() 120781cb6ddcSMark Murray * Handle special character suboption of LINEMODE. 120881cb6ddcSMark Murray */ 120981cb6ddcSMark Murray 121081cb6ddcSMark Murray struct spc { 121181cb6ddcSMark Murray cc_t val; 121281cb6ddcSMark Murray cc_t *valp; 121381cb6ddcSMark Murray char flags; /* Current flags & level */ 121481cb6ddcSMark Murray char mylevel; /* Maximum level & flags */ 121581cb6ddcSMark Murray } spc_data[NSLC+1]; 121681cb6ddcSMark Murray 121781cb6ddcSMark Murray #define SLC_IMPORT 0 121881cb6ddcSMark Murray #define SLC_EXPORT 1 121981cb6ddcSMark Murray #define SLC_RVALUE 2 122081cb6ddcSMark Murray static int slc_mode = SLC_EXPORT; 122181cb6ddcSMark Murray 122281cb6ddcSMark Murray void 122381cb6ddcSMark Murray slc_init() 122481cb6ddcSMark Murray { 122581cb6ddcSMark Murray register struct spc *spcp; 122681cb6ddcSMark Murray 122781cb6ddcSMark Murray localchars = 1; 122881cb6ddcSMark Murray for (spcp = spc_data; spcp < &spc_data[NSLC+1]; spcp++) { 122981cb6ddcSMark Murray spcp->val = 0; 123081cb6ddcSMark Murray spcp->valp = 0; 123181cb6ddcSMark Murray spcp->flags = spcp->mylevel = SLC_NOSUPPORT; 123281cb6ddcSMark Murray } 123381cb6ddcSMark Murray 123481cb6ddcSMark Murray #define initfunc(func, flags) { \ 123581cb6ddcSMark Murray spcp = &spc_data[func]; \ 123604c426ccSMark Murray if ((spcp->valp = tcval(func))) { \ 123781cb6ddcSMark Murray spcp->val = *spcp->valp; \ 123881cb6ddcSMark Murray spcp->mylevel = SLC_VARIABLE|flags; \ 123981cb6ddcSMark Murray } else { \ 124081cb6ddcSMark Murray spcp->val = 0; \ 124181cb6ddcSMark Murray spcp->mylevel = SLC_DEFAULT; \ 124281cb6ddcSMark Murray } \ 124381cb6ddcSMark Murray } 124481cb6ddcSMark Murray 124581cb6ddcSMark Murray initfunc(SLC_SYNCH, 0); 124681cb6ddcSMark Murray /* No BRK */ 124781cb6ddcSMark Murray initfunc(SLC_AO, 0); 124881cb6ddcSMark Murray initfunc(SLC_AYT, 0); 124981cb6ddcSMark Murray /* No EOR */ 125081cb6ddcSMark Murray initfunc(SLC_ABORT, SLC_FLUSHIN|SLC_FLUSHOUT); 125181cb6ddcSMark Murray initfunc(SLC_EOF, 0); 125281cb6ddcSMark Murray #ifndef SYSV_TERMIO 125381cb6ddcSMark Murray initfunc(SLC_SUSP, SLC_FLUSHIN); 125481cb6ddcSMark Murray #endif 125581cb6ddcSMark Murray initfunc(SLC_EC, 0); 125681cb6ddcSMark Murray initfunc(SLC_EL, 0); 125781cb6ddcSMark Murray #ifndef SYSV_TERMIO 125881cb6ddcSMark Murray initfunc(SLC_EW, 0); 125981cb6ddcSMark Murray initfunc(SLC_RP, 0); 126081cb6ddcSMark Murray initfunc(SLC_LNEXT, 0); 126181cb6ddcSMark Murray #endif 126281cb6ddcSMark Murray initfunc(SLC_XON, 0); 126381cb6ddcSMark Murray initfunc(SLC_XOFF, 0); 126481cb6ddcSMark Murray #ifdef SYSV_TERMIO 126581cb6ddcSMark Murray spc_data[SLC_XON].mylevel = SLC_CANTCHANGE; 126681cb6ddcSMark Murray spc_data[SLC_XOFF].mylevel = SLC_CANTCHANGE; 126781cb6ddcSMark Murray #endif 126881cb6ddcSMark Murray initfunc(SLC_FORW1, 0); 126981cb6ddcSMark Murray #ifdef USE_TERMIO 127081cb6ddcSMark Murray initfunc(SLC_FORW2, 0); 127181cb6ddcSMark Murray /* No FORW2 */ 127281cb6ddcSMark Murray #endif 127381cb6ddcSMark Murray 127481cb6ddcSMark Murray initfunc(SLC_IP, SLC_FLUSHIN|SLC_FLUSHOUT); 127581cb6ddcSMark Murray #undef initfunc 127681cb6ddcSMark Murray 127781cb6ddcSMark Murray if (slc_mode == SLC_EXPORT) 127881cb6ddcSMark Murray slc_export(); 127981cb6ddcSMark Murray else 128081cb6ddcSMark Murray slc_import(1); 128181cb6ddcSMark Murray 128281cb6ddcSMark Murray } 128381cb6ddcSMark Murray 128481cb6ddcSMark Murray void 128581cb6ddcSMark Murray slcstate() 128681cb6ddcSMark Murray { 128781cb6ddcSMark Murray printf("Special characters are %s values\n", 128881cb6ddcSMark Murray slc_mode == SLC_IMPORT ? "remote default" : 128981cb6ddcSMark Murray slc_mode == SLC_EXPORT ? "local" : 129081cb6ddcSMark Murray "remote"); 129181cb6ddcSMark Murray } 129281cb6ddcSMark Murray 129381cb6ddcSMark Murray void 129481cb6ddcSMark Murray slc_mode_export() 129581cb6ddcSMark Murray { 129681cb6ddcSMark Murray slc_mode = SLC_EXPORT; 129781cb6ddcSMark Murray if (my_state_is_will(TELOPT_LINEMODE)) 129881cb6ddcSMark Murray slc_export(); 129981cb6ddcSMark Murray } 130081cb6ddcSMark Murray 130181cb6ddcSMark Murray void 130281cb6ddcSMark Murray slc_mode_import(def) 130381cb6ddcSMark Murray int def; 130481cb6ddcSMark Murray { 130581cb6ddcSMark Murray slc_mode = def ? SLC_IMPORT : SLC_RVALUE; 130681cb6ddcSMark Murray if (my_state_is_will(TELOPT_LINEMODE)) 130781cb6ddcSMark Murray slc_import(def); 130881cb6ddcSMark Murray } 130981cb6ddcSMark Murray 131081cb6ddcSMark Murray unsigned char slc_import_val[] = { 131181cb6ddcSMark Murray IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_VARIABLE, 0, IAC, SE 131281cb6ddcSMark Murray }; 131381cb6ddcSMark Murray unsigned char slc_import_def[] = { 131481cb6ddcSMark Murray IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_DEFAULT, 0, IAC, SE 131581cb6ddcSMark Murray }; 131681cb6ddcSMark Murray 131781cb6ddcSMark Murray void 131881cb6ddcSMark Murray slc_import(def) 131981cb6ddcSMark Murray int def; 132081cb6ddcSMark Murray { 132181cb6ddcSMark Murray if (NETROOM() > sizeof(slc_import_val)) { 132281cb6ddcSMark Murray if (def) { 132381cb6ddcSMark Murray ring_supply_data(&netoring, slc_import_def, sizeof(slc_import_def)); 132481cb6ddcSMark Murray printsub('>', &slc_import_def[2], sizeof(slc_import_def)-2); 132581cb6ddcSMark Murray } else { 132681cb6ddcSMark Murray ring_supply_data(&netoring, slc_import_val, sizeof(slc_import_val)); 132781cb6ddcSMark Murray printsub('>', &slc_import_val[2], sizeof(slc_import_val)-2); 132881cb6ddcSMark Murray } 132981cb6ddcSMark Murray } 133081cb6ddcSMark Murray /*@*/ else printf("slc_import: not enough room\n"); 133181cb6ddcSMark Murray } 133281cb6ddcSMark Murray 133381cb6ddcSMark Murray void 133481cb6ddcSMark Murray slc_export() 133581cb6ddcSMark Murray { 133681cb6ddcSMark Murray register struct spc *spcp; 133781cb6ddcSMark Murray 133881cb6ddcSMark Murray TerminalDefaultChars(); 133981cb6ddcSMark Murray 134081cb6ddcSMark Murray slc_start_reply(); 134181cb6ddcSMark Murray for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) { 134281cb6ddcSMark Murray if (spcp->mylevel != SLC_NOSUPPORT) { 134381cb6ddcSMark Murray if (spcp->val == (cc_t)(_POSIX_VDISABLE)) 134481cb6ddcSMark Murray spcp->flags = SLC_NOSUPPORT; 134581cb6ddcSMark Murray else 134681cb6ddcSMark Murray spcp->flags = spcp->mylevel; 134781cb6ddcSMark Murray if (spcp->valp) 134881cb6ddcSMark Murray spcp->val = *spcp->valp; 134981cb6ddcSMark Murray slc_add_reply(spcp - spc_data, spcp->flags, spcp->val); 135081cb6ddcSMark Murray } 135181cb6ddcSMark Murray } 135281cb6ddcSMark Murray slc_end_reply(); 135381cb6ddcSMark Murray (void)slc_update(); 135481cb6ddcSMark Murray setconnmode(1); /* Make sure the character values are set */ 135581cb6ddcSMark Murray } 135681cb6ddcSMark Murray 135781cb6ddcSMark Murray void 135881cb6ddcSMark Murray slc(cp, len) 135981cb6ddcSMark Murray register unsigned char *cp; 136081cb6ddcSMark Murray int len; 136181cb6ddcSMark Murray { 136281cb6ddcSMark Murray register struct spc *spcp; 136381cb6ddcSMark Murray register int func,level; 136481cb6ddcSMark Murray 136581cb6ddcSMark Murray slc_start_reply(); 136681cb6ddcSMark Murray 136781cb6ddcSMark Murray for (; len >= 3; len -=3, cp +=3) { 136881cb6ddcSMark Murray 136981cb6ddcSMark Murray func = cp[SLC_FUNC]; 137081cb6ddcSMark Murray 137181cb6ddcSMark Murray if (func == 0) { 137281cb6ddcSMark Murray /* 137381cb6ddcSMark Murray * Client side: always ignore 0 function. 137481cb6ddcSMark Murray */ 137581cb6ddcSMark Murray continue; 137681cb6ddcSMark Murray } 137781cb6ddcSMark Murray if (func > NSLC) { 137881cb6ddcSMark Murray if ((cp[SLC_FLAGS] & SLC_LEVELBITS) != SLC_NOSUPPORT) 137981cb6ddcSMark Murray slc_add_reply(func, SLC_NOSUPPORT, 0); 138081cb6ddcSMark Murray continue; 138181cb6ddcSMark Murray } 138281cb6ddcSMark Murray 138381cb6ddcSMark Murray spcp = &spc_data[func]; 138481cb6ddcSMark Murray 138581cb6ddcSMark Murray level = cp[SLC_FLAGS]&(SLC_LEVELBITS|SLC_ACK); 138681cb6ddcSMark Murray 138781cb6ddcSMark Murray if ((cp[SLC_VALUE] == (unsigned char)spcp->val) && 138881cb6ddcSMark Murray ((level&SLC_LEVELBITS) == (spcp->flags&SLC_LEVELBITS))) { 138981cb6ddcSMark Murray continue; 139081cb6ddcSMark Murray } 139181cb6ddcSMark Murray 139281cb6ddcSMark Murray if (level == (SLC_DEFAULT|SLC_ACK)) { 139381cb6ddcSMark Murray /* 139481cb6ddcSMark Murray * This is an error condition, the SLC_ACK 139581cb6ddcSMark Murray * bit should never be set for the SLC_DEFAULT 139681cb6ddcSMark Murray * level. Our best guess to recover is to 139781cb6ddcSMark Murray * ignore the SLC_ACK bit. 139881cb6ddcSMark Murray */ 139981cb6ddcSMark Murray cp[SLC_FLAGS] &= ~SLC_ACK; 140081cb6ddcSMark Murray } 140181cb6ddcSMark Murray 140281cb6ddcSMark Murray if (level == ((spcp->flags&SLC_LEVELBITS)|SLC_ACK)) { 140381cb6ddcSMark Murray spcp->val = (cc_t)cp[SLC_VALUE]; 140481cb6ddcSMark Murray spcp->flags = cp[SLC_FLAGS]; /* include SLC_ACK */ 140581cb6ddcSMark Murray continue; 140681cb6ddcSMark Murray } 140781cb6ddcSMark Murray 140881cb6ddcSMark Murray level &= ~SLC_ACK; 140981cb6ddcSMark Murray 141081cb6ddcSMark Murray if (level <= (spcp->mylevel&SLC_LEVELBITS)) { 141181cb6ddcSMark Murray spcp->flags = cp[SLC_FLAGS]|SLC_ACK; 141281cb6ddcSMark Murray spcp->val = (cc_t)cp[SLC_VALUE]; 141381cb6ddcSMark Murray } 141481cb6ddcSMark Murray if (level == SLC_DEFAULT) { 141581cb6ddcSMark Murray if ((spcp->mylevel&SLC_LEVELBITS) != SLC_DEFAULT) 141681cb6ddcSMark Murray spcp->flags = spcp->mylevel; 141781cb6ddcSMark Murray else 141881cb6ddcSMark Murray spcp->flags = SLC_NOSUPPORT; 141981cb6ddcSMark Murray } 142081cb6ddcSMark Murray slc_add_reply(func, spcp->flags, spcp->val); 142181cb6ddcSMark Murray } 142281cb6ddcSMark Murray slc_end_reply(); 142381cb6ddcSMark Murray if (slc_update()) 142481cb6ddcSMark Murray setconnmode(1); /* set the new character values */ 142581cb6ddcSMark Murray } 142681cb6ddcSMark Murray 142781cb6ddcSMark Murray void 142881cb6ddcSMark Murray slc_check() 142981cb6ddcSMark Murray { 143081cb6ddcSMark Murray register struct spc *spcp; 143181cb6ddcSMark Murray 143281cb6ddcSMark Murray slc_start_reply(); 143381cb6ddcSMark Murray for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) { 143481cb6ddcSMark Murray if (spcp->valp && spcp->val != *spcp->valp) { 143581cb6ddcSMark Murray spcp->val = *spcp->valp; 143681cb6ddcSMark Murray if (spcp->val == (cc_t)(_POSIX_VDISABLE)) 143781cb6ddcSMark Murray spcp->flags = SLC_NOSUPPORT; 143881cb6ddcSMark Murray else 143981cb6ddcSMark Murray spcp->flags = spcp->mylevel; 144081cb6ddcSMark Murray slc_add_reply(spcp - spc_data, spcp->flags, spcp->val); 144181cb6ddcSMark Murray } 144281cb6ddcSMark Murray } 144381cb6ddcSMark Murray slc_end_reply(); 144481cb6ddcSMark Murray setconnmode(1); 144581cb6ddcSMark Murray } 144681cb6ddcSMark Murray 144781cb6ddcSMark Murray 144881cb6ddcSMark Murray unsigned char slc_reply[128]; 144981cb6ddcSMark Murray unsigned char *slc_replyp; 145081cb6ddcSMark Murray 145181cb6ddcSMark Murray void 145281cb6ddcSMark Murray slc_start_reply() 145381cb6ddcSMark Murray { 145481cb6ddcSMark Murray slc_replyp = slc_reply; 145581cb6ddcSMark Murray *slc_replyp++ = IAC; 145681cb6ddcSMark Murray *slc_replyp++ = SB; 145781cb6ddcSMark Murray *slc_replyp++ = TELOPT_LINEMODE; 145881cb6ddcSMark Murray *slc_replyp++ = LM_SLC; 145981cb6ddcSMark Murray } 146081cb6ddcSMark Murray 146181cb6ddcSMark Murray void 146281cb6ddcSMark Murray slc_add_reply(func, flags, value) 146381cb6ddcSMark Murray unsigned char func; 146481cb6ddcSMark Murray unsigned char flags; 146581cb6ddcSMark Murray cc_t value; 146681cb6ddcSMark Murray { 146781cb6ddcSMark Murray if ((*slc_replyp++ = func) == IAC) 146881cb6ddcSMark Murray *slc_replyp++ = IAC; 146981cb6ddcSMark Murray if ((*slc_replyp++ = flags) == IAC) 147081cb6ddcSMark Murray *slc_replyp++ = IAC; 147181cb6ddcSMark Murray if ((*slc_replyp++ = (unsigned char)value) == IAC) 147281cb6ddcSMark Murray *slc_replyp++ = IAC; 147381cb6ddcSMark Murray } 147481cb6ddcSMark Murray 147581cb6ddcSMark Murray void 147681cb6ddcSMark Murray slc_end_reply() 147781cb6ddcSMark Murray { 147881cb6ddcSMark Murray register int len; 147981cb6ddcSMark Murray 148081cb6ddcSMark Murray *slc_replyp++ = IAC; 148181cb6ddcSMark Murray *slc_replyp++ = SE; 148281cb6ddcSMark Murray len = slc_replyp - slc_reply; 148381cb6ddcSMark Murray if (len <= 6) 148481cb6ddcSMark Murray return; 148581cb6ddcSMark Murray if (NETROOM() > len) { 148681cb6ddcSMark Murray ring_supply_data(&netoring, slc_reply, slc_replyp - slc_reply); 148781cb6ddcSMark Murray printsub('>', &slc_reply[2], slc_replyp - slc_reply - 2); 148881cb6ddcSMark Murray } 148981cb6ddcSMark Murray /*@*/else printf("slc_end_reply: not enough room\n"); 149081cb6ddcSMark Murray } 149181cb6ddcSMark Murray 149281cb6ddcSMark Murray int 149381cb6ddcSMark Murray slc_update() 149481cb6ddcSMark Murray { 149581cb6ddcSMark Murray register struct spc *spcp; 149681cb6ddcSMark Murray int need_update = 0; 149781cb6ddcSMark Murray 149881cb6ddcSMark Murray for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) { 149981cb6ddcSMark Murray if (!(spcp->flags&SLC_ACK)) 150081cb6ddcSMark Murray continue; 150181cb6ddcSMark Murray spcp->flags &= ~SLC_ACK; 150281cb6ddcSMark Murray if (spcp->valp && (*spcp->valp != spcp->val)) { 150381cb6ddcSMark Murray *spcp->valp = spcp->val; 150481cb6ddcSMark Murray need_update = 1; 150581cb6ddcSMark Murray } 150681cb6ddcSMark Murray } 150781cb6ddcSMark Murray return(need_update); 150881cb6ddcSMark Murray } 150981cb6ddcSMark Murray 151081cb6ddcSMark Murray #ifdef OLD_ENVIRON 151181cb6ddcSMark Murray # ifdef ENV_HACK 151281cb6ddcSMark Murray /* 151381cb6ddcSMark Murray * Earlier version of telnet/telnetd from the BSD code had 151481cb6ddcSMark Murray * the definitions of VALUE and VAR reversed. To ensure 151581cb6ddcSMark Murray * maximum interoperability, we assume that the server is 151681cb6ddcSMark Murray * an older BSD server, until proven otherwise. The newer 151781cb6ddcSMark Murray * BSD servers should be able to handle either definition, 151881cb6ddcSMark Murray * so it is better to use the wrong values if we don't 151981cb6ddcSMark Murray * know what type of server it is. 152081cb6ddcSMark Murray */ 152181cb6ddcSMark Murray int env_auto = 1; 152281cb6ddcSMark Murray int old_env_var = OLD_ENV_VAR; 152381cb6ddcSMark Murray int old_env_value = OLD_ENV_VALUE; 152481cb6ddcSMark Murray # else 152581cb6ddcSMark Murray # define old_env_var OLD_ENV_VAR 152681cb6ddcSMark Murray # define old_env_value OLD_ENV_VALUE 152781cb6ddcSMark Murray # endif 152881cb6ddcSMark Murray #endif 152981cb6ddcSMark Murray 153081cb6ddcSMark Murray void 153181cb6ddcSMark Murray env_opt(buf, len) 153281cb6ddcSMark Murray register unsigned char *buf; 153381cb6ddcSMark Murray register int len; 153481cb6ddcSMark Murray { 153581cb6ddcSMark Murray register unsigned char *ep = 0, *epc = 0; 153681cb6ddcSMark Murray register int i; 153781cb6ddcSMark Murray 153881cb6ddcSMark Murray switch(buf[0]&0xff) { 153981cb6ddcSMark Murray case TELQUAL_SEND: 154081cb6ddcSMark Murray env_opt_start(); 154181cb6ddcSMark Murray if (len == 1) { 154281cb6ddcSMark Murray env_opt_add(NULL); 154381cb6ddcSMark Murray } else for (i = 1; i < len; i++) { 154481cb6ddcSMark Murray switch (buf[i]&0xff) { 154581cb6ddcSMark Murray #ifdef OLD_ENVIRON 154681cb6ddcSMark Murray case OLD_ENV_VAR: 154781cb6ddcSMark Murray # ifdef ENV_HACK 154881cb6ddcSMark Murray if (telopt_environ == TELOPT_OLD_ENVIRON 154981cb6ddcSMark Murray && env_auto) { 155081cb6ddcSMark Murray /* Server has the same definitions */ 155181cb6ddcSMark Murray old_env_var = OLD_ENV_VAR; 155281cb6ddcSMark Murray old_env_value = OLD_ENV_VALUE; 155381cb6ddcSMark Murray } 155481cb6ddcSMark Murray /* FALL THROUGH */ 155581cb6ddcSMark Murray # endif 155681cb6ddcSMark Murray case OLD_ENV_VALUE: 155781cb6ddcSMark Murray /* 155881cb6ddcSMark Murray * Although OLD_ENV_VALUE is not legal, we will 155981cb6ddcSMark Murray * still recognize it, just in case it is an 156081cb6ddcSMark Murray * old server that has VAR & VALUE mixed up... 156181cb6ddcSMark Murray */ 156281cb6ddcSMark Murray /* FALL THROUGH */ 156381cb6ddcSMark Murray #else 156481cb6ddcSMark Murray case NEW_ENV_VAR: 156581cb6ddcSMark Murray #endif 156681cb6ddcSMark Murray case ENV_USERVAR: 156781cb6ddcSMark Murray if (ep) { 156881cb6ddcSMark Murray *epc = 0; 156981cb6ddcSMark Murray env_opt_add(ep); 157081cb6ddcSMark Murray } 157181cb6ddcSMark Murray ep = epc = &buf[i+1]; 157281cb6ddcSMark Murray break; 157381cb6ddcSMark Murray case ENV_ESC: 157481cb6ddcSMark Murray i++; 157581cb6ddcSMark Murray /*FALL THROUGH*/ 157681cb6ddcSMark Murray default: 157781cb6ddcSMark Murray if (epc) 157881cb6ddcSMark Murray *epc++ = buf[i]; 157981cb6ddcSMark Murray break; 158081cb6ddcSMark Murray } 158181cb6ddcSMark Murray } 158281cb6ddcSMark Murray if (ep) { 158381cb6ddcSMark Murray *epc = 0; 158481cb6ddcSMark Murray env_opt_add(ep); 158581cb6ddcSMark Murray } 158681cb6ddcSMark Murray env_opt_end(1); 158781cb6ddcSMark Murray break; 158881cb6ddcSMark Murray 158981cb6ddcSMark Murray case TELQUAL_IS: 159081cb6ddcSMark Murray case TELQUAL_INFO: 159181cb6ddcSMark Murray /* Ignore for now. We shouldn't get it anyway. */ 159281cb6ddcSMark Murray break; 159381cb6ddcSMark Murray 159481cb6ddcSMark Murray default: 159581cb6ddcSMark Murray break; 159681cb6ddcSMark Murray } 159781cb6ddcSMark Murray } 159881cb6ddcSMark Murray 159981cb6ddcSMark Murray #define OPT_REPLY_SIZE 256 160081cb6ddcSMark Murray unsigned char *opt_reply; 160181cb6ddcSMark Murray unsigned char *opt_replyp; 160281cb6ddcSMark Murray unsigned char *opt_replyend; 160381cb6ddcSMark Murray 160481cb6ddcSMark Murray void 160581cb6ddcSMark Murray env_opt_start() 160681cb6ddcSMark Murray { 160781cb6ddcSMark Murray if (opt_reply) 160881cb6ddcSMark Murray opt_reply = (unsigned char *)realloc(opt_reply, OPT_REPLY_SIZE); 160981cb6ddcSMark Murray else 161081cb6ddcSMark Murray opt_reply = (unsigned char *)malloc(OPT_REPLY_SIZE); 161181cb6ddcSMark Murray if (opt_reply == NULL) { 161281cb6ddcSMark Murray /*@*/ printf("env_opt_start: malloc()/realloc() failed!!!\n"); 161381cb6ddcSMark Murray opt_reply = opt_replyp = opt_replyend = NULL; 161481cb6ddcSMark Murray return; 161581cb6ddcSMark Murray } 161681cb6ddcSMark Murray opt_replyp = opt_reply; 161781cb6ddcSMark Murray opt_replyend = opt_reply + OPT_REPLY_SIZE; 161881cb6ddcSMark Murray *opt_replyp++ = IAC; 161981cb6ddcSMark Murray *opt_replyp++ = SB; 162081cb6ddcSMark Murray *opt_replyp++ = telopt_environ; 162181cb6ddcSMark Murray *opt_replyp++ = TELQUAL_IS; 162281cb6ddcSMark Murray } 162381cb6ddcSMark Murray 162481cb6ddcSMark Murray void 162581cb6ddcSMark Murray env_opt_start_info() 162681cb6ddcSMark Murray { 162781cb6ddcSMark Murray env_opt_start(); 162881cb6ddcSMark Murray if (opt_replyp) 162981cb6ddcSMark Murray opt_replyp[-1] = TELQUAL_INFO; 163081cb6ddcSMark Murray } 163181cb6ddcSMark Murray 163281cb6ddcSMark Murray void 163381cb6ddcSMark Murray env_opt_add(ep) 163481cb6ddcSMark Murray register unsigned char *ep; 163581cb6ddcSMark Murray { 163681cb6ddcSMark Murray register unsigned char *vp, c; 163781cb6ddcSMark Murray 163881cb6ddcSMark Murray if (opt_reply == NULL) /*XXX*/ 163981cb6ddcSMark Murray return; /*XXX*/ 164081cb6ddcSMark Murray 164181cb6ddcSMark Murray if (ep == NULL || *ep == '\0') { 164281cb6ddcSMark Murray /* Send user defined variables first. */ 164381cb6ddcSMark Murray env_default(1, 0); 164404c426ccSMark Murray while ((ep = env_default(0, 0))) 164581cb6ddcSMark Murray env_opt_add(ep); 164681cb6ddcSMark Murray 164781cb6ddcSMark Murray /* Now add the list of well know variables. */ 164881cb6ddcSMark Murray env_default(1, 1); 164904c426ccSMark Murray while ((ep = env_default(0, 1))) 165081cb6ddcSMark Murray env_opt_add(ep); 165181cb6ddcSMark Murray return; 165281cb6ddcSMark Murray } 165381cb6ddcSMark Murray vp = env_getvalue(ep); 165481cb6ddcSMark Murray if (opt_replyp + (vp ? strlen((char *)vp) : 0) + 165581cb6ddcSMark Murray strlen((char *)ep) + 6 > opt_replyend) 165681cb6ddcSMark Murray { 165781cb6ddcSMark Murray register int len; 165881cb6ddcSMark Murray opt_replyend += OPT_REPLY_SIZE; 165981cb6ddcSMark Murray len = opt_replyend - opt_reply; 166081cb6ddcSMark Murray opt_reply = (unsigned char *)realloc(opt_reply, len); 166181cb6ddcSMark Murray if (opt_reply == NULL) { 166281cb6ddcSMark Murray /*@*/ printf("env_opt_add: realloc() failed!!!\n"); 166381cb6ddcSMark Murray opt_reply = opt_replyp = opt_replyend = NULL; 166481cb6ddcSMark Murray return; 166581cb6ddcSMark Murray } 166681cb6ddcSMark Murray opt_replyp = opt_reply + len - (opt_replyend - opt_replyp); 166781cb6ddcSMark Murray opt_replyend = opt_reply + len; 166881cb6ddcSMark Murray } 166981cb6ddcSMark Murray if (opt_welldefined(ep)) 167081cb6ddcSMark Murray #ifdef OLD_ENVIRON 167181cb6ddcSMark Murray if (telopt_environ == TELOPT_OLD_ENVIRON) 167281cb6ddcSMark Murray *opt_replyp++ = old_env_var; 167381cb6ddcSMark Murray else 167481cb6ddcSMark Murray #endif 167581cb6ddcSMark Murray *opt_replyp++ = NEW_ENV_VAR; 167681cb6ddcSMark Murray else 167781cb6ddcSMark Murray *opt_replyp++ = ENV_USERVAR; 167881cb6ddcSMark Murray for (;;) { 167904c426ccSMark Murray while ((c = *ep++)) { 168081cb6ddcSMark Murray switch(c&0xff) { 168181cb6ddcSMark Murray case IAC: 168281cb6ddcSMark Murray *opt_replyp++ = IAC; 168381cb6ddcSMark Murray break; 168481cb6ddcSMark Murray case NEW_ENV_VAR: 168581cb6ddcSMark Murray case NEW_ENV_VALUE: 168681cb6ddcSMark Murray case ENV_ESC: 168781cb6ddcSMark Murray case ENV_USERVAR: 168881cb6ddcSMark Murray *opt_replyp++ = ENV_ESC; 168981cb6ddcSMark Murray break; 169081cb6ddcSMark Murray } 169181cb6ddcSMark Murray *opt_replyp++ = c; 169281cb6ddcSMark Murray } 169304c426ccSMark Murray if ((ep = vp)) { 169481cb6ddcSMark Murray #ifdef OLD_ENVIRON 169581cb6ddcSMark Murray if (telopt_environ == TELOPT_OLD_ENVIRON) 169681cb6ddcSMark Murray *opt_replyp++ = old_env_value; 169781cb6ddcSMark Murray else 169881cb6ddcSMark Murray #endif 169981cb6ddcSMark Murray *opt_replyp++ = NEW_ENV_VALUE; 170081cb6ddcSMark Murray vp = NULL; 170181cb6ddcSMark Murray } else 170281cb6ddcSMark Murray break; 170381cb6ddcSMark Murray } 170481cb6ddcSMark Murray } 170581cb6ddcSMark Murray 170681cb6ddcSMark Murray int 170781cb6ddcSMark Murray opt_welldefined(ep) 170881cb6ddcSMark Murray char *ep; 170981cb6ddcSMark Murray { 171081cb6ddcSMark Murray if ((strcmp(ep, "USER") == 0) || 171181cb6ddcSMark Murray (strcmp(ep, "DISPLAY") == 0) || 171281cb6ddcSMark Murray (strcmp(ep, "PRINTER") == 0) || 171381cb6ddcSMark Murray (strcmp(ep, "SYSTEMTYPE") == 0) || 171481cb6ddcSMark Murray (strcmp(ep, "JOB") == 0) || 171581cb6ddcSMark Murray (strcmp(ep, "ACCT") == 0)) 171681cb6ddcSMark Murray return(1); 171781cb6ddcSMark Murray return(0); 171881cb6ddcSMark Murray } 171981cb6ddcSMark Murray void 172081cb6ddcSMark Murray env_opt_end(emptyok) 172181cb6ddcSMark Murray register int emptyok; 172281cb6ddcSMark Murray { 172381cb6ddcSMark Murray register int len; 172481cb6ddcSMark Murray 172581cb6ddcSMark Murray len = opt_replyp - opt_reply + 2; 172681cb6ddcSMark Murray if (emptyok || len > 6) { 172781cb6ddcSMark Murray *opt_replyp++ = IAC; 172881cb6ddcSMark Murray *opt_replyp++ = SE; 172981cb6ddcSMark Murray if (NETROOM() > len) { 173081cb6ddcSMark Murray ring_supply_data(&netoring, opt_reply, len); 173181cb6ddcSMark Murray printsub('>', &opt_reply[2], len - 2); 173281cb6ddcSMark Murray } 173381cb6ddcSMark Murray /*@*/ else printf("slc_end_reply: not enough room\n"); 173481cb6ddcSMark Murray } 173581cb6ddcSMark Murray if (opt_reply) { 173681cb6ddcSMark Murray free(opt_reply); 173781cb6ddcSMark Murray opt_reply = opt_replyp = opt_replyend = NULL; 173881cb6ddcSMark Murray } 173981cb6ddcSMark Murray } 174081cb6ddcSMark Murray 174181cb6ddcSMark Murray 174281cb6ddcSMark Murray 174381cb6ddcSMark Murray int 174481cb6ddcSMark Murray telrcv() 174581cb6ddcSMark Murray { 174681cb6ddcSMark Murray register int c; 174781cb6ddcSMark Murray register int scc; 174881cb6ddcSMark Murray register unsigned char *sbp; 174981cb6ddcSMark Murray int count; 175081cb6ddcSMark Murray int returnValue = 0; 175181cb6ddcSMark Murray 175281cb6ddcSMark Murray scc = 0; 175381cb6ddcSMark Murray count = 0; 175481cb6ddcSMark Murray while (TTYROOM() > 2) { 175581cb6ddcSMark Murray if (scc == 0) { 175681cb6ddcSMark Murray if (count) { 175781cb6ddcSMark Murray ring_consumed(&netiring, count); 175881cb6ddcSMark Murray returnValue = 1; 175981cb6ddcSMark Murray count = 0; 176081cb6ddcSMark Murray } 176181cb6ddcSMark Murray sbp = netiring.consume; 176281cb6ddcSMark Murray scc = ring_full_consecutive(&netiring); 176381cb6ddcSMark Murray if (scc == 0) { 176481cb6ddcSMark Murray /* No more data coming in */ 176581cb6ddcSMark Murray break; 176681cb6ddcSMark Murray } 176781cb6ddcSMark Murray } 176881cb6ddcSMark Murray 176981cb6ddcSMark Murray c = *sbp++ & 0xff, scc--; count++; 177081cb6ddcSMark Murray #ifdef ENCRYPTION 177181cb6ddcSMark Murray if (decrypt_input) 177281cb6ddcSMark Murray c = (*decrypt_input)(c); 177381cb6ddcSMark Murray #endif /* ENCRYPTION */ 177481cb6ddcSMark Murray 177581cb6ddcSMark Murray switch (telrcv_state) { 177681cb6ddcSMark Murray 177781cb6ddcSMark Murray case TS_CR: 177881cb6ddcSMark Murray telrcv_state = TS_DATA; 177981cb6ddcSMark Murray if (c == '\0') { 178081cb6ddcSMark Murray break; /* Ignore \0 after CR */ 178181cb6ddcSMark Murray } 178281cb6ddcSMark Murray else if ((c == '\n') && my_want_state_is_dont(TELOPT_ECHO) && !crmod) { 178381cb6ddcSMark Murray TTYADD(c); 178481cb6ddcSMark Murray break; 178581cb6ddcSMark Murray } 178681cb6ddcSMark Murray /* Else, fall through */ 178781cb6ddcSMark Murray 178881cb6ddcSMark Murray case TS_DATA: 178981cb6ddcSMark Murray if (c == IAC) { 179081cb6ddcSMark Murray telrcv_state = TS_IAC; 179181cb6ddcSMark Murray break; 179281cb6ddcSMark Murray } 179381cb6ddcSMark Murray # if defined(TN3270) 179481cb6ddcSMark Murray if (In3270) { 179581cb6ddcSMark Murray *Ifrontp++ = c; 179681cb6ddcSMark Murray while (scc > 0) { 179781cb6ddcSMark Murray c = *sbp++ & 0377, scc--; count++; 179881cb6ddcSMark Murray #ifdef ENCRYPTION 179981cb6ddcSMark Murray if (decrypt_input) 180081cb6ddcSMark Murray c = (*decrypt_input)(c); 180181cb6ddcSMark Murray #endif /* ENCRYPTION */ 180281cb6ddcSMark Murray if (c == IAC) { 180381cb6ddcSMark Murray telrcv_state = TS_IAC; 180481cb6ddcSMark Murray break; 180581cb6ddcSMark Murray } 180681cb6ddcSMark Murray *Ifrontp++ = c; 180781cb6ddcSMark Murray } 180881cb6ddcSMark Murray } else 180981cb6ddcSMark Murray # endif /* defined(TN3270) */ 181081cb6ddcSMark Murray /* 181181cb6ddcSMark Murray * The 'crmod' hack (see following) is needed 181281cb6ddcSMark Murray * since we can't * set CRMOD on output only. 181381cb6ddcSMark Murray * Machines like MULTICS like to send \r without 181481cb6ddcSMark Murray * \n; since we must turn off CRMOD to get proper 181581cb6ddcSMark Murray * input, the mapping is done here (sigh). 181681cb6ddcSMark Murray */ 181781cb6ddcSMark Murray if ((c == '\r') && my_want_state_is_dont(TELOPT_BINARY)) { 181881cb6ddcSMark Murray if (scc > 0) { 181981cb6ddcSMark Murray c = *sbp&0xff; 182081cb6ddcSMark Murray #ifdef ENCRYPTION 182181cb6ddcSMark Murray if (decrypt_input) 182281cb6ddcSMark Murray c = (*decrypt_input)(c); 182381cb6ddcSMark Murray #endif /* ENCRYPTION */ 182481cb6ddcSMark Murray if (c == 0) { 182581cb6ddcSMark Murray sbp++, scc--; count++; 182681cb6ddcSMark Murray /* a "true" CR */ 182781cb6ddcSMark Murray TTYADD('\r'); 182881cb6ddcSMark Murray } else if (my_want_state_is_dont(TELOPT_ECHO) && 182981cb6ddcSMark Murray (c == '\n')) { 183081cb6ddcSMark Murray sbp++, scc--; count++; 183181cb6ddcSMark Murray TTYADD('\n'); 183281cb6ddcSMark Murray } else { 183381cb6ddcSMark Murray #ifdef ENCRYPTION 183481cb6ddcSMark Murray if (decrypt_input) 183581cb6ddcSMark Murray (*decrypt_input)(-1); 183681cb6ddcSMark Murray #endif /* ENCRYPTION */ 183781cb6ddcSMark Murray 183881cb6ddcSMark Murray TTYADD('\r'); 183981cb6ddcSMark Murray if (crmod) { 184081cb6ddcSMark Murray TTYADD('\n'); 184181cb6ddcSMark Murray } 184281cb6ddcSMark Murray } 184381cb6ddcSMark Murray } else { 184481cb6ddcSMark Murray telrcv_state = TS_CR; 184581cb6ddcSMark Murray TTYADD('\r'); 184681cb6ddcSMark Murray if (crmod) { 184781cb6ddcSMark Murray TTYADD('\n'); 184881cb6ddcSMark Murray } 184981cb6ddcSMark Murray } 185081cb6ddcSMark Murray } else { 185181cb6ddcSMark Murray TTYADD(c); 185281cb6ddcSMark Murray } 185381cb6ddcSMark Murray continue; 185481cb6ddcSMark Murray 185581cb6ddcSMark Murray case TS_IAC: 185681cb6ddcSMark Murray process_iac: 185781cb6ddcSMark Murray switch (c) { 185881cb6ddcSMark Murray 185981cb6ddcSMark Murray case WILL: 186081cb6ddcSMark Murray telrcv_state = TS_WILL; 186181cb6ddcSMark Murray continue; 186281cb6ddcSMark Murray 186381cb6ddcSMark Murray case WONT: 186481cb6ddcSMark Murray telrcv_state = TS_WONT; 186581cb6ddcSMark Murray continue; 186681cb6ddcSMark Murray 186781cb6ddcSMark Murray case DO: 186881cb6ddcSMark Murray telrcv_state = TS_DO; 186981cb6ddcSMark Murray continue; 187081cb6ddcSMark Murray 187181cb6ddcSMark Murray case DONT: 187281cb6ddcSMark Murray telrcv_state = TS_DONT; 187381cb6ddcSMark Murray continue; 187481cb6ddcSMark Murray 187581cb6ddcSMark Murray case DM: 187681cb6ddcSMark Murray /* 187781cb6ddcSMark Murray * We may have missed an urgent notification, 187881cb6ddcSMark Murray * so make sure we flush whatever is in the 187981cb6ddcSMark Murray * buffer currently. 188081cb6ddcSMark Murray */ 188181cb6ddcSMark Murray printoption("RCVD", IAC, DM); 188281cb6ddcSMark Murray SYNCHing = 1; 188381cb6ddcSMark Murray (void) ttyflush(1); 188481cb6ddcSMark Murray SYNCHing = stilloob(); 188581cb6ddcSMark Murray settimer(gotDM); 188681cb6ddcSMark Murray break; 188781cb6ddcSMark Murray 188881cb6ddcSMark Murray case SB: 188981cb6ddcSMark Murray SB_CLEAR(); 189081cb6ddcSMark Murray telrcv_state = TS_SB; 189181cb6ddcSMark Murray continue; 189281cb6ddcSMark Murray 189381cb6ddcSMark Murray # if defined(TN3270) 189481cb6ddcSMark Murray case EOR: 189581cb6ddcSMark Murray if (In3270) { 189681cb6ddcSMark Murray if (Ibackp == Ifrontp) { 189781cb6ddcSMark Murray Ibackp = Ifrontp = Ibuf; 189881cb6ddcSMark Murray ISend = 0; /* should have been! */ 189981cb6ddcSMark Murray } else { 190081cb6ddcSMark Murray Ibackp += DataFromNetwork(Ibackp, Ifrontp-Ibackp, 1); 190181cb6ddcSMark Murray ISend = 1; 190281cb6ddcSMark Murray } 190381cb6ddcSMark Murray } 190481cb6ddcSMark Murray printoption("RCVD", IAC, EOR); 190581cb6ddcSMark Murray break; 190681cb6ddcSMark Murray # endif /* defined(TN3270) */ 190781cb6ddcSMark Murray 190881cb6ddcSMark Murray case IAC: 190981cb6ddcSMark Murray # if !defined(TN3270) 191081cb6ddcSMark Murray TTYADD(IAC); 191181cb6ddcSMark Murray # else /* !defined(TN3270) */ 191281cb6ddcSMark Murray if (In3270) { 191381cb6ddcSMark Murray *Ifrontp++ = IAC; 191481cb6ddcSMark Murray } else { 191581cb6ddcSMark Murray TTYADD(IAC); 191681cb6ddcSMark Murray } 191781cb6ddcSMark Murray # endif /* !defined(TN3270) */ 191881cb6ddcSMark Murray break; 191981cb6ddcSMark Murray 192081cb6ddcSMark Murray case NOP: 192181cb6ddcSMark Murray case GA: 192281cb6ddcSMark Murray default: 192381cb6ddcSMark Murray printoption("RCVD", IAC, c); 192481cb6ddcSMark Murray break; 192581cb6ddcSMark Murray } 192681cb6ddcSMark Murray telrcv_state = TS_DATA; 192781cb6ddcSMark Murray continue; 192881cb6ddcSMark Murray 192981cb6ddcSMark Murray case TS_WILL: 193081cb6ddcSMark Murray printoption("RCVD", WILL, c); 193181cb6ddcSMark Murray willoption(c); 193281cb6ddcSMark Murray SetIn3270(); 193381cb6ddcSMark Murray telrcv_state = TS_DATA; 193481cb6ddcSMark Murray continue; 193581cb6ddcSMark Murray 193681cb6ddcSMark Murray case TS_WONT: 193781cb6ddcSMark Murray printoption("RCVD", WONT, c); 193881cb6ddcSMark Murray wontoption(c); 193981cb6ddcSMark Murray SetIn3270(); 194081cb6ddcSMark Murray telrcv_state = TS_DATA; 194181cb6ddcSMark Murray continue; 194281cb6ddcSMark Murray 194381cb6ddcSMark Murray case TS_DO: 194481cb6ddcSMark Murray printoption("RCVD", DO, c); 194581cb6ddcSMark Murray dooption(c); 194681cb6ddcSMark Murray SetIn3270(); 194781cb6ddcSMark Murray if (c == TELOPT_NAWS) { 194881cb6ddcSMark Murray sendnaws(); 194981cb6ddcSMark Murray } else if (c == TELOPT_LFLOW) { 195081cb6ddcSMark Murray localflow = 1; 195181cb6ddcSMark Murray setcommandmode(); 195281cb6ddcSMark Murray setconnmode(0); 195381cb6ddcSMark Murray } 195481cb6ddcSMark Murray telrcv_state = TS_DATA; 195581cb6ddcSMark Murray continue; 195681cb6ddcSMark Murray 195781cb6ddcSMark Murray case TS_DONT: 195881cb6ddcSMark Murray printoption("RCVD", DONT, c); 195981cb6ddcSMark Murray dontoption(c); 196081cb6ddcSMark Murray flushline = 1; 196181cb6ddcSMark Murray setconnmode(0); /* set new tty mode (maybe) */ 196281cb6ddcSMark Murray SetIn3270(); 196381cb6ddcSMark Murray telrcv_state = TS_DATA; 196481cb6ddcSMark Murray continue; 196581cb6ddcSMark Murray 196681cb6ddcSMark Murray case TS_SB: 196781cb6ddcSMark Murray if (c == IAC) { 196881cb6ddcSMark Murray telrcv_state = TS_SE; 196981cb6ddcSMark Murray } else { 197081cb6ddcSMark Murray SB_ACCUM(c); 197181cb6ddcSMark Murray } 197281cb6ddcSMark Murray continue; 197381cb6ddcSMark Murray 197481cb6ddcSMark Murray case TS_SE: 197581cb6ddcSMark Murray if (c != SE) { 197681cb6ddcSMark Murray if (c != IAC) { 197781cb6ddcSMark Murray /* 197881cb6ddcSMark Murray * This is an error. We only expect to get 197981cb6ddcSMark Murray * "IAC IAC" or "IAC SE". Several things may 198081cb6ddcSMark Murray * have happend. An IAC was not doubled, the 198181cb6ddcSMark Murray * IAC SE was left off, or another option got 198281cb6ddcSMark Murray * inserted into the suboption are all possibilities. 198381cb6ddcSMark Murray * If we assume that the IAC was not doubled, 198481cb6ddcSMark Murray * and really the IAC SE was left off, we could 198581cb6ddcSMark Murray * get into an infinate loop here. So, instead, 198681cb6ddcSMark Murray * we terminate the suboption, and process the 198781cb6ddcSMark Murray * partial suboption if we can. 198881cb6ddcSMark Murray */ 198981cb6ddcSMark Murray SB_ACCUM(IAC); 199081cb6ddcSMark Murray SB_ACCUM(c); 199181cb6ddcSMark Murray subpointer -= 2; 199281cb6ddcSMark Murray SB_TERM(); 199381cb6ddcSMark Murray 199481cb6ddcSMark Murray printoption("In SUBOPTION processing, RCVD", IAC, c); 199581cb6ddcSMark Murray suboption(); /* handle sub-option */ 199681cb6ddcSMark Murray SetIn3270(); 199781cb6ddcSMark Murray telrcv_state = TS_IAC; 199881cb6ddcSMark Murray goto process_iac; 199981cb6ddcSMark Murray } 200081cb6ddcSMark Murray SB_ACCUM(c); 200181cb6ddcSMark Murray telrcv_state = TS_SB; 200281cb6ddcSMark Murray } else { 200381cb6ddcSMark Murray SB_ACCUM(IAC); 200481cb6ddcSMark Murray SB_ACCUM(SE); 200581cb6ddcSMark Murray subpointer -= 2; 200681cb6ddcSMark Murray SB_TERM(); 200781cb6ddcSMark Murray suboption(); /* handle sub-option */ 200881cb6ddcSMark Murray SetIn3270(); 200981cb6ddcSMark Murray telrcv_state = TS_DATA; 201081cb6ddcSMark Murray } 201181cb6ddcSMark Murray } 201281cb6ddcSMark Murray } 201381cb6ddcSMark Murray if (count) 201481cb6ddcSMark Murray ring_consumed(&netiring, count); 201581cb6ddcSMark Murray return returnValue||count; 201681cb6ddcSMark Murray } 201781cb6ddcSMark Murray 201881cb6ddcSMark Murray static int bol = 1, local = 0; 201981cb6ddcSMark Murray 202081cb6ddcSMark Murray int 202181cb6ddcSMark Murray rlogin_susp() 202281cb6ddcSMark Murray { 202381cb6ddcSMark Murray if (local) { 202481cb6ddcSMark Murray local = 0; 202581cb6ddcSMark Murray bol = 1; 202681cb6ddcSMark Murray command(0, "z\n", 2); 202781cb6ddcSMark Murray return(1); 202881cb6ddcSMark Murray } 202981cb6ddcSMark Murray return(0); 203081cb6ddcSMark Murray } 203181cb6ddcSMark Murray 203281cb6ddcSMark Murray static int 203381cb6ddcSMark Murray telsnd() 203481cb6ddcSMark Murray { 203581cb6ddcSMark Murray int tcc; 203681cb6ddcSMark Murray int count; 203781cb6ddcSMark Murray int returnValue = 0; 203881cb6ddcSMark Murray unsigned char *tbp; 203981cb6ddcSMark Murray 204081cb6ddcSMark Murray tcc = 0; 204181cb6ddcSMark Murray count = 0; 204281cb6ddcSMark Murray while (NETROOM() > 2) { 204381cb6ddcSMark Murray register int sc; 204481cb6ddcSMark Murray register int c; 204581cb6ddcSMark Murray 204681cb6ddcSMark Murray if (tcc == 0) { 204781cb6ddcSMark Murray if (count) { 204881cb6ddcSMark Murray ring_consumed(&ttyiring, count); 204981cb6ddcSMark Murray returnValue = 1; 205081cb6ddcSMark Murray count = 0; 205181cb6ddcSMark Murray } 205281cb6ddcSMark Murray tbp = ttyiring.consume; 205381cb6ddcSMark Murray tcc = ring_full_consecutive(&ttyiring); 205481cb6ddcSMark Murray if (tcc == 0) { 205581cb6ddcSMark Murray break; 205681cb6ddcSMark Murray } 205781cb6ddcSMark Murray } 205881cb6ddcSMark Murray c = *tbp++ & 0xff, sc = strip(c), tcc--; count++; 205981cb6ddcSMark Murray if (rlogin != _POSIX_VDISABLE) { 206081cb6ddcSMark Murray if (bol) { 206181cb6ddcSMark Murray bol = 0; 206281cb6ddcSMark Murray if (sc == rlogin) { 206381cb6ddcSMark Murray local = 1; 206481cb6ddcSMark Murray continue; 206581cb6ddcSMark Murray } 206681cb6ddcSMark Murray } else if (local) { 206781cb6ddcSMark Murray local = 0; 206881cb6ddcSMark Murray if (sc == '.' || c == termEofChar) { 206981cb6ddcSMark Murray bol = 1; 207081cb6ddcSMark Murray command(0, "close\n", 6); 207181cb6ddcSMark Murray continue; 207281cb6ddcSMark Murray } 207381cb6ddcSMark Murray if (sc == termSuspChar) { 207481cb6ddcSMark Murray bol = 1; 207581cb6ddcSMark Murray command(0, "z\n", 2); 207681cb6ddcSMark Murray continue; 207781cb6ddcSMark Murray } 207881cb6ddcSMark Murray if (sc == escape) { 207981cb6ddcSMark Murray command(0, (char *)tbp, tcc); 208081cb6ddcSMark Murray bol = 1; 208181cb6ddcSMark Murray count += tcc; 208281cb6ddcSMark Murray tcc = 0; 208381cb6ddcSMark Murray flushline = 1; 208481cb6ddcSMark Murray break; 208581cb6ddcSMark Murray } 208681cb6ddcSMark Murray if (sc != rlogin) { 208781cb6ddcSMark Murray ++tcc; 208881cb6ddcSMark Murray --tbp; 208981cb6ddcSMark Murray --count; 209081cb6ddcSMark Murray c = sc = rlogin; 209181cb6ddcSMark Murray } 209281cb6ddcSMark Murray } 209381cb6ddcSMark Murray if ((sc == '\n') || (sc == '\r')) 209481cb6ddcSMark Murray bol = 1; 209542cf8219SRuslan Ermilov } else if (escape != _POSIX_VDISABLE && sc == escape) { 209681cb6ddcSMark Murray /* 209781cb6ddcSMark Murray * Double escape is a pass through of a single escape character. 209881cb6ddcSMark Murray */ 209981cb6ddcSMark Murray if (tcc && strip(*tbp) == escape) { 210081cb6ddcSMark Murray tbp++; 210181cb6ddcSMark Murray tcc--; 210281cb6ddcSMark Murray count++; 210381cb6ddcSMark Murray bol = 0; 210481cb6ddcSMark Murray } else { 210581cb6ddcSMark Murray command(0, (char *)tbp, tcc); 210681cb6ddcSMark Murray bol = 1; 210781cb6ddcSMark Murray count += tcc; 210881cb6ddcSMark Murray tcc = 0; 210981cb6ddcSMark Murray flushline = 1; 211081cb6ddcSMark Murray break; 211181cb6ddcSMark Murray } 211281cb6ddcSMark Murray } else 211381cb6ddcSMark Murray bol = 0; 211481cb6ddcSMark Murray #ifdef KLUDGELINEMODE 211581cb6ddcSMark Murray if (kludgelinemode && (globalmode&MODE_EDIT) && (sc == echoc)) { 211681cb6ddcSMark Murray if (tcc > 0 && strip(*tbp) == echoc) { 211781cb6ddcSMark Murray tcc--; tbp++; count++; 211881cb6ddcSMark Murray } else { 211981cb6ddcSMark Murray dontlecho = !dontlecho; 212081cb6ddcSMark Murray settimer(echotoggle); 212181cb6ddcSMark Murray setconnmode(0); 212281cb6ddcSMark Murray flushline = 1; 212381cb6ddcSMark Murray break; 212481cb6ddcSMark Murray } 212581cb6ddcSMark Murray } 212681cb6ddcSMark Murray #endif 212781cb6ddcSMark Murray if (MODE_LOCAL_CHARS(globalmode)) { 212881cb6ddcSMark Murray if (TerminalSpecialChars(sc) == 0) { 212981cb6ddcSMark Murray bol = 1; 213081cb6ddcSMark Murray break; 213181cb6ddcSMark Murray } 213281cb6ddcSMark Murray } 213381cb6ddcSMark Murray if (my_want_state_is_wont(TELOPT_BINARY)) { 213481cb6ddcSMark Murray switch (c) { 213581cb6ddcSMark Murray case '\n': 213681cb6ddcSMark Murray /* 213781cb6ddcSMark Murray * If we are in CRMOD mode (\r ==> \n) 213881cb6ddcSMark Murray * on our local machine, then probably 213981cb6ddcSMark Murray * a newline (unix) is CRLF (TELNET). 214081cb6ddcSMark Murray */ 214181cb6ddcSMark Murray if (MODE_LOCAL_CHARS(globalmode)) { 214281cb6ddcSMark Murray NETADD('\r'); 214381cb6ddcSMark Murray } 214481cb6ddcSMark Murray NETADD('\n'); 214581cb6ddcSMark Murray bol = flushline = 1; 214681cb6ddcSMark Murray break; 214781cb6ddcSMark Murray case '\r': 214881cb6ddcSMark Murray if (!crlf) { 214981cb6ddcSMark Murray NET2ADD('\r', '\0'); 215081cb6ddcSMark Murray } else { 215181cb6ddcSMark Murray NET2ADD('\r', '\n'); 215281cb6ddcSMark Murray } 215381cb6ddcSMark Murray bol = flushline = 1; 215481cb6ddcSMark Murray break; 215581cb6ddcSMark Murray case IAC: 215681cb6ddcSMark Murray NET2ADD(IAC, IAC); 215781cb6ddcSMark Murray break; 215881cb6ddcSMark Murray default: 215981cb6ddcSMark Murray NETADD(c); 216081cb6ddcSMark Murray break; 216181cb6ddcSMark Murray } 216281cb6ddcSMark Murray } else if (c == IAC) { 216381cb6ddcSMark Murray NET2ADD(IAC, IAC); 216481cb6ddcSMark Murray } else { 216581cb6ddcSMark Murray NETADD(c); 216681cb6ddcSMark Murray } 216781cb6ddcSMark Murray } 216881cb6ddcSMark Murray if (count) 216981cb6ddcSMark Murray ring_consumed(&ttyiring, count); 217081cb6ddcSMark Murray return returnValue||count; /* Non-zero if we did anything */ 217181cb6ddcSMark Murray } 217281cb6ddcSMark Murray 217381cb6ddcSMark Murray /* 217481cb6ddcSMark Murray * Scheduler() 217581cb6ddcSMark Murray * 217681cb6ddcSMark Murray * Try to do something. 217781cb6ddcSMark Murray * 217881cb6ddcSMark Murray * If we do something useful, return 1; else return 0. 217981cb6ddcSMark Murray * 218081cb6ddcSMark Murray */ 218181cb6ddcSMark Murray 218281cb6ddcSMark Murray 218381cb6ddcSMark Murray int 218481cb6ddcSMark Murray Scheduler(block) 218581cb6ddcSMark Murray int block; /* should we block in the select ? */ 218681cb6ddcSMark Murray { 218781cb6ddcSMark Murray /* One wants to be a bit careful about setting returnValue 218881cb6ddcSMark Murray * to one, since a one implies we did some useful work, 218981cb6ddcSMark Murray * and therefore probably won't be called to block next 219081cb6ddcSMark Murray * time (TN3270 mode only). 219181cb6ddcSMark Murray */ 219281cb6ddcSMark Murray int returnValue; 219381cb6ddcSMark Murray int netin, netout, netex, ttyin, ttyout; 219481cb6ddcSMark Murray 219581cb6ddcSMark Murray /* Decide which rings should be processed */ 219681cb6ddcSMark Murray 219781cb6ddcSMark Murray netout = ring_full_count(&netoring) && 219881cb6ddcSMark Murray (flushline || 219981cb6ddcSMark Murray (my_want_state_is_wont(TELOPT_LINEMODE) 220081cb6ddcSMark Murray #ifdef KLUDGELINEMODE 220181cb6ddcSMark Murray && (!kludgelinemode || my_want_state_is_do(TELOPT_SGA)) 220281cb6ddcSMark Murray #endif 220381cb6ddcSMark Murray ) || 220481cb6ddcSMark Murray my_want_state_is_will(TELOPT_BINARY)); 220581cb6ddcSMark Murray ttyout = ring_full_count(&ttyoring); 220681cb6ddcSMark Murray 220781cb6ddcSMark Murray #if defined(TN3270) 220804c426ccSMark Murray ttyin = ring_empty_count(&ttyiring) && (clienteof == 0) && (shell_active == 0); 220981cb6ddcSMark Murray #else /* defined(TN3270) */ 221004c426ccSMark Murray ttyin = ring_empty_count(&ttyiring) && (clienteof == 0); 221181cb6ddcSMark Murray #endif /* defined(TN3270) */ 221281cb6ddcSMark Murray 221381cb6ddcSMark Murray #if defined(TN3270) 221481cb6ddcSMark Murray netin = ring_empty_count(&netiring); 221581cb6ddcSMark Murray # else /* !defined(TN3270) */ 221681cb6ddcSMark Murray netin = !ISend && ring_empty_count(&netiring); 221781cb6ddcSMark Murray # endif /* !defined(TN3270) */ 221881cb6ddcSMark Murray 221981cb6ddcSMark Murray netex = !SYNCHing; 222081cb6ddcSMark Murray 222181cb6ddcSMark Murray /* If we have seen a signal recently, reset things */ 222281cb6ddcSMark Murray # if defined(TN3270) && defined(unix) 222381cb6ddcSMark Murray if (HaveInput) { 222481cb6ddcSMark Murray HaveInput = 0; 222581cb6ddcSMark Murray (void) signal(SIGIO, inputAvailable); 222681cb6ddcSMark Murray } 222781cb6ddcSMark Murray #endif /* defined(TN3270) && defined(unix) */ 222881cb6ddcSMark Murray 222981cb6ddcSMark Murray /* Call to system code to process rings */ 223081cb6ddcSMark Murray 223181cb6ddcSMark Murray returnValue = process_rings(netin, netout, netex, ttyin, ttyout, !block); 223281cb6ddcSMark Murray 223381cb6ddcSMark Murray /* Now, look at the input rings, looking for work to do. */ 223481cb6ddcSMark Murray 223581cb6ddcSMark Murray if (ring_full_count(&ttyiring)) { 223681cb6ddcSMark Murray # if defined(TN3270) 223781cb6ddcSMark Murray if (In3270) { 223881cb6ddcSMark Murray int c; 223981cb6ddcSMark Murray 224081cb6ddcSMark Murray c = DataFromTerminal(ttyiring.consume, 224181cb6ddcSMark Murray ring_full_consecutive(&ttyiring)); 224281cb6ddcSMark Murray if (c) { 224381cb6ddcSMark Murray returnValue = 1; 224481cb6ddcSMark Murray ring_consumed(&ttyiring, c); 224581cb6ddcSMark Murray } 224681cb6ddcSMark Murray } else { 224781cb6ddcSMark Murray # endif /* defined(TN3270) */ 224881cb6ddcSMark Murray returnValue |= telsnd(); 224981cb6ddcSMark Murray # if defined(TN3270) 225081cb6ddcSMark Murray } 225181cb6ddcSMark Murray # endif /* defined(TN3270) */ 225281cb6ddcSMark Murray } 225381cb6ddcSMark Murray 225481cb6ddcSMark Murray if (ring_full_count(&netiring)) { 225581cb6ddcSMark Murray # if !defined(TN3270) 225681cb6ddcSMark Murray returnValue |= telrcv(); 225781cb6ddcSMark Murray # else /* !defined(TN3270) */ 225881cb6ddcSMark Murray returnValue = Push3270(); 225981cb6ddcSMark Murray # endif /* !defined(TN3270) */ 226081cb6ddcSMark Murray } 226181cb6ddcSMark Murray return returnValue; 226281cb6ddcSMark Murray } 226381cb6ddcSMark Murray 226481cb6ddcSMark Murray /* 226581cb6ddcSMark Murray * Select from tty and network... 226681cb6ddcSMark Murray */ 226781cb6ddcSMark Murray void 226881cb6ddcSMark Murray telnet(user) 226981cb6ddcSMark Murray char *user; 227081cb6ddcSMark Murray { 227181cb6ddcSMark Murray sys_telnet_init(); 227281cb6ddcSMark Murray 227381cb6ddcSMark Murray #if defined(AUTHENTICATION) || defined(ENCRYPTION) 227481cb6ddcSMark Murray { 227581cb6ddcSMark Murray static char local_host[256] = { 0 }; 227681cb6ddcSMark Murray 227781cb6ddcSMark Murray if (!local_host[0]) { 227881cb6ddcSMark Murray gethostname(local_host, sizeof(local_host)); 227981cb6ddcSMark Murray local_host[sizeof(local_host)-1] = 0; 228081cb6ddcSMark Murray } 228181cb6ddcSMark Murray auth_encrypt_init(local_host, hostname, "TELNET", 0); 228281cb6ddcSMark Murray auth_encrypt_user(user); 228381cb6ddcSMark Murray } 228481cb6ddcSMark Murray #endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */ 228581cb6ddcSMark Murray # if !defined(TN3270) 228681cb6ddcSMark Murray if (telnetport) { 228781cb6ddcSMark Murray #if defined(AUTHENTICATION) 228881cb6ddcSMark Murray if (autologin) 228981cb6ddcSMark Murray send_will(TELOPT_AUTHENTICATION, 1); 229081cb6ddcSMark Murray #endif 229181cb6ddcSMark Murray #ifdef ENCRYPTION 229281cb6ddcSMark Murray send_do(TELOPT_ENCRYPT, 1); 229381cb6ddcSMark Murray send_will(TELOPT_ENCRYPT, 1); 229481cb6ddcSMark Murray #endif /* ENCRYPTION */ 229581cb6ddcSMark Murray send_do(TELOPT_SGA, 1); 229681cb6ddcSMark Murray send_will(TELOPT_TTYPE, 1); 229781cb6ddcSMark Murray send_will(TELOPT_NAWS, 1); 229881cb6ddcSMark Murray send_will(TELOPT_TSPEED, 1); 229981cb6ddcSMark Murray send_will(TELOPT_LFLOW, 1); 230081cb6ddcSMark Murray send_will(TELOPT_LINEMODE, 1); 230181cb6ddcSMark Murray send_will(TELOPT_NEW_ENVIRON, 1); 230281cb6ddcSMark Murray send_do(TELOPT_STATUS, 1); 230381cb6ddcSMark Murray if (env_getvalue((unsigned char *)"DISPLAY")) 230481cb6ddcSMark Murray send_will(TELOPT_XDISPLOC, 1); 230581cb6ddcSMark Murray if (eight) 230681cb6ddcSMark Murray tel_enter_binary(eight); 230781cb6ddcSMark Murray } 230881cb6ddcSMark Murray # endif /* !defined(TN3270) */ 230981cb6ddcSMark Murray 231081cb6ddcSMark Murray # if !defined(TN3270) 231181cb6ddcSMark Murray for (;;) { 231281cb6ddcSMark Murray int schedValue; 231381cb6ddcSMark Murray 231481cb6ddcSMark Murray while ((schedValue = Scheduler(0)) != 0) { 231581cb6ddcSMark Murray if (schedValue == -1) { 231681cb6ddcSMark Murray setcommandmode(); 231781cb6ddcSMark Murray return; 231881cb6ddcSMark Murray } 231981cb6ddcSMark Murray } 232081cb6ddcSMark Murray 232181cb6ddcSMark Murray if (Scheduler(1) == -1) { 232281cb6ddcSMark Murray setcommandmode(); 232381cb6ddcSMark Murray return; 232481cb6ddcSMark Murray } 232581cb6ddcSMark Murray } 232681cb6ddcSMark Murray # else /* !defined(TN3270) */ 232781cb6ddcSMark Murray for (;;) { 232881cb6ddcSMark Murray int schedValue; 232981cb6ddcSMark Murray 233081cb6ddcSMark Murray while (!In3270 && !shell_active) { 233181cb6ddcSMark Murray if (Scheduler(1) == -1) { 233281cb6ddcSMark Murray setcommandmode(); 233381cb6ddcSMark Murray return; 233481cb6ddcSMark Murray } 233581cb6ddcSMark Murray } 233681cb6ddcSMark Murray 233781cb6ddcSMark Murray while ((schedValue = Scheduler(0)) != 0) { 233881cb6ddcSMark Murray if (schedValue == -1) { 233981cb6ddcSMark Murray setcommandmode(); 234081cb6ddcSMark Murray return; 234181cb6ddcSMark Murray } 234281cb6ddcSMark Murray } 234381cb6ddcSMark Murray /* If there is data waiting to go out to terminal, don't 234481cb6ddcSMark Murray * schedule any more data for the terminal. 234581cb6ddcSMark Murray */ 234681cb6ddcSMark Murray if (ring_full_count(&ttyoring)) { 234781cb6ddcSMark Murray schedValue = 1; 234881cb6ddcSMark Murray } else { 234981cb6ddcSMark Murray if (shell_active) { 235081cb6ddcSMark Murray if (shell_continue() == 0) { 235181cb6ddcSMark Murray ConnectScreen(); 235281cb6ddcSMark Murray } 235381cb6ddcSMark Murray } else if (In3270) { 235481cb6ddcSMark Murray schedValue = DoTerminalOutput(); 235581cb6ddcSMark Murray } 235681cb6ddcSMark Murray } 235781cb6ddcSMark Murray if (schedValue && (shell_active == 0)) { 235881cb6ddcSMark Murray if (Scheduler(1) == -1) { 235981cb6ddcSMark Murray setcommandmode(); 236081cb6ddcSMark Murray return; 236181cb6ddcSMark Murray } 236281cb6ddcSMark Murray } 236381cb6ddcSMark Murray } 236481cb6ddcSMark Murray # endif /* !defined(TN3270) */ 236581cb6ddcSMark Murray } 236681cb6ddcSMark Murray 236781cb6ddcSMark Murray #if 0 /* XXX - this not being in is a bug */ 236881cb6ddcSMark Murray /* 236981cb6ddcSMark Murray * nextitem() 237081cb6ddcSMark Murray * 237181cb6ddcSMark Murray * Return the address of the next "item" in the TELNET data 237281cb6ddcSMark Murray * stream. This will be the address of the next character if 237381cb6ddcSMark Murray * the current address is a user data character, or it will 237481cb6ddcSMark Murray * be the address of the character following the TELNET command 237581cb6ddcSMark Murray * if the current address is a TELNET IAC ("I Am a Command") 237681cb6ddcSMark Murray * character. 237781cb6ddcSMark Murray */ 237881cb6ddcSMark Murray 237981cb6ddcSMark Murray static char * 238081cb6ddcSMark Murray nextitem(current) 238181cb6ddcSMark Murray char *current; 238281cb6ddcSMark Murray { 238381cb6ddcSMark Murray if ((*current&0xff) != IAC) { 238481cb6ddcSMark Murray return current+1; 238581cb6ddcSMark Murray } 238681cb6ddcSMark Murray switch (*(current+1)&0xff) { 238781cb6ddcSMark Murray case DO: 238881cb6ddcSMark Murray case DONT: 238981cb6ddcSMark Murray case WILL: 239081cb6ddcSMark Murray case WONT: 239181cb6ddcSMark Murray return current+3; 239281cb6ddcSMark Murray case SB: /* loop forever looking for the SE */ 239381cb6ddcSMark Murray { 239481cb6ddcSMark Murray register char *look = current+2; 239581cb6ddcSMark Murray 239681cb6ddcSMark Murray for (;;) { 239781cb6ddcSMark Murray if ((*look++&0xff) == IAC) { 239881cb6ddcSMark Murray if ((*look++&0xff) == SE) { 239981cb6ddcSMark Murray return look; 240081cb6ddcSMark Murray } 240181cb6ddcSMark Murray } 240281cb6ddcSMark Murray } 240381cb6ddcSMark Murray } 240481cb6ddcSMark Murray default: 240581cb6ddcSMark Murray return current+2; 240681cb6ddcSMark Murray } 240781cb6ddcSMark Murray } 240881cb6ddcSMark Murray #endif /* 0 */ 240981cb6ddcSMark Murray 241081cb6ddcSMark Murray /* 241181cb6ddcSMark Murray * netclear() 241281cb6ddcSMark Murray * 241381cb6ddcSMark Murray * We are about to do a TELNET SYNCH operation. Clear 241481cb6ddcSMark Murray * the path to the network. 241581cb6ddcSMark Murray * 241681cb6ddcSMark Murray * Things are a bit tricky since we may have sent the first 241781cb6ddcSMark Murray * byte or so of a previous TELNET command into the network. 241881cb6ddcSMark Murray * So, we have to scan the network buffer from the beginning 241981cb6ddcSMark Murray * until we are up to where we want to be. 242081cb6ddcSMark Murray * 242181cb6ddcSMark Murray * A side effect of what we do, just to keep things 242281cb6ddcSMark Murray * simple, is to clear the urgent data pointer. The principal 242381cb6ddcSMark Murray * caller should be setting the urgent data pointer AFTER calling 242481cb6ddcSMark Murray * us in any case. 242581cb6ddcSMark Murray */ 242681cb6ddcSMark Murray 242781cb6ddcSMark Murray static void 242881cb6ddcSMark Murray netclear() 242981cb6ddcSMark Murray { 243081cb6ddcSMark Murray #if 0 /* XXX */ 243181cb6ddcSMark Murray register char *thisitem, *next; 243281cb6ddcSMark Murray char *good; 243381cb6ddcSMark Murray #define wewant(p) ((nfrontp > p) && ((*p&0xff) == IAC) && \ 243481cb6ddcSMark Murray ((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL)) 243581cb6ddcSMark Murray 243681cb6ddcSMark Murray thisitem = netobuf; 243781cb6ddcSMark Murray 243881cb6ddcSMark Murray while ((next = nextitem(thisitem)) <= netobuf.send) { 243981cb6ddcSMark Murray thisitem = next; 244081cb6ddcSMark Murray } 244181cb6ddcSMark Murray 244281cb6ddcSMark Murray /* Now, thisitem is first before/at boundary. */ 244381cb6ddcSMark Murray 244481cb6ddcSMark Murray good = netobuf; /* where the good bytes go */ 244581cb6ddcSMark Murray 244681cb6ddcSMark Murray while (netoring.add > thisitem) { 244781cb6ddcSMark Murray if (wewant(thisitem)) { 244881cb6ddcSMark Murray int length; 244981cb6ddcSMark Murray 245081cb6ddcSMark Murray next = thisitem; 245181cb6ddcSMark Murray do { 245281cb6ddcSMark Murray next = nextitem(next); 245381cb6ddcSMark Murray } while (wewant(next) && (nfrontp > next)); 245481cb6ddcSMark Murray length = next-thisitem; 245521f083c0SMark Murray memcpy(good, thisitem, length); 245681cb6ddcSMark Murray good += length; 245781cb6ddcSMark Murray thisitem = next; 245881cb6ddcSMark Murray } else { 245981cb6ddcSMark Murray thisitem = nextitem(thisitem); 246081cb6ddcSMark Murray } 246181cb6ddcSMark Murray } 246281cb6ddcSMark Murray 246381cb6ddcSMark Murray #endif /* 0 */ 246481cb6ddcSMark Murray } 246581cb6ddcSMark Murray 246681cb6ddcSMark Murray /* 246781cb6ddcSMark Murray * These routines add various telnet commands to the data stream. 246881cb6ddcSMark Murray */ 246981cb6ddcSMark Murray 247081cb6ddcSMark Murray static void 247181cb6ddcSMark Murray doflush() 247281cb6ddcSMark Murray { 247381cb6ddcSMark Murray NET2ADD(IAC, DO); 247481cb6ddcSMark Murray NETADD(TELOPT_TM); 247581cb6ddcSMark Murray flushline = 1; 247681cb6ddcSMark Murray flushout = 1; 247781cb6ddcSMark Murray (void) ttyflush(1); /* Flush/drop output */ 247881cb6ddcSMark Murray /* do printoption AFTER flush, otherwise the output gets tossed... */ 247981cb6ddcSMark Murray printoption("SENT", DO, TELOPT_TM); 248081cb6ddcSMark Murray } 248181cb6ddcSMark Murray 248281cb6ddcSMark Murray void 248381cb6ddcSMark Murray xmitAO() 248481cb6ddcSMark Murray { 248581cb6ddcSMark Murray NET2ADD(IAC, AO); 248681cb6ddcSMark Murray printoption("SENT", IAC, AO); 248781cb6ddcSMark Murray if (autoflush) { 248881cb6ddcSMark Murray doflush(); 248981cb6ddcSMark Murray } 249081cb6ddcSMark Murray } 249181cb6ddcSMark Murray 249281cb6ddcSMark Murray 249381cb6ddcSMark Murray void 249481cb6ddcSMark Murray xmitEL() 249581cb6ddcSMark Murray { 249681cb6ddcSMark Murray NET2ADD(IAC, EL); 249781cb6ddcSMark Murray printoption("SENT", IAC, EL); 249881cb6ddcSMark Murray } 249981cb6ddcSMark Murray 250081cb6ddcSMark Murray void 250181cb6ddcSMark Murray xmitEC() 250281cb6ddcSMark Murray { 250381cb6ddcSMark Murray NET2ADD(IAC, EC); 250481cb6ddcSMark Murray printoption("SENT", IAC, EC); 250581cb6ddcSMark Murray } 250681cb6ddcSMark Murray 250781cb6ddcSMark Murray 250881cb6ddcSMark Murray int 250981cb6ddcSMark Murray dosynch() 251081cb6ddcSMark Murray { 251181cb6ddcSMark Murray netclear(); /* clear the path to the network */ 251281cb6ddcSMark Murray NETADD(IAC); 251381cb6ddcSMark Murray setneturg(); 251481cb6ddcSMark Murray NETADD(DM); 251581cb6ddcSMark Murray printoption("SENT", IAC, DM); 251681cb6ddcSMark Murray return 1; 251781cb6ddcSMark Murray } 251881cb6ddcSMark Murray 251981cb6ddcSMark Murray int want_status_response = 0; 252081cb6ddcSMark Murray 252181cb6ddcSMark Murray int 252281cb6ddcSMark Murray get_status() 252381cb6ddcSMark Murray { 252481cb6ddcSMark Murray unsigned char tmp[16]; 252581cb6ddcSMark Murray register unsigned char *cp; 252681cb6ddcSMark Murray 252781cb6ddcSMark Murray if (my_want_state_is_dont(TELOPT_STATUS)) { 252881cb6ddcSMark Murray printf("Remote side does not support STATUS option\n"); 252981cb6ddcSMark Murray return 0; 253081cb6ddcSMark Murray } 253181cb6ddcSMark Murray cp = tmp; 253281cb6ddcSMark Murray 253381cb6ddcSMark Murray *cp++ = IAC; 253481cb6ddcSMark Murray *cp++ = SB; 253581cb6ddcSMark Murray *cp++ = TELOPT_STATUS; 253681cb6ddcSMark Murray *cp++ = TELQUAL_SEND; 253781cb6ddcSMark Murray *cp++ = IAC; 253881cb6ddcSMark Murray *cp++ = SE; 253981cb6ddcSMark Murray if (NETROOM() >= cp - tmp) { 254081cb6ddcSMark Murray ring_supply_data(&netoring, tmp, cp-tmp); 254181cb6ddcSMark Murray printsub('>', tmp+2, cp - tmp - 2); 254281cb6ddcSMark Murray } 254381cb6ddcSMark Murray ++want_status_response; 254481cb6ddcSMark Murray return 1; 254581cb6ddcSMark Murray } 254681cb6ddcSMark Murray 254781cb6ddcSMark Murray void 254881cb6ddcSMark Murray intp() 254981cb6ddcSMark Murray { 255081cb6ddcSMark Murray NET2ADD(IAC, IP); 255181cb6ddcSMark Murray printoption("SENT", IAC, IP); 255281cb6ddcSMark Murray flushline = 1; 255381cb6ddcSMark Murray if (autoflush) { 255481cb6ddcSMark Murray doflush(); 255581cb6ddcSMark Murray } 255681cb6ddcSMark Murray if (autosynch) { 255781cb6ddcSMark Murray dosynch(); 255881cb6ddcSMark Murray } 255981cb6ddcSMark Murray } 256081cb6ddcSMark Murray 256181cb6ddcSMark Murray void 256281cb6ddcSMark Murray sendbrk() 256381cb6ddcSMark Murray { 256481cb6ddcSMark Murray NET2ADD(IAC, BREAK); 256581cb6ddcSMark Murray printoption("SENT", IAC, BREAK); 256681cb6ddcSMark Murray flushline = 1; 256781cb6ddcSMark Murray if (autoflush) { 256881cb6ddcSMark Murray doflush(); 256981cb6ddcSMark Murray } 257081cb6ddcSMark Murray if (autosynch) { 257181cb6ddcSMark Murray dosynch(); 257281cb6ddcSMark Murray } 257381cb6ddcSMark Murray } 257481cb6ddcSMark Murray 257581cb6ddcSMark Murray void 257681cb6ddcSMark Murray sendabort() 257781cb6ddcSMark Murray { 257881cb6ddcSMark Murray NET2ADD(IAC, ABORT); 257981cb6ddcSMark Murray printoption("SENT", IAC, ABORT); 258081cb6ddcSMark Murray flushline = 1; 258181cb6ddcSMark Murray if (autoflush) { 258281cb6ddcSMark Murray doflush(); 258381cb6ddcSMark Murray } 258481cb6ddcSMark Murray if (autosynch) { 258581cb6ddcSMark Murray dosynch(); 258681cb6ddcSMark Murray } 258781cb6ddcSMark Murray } 258881cb6ddcSMark Murray 258981cb6ddcSMark Murray void 259081cb6ddcSMark Murray sendsusp() 259181cb6ddcSMark Murray { 259281cb6ddcSMark Murray NET2ADD(IAC, SUSP); 259381cb6ddcSMark Murray printoption("SENT", IAC, SUSP); 259481cb6ddcSMark Murray flushline = 1; 259581cb6ddcSMark Murray if (autoflush) { 259681cb6ddcSMark Murray doflush(); 259781cb6ddcSMark Murray } 259881cb6ddcSMark Murray if (autosynch) { 259981cb6ddcSMark Murray dosynch(); 260081cb6ddcSMark Murray } 260181cb6ddcSMark Murray } 260281cb6ddcSMark Murray 260381cb6ddcSMark Murray void 260481cb6ddcSMark Murray sendeof() 260581cb6ddcSMark Murray { 260681cb6ddcSMark Murray NET2ADD(IAC, xEOF); 260781cb6ddcSMark Murray printoption("SENT", IAC, xEOF); 260881cb6ddcSMark Murray } 260981cb6ddcSMark Murray 261081cb6ddcSMark Murray void 261181cb6ddcSMark Murray sendayt() 261281cb6ddcSMark Murray { 261381cb6ddcSMark Murray NET2ADD(IAC, AYT); 261481cb6ddcSMark Murray printoption("SENT", IAC, AYT); 261581cb6ddcSMark Murray } 261681cb6ddcSMark Murray 261781cb6ddcSMark Murray /* 261881cb6ddcSMark Murray * Send a window size update to the remote system. 261981cb6ddcSMark Murray */ 262081cb6ddcSMark Murray 262181cb6ddcSMark Murray void 262281cb6ddcSMark Murray sendnaws() 262381cb6ddcSMark Murray { 262481cb6ddcSMark Murray long rows, cols; 262581cb6ddcSMark Murray unsigned char tmp[16]; 262681cb6ddcSMark Murray register unsigned char *cp; 262781cb6ddcSMark Murray 262881cb6ddcSMark Murray if (my_state_is_wont(TELOPT_NAWS)) 262981cb6ddcSMark Murray return; 263081cb6ddcSMark Murray 263181cb6ddcSMark Murray #define PUTSHORT(cp, x) { if ((*cp++ = ((x)>>8)&0xff) == IAC) *cp++ = IAC; \ 263281cb6ddcSMark Murray if ((*cp++ = ((x))&0xff) == IAC) *cp++ = IAC; } 263381cb6ddcSMark Murray 263481cb6ddcSMark Murray if (TerminalWindowSize(&rows, &cols) == 0) { /* Failed */ 263581cb6ddcSMark Murray return; 263681cb6ddcSMark Murray } 263781cb6ddcSMark Murray 263881cb6ddcSMark Murray cp = tmp; 263981cb6ddcSMark Murray 264081cb6ddcSMark Murray *cp++ = IAC; 264181cb6ddcSMark Murray *cp++ = SB; 264281cb6ddcSMark Murray *cp++ = TELOPT_NAWS; 264381cb6ddcSMark Murray PUTSHORT(cp, cols); 264481cb6ddcSMark Murray PUTSHORT(cp, rows); 264581cb6ddcSMark Murray *cp++ = IAC; 264681cb6ddcSMark Murray *cp++ = SE; 264781cb6ddcSMark Murray if (NETROOM() >= cp - tmp) { 264881cb6ddcSMark Murray ring_supply_data(&netoring, tmp, cp-tmp); 264981cb6ddcSMark Murray printsub('>', tmp+2, cp - tmp - 2); 265081cb6ddcSMark Murray } 265181cb6ddcSMark Murray } 265281cb6ddcSMark Murray 265381cb6ddcSMark Murray void 265481cb6ddcSMark Murray tel_enter_binary(rw) 265581cb6ddcSMark Murray int rw; 265681cb6ddcSMark Murray { 265781cb6ddcSMark Murray if (rw&1) 265881cb6ddcSMark Murray send_do(TELOPT_BINARY, 1); 265981cb6ddcSMark Murray if (rw&2) 266081cb6ddcSMark Murray send_will(TELOPT_BINARY, 1); 266181cb6ddcSMark Murray } 266281cb6ddcSMark Murray 266381cb6ddcSMark Murray void 266481cb6ddcSMark Murray tel_leave_binary(rw) 266581cb6ddcSMark Murray int rw; 266681cb6ddcSMark Murray { 266781cb6ddcSMark Murray if (rw&1) 266881cb6ddcSMark Murray send_dont(TELOPT_BINARY, 1); 266981cb6ddcSMark Murray if (rw&2) 267081cb6ddcSMark Murray send_wont(TELOPT_BINARY, 1); 267181cb6ddcSMark Murray } 2672