111758Ssam #ifndef lint 232377Sminshall static char copyright[] = 332377Sminshall "@(#) Copyright (c) 1984-1987 Regents of the University of California.\n\ 421580Sdist All rights reserved.\n"; 532377Sminshall #endif /* not lint */ 611758Ssam 721580Sdist #ifndef lint 832377Sminshall static char sccsid[] = "@(#)telnet.c 1.2 (Berkeley) 9/25/87"; 932377Sminshall #endif /* not lint */ 1021580Sdist 119217Ssam #include <sys/types.h> 1232377Sminshall #include <sys/time.h> 139217Ssam #include <sys/socket.h> 149217Ssam 159217Ssam #include <netinet/in.h> 169217Ssam 1732377Sminshall #if defined(unix) 1832377Sminshall /* By the way, we need to include curses.h before telnet.h since, 1932377Sminshall * among other things, telnet.h #defines 'DO', which is a variable 2032377Sminshall * declared in curses.h. 2132377Sminshall */ 2232377Sminshall #include <curses.h> 2332377Sminshall #endif /* defined(unix) */ 2432377Sminshall 2512212Ssam #include <arpa/telnet.h> 2632377Sminshall 2732377Sminshall #if !defined(NOT43) 2827186Sminshall #include <arpa/inet.h> 2932377Sminshall #else /* !defined(NOT43) */ 3032377Sminshall extern unsigned long inet_addr(); 3132377Sminshall extern char *inet_ntoa(); 3232377Sminshall #endif /* !defined(NOT43) */ 3312212Ssam 346000Sroot #include <ctype.h> 356000Sroot #include <errno.h> 368345Ssam #include <netdb.h> 3732377Sminshall 3832377Sminshall #if defined(unix) 3927186Sminshall #include <strings.h> 4032377Sminshall #else /* defined(unix) */ 4132377Sminshall #include <string.h> 4232377Sminshall #endif /* defined(unix) */ 439217Ssam 44*32381Sminshall #include "ring.h" 45*32381Sminshall 4632377Sminshall #include "defines.h" 4732377Sminshall #include "externs.h" 4832377Sminshall #include "types.h" 4932377Sminshall #include "general.h" 5027178Sminshall 5127178Sminshall 5232377Sminshall void setcommandmode(), command(); /* forward declarations */ 5332377Sminshall 5427676Sminshall #ifndef FD_SETSIZE 5527178Sminshall /* 5627178Sminshall * The following is defined just in case someone should want to run 5727178Sminshall * this telnet on a 4.2 system. 5827178Sminshall * 5927178Sminshall */ 6027178Sminshall 6127676Sminshall #define FD_SET(n, p) ((p)->fds_bits[0] |= (1<<(n))) 6227676Sminshall #define FD_CLR(n, p) ((p)->fds_bits[0] &= ~(1<<(n))) 6327676Sminshall #define FD_ISSET(n, p) ((p)->fds_bits[0] & (1<<(n))) 6427676Sminshall #define FD_ZERO(p) ((p)->fds_bits[0] = 0) 6527178Sminshall 6627178Sminshall #endif 6727178Sminshall 6827228Sminshall #define strip(x) ((x)&0x7f) 6932377Sminshall #define min(x,y) ((x<y)? x:y) 706000Sroot 7132377Sminshall #if defined(TN3270) 7232377Sminshall static char Ibuf[8*BUFSIZ], *Ifrontp, *Ibackp; 7332377Sminshall #endif /* defined(TN3270) */ 7427088Sminshall 756000Sroot 7632377Sminshall static char subbuffer[SUBBUFSIZE], 7732377Sminshall *subpointer, *subend; /* buffer for sub-options */ 7827676Sminshall #define SB_CLEAR() subpointer = subbuffer; 7927676Sminshall #define SB_TERM() subend = subpointer; 8027676Sminshall #define SB_ACCUM(c) if (subpointer < (subbuffer+sizeof subbuffer)) { \ 8127676Sminshall *subpointer++ = (c); \ 8227676Sminshall } 8327676Sminshall 8432377Sminshall static char sb_terminal[] = { IAC, SB, 8532377Sminshall TELOPT_TTYPE, TELQUAL_IS, 8632377Sminshall 'I', 'B', 'M', '-', '3', '2', '7', '8', '-', '2', 8732377Sminshall IAC, SE }; 8832377Sminshall #define SBTERMMODEL 13 8932377Sminshall 9032377Sminshall 916000Sroot char hisopts[256]; 926000Sroot char myopts[256]; 936000Sroot 946000Sroot char doopt[] = { IAC, DO, '%', 'c', 0 }; 956000Sroot char dont[] = { IAC, DONT, '%', 'c', 0 }; 966000Sroot char will[] = { IAC, WILL, '%', 'c', 0 }; 976000Sroot char wont[] = { IAC, WONT, '%', 'c', 0 }; 986000Sroot 9932377Sminshall static char sibuf[BUFSIZ], *sbp; 10032377Sminshall static char tibuf[BUFSIZ], *tbp; 10132377Sminshall static fd_set ibits, obits, xbits; 10227088Sminshall 10327088Sminshall 10432377Sminshall int 10532377Sminshall connected, 10632377Sminshall net, 10732377Sminshall scc, 10832377Sminshall tcc, 10932377Sminshall showoptions, 11032377Sminshall In3270, /* Are we in 3270 mode? */ 11132377Sminshall ISend, /* trying to send network data in */ 11232377Sminshall debug = 0, 11332377Sminshall crmod, 11432377Sminshall netdata, /* Print out network data flow */ 11532377Sminshall crlf, /* Should '\r' be mapped to <CR><LF> (or <CR><NUL>)? */ 11632377Sminshall noasynch = 0, /* User specified "-noasynch" on command line */ 11732377Sminshall askedSGA = 0, /* We have talked about suppress go ahead */ 11832377Sminshall telnetport = 1; 11927088Sminshall 12032377Sminshall #define CONTROL(x) ((x)&0x1f) /* CTRL(x) is not portable */ 1216000Sroot 12232377Sminshall char 12332377Sminshall *prompt = 0, 12432377Sminshall escape, 12532377Sminshall echoc; 12627186Sminshall 12732377Sminshall int 12832377Sminshall SYNCHing, /* we are in TELNET SYNCH mode */ 12932377Sminshall flushout, /* flush output */ 13032377Sminshall autoflush = 0, /* flush output when interrupting? */ 13132377Sminshall autosynch, /* send interrupt characters with SYNCH? */ 13232377Sminshall localchars, /* we recognize interrupt/quit */ 13332377Sminshall donelclchars, /* the user has set "localchars" */ 13432377Sminshall donebinarytoggle, /* the user has put us in binary */ 13532377Sminshall dontlecho, /* do we suppress local echoing right now? */ 13632377Sminshall globalmode; 1376000Sroot 13832377Sminshall /* The following are some tn3270 specific flags */ 13932377Sminshall #if defined(TN3270) 1406000Sroot 14132377Sminshall static int 14232377Sminshall Sent3270TerminalType; /* Have we said we are a 3270? */ 1436000Sroot 14432377Sminshall #endif /* defined(TN3270) */ 14527186Sminshall int 14627186Sminshall 14732377Sminshall tout, /* Output file descriptor */ 14832377Sminshall tin; /* Input file descriptor */ 14927186Sminshall 15027186Sminshall 15127186Sminshall 15227186Sminshall /* 1536000Sroot * Telnet receiver states for fsm 1546000Sroot */ 1556000Sroot #define TS_DATA 0 1566000Sroot #define TS_IAC 1 1576000Sroot #define TS_WILL 2 1586000Sroot #define TS_WONT 3 1596000Sroot #define TS_DO 4 1606000Sroot #define TS_DONT 5 16127021Sminshall #define TS_CR 6 16227676Sminshall #define TS_SB 7 /* sub-option collection */ 16327676Sminshall #define TS_SE 8 /* looking for sub-option end */ 1646000Sroot 16532377Sminshall static int telrcv_state; 1666000Sroot 16732377Sminshall jmp_buf toplevel = { 0 }; 16832377Sminshall jmp_buf peerdied; 1696000Sroot 17032377Sminshall int flushline; 17127021Sminshall 17232377Sminshall /* 17332377Sminshall * The following are some clocks used to decide how to interpret 17432377Sminshall * the relationship between various variables. 17532377Sminshall */ 1766000Sroot 17732377Sminshall Clocks clocks; 17832377Sminshall 17932377Sminshall Modelist modelist[] = { 18032377Sminshall { "telnet command mode", COMMAND_LINE }, 18132377Sminshall { "character-at-a-time mode", 0 }, 18232377Sminshall { "character-at-a-time mode (local echo)", LOCAL_ECHO|LOCAL_CHARS }, 18332377Sminshall { "line-by-line mode (remote echo)", LINE | LOCAL_CHARS }, 18432377Sminshall { "line-by-line mode", LINE | LOCAL_ECHO | LOCAL_CHARS }, 18532377Sminshall { "line-by-line mode (local echoing suppressed)", LINE | LOCAL_CHARS }, 18632377Sminshall { "3270 mode", 0 }, 18732377Sminshall }; 1886000Sroot 18932377Sminshall 19032377Sminshall /* 19132377Sminshall * Initialize telnet environment. 19232377Sminshall */ 1936000Sroot 19432377Sminshall init_telnet() 19532377Sminshall { 19632377Sminshall /* Don't change telnetport */ 19732377Sminshall SB_CLEAR(); 19832377Sminshall ClearArray(hisopts); 19932377Sminshall ClearArray(myopts); 20032377Sminshall sbp = sibuf; 20132377Sminshall tbp = tibuf; 2026000Sroot 20332377Sminshall connected = net = scc = tcc = In3270 = ISend = donebinarytoggle = 0; 20432377Sminshall telnetport = 0; 2056000Sroot 20632377Sminshall #if defined(unix) && defined(TN3270) 20732377Sminshall HaveInput = 0; 20832377Sminshall #endif /* defined(unix) && defined(TN3270) */ 2096000Sroot 21032377Sminshall SYNCHing = 0; 2116000Sroot 21232377Sminshall errno = 0; 21327676Sminshall 21432377Sminshall /* Don't change NetTrace */ 2156000Sroot 21632377Sminshall escape = CONTROL(']'); 21732377Sminshall echoc = CONTROL('E'); 2186000Sroot 21932377Sminshall flushline = 1; 22032377Sminshall telrcv_state = TS_DATA; 22132377Sminshall } 2226000Sroot 2236000Sroot 22432377Sminshall void 22527676Sminshall willoption(option, reply) 22627676Sminshall int option, reply; 2276000Sroot { 2286000Sroot char *fmt; 2296000Sroot 2306000Sroot switch (option) { 2316000Sroot 2326000Sroot case TELOPT_ECHO: 23332377Sminshall # if defined(TN3270) 23432377Sminshall /* 23532377Sminshall * The following is a pain in the rear-end. 23632377Sminshall * Various IBM servers (some versions of Wiscnet, 23732377Sminshall * possibly Fibronics/Spartacus, and who knows who 23832377Sminshall * else) will NOT allow us to send "DO SGA" too early 23932377Sminshall * in the setup proceedings. On the other hand, 24032377Sminshall * 4.2 servers (telnetd) won't set SGA correctly. 24132377Sminshall * So, we are stuck. Empirically (but, based on 24232377Sminshall * a VERY small sample), the IBM servers don't send 24332377Sminshall * out anything about ECHO, so we postpone our sending 24432377Sminshall * "DO SGA" until we see "WILL ECHO" (which 4.2 servers 24532377Sminshall * DO send). 24632377Sminshall */ 24732377Sminshall { 24832377Sminshall if (askedSGA == 0) { 24932377Sminshall askedSGA = 1; 25032377Sminshall if (!hisopts[TELOPT_SGA]) { 25132377Sminshall willoption(TELOPT_SGA, 0); 25232377Sminshall } 25332377Sminshall } 25432377Sminshall } 25532377Sminshall /* Fall through */ 25632377Sminshall case TELOPT_EOR: 25732377Sminshall case TELOPT_BINARY: 25832377Sminshall #endif /* defined(TN3270) */ 2596000Sroot case TELOPT_SGA: 26027110Sminshall settimer(modenegotiated); 2616000Sroot hisopts[option] = 1; 2626000Sroot fmt = doopt; 26327110Sminshall setconnmode(); /* possibly set new tty mode */ 2646000Sroot break; 2656000Sroot 2666000Sroot case TELOPT_TM: 26727110Sminshall return; /* Never reply to TM will's/wont's */ 2686000Sroot 2696000Sroot default: 2706000Sroot fmt = dont; 2716000Sroot break; 2726000Sroot } 273*32381Sminshall netoprint(fmt, option); 27427676Sminshall if (reply) 27532377Sminshall printoption(">SENT", fmt, option, reply); 27627676Sminshall else 27732377Sminshall printoption("<SENT", fmt, option, reply); 2786000Sroot } 2796000Sroot 28032377Sminshall void 28127676Sminshall wontoption(option, reply) 28227676Sminshall int option, reply; 2836000Sroot { 2846000Sroot char *fmt; 2856000Sroot 2866000Sroot switch (option) { 2876000Sroot 2886000Sroot case TELOPT_ECHO: 2896000Sroot case TELOPT_SGA: 29027110Sminshall settimer(modenegotiated); 2916000Sroot hisopts[option] = 0; 2926000Sroot fmt = dont; 29327110Sminshall setconnmode(); /* Set new tty mode */ 2946000Sroot break; 2956000Sroot 29627110Sminshall case TELOPT_TM: 29727110Sminshall return; /* Never reply to TM will's/wont's */ 29827110Sminshall 2996000Sroot default: 3006000Sroot fmt = dont; 3016000Sroot } 302*32381Sminshall netoprint(fmt, option); 30327676Sminshall if (reply) 30432377Sminshall printoption(">SENT", fmt, option, reply); 30527676Sminshall else 30632377Sminshall printoption("<SENT", fmt, option, reply); 3076000Sroot } 3086000Sroot 30932377Sminshall static void 3106000Sroot dooption(option) 3116000Sroot int option; 3126000Sroot { 3136000Sroot char *fmt; 3146000Sroot 3156000Sroot switch (option) { 3166000Sroot 3176000Sroot case TELOPT_TM: 31813231Ssam fmt = will; 31913231Ssam break; 32013231Ssam 32132377Sminshall # if defined(TN3270) 32232377Sminshall case TELOPT_EOR: 32332377Sminshall case TELOPT_BINARY: 32432377Sminshall # endif /* defined(TN3270) */ 32527676Sminshall case TELOPT_TTYPE: /* terminal type option */ 32627110Sminshall case TELOPT_SGA: /* no big deal */ 3276000Sroot fmt = will; 32827110Sminshall myopts[option] = 1; 3296000Sroot break; 3306000Sroot 33127110Sminshall case TELOPT_ECHO: /* We're never going to echo... */ 3326000Sroot default: 3336000Sroot fmt = wont; 3346000Sroot break; 3356000Sroot } 336*32381Sminshall netoprint(fmt, option); 33732377Sminshall printoption(">SENT", fmt, option, 0); 3386000Sroot } 33927676Sminshall 34027676Sminshall /* 34127676Sminshall * suboption() 34227676Sminshall * 34327676Sminshall * Look at the sub-option buffer, and try to be helpful to the other 34427676Sminshall * side. 34527676Sminshall * 34627676Sminshall * Currently we recognize: 34727676Sminshall * 34827676Sminshall * Terminal type, send request. 34927676Sminshall */ 35027676Sminshall 35132377Sminshall static void 35227676Sminshall suboption() 35327676Sminshall { 35432377Sminshall printsub("<", subbuffer, subend-subbuffer+1); 35527676Sminshall switch (subbuffer[0]&0xff) { 35627676Sminshall case TELOPT_TTYPE: 35727676Sminshall if ((subbuffer[1]&0xff) != TELQUAL_SEND) { 35827676Sminshall ; 35927676Sminshall } else { 36027676Sminshall char *name; 36127676Sminshall char namebuf[41]; 36232377Sminshall extern char *getenv(); 36327676Sminshall int len; 36427676Sminshall 36532377Sminshall #if defined(TN3270) 36632377Sminshall /* 36732377Sminshall * Try to send a 3270 type terminal name. Decide which one based 36832377Sminshall * on the format of our screen, and (in the future) color 36932377Sminshall * capaiblities. 37032377Sminshall */ 37132377Sminshall #if defined(unix) 37232377Sminshall if (initscr() != ERR) { /* Initialize curses to get line size */ 37332377Sminshall MaxNumberLines = LINES; 37432377Sminshall MaxNumberColumns = COLS; 37532377Sminshall } 37632377Sminshall #else /* defined(unix) */ 37732377Sminshall InitTerminal(); 37832377Sminshall #endif /* defined(unix) */ 37932377Sminshall if ((MaxNumberLines >= 24) && (MaxNumberColumns >= 80)) { 38032377Sminshall Sent3270TerminalType = 1; 38132377Sminshall if ((MaxNumberLines >= 27) && (MaxNumberColumns >= 132)) { 38232377Sminshall MaxNumberLines = 27; 38332377Sminshall MaxNumberColumns = 132; 38432377Sminshall sb_terminal[SBTERMMODEL] = '5'; 38532377Sminshall } else if (MaxNumberLines >= 43) { 38632377Sminshall MaxNumberLines = 43; 38732377Sminshall MaxNumberColumns = 80; 38832377Sminshall sb_terminal[SBTERMMODEL] = '4'; 38932377Sminshall } else if (MaxNumberLines >= 32) { 39032377Sminshall MaxNumberLines = 32; 39132377Sminshall MaxNumberColumns = 80; 39232377Sminshall sb_terminal[SBTERMMODEL] = '3'; 39332377Sminshall } else { 39432377Sminshall MaxNumberLines = 24; 39532377Sminshall MaxNumberColumns = 80; 39632377Sminshall sb_terminal[SBTERMMODEL] = '2'; 39732377Sminshall } 39832377Sminshall NumberLines = 24; /* before we start out... */ 39932377Sminshall NumberColumns = 80; 40032377Sminshall ScreenSize = NumberLines*NumberColumns; 40132377Sminshall if ((MaxNumberLines*MaxNumberColumns) > MAXSCREENSIZE) { 402*32381Sminshall ExitString("Programming error: MAXSCREENSIZE too small.\n", 403*32381Sminshall 1); 40432377Sminshall /*NOTREACHED*/ 40532377Sminshall } 406*32381Sminshall printsub(">", sb_terminal+2, sizeof sb_terminal-2); 407*32381Sminshall ring_add_data(&netoring, sb_terminal, sizeof sb_terminal); 40832377Sminshall return; 40932377Sminshall } 41032377Sminshall #endif /* defined(TN3270) */ 41132377Sminshall 41227676Sminshall name = getenv("TERM"); 41327676Sminshall if ((name == 0) || ((len = strlen(name)) > 40)) { 41427676Sminshall name = "UNKNOWN"; 41527676Sminshall } 41627676Sminshall if ((len + 4+2) < NETROOM()) { 41727676Sminshall strcpy(namebuf, name); 41827676Sminshall upcase(namebuf); 419*32381Sminshall netoprint("%c%c%c%c%s%c%c", IAC, SB, TELOPT_TTYPE, 42027676Sminshall TELQUAL_IS, namebuf, IAC, SE); 421*32381Sminshall /* XXX */ 422*32381Sminshall /* printsub(">", nfrontp+2, 4+strlen(namebuf)+2-2-2); */ 42332377Sminshall } else { 424*32381Sminshall ExitString("No room in buffer for terminal type.\n", 42532377Sminshall 1); 42632377Sminshall /*NOTREACHED*/ 42727676Sminshall } 42827676Sminshall } 42927676Sminshall 43027676Sminshall default: 43127676Sminshall break; 43227676Sminshall } 43327676Sminshall } 43427088Sminshall 43532377Sminshall #if defined(TN3270) 43632377Sminshall static void 43732377Sminshall SetIn3270() 43827088Sminshall { 43932377Sminshall if (Sent3270TerminalType && myopts[TELOPT_BINARY] 44032377Sminshall && hisopts[TELOPT_BINARY] && !donebinarytoggle) { 44132377Sminshall if (!In3270) { 44232377Sminshall In3270 = 1; 44332377Sminshall Init3270(); /* Initialize 3270 functions */ 44432377Sminshall /* initialize terminal key mapping */ 44532377Sminshall InitTerminal(); /* Start terminal going */ 44632377Sminshall setconnmode(); 44732377Sminshall } 44832377Sminshall } else { 44932377Sminshall if (In3270) { 45032377Sminshall StopScreen(1); 45132377Sminshall In3270 = 0; 45232377Sminshall Stop3270(); /* Tell 3270 we aren't here anymore */ 45332377Sminshall setconnmode(); 45432377Sminshall } 45527228Sminshall } 45627088Sminshall } 45732377Sminshall #endif /* defined(TN3270) */ 45832377Sminshall 45927088Sminshall 46032377Sminshall static void 46132377Sminshall telrcv() 46227110Sminshall { 46332377Sminshall register int c; 46432377Sminshall static int telrcv_state = TS_DATA; 46532377Sminshall # if defined(TN3270) 46632377Sminshall register int Scc; 46732377Sminshall register char *Sbp; 46832377Sminshall # endif /* defined(TN3270) */ 46927088Sminshall 47032377Sminshall while ((scc > 0) && (TTYROOM() > 2)) { 47132377Sminshall c = *sbp++ & 0xff, scc--; 47232377Sminshall switch (telrcv_state) { 47327110Sminshall 47432377Sminshall case TS_CR: 47532377Sminshall telrcv_state = TS_DATA; 47632377Sminshall if (c == '\0') { 47732377Sminshall break; /* Ignore \0 after CR */ 47832377Sminshall } else if (c == '\n') { 47932377Sminshall if (hisopts[TELOPT_ECHO] && !crmod) { 48032377Sminshall TTYADD(c); 48132377Sminshall } 48232377Sminshall break; 48332377Sminshall } 48432377Sminshall /* Else, fall through */ 48527088Sminshall 48632377Sminshall case TS_DATA: 48732377Sminshall if (c == IAC) { 48832377Sminshall telrcv_state = TS_IAC; 48932377Sminshall continue; 49032377Sminshall } 49132377Sminshall # if defined(TN3270) 49232377Sminshall if (In3270) { 49332377Sminshall *Ifrontp++ = c; 49432377Sminshall Sbp = sbp; 49532377Sminshall Scc = scc; 49632377Sminshall while (Scc > 0) { 49732377Sminshall c = *Sbp++ & 0377, Scc--; 49832377Sminshall if (c == IAC) { 49932377Sminshall telrcv_state = TS_IAC; 50032377Sminshall break; 50132377Sminshall } 50232377Sminshall *Ifrontp++ = c; 50332377Sminshall } 50432377Sminshall sbp = Sbp; 50532377Sminshall scc = Scc; 50632377Sminshall } else 50732377Sminshall # endif /* defined(TN3270) */ 50832377Sminshall /* 50932377Sminshall * The 'crmod' hack (see following) is needed 51032377Sminshall * since we can't * set CRMOD on output only. 51132377Sminshall * Machines like MULTICS like to send \r without 51232377Sminshall * \n; since we must turn off CRMOD to get proper 51332377Sminshall * input, the mapping is done here (sigh). 51432377Sminshall */ 51532377Sminshall if ((c == '\r') && !hisopts[TELOPT_BINARY]) { 51632377Sminshall if (scc > 0) { 51732377Sminshall c = *sbp&0xff; 51832377Sminshall if (c == 0) { 51932377Sminshall sbp++, scc--; 52032377Sminshall /* a "true" CR */ 52132377Sminshall TTYADD('\r'); 52232377Sminshall } else if (!hisopts[TELOPT_ECHO] && 52332377Sminshall (c == '\n')) { 52432377Sminshall sbp++, scc--; 52532377Sminshall TTYADD('\n'); 52632377Sminshall } else { 52732377Sminshall TTYADD('\r'); 52832377Sminshall if (crmod) { 52932377Sminshall TTYADD('\n'); 53032377Sminshall } 53132377Sminshall } 53232377Sminshall } else { 53332377Sminshall telrcv_state = TS_CR; 53432377Sminshall TTYADD('\r'); 53532377Sminshall if (crmod) { 53632377Sminshall TTYADD('\n'); 53732377Sminshall } 53832377Sminshall } 53932377Sminshall } else { 54032377Sminshall TTYADD(c); 54132377Sminshall } 54232377Sminshall continue; 54327088Sminshall 54432377Sminshall case TS_IAC: 54532377Sminshall switch (c) { 54632377Sminshall 54732377Sminshall case WILL: 54832377Sminshall telrcv_state = TS_WILL; 54932377Sminshall continue; 55027261Sminshall 55132377Sminshall case WONT: 55232377Sminshall telrcv_state = TS_WONT; 55332377Sminshall continue; 55427261Sminshall 55532377Sminshall case DO: 55632377Sminshall telrcv_state = TS_DO; 55732377Sminshall continue; 55827261Sminshall 55932377Sminshall case DONT: 56032377Sminshall telrcv_state = TS_DONT; 56132377Sminshall continue; 56227261Sminshall 56332377Sminshall case DM: 56432377Sminshall /* 56532377Sminshall * We may have missed an urgent notification, 56632377Sminshall * so make sure we flush whatever is in the 56732377Sminshall * buffer currently. 56832377Sminshall */ 56932377Sminshall SYNCHing = 1; 57032377Sminshall ttyflush(1); 57132377Sminshall SYNCHing = stilloob(net); 57232377Sminshall settimer(gotDM); 57332377Sminshall break; 57427088Sminshall 57532377Sminshall case NOP: 57632377Sminshall case GA: 57732377Sminshall break; 57827088Sminshall 57932377Sminshall case SB: 58032377Sminshall SB_CLEAR(); 58132377Sminshall telrcv_state = TS_SB; 58232377Sminshall continue; 58327261Sminshall 58432377Sminshall # if defined(TN3270) 58532377Sminshall case EOR: 58632377Sminshall if (In3270) { 58732377Sminshall Ibackp += DataFromNetwork(Ibackp, Ifrontp-Ibackp, 1); 58832377Sminshall if (Ibackp == Ifrontp) { 58932377Sminshall Ibackp = Ifrontp = Ibuf; 59032377Sminshall ISend = 0; /* should have been! */ 59132377Sminshall } else { 59232377Sminshall ISend = 1; 59327088Sminshall } 59427088Sminshall } 59527088Sminshall break; 59632377Sminshall # endif /* defined(TN3270) */ 59732377Sminshall 59832377Sminshall case IAC: 59932377Sminshall # if !defined(TN3270) 60032377Sminshall TTYADD(IAC); 60132377Sminshall # else /* !defined(TN3270) */ 60232377Sminshall if (In3270) { 60332377Sminshall *Ifrontp++ = IAC; 60432377Sminshall } else { 60532377Sminshall TTYADD(IAC); 60632377Sminshall } 60732377Sminshall # endif /* !defined(TN3270) */ 60827088Sminshall break; 60932377Sminshall 61027088Sminshall default: 61127088Sminshall break; 61227088Sminshall } 61332377Sminshall telrcv_state = TS_DATA; 61432377Sminshall continue; 61527088Sminshall 61632377Sminshall case TS_WILL: 61732377Sminshall printoption(">RCVD", will, c, !hisopts[c]); 61832377Sminshall if (c == TELOPT_TM) { 61932377Sminshall if (flushout) { 62032377Sminshall flushout = 0; 62132377Sminshall } 62232377Sminshall } else if (!hisopts[c]) { 62332377Sminshall willoption(c, 1); 62432377Sminshall } 62532377Sminshall SetIn3270(); 62632377Sminshall telrcv_state = TS_DATA; 62732377Sminshall continue; 62827110Sminshall 62932377Sminshall case TS_WONT: 63032377Sminshall printoption(">RCVD", wont, c, hisopts[c]); 63132377Sminshall if (c == TELOPT_TM) { 63232377Sminshall if (flushout) { 63332377Sminshall flushout = 0; 63432377Sminshall } 63532377Sminshall } else if (hisopts[c]) { 63632377Sminshall wontoption(c, 1); 63732377Sminshall } 63832377Sminshall SetIn3270(); 63932377Sminshall telrcv_state = TS_DATA; 64032377Sminshall continue; 64127088Sminshall 64232377Sminshall case TS_DO: 64332377Sminshall printoption(">RCVD", doopt, c, !myopts[c]); 64432377Sminshall if (!myopts[c]) 64532377Sminshall dooption(c); 64632377Sminshall SetIn3270(); 64732377Sminshall telrcv_state = TS_DATA; 64832377Sminshall continue; 64927088Sminshall 65032377Sminshall case TS_DONT: 65132377Sminshall printoption(">RCVD", dont, c, myopts[c]); 65232377Sminshall if (myopts[c]) { 65332377Sminshall myopts[c] = 0; 654*32381Sminshall netoprint(wont, c); 65532377Sminshall flushline = 1; 65632377Sminshall setconnmode(); /* set new tty mode (maybe) */ 65732377Sminshall printoption(">SENT", wont, c, 0); 65832377Sminshall } 65932377Sminshall SetIn3270(); 66032377Sminshall telrcv_state = TS_DATA; 66132377Sminshall continue; 66227088Sminshall 66332377Sminshall case TS_SB: 66432377Sminshall if (c == IAC) { 66532377Sminshall telrcv_state = TS_SE; 66632377Sminshall } else { 66732377Sminshall SB_ACCUM(c); 66832377Sminshall } 66932377Sminshall continue; 67027088Sminshall 67132377Sminshall case TS_SE: 67232377Sminshall if (c != SE) { 67332377Sminshall if (c != IAC) { 67432377Sminshall SB_ACCUM(IAC); 67532377Sminshall } 67632377Sminshall SB_ACCUM(c); 67732377Sminshall telrcv_state = TS_SB; 67832377Sminshall } else { 67932377Sminshall SB_TERM(); 68032377Sminshall suboption(); /* handle sub-option */ 68132377Sminshall SetIn3270(); 68232377Sminshall telrcv_state = TS_DATA; 68332377Sminshall } 68427088Sminshall } 68527088Sminshall } 68627088Sminshall } 68732377Sminshall 68832377Sminshall #if defined(TN3270) 68932377Sminshall static void 69032377Sminshall SetForExit() 69132377Sminshall { 69232377Sminshall setconnmode(); 69332377Sminshall if (In3270) { 69432377Sminshall Finish3270(); 69532377Sminshall } 69632377Sminshall setcommandmode(); 69732377Sminshall fflush(stdout); 69832377Sminshall fflush(stderr); 69932377Sminshall if (In3270) { 70032377Sminshall StopScreen(1); 70132377Sminshall } 70232377Sminshall setconnmode(); 70332377Sminshall setcommandmode(); 70432377Sminshall } 70527088Sminshall 70632377Sminshall static void 70732377Sminshall Exit(returnCode) 70832377Sminshall int returnCode; 70927088Sminshall { 71032377Sminshall SetForExit(); 71132377Sminshall exit(returnCode); 71227088Sminshall } 71327088Sminshall 71432377Sminshall void 715*32381Sminshall ExitString(string, returnCode) 71632377Sminshall char *string; 71732377Sminshall int returnCode; 71827088Sminshall { 71932377Sminshall SetForExit(); 720*32381Sminshall fwrite(string, 1, strlen(string), stderr); 72132377Sminshall exit(returnCode); 72227088Sminshall } 72327088Sminshall 72432377Sminshall void 72532377Sminshall ExitPerror(string, returnCode) 72632377Sminshall char *string; 72732377Sminshall int returnCode; 72827088Sminshall { 72932377Sminshall SetForExit(); 73032377Sminshall perror(string); 73132377Sminshall exit(returnCode); 73232377Sminshall } 73332377Sminshall #endif /* defined(TN3270) */ 73427088Sminshall 73527088Sminshall 73627088Sminshall /* 73732377Sminshall * Scheduler() 73832377Sminshall * 73932377Sminshall * Try to do something. 74032377Sminshall * 74132377Sminshall * If we do something useful, return 1; else return 0. 74232377Sminshall * 74327110Sminshall */ 74427110Sminshall 74527110Sminshall 74632377Sminshall int 74732377Sminshall Scheduler(block) 74832377Sminshall int block; /* should we block in the select ? */ 74927110Sminshall { 75032377Sminshall register int c; 75132377Sminshall /* One wants to be a bit careful about setting returnValue 75232377Sminshall * to one, since a one implies we did some useful work, 75332377Sminshall * and therefore probably won't be called to block next 75432377Sminshall * time (TN3270 mode only). 75532377Sminshall */ 75632377Sminshall int returnValue = 0; 75732377Sminshall static struct timeval TimeValue = { 0 }; 75827110Sminshall 75932377Sminshall if (scc < 0 && tcc < 0) { 76032377Sminshall return -1; 76127110Sminshall } 76227110Sminshall 76332377Sminshall if ((!MODE_LINE(globalmode) || flushline) && NETBYTES()) { 76432377Sminshall FD_SET(net, &obits); 76532377Sminshall } 76632377Sminshall #if !defined(MSDOS) 76732377Sminshall if (TTYBYTES()) { 76832377Sminshall FD_SET(tout, &obits); 76927110Sminshall } 77032377Sminshall #if defined(TN3270) 77132377Sminshall if ((tcc == 0) && NETROOM() && (shell_active == 0)) { 77232377Sminshall FD_SET(tin, &ibits); 77327110Sminshall } 77432377Sminshall #else /* defined(TN3270) */ 77532377Sminshall if ((tcc == 0) && NETROOM()) { 77632377Sminshall FD_SET(tin, &ibits); 77727110Sminshall } 77832377Sminshall #endif /* defined(TN3270) */ 77932377Sminshall #endif /* !defined(MSDOS) */ 78032377Sminshall # if !defined(TN3270) 78132377Sminshall if (TTYROOM()) { 78232377Sminshall FD_SET(net, &ibits); 78327110Sminshall } 78432377Sminshall # else /* !defined(TN3270) */ 78532377Sminshall if (!ISend && TTYROOM()) { 78632377Sminshall FD_SET(net, &ibits); 78727110Sminshall } 78832377Sminshall # endif /* !defined(TN3270) */ 78932377Sminshall if (!SYNCHing) { 79032377Sminshall FD_SET(net, &xbits); 79132377Sminshall } 79232377Sminshall # if defined(TN3270) && defined(unix) 79332377Sminshall if (HaveInput) { 79432377Sminshall HaveInput = 0; 79532377Sminshall signal(SIGIO, inputAvailable); 79632377Sminshall } 79732377Sminshall #endif /* defined(TN3270) && defined(unix) */ 79832377Sminshall if ((c = select(16, &ibits, &obits, &xbits, 79932377Sminshall block? (struct timeval *)0 : &TimeValue)) < 0) { 80032377Sminshall if (c == -1) { 80132377Sminshall /* 80232377Sminshall * we can get EINTR if we are in line mode, 80332377Sminshall * and the user does an escape (TSTP), or 80432377Sminshall * some other signal generator. 80532377Sminshall */ 80632377Sminshall if (errno == EINTR) { 80732377Sminshall return 0; 80832377Sminshall } 80932377Sminshall # if defined(TN3270) 81032377Sminshall /* 81132377Sminshall * we can get EBADF if we were in transparent 81232377Sminshall * mode, and the transcom process died. 81332377Sminshall */ 81432377Sminshall if (errno == EBADF) { 81532377Sminshall /* 81632377Sminshall * zero the bits (even though kernel does it) 81732377Sminshall * to make sure we are selecting on the right 81832377Sminshall * ones. 81932377Sminshall */ 82032377Sminshall FD_ZERO(&ibits); 82132377Sminshall FD_ZERO(&obits); 82232377Sminshall FD_ZERO(&xbits); 82332377Sminshall return 0; 82432377Sminshall } 82532377Sminshall # endif /* defined(TN3270) */ 82632377Sminshall /* I don't like this, does it ever happen? */ 82732377Sminshall printf("sleep(5) from telnet, after select\r\n"); 82832377Sminshall #if defined(unix) 82932377Sminshall sleep(5); 83032377Sminshall #endif /* defined(unix) */ 83127110Sminshall } 83227261Sminshall return 0; 83327110Sminshall } 83432377Sminshall 83532377Sminshall /* 83632377Sminshall * Any urgent data? 83732377Sminshall */ 83832377Sminshall if (FD_ISSET(net, &xbits)) { 83932377Sminshall FD_CLR(net, &xbits); 84032377Sminshall SYNCHing = 1; 84132377Sminshall ttyflush(1); /* flush already enqueued data */ 84227110Sminshall } 84327178Sminshall 84432377Sminshall /* 84532377Sminshall * Something to read from the network... 84632377Sminshall */ 84732377Sminshall if (FD_ISSET(net, &ibits)) { 84832377Sminshall int canread; 84927178Sminshall 85032377Sminshall FD_CLR(net, &ibits); 85132377Sminshall if (scc == 0) { 85232377Sminshall sbp = sibuf; 85332377Sminshall } 85432377Sminshall canread = sibuf + sizeof sibuf - (sbp+scc); 85532377Sminshall #if !defined(SO_OOBINLINE) 85632377Sminshall /* 85732377Sminshall * In 4.2 (and some early 4.3) systems, the 85832377Sminshall * OOB indication and data handling in the kernel 85932377Sminshall * is such that if two separate TCP Urgent requests 86032377Sminshall * come in, one byte of TCP data will be overlaid. 86132377Sminshall * This is fatal for Telnet, but we try to live 86232377Sminshall * with it. 86332377Sminshall * 86432377Sminshall * In addition, in 4.2 (and...), a special protocol 86532377Sminshall * is needed to pick up the TCP Urgent data in 86632377Sminshall * the correct sequence. 86732377Sminshall * 86832377Sminshall * What we do is: if we think we are in urgent 86932377Sminshall * mode, we look to see if we are "at the mark". 87032377Sminshall * If we are, we do an OOB receive. If we run 87132377Sminshall * this twice, we will do the OOB receive twice, 87232377Sminshall * but the second will fail, since the second 87332377Sminshall * time we were "at the mark", but there wasn't 87432377Sminshall * any data there (the kernel doesn't reset 87532377Sminshall * "at the mark" until we do a normal read). 87632377Sminshall * Once we've read the OOB data, we go ahead 87732377Sminshall * and do normal reads. 87832377Sminshall * 87932377Sminshall * There is also another problem, which is that 88032377Sminshall * since the OOB byte we read doesn't put us 88132377Sminshall * out of OOB state, and since that byte is most 88232377Sminshall * likely the TELNET DM (data mark), we would 88332377Sminshall * stay in the TELNET SYNCH (SYNCHing) state. 88432377Sminshall * So, clocks to the rescue. If we've "just" 88532377Sminshall * received a DM, then we test for the 88632377Sminshall * presence of OOB data when the receive OOB 88732377Sminshall * fails (and AFTER we did the normal mode read 88832377Sminshall * to clear "at the mark"). 88932377Sminshall */ 89032377Sminshall if (SYNCHing) { 89132377Sminshall int atmark; 89232377Sminshall 89332377Sminshall ioctl(net, SIOCATMARK, (char *)&atmark); 89432377Sminshall if (atmark) { 89532377Sminshall c = recv(net, sbp+scc, canread, MSG_OOB); 89632377Sminshall if ((c == -1) && (errno == EINVAL)) { 89732377Sminshall c = recv(net, sbp+scc, canread, 0); 89832377Sminshall if (clocks.didnetreceive < clocks.gotDM) { 89932377Sminshall SYNCHing = stilloob(net); 90027261Sminshall } 90132377Sminshall } 90232377Sminshall } else { 90332377Sminshall c = recv(net, sbp+scc, canread, 0); 90432377Sminshall } 90532377Sminshall } else { 90632377Sminshall c = recv(net, sbp+scc, canread, 0); 90732377Sminshall } 90832377Sminshall settimer(didnetreceive); 90932377Sminshall #else /* !defined(SO_OOBINLINE) */ 91032377Sminshall c = recv(net, sbp+scc, canread, 0); 91132377Sminshall #endif /* !defined(SO_OOBINLINE) */ 91232377Sminshall if (c < 0 && errno == EWOULDBLOCK) { 91332377Sminshall c = 0; 91432377Sminshall } else if (c <= 0) { 91532377Sminshall return -1; 91632377Sminshall } 91732377Sminshall if (netdata) { 91832377Sminshall Dump('<', sbp+scc, c); 91932377Sminshall } 92032377Sminshall scc += c; 92132377Sminshall returnValue = 1; 92232377Sminshall } 92327178Sminshall 92432377Sminshall /* 92532377Sminshall * Something to read from the tty... 92632377Sminshall */ 92732377Sminshall #if defined(MSDOS) 92832377Sminshall if ((tcc == 0) && NETROOM() && (shell_active == 0) && TerminalCanRead()) 92932377Sminshall #else /* defined(MSDOS) */ 93032377Sminshall if (FD_ISSET(tin, &ibits)) 93132377Sminshall #endif /* defined(MSDOS) */ 93232377Sminshall { 93332377Sminshall FD_CLR(tin, &ibits); 93432377Sminshall if (tcc == 0) { 93532377Sminshall tbp = tibuf; /* nothing left, reset */ 93627178Sminshall } 93732377Sminshall c = TerminalRead(tin, tbp, tibuf+sizeof tibuf - tbp); 93832377Sminshall if (c < 0 && errno == EWOULDBLOCK) { 93932377Sminshall c = 0; 94032377Sminshall } else { 94132377Sminshall #if defined(unix) 94232377Sminshall /* EOF detection for line mode!!!! */ 94332377Sminshall if (c == 0 && MODE_LOCAL_CHARS(globalmode)) { 94432377Sminshall /* must be an EOF... */ 94532377Sminshall *tbp = termEofChar; 94632377Sminshall c = 1; 94732377Sminshall } 94832377Sminshall #endif /* defined(unix) */ 94932377Sminshall if (c <= 0) { 95032377Sminshall tcc = c; 95132377Sminshall return -1; 95232377Sminshall } 95327178Sminshall } 95432377Sminshall tcc += c; 95532377Sminshall returnValue = 1; /* did something useful */ 95632377Sminshall } 95727178Sminshall 95832377Sminshall # if defined(TN3270) 95932377Sminshall if (tcc > 0) { 96032377Sminshall if (In3270) { 96132377Sminshall c = DataFromTerminal(tbp, tcc); 96232377Sminshall if (c) { 96332377Sminshall returnValue = 1; 96432377Sminshall } 96532377Sminshall tcc -= c; 96632377Sminshall tbp += c; 96732377Sminshall } else { 96832377Sminshall # endif /* defined(TN3270) */ 96932377Sminshall returnValue = 1; 97032377Sminshall while (tcc > 0) { 97132377Sminshall register int sc; 97232377Sminshall 97332377Sminshall if (NETROOM() < 2) { 97432377Sminshall flushline = 1; 97532377Sminshall break; 97627186Sminshall } 97732377Sminshall c = *tbp++ & 0xff, sc = strip(c), tcc--; 97832377Sminshall if (sc == escape) { 97932377Sminshall command(0); 98032377Sminshall tcc = 0; 98132377Sminshall flushline = 1; 98232377Sminshall break; 98332377Sminshall } else if (MODE_LINE(globalmode) && (sc == echoc)) { 98432377Sminshall if (tcc > 0 && strip(*tbp) == echoc) { 98532377Sminshall tbp++; 98632377Sminshall tcc--; 98732377Sminshall } else { 98832377Sminshall dontlecho = !dontlecho; 98932377Sminshall settimer(echotoggle); 99032377Sminshall setconnmode(); 99132377Sminshall tcc = 0; 99232377Sminshall flushline = 1; 99332377Sminshall break; 99432377Sminshall } 99527186Sminshall } 99632377Sminshall if (localchars) { 99732377Sminshall if (TerminalSpecialChars(sc) == 0) { 99832377Sminshall break; 99932377Sminshall } 100032377Sminshall } 100132377Sminshall if (!myopts[TELOPT_BINARY]) { 100232377Sminshall switch (c) { 100332377Sminshall case '\n': 100432377Sminshall /* 100532377Sminshall * If we are in CRMOD mode (\r ==> \n) 100632377Sminshall * on our local machine, then probably 100732377Sminshall * a newline (unix) is CRLF (TELNET). 100832377Sminshall */ 100932377Sminshall if (MODE_LOCAL_CHARS(globalmode)) { 101032377Sminshall NETADD('\r'); 101132377Sminshall } 101232377Sminshall NETADD('\n'); 101332377Sminshall flushline = 1; 101432377Sminshall break; 101532377Sminshall case '\r': 101632377Sminshall if (!crlf) { 101732377Sminshall NET2ADD('\r', '\0'); 101832377Sminshall } else { 101932377Sminshall NET2ADD('\r', '\n'); 102032377Sminshall } 102132377Sminshall flushline = 1; 102232377Sminshall break; 102332377Sminshall case IAC: 102432377Sminshall NET2ADD(IAC, IAC); 102532377Sminshall break; 102632377Sminshall default: 102732377Sminshall NETADD(c); 102832377Sminshall break; 102932377Sminshall } 103032377Sminshall } else if (c == IAC) { 103132377Sminshall NET2ADD(IAC, IAC); 103232377Sminshall } else { 103332377Sminshall NETADD(c); 103432377Sminshall } 103527178Sminshall } 103632377Sminshall # if defined(TN3270) 103727178Sminshall } 103827178Sminshall } 103932377Sminshall # endif /* defined(TN3270) */ 104032377Sminshall 104132377Sminshall if ((!MODE_LINE(globalmode) || flushline || myopts[TELOPT_BINARY]) && 104232377Sminshall FD_ISSET(net, &obits) && (NETBYTES() > 0)) { 104332377Sminshall FD_CLR(net, &obits); 104432377Sminshall returnValue = netflush(); 104532377Sminshall } 104632377Sminshall if (scc > 0) { 104732377Sminshall # if !defined(TN3270) 104832377Sminshall telrcv(); 104932377Sminshall returnValue = 1; 105032377Sminshall # else /* !defined(TN3270) */ 105132377Sminshall returnValue = Push3270(); 105232377Sminshall # endif /* !defined(TN3270) */ 105332377Sminshall } 105432377Sminshall #if defined(MSDOS) 105532377Sminshall if (TTYBYTES()) 105632377Sminshall #else /* defined(MSDOS) */ 105732377Sminshall if (FD_ISSET(tout, &obits) && (TTYBYTES() > 0)) 105832377Sminshall #endif /* defined(MSDOS) */ 105932377Sminshall { 106032377Sminshall FD_CLR(tout, &obits); 106132377Sminshall returnValue = ttyflush(SYNCHing|flushout); 106232377Sminshall } 106332377Sminshall return returnValue; 106427178Sminshall } 106527178Sminshall 106627178Sminshall /* 106732377Sminshall * Select from tty and network... 106827088Sminshall */ 106932377Sminshall void 107032377Sminshall telnet() 107127088Sminshall { 107232377Sminshall #if defined(MSDOS) 107332377Sminshall #define SCHED_BLOCK 0 /* Don't block in MSDOS */ 107432377Sminshall #else /* defined(MSDOS) */ 107532377Sminshall #define SCHED_BLOCK 1 107632377Sminshall #endif /* defined(MSDOS) */ 107727088Sminshall 107832377Sminshall #if defined(TN3270) && defined(unix) 107932377Sminshall int myPid; 108032377Sminshall #endif /* defined(TN3270) */ 108127088Sminshall 108232377Sminshall tout = fileno(stdout); 108332377Sminshall tin = fileno(stdin); 108432377Sminshall setconnmode(); 108532377Sminshall scc = 0; 108632377Sminshall tcc = 0; 108732377Sminshall FD_ZERO(&ibits); 108832377Sminshall FD_ZERO(&obits); 108932377Sminshall FD_ZERO(&xbits); 109027261Sminshall 109132377Sminshall NetNonblockingIO(net, 1); 109227088Sminshall 109332377Sminshall #if defined(TN3270) 109432377Sminshall if (noasynch == 0) { /* DBX can't handle! */ 109532377Sminshall NetSigIO(net, 1); 109632377Sminshall } 109732377Sminshall NetSetPgrp(net); 109832377Sminshall #endif /* defined(TN3270) */ 109927088Sminshall 110027088Sminshall 110132377Sminshall #if defined(SO_OOBINLINE) && !defined(MSDOS) 110232377Sminshall SetSockOpt(net, SOL_SOCKET, SO_OOBINLINE, 1); 110332377Sminshall #endif /* defined(SO_OOBINLINE) && !defined(MSDOS) */ 110427088Sminshall 110532377Sminshall # if !defined(TN3270) 110632377Sminshall if (telnetport) { 110732377Sminshall if (!hisopts[TELOPT_SGA]) { 110832377Sminshall willoption(TELOPT_SGA, 0); 110927110Sminshall } 111032377Sminshall if (!myopts[TELOPT_TTYPE]) { 111132377Sminshall dooption(TELOPT_TTYPE, 0); 111232377Sminshall } 111327178Sminshall } 111432377Sminshall # endif /* !defined(TN3270) */ 111527088Sminshall 111632377Sminshall # if !defined(TN3270) 111732377Sminshall for (;;) { 111832377Sminshall if (Scheduler(SCHED_BLOCK) == -1) { 111932377Sminshall setcommandmode(); 112032377Sminshall return; 112132377Sminshall } 112232377Sminshall } 112332377Sminshall # else /* !defined(TN3270) */ 112432377Sminshall for (;;) { 112532377Sminshall int schedValue; 112627088Sminshall 112732377Sminshall while (!In3270 && !shell_active) { 112832377Sminshall if (Scheduler(SCHED_BLOCK) == -1) { 112932377Sminshall setcommandmode(); 113032377Sminshall return; 113132377Sminshall } 113227088Sminshall } 113332377Sminshall 113432377Sminshall while ((schedValue = Scheduler(0)) != 0) { 113532377Sminshall if (schedValue == -1) { 113632377Sminshall setcommandmode(); 113732377Sminshall return; 113832377Sminshall } 113927088Sminshall } 114032377Sminshall /* If there is data waiting to go out to terminal, don't 114132377Sminshall * schedule any more data for the terminal. 114232377Sminshall */ 114332377Sminshall if (tfrontp-tbackp) { 114432377Sminshall schedValue = 1; 114527088Sminshall } else { 114632377Sminshall if (shell_active) { 114732377Sminshall if (shell_continue() == 0) { 114832377Sminshall ConnectScreen(); 114927088Sminshall } 115032377Sminshall } else if (In3270) { 115132377Sminshall schedValue = DoTerminalOutput(); 115232377Sminshall } 115327088Sminshall } 115432377Sminshall if (schedValue && (shell_active == 0)) { 115532377Sminshall if (Scheduler(SCHED_BLOCK) == -1) { 115632377Sminshall setcommandmode(); 115732377Sminshall return; 115832377Sminshall } 115927088Sminshall } 116032377Sminshall } 116132377Sminshall # endif /* !defined(TN3270) */ 116227088Sminshall } 116332377Sminshall 116427088Sminshall /* 116532377Sminshall * These routines add various telnet commands to the data stream. 116627088Sminshall */ 116732377Sminshall 116832377Sminshall void 116932377Sminshall xmitAO() 117027088Sminshall { 117132377Sminshall NET2ADD(IAC, AO); 117232377Sminshall if (autoflush) { 117332377Sminshall doflush(); 117432377Sminshall } 117532377Sminshall } 117627088Sminshall 117732377Sminshall 117832377Sminshall void 117932377Sminshall xmitEL() 118027088Sminshall { 118132377Sminshall NET2ADD(IAC, EL); 118227088Sminshall } 118327088Sminshall 118432377Sminshall void 118532377Sminshall xmitEC() 118627088Sminshall { 118732377Sminshall NET2ADD(IAC, EC); 118827088Sminshall } 118927088Sminshall 119032377Sminshall 119132377Sminshall #if defined(NOT43) 119232377Sminshall int 119332377Sminshall #else /* defined(NOT43) */ 119432377Sminshall void 119532377Sminshall #endif /* defined(NOT43) */ 119632377Sminshall dosynch() 119727088Sminshall { 119832377Sminshall netclear(); /* clear the path to the network */ 119932377Sminshall NET2ADD(IAC, DM); 120027088Sminshall 120132377Sminshall #if defined(NOT43) 120232377Sminshall return 0; 120332377Sminshall #endif /* defined(NOT43) */ 120427088Sminshall } 120527088Sminshall 120632377Sminshall void 120732377Sminshall doflush() 120827088Sminshall { 120932377Sminshall NET2ADD(IAC, DO); 121032377Sminshall NETADD(TELOPT_TM); 121132377Sminshall flushline = 1; 121232377Sminshall flushout = 1; 121332377Sminshall ttyflush(1); /* Flush/drop output */ 121432377Sminshall /* do printoption AFTER flush, otherwise the output gets tossed... */ 121532377Sminshall printoption("<SENT", doopt, TELOPT_TM, 0); 121627088Sminshall } 121727088Sminshall 121832377Sminshall void 121932377Sminshall intp() 122027088Sminshall { 122132377Sminshall NET2ADD(IAC, IP); 122232377Sminshall flushline = 1; 122332377Sminshall if (autoflush) { 122432377Sminshall doflush(); 122532377Sminshall } 122632377Sminshall if (autosynch) { 122732377Sminshall dosynch(); 122832377Sminshall } 122927088Sminshall } 123027186Sminshall 123132377Sminshall void 123232377Sminshall sendbrk() 123327186Sminshall { 123432377Sminshall NET2ADD(IAC, BREAK); 123532377Sminshall flushline = 1; 123632377Sminshall if (autoflush) { 123732377Sminshall doflush(); 123832377Sminshall } 123932377Sminshall if (autosynch) { 124032377Sminshall dosynch(); 124132377Sminshall } 124227186Sminshall } 1243