termstat.c revision 72089
129088Smarkm/* 229088Smarkm * Copyright (c) 1989, 1993 329088Smarkm * The Regents of the University of California. All rights reserved. 429088Smarkm * 529088Smarkm * Redistribution and use in source and binary forms, with or without 629088Smarkm * modification, are permitted provided that the following conditions 729088Smarkm * are met: 829088Smarkm * 1. Redistributions of source code must retain the above copyright 929088Smarkm * notice, this list of conditions and the following disclaimer. 1029088Smarkm * 2. Redistributions in binary form must reproduce the above copyright 1129088Smarkm * notice, this list of conditions and the following disclaimer in the 1229088Smarkm * documentation and/or other materials provided with the distribution. 1329088Smarkm * 3. All advertising materials mentioning features or use of this software 1429088Smarkm * must display the following acknowledgement: 1529088Smarkm * This product includes software developed by the University of 1629088Smarkm * California, Berkeley and its contributors. 1729088Smarkm * 4. Neither the name of the University nor the names of its contributors 1829088Smarkm * may be used to endorse or promote products derived from this software 1929088Smarkm * without specific prior written permission. 2029088Smarkm * 2129088Smarkm * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2229088Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2329088Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2429088Smarkm * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2529088Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2629088Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2729088Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2829088Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2929088Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3029088Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3129088Smarkm * SUCH DAMAGE. 3229088Smarkm */ 3329088Smarkm 3429088Smarkm#ifndef lint 3531622Scharnier#if 0 3629181Smarkmstatic const char sccsid[] = "@(#)termstat.c 8.2 (Berkeley) 5/30/95"; 3731622Scharnier#endif 3831622Scharnierstatic const char rcsid[] = 3950479Speter "$FreeBSD: head/contrib/telnet/telnetd/termstat.c 72089 2001-02-06 10:39:38Z asmodai $"; 4029088Smarkm#endif /* not lint */ 4129088Smarkm 4229088Smarkm#include "telnetd.h" 4329088Smarkm 4429181Smarkm#if defined(ENCRYPTION) 4529181Smarkm#include <libtelnet/encrypt.h> 4629181Smarkm#endif 4729181Smarkm 4829088Smarkm/* 4929088Smarkm * local variables 5029088Smarkm */ 5129088Smarkmint def_tspeed = -1, def_rspeed = -1; 5229088Smarkm#ifdef TIOCSWINSZ 5329088Smarkmint def_row = 0, def_col = 0; 5429088Smarkm#endif 5529088Smarkm#ifdef LINEMODE 5629088Smarkmstatic int _terminit = 0; 5729088Smarkm#endif /* LINEMODE */ 5829088Smarkm 5929088Smarkm#if defined(CRAY2) && defined(UNICOS5) 6029088Smarkmint newmap = 1; /* nonzero if \n maps to ^M^J */ 6129088Smarkm#endif 6229088Smarkm 6329088Smarkm#ifdef LINEMODE 6429088Smarkm/* 6529088Smarkm * localstat 6629088Smarkm * 6729088Smarkm * This function handles all management of linemode. 6829088Smarkm * 6929088Smarkm * Linemode allows the client to do the local editing of data 7029088Smarkm * and send only complete lines to the server. Linemode state is 7129088Smarkm * based on the state of the pty driver. If the pty is set for 7229088Smarkm * external processing, then we can use linemode. Further, if we 7329088Smarkm * can use real linemode, then we can look at the edit control bits 7429088Smarkm * in the pty to determine what editing the client should do. 7529088Smarkm * 7629088Smarkm * Linemode support uses the following state flags to keep track of 7729088Smarkm * current and desired linemode state. 7829088Smarkm * alwayslinemode : true if -l was specified on the telnetd 7929088Smarkm * command line. It means to have linemode on as much as 8029088Smarkm * possible. 8129088Smarkm * 8229088Smarkm * lmodetype: signifies whether the client can 8329088Smarkm * handle real linemode, or if use of kludgeomatic linemode 8429088Smarkm * is preferred. It will be set to one of the following: 8529088Smarkm * REAL_LINEMODE : use linemode option 8629088Smarkm * NO_KLUDGE : don't initiate kludge linemode. 8729088Smarkm * KLUDGE_LINEMODE : use kludge linemode 8829088Smarkm * NO_LINEMODE : client is ignorant of linemode 8929088Smarkm * 9029088Smarkm * linemode, uselinemode : linemode is true if linemode 9129088Smarkm * is currently on, uselinemode is the state that we wish 9229088Smarkm * to be in. If another function wishes to turn linemode 9329088Smarkm * on or off, it sets or clears uselinemode. 9429088Smarkm * 9529088Smarkm * editmode, useeditmode : like linemode/uselinemode, but 9629088Smarkm * these contain the edit mode states (edit and trapsig). 9729088Smarkm * 9829088Smarkm * The state variables correspond to some of the state information 9929088Smarkm * in the pty. 10029088Smarkm * linemode: 10129088Smarkm * In real linemode, this corresponds to whether the pty 10229088Smarkm * expects external processing of incoming data. 10329088Smarkm * In kludge linemode, this more closely corresponds to the 10429088Smarkm * whether normal processing is on or not. (ICANON in 10529088Smarkm * system V, or COOKED mode in BSD.) 10629088Smarkm * If the -l option was specified (alwayslinemode), then 10729088Smarkm * an attempt is made to force external processing on at 10829088Smarkm * all times. 10929088Smarkm * 11029088Smarkm * The following heuristics are applied to determine linemode 11129088Smarkm * handling within the server. 11229088Smarkm * 1) Early on in starting up the server, an attempt is made 11329088Smarkm * to negotiate the linemode option. If this succeeds 11429088Smarkm * then lmodetype is set to REAL_LINEMODE and all linemode 11529088Smarkm * processing occurs in the context of the linemode option. 11629088Smarkm * 2) If the attempt to negotiate the linemode option failed, 11729088Smarkm * and the "-k" (don't initiate kludge linemode) isn't set, 11829088Smarkm * then we try to use kludge linemode. We test for this 11929088Smarkm * capability by sending "do Timing Mark". If a positive 12029088Smarkm * response comes back, then we assume that the client 12129088Smarkm * understands kludge linemode (ech!) and the 12229088Smarkm * lmodetype flag is set to KLUDGE_LINEMODE. 12329088Smarkm * 3) Otherwise, linemode is not supported at all and 12429088Smarkm * lmodetype remains set to NO_LINEMODE (which happens 12529088Smarkm * to be 0 for convenience). 12629088Smarkm * 4) At any time a command arrives that implies a higher 12729088Smarkm * state of linemode support in the client, we move to that 12829088Smarkm * linemode support. 12929088Smarkm * 13029088Smarkm * A short explanation of kludge linemode is in order here. 13129088Smarkm * 1) The heuristic to determine support for kludge linemode 13229088Smarkm * is to send a do timing mark. We assume that a client 13329088Smarkm * that supports timing marks also supports kludge linemode. 13429088Smarkm * A risky proposition at best. 13529088Smarkm * 2) Further negotiation of linemode is done by changing the 13629088Smarkm * the server's state regarding SGA. If server will SGA, 13729088Smarkm * then linemode is off, if server won't SGA, then linemode 13829088Smarkm * is on. 13929088Smarkm */ 14029088Smarkm void 14129088Smarkmlocalstat() 14229088Smarkm{ 14329088Smarkm void netflush(); 14429088Smarkm int need_will_echo = 0; 14529088Smarkm 14629088Smarkm#if defined(CRAY2) && defined(UNICOS5) 14729088Smarkm /* 14829088Smarkm * Keep track of that ol' CR/NL mapping while we're in the 14929088Smarkm * neighborhood. 15029088Smarkm */ 15129088Smarkm newmap = tty_isnewmap(); 15229088Smarkm#endif /* defined(CRAY2) && defined(UNICOS5) */ 15329088Smarkm 15429088Smarkm /* 15529181Smarkm * Check for changes to flow control if client supports it. 15629181Smarkm */ 15729181Smarkm flowstat(); 15829181Smarkm 15929181Smarkm /* 16029181Smarkm * Check linemode on/off state 16129181Smarkm */ 16229181Smarkm uselinemode = tty_linemode(); 16329181Smarkm 16429181Smarkm /* 16529181Smarkm * If alwayslinemode is on, and pty is changing to turn it off, then 16629181Smarkm * force linemode back on. 16729181Smarkm */ 16829181Smarkm if (alwayslinemode && linemode && !uselinemode) { 16929181Smarkm uselinemode = 1; 17029181Smarkm tty_setlinemode(uselinemode); 17129181Smarkm } 17229181Smarkm 17329181Smarkm if (uselinemode) { 17429181Smarkm /* 17529088Smarkm * Check for state of BINARY options. 17629181Smarkm * 17729181Smarkm * We only need to do the binary dance if we are actually going 17829181Smarkm * to use linemode. As this confuses some telnet clients 17929181Smarkm * that don't support linemode, and doesn't gain us 18029181Smarkm * anything, we don't do it unless we're doing linemode. 18129181Smarkm * -Crh (henrich@msu.edu) 18229088Smarkm */ 18329181Smarkm 18429088Smarkm if (tty_isbinaryin()) { 18529088Smarkm if (his_want_state_is_wont(TELOPT_BINARY)) 18629088Smarkm send_do(TELOPT_BINARY, 1); 18729088Smarkm } else { 18829088Smarkm if (his_want_state_is_will(TELOPT_BINARY)) 18929088Smarkm send_dont(TELOPT_BINARY, 1); 19029088Smarkm } 19129088Smarkm 19229088Smarkm if (tty_isbinaryout()) { 19329088Smarkm if (my_want_state_is_wont(TELOPT_BINARY)) 19429088Smarkm send_will(TELOPT_BINARY, 1); 19529088Smarkm } else { 19629088Smarkm if (my_want_state_is_will(TELOPT_BINARY)) 19729088Smarkm send_wont(TELOPT_BINARY, 1); 19829088Smarkm } 19929088Smarkm } 20029088Smarkm 20129088Smarkm#ifdef ENCRYPTION 20229088Smarkm /* 20329088Smarkm * If the terminal is not echoing, but editing is enabled, 20429088Smarkm * something like password input is going to happen, so 20529088Smarkm * if we the other side is not currently sending encrypted 20629088Smarkm * data, ask the other side to start encrypting. 20729088Smarkm */ 20829088Smarkm if (his_state_is_will(TELOPT_ENCRYPT)) { 20929088Smarkm static int enc_passwd = 0; 21029088Smarkm if (uselinemode && !tty_isecho() && tty_isediting() 21129088Smarkm && (enc_passwd == 0) && !decrypt_input) { 21229088Smarkm encrypt_send_request_start(); 21329088Smarkm enc_passwd = 1; 21429088Smarkm } else if (enc_passwd) { 21529088Smarkm encrypt_send_request_end(); 21629088Smarkm enc_passwd = 0; 21729088Smarkm } 21829088Smarkm } 21929088Smarkm#endif /* ENCRYPTION */ 22029088Smarkm 22129088Smarkm /* 22229088Smarkm * Do echo mode handling as soon as we know what the 22329088Smarkm * linemode is going to be. 22429088Smarkm * If the pty has echo turned off, then tell the client that 22529088Smarkm * the server will echo. If echo is on, then the server 22629088Smarkm * will echo if in character mode, but in linemode the 22729088Smarkm * client should do local echoing. The state machine will 22829088Smarkm * not send anything if it is unnecessary, so don't worry 22929088Smarkm * about that here. 23029088Smarkm * 23129088Smarkm * If we need to send the WILL ECHO (because echo is off), 23229088Smarkm * then delay that until after we have changed the MODE. 23329088Smarkm * This way, when the user is turning off both editing 23429088Smarkm * and echo, the client will get editing turned off first. 23529088Smarkm * This keeps the client from going into encryption mode 23629088Smarkm * and then right back out if it is doing auto-encryption 23729088Smarkm * when passwords are being typed. 23829088Smarkm */ 23929088Smarkm if (uselinemode) { 24029088Smarkm if (tty_isecho()) 24129088Smarkm send_wont(TELOPT_ECHO, 1); 24229088Smarkm else 24329088Smarkm need_will_echo = 1; 24429088Smarkm#ifdef KLUDGELINEMODE 24529088Smarkm if (lmodetype == KLUDGE_OK) 24629088Smarkm lmodetype = KLUDGE_LINEMODE; 24729088Smarkm#endif 24829088Smarkm } 24929088Smarkm 25029088Smarkm /* 25129088Smarkm * If linemode is being turned off, send appropriate 25229088Smarkm * command and then we're all done. 25329088Smarkm */ 25429088Smarkm if (!uselinemode && linemode) { 25529088Smarkm# ifdef KLUDGELINEMODE 25629088Smarkm if (lmodetype == REAL_LINEMODE) { 25729088Smarkm# endif /* KLUDGELINEMODE */ 25829088Smarkm send_dont(TELOPT_LINEMODE, 1); 25929088Smarkm# ifdef KLUDGELINEMODE 26029088Smarkm } else if (lmodetype == KLUDGE_LINEMODE) 26129088Smarkm send_will(TELOPT_SGA, 1); 26229088Smarkm# endif /* KLUDGELINEMODE */ 26329088Smarkm send_will(TELOPT_ECHO, 1); 26429088Smarkm linemode = uselinemode; 26529088Smarkm goto done; 26629088Smarkm } 26729088Smarkm 26829088Smarkm# ifdef KLUDGELINEMODE 26929088Smarkm /* 27029088Smarkm * If using real linemode check edit modes for possible later use. 27129088Smarkm * If we are in kludge linemode, do the SGA negotiation. 27229088Smarkm */ 27329088Smarkm if (lmodetype == REAL_LINEMODE) { 27429088Smarkm# endif /* KLUDGELINEMODE */ 27529088Smarkm useeditmode = 0; 27629088Smarkm if (tty_isediting()) 27729088Smarkm useeditmode |= MODE_EDIT; 27829088Smarkm if (tty_istrapsig()) 27929088Smarkm useeditmode |= MODE_TRAPSIG; 28029088Smarkm if (tty_issofttab()) 28129088Smarkm useeditmode |= MODE_SOFT_TAB; 28229088Smarkm if (tty_islitecho()) 28329088Smarkm useeditmode |= MODE_LIT_ECHO; 28429088Smarkm# ifdef KLUDGELINEMODE 28529088Smarkm } else if (lmodetype == KLUDGE_LINEMODE) { 28629088Smarkm if (tty_isediting() && uselinemode) 28729088Smarkm send_wont(TELOPT_SGA, 1); 28829088Smarkm else 28929088Smarkm send_will(TELOPT_SGA, 1); 29029088Smarkm } 29129088Smarkm# endif /* KLUDGELINEMODE */ 29229088Smarkm 29329088Smarkm /* 29429088Smarkm * Negotiate linemode on if pty state has changed to turn it on. 29529088Smarkm * Send appropriate command and send along edit mode, then all done. 29629088Smarkm */ 29729088Smarkm if (uselinemode && !linemode) { 29829088Smarkm# ifdef KLUDGELINEMODE 29929088Smarkm if (lmodetype == KLUDGE_LINEMODE) { 30029088Smarkm send_wont(TELOPT_SGA, 1); 30129088Smarkm } else if (lmodetype == REAL_LINEMODE) { 30229088Smarkm# endif /* KLUDGELINEMODE */ 30329088Smarkm send_do(TELOPT_LINEMODE, 1); 30429088Smarkm /* send along edit modes */ 30529088Smarkm (void) sprintf(nfrontp, "%c%c%c%c%c%c%c", IAC, SB, 30629088Smarkm TELOPT_LINEMODE, LM_MODE, useeditmode, 30729088Smarkm IAC, SE); 30829088Smarkm nfrontp += 7; 30929088Smarkm editmode = useeditmode; 31029088Smarkm# ifdef KLUDGELINEMODE 31129088Smarkm } 31229088Smarkm# endif /* KLUDGELINEMODE */ 31329088Smarkm linemode = uselinemode; 31429088Smarkm goto done; 31529088Smarkm } 31629088Smarkm 31729088Smarkm# ifdef KLUDGELINEMODE 31829088Smarkm /* 31929088Smarkm * None of what follows is of any value if not using 32029088Smarkm * real linemode. 32129088Smarkm */ 32229088Smarkm if (lmodetype < REAL_LINEMODE) 32329088Smarkm goto done; 32429088Smarkm# endif /* KLUDGELINEMODE */ 32529088Smarkm 32629088Smarkm if (linemode && his_state_is_will(TELOPT_LINEMODE)) { 32729088Smarkm /* 32829088Smarkm * If edit mode changed, send edit mode. 32929088Smarkm */ 33029088Smarkm if (useeditmode != editmode) { 33129088Smarkm /* 33229088Smarkm * Send along appropriate edit mode mask. 33329088Smarkm */ 33429088Smarkm (void) sprintf(nfrontp, "%c%c%c%c%c%c%c", IAC, SB, 33529088Smarkm TELOPT_LINEMODE, LM_MODE, useeditmode, 33629088Smarkm IAC, SE); 33729088Smarkm nfrontp += 7; 33829088Smarkm editmode = useeditmode; 33929088Smarkm } 34029088Smarkm 34129088Smarkm 34229088Smarkm /* 34329088Smarkm * Check for changes to special characters in use. 34429088Smarkm */ 34529088Smarkm start_slc(0); 34629088Smarkm check_slc(); 34729088Smarkm (void) end_slc(0); 34829088Smarkm } 34929088Smarkm 35029088Smarkmdone: 35129088Smarkm if (need_will_echo) 35229088Smarkm send_will(TELOPT_ECHO, 1); 35329088Smarkm /* 35429088Smarkm * Some things should be deferred until after the pty state has 35529088Smarkm * been set by the local process. Do those things that have been 35629088Smarkm * deferred now. This only happens once. 35729088Smarkm */ 35829088Smarkm if (_terminit == 0) { 35929088Smarkm _terminit = 1; 36029088Smarkm defer_terminit(); 36129088Smarkm } 36229088Smarkm 36329088Smarkm netflush(); 36429088Smarkm set_termbuf(); 36529088Smarkm return; 36629088Smarkm 36729088Smarkm} /* end of localstat */ 36829088Smarkm#endif /* LINEMODE */ 36929088Smarkm 37029088Smarkm/* 37129088Smarkm * flowstat 37229088Smarkm * 37329088Smarkm * Check for changes to flow control 37429088Smarkm */ 37529088Smarkm void 37629088Smarkmflowstat() 37729088Smarkm{ 37829088Smarkm if (his_state_is_will(TELOPT_LFLOW)) { 37929088Smarkm if (tty_flowmode() != flowmode) { 38029088Smarkm flowmode = tty_flowmode(); 38129088Smarkm (void) sprintf(nfrontp, "%c%c%c%c%c%c", 38229088Smarkm IAC, SB, TELOPT_LFLOW, 38329088Smarkm flowmode ? LFLOW_ON : LFLOW_OFF, 38429088Smarkm IAC, SE); 38529088Smarkm nfrontp += 6; 38629088Smarkm } 38729088Smarkm if (tty_restartany() != restartany) { 38829088Smarkm restartany = tty_restartany(); 38929088Smarkm (void) sprintf(nfrontp, "%c%c%c%c%c%c", 39029088Smarkm IAC, SB, TELOPT_LFLOW, 39129088Smarkm restartany ? LFLOW_RESTART_ANY 39229088Smarkm : LFLOW_RESTART_XON, 39329088Smarkm IAC, SE); 39429088Smarkm nfrontp += 6; 39529088Smarkm } 39629088Smarkm } 39729088Smarkm} 39829088Smarkm 39929088Smarkm/* 40029088Smarkm * clientstat 40129088Smarkm * 40229088Smarkm * Process linemode related requests from the client. 40329088Smarkm * Client can request a change to only one of linemode, editmode or slc's 40429088Smarkm * at a time, and if using kludge linemode, then only linemode may be 40529088Smarkm * affected. 40629088Smarkm */ 40729088Smarkm void 40829088Smarkmclientstat(code, parm1, parm2) 40929088Smarkm register int code, parm1, parm2; 41029088Smarkm{ 41129088Smarkm void netflush(); 41229088Smarkm 41329088Smarkm /* 41429088Smarkm * Get a copy of terminal characteristics. 41529088Smarkm */ 41629088Smarkm init_termbuf(); 41729088Smarkm 41829088Smarkm /* 41929088Smarkm * Process request from client. code tells what it is. 42029088Smarkm */ 42129088Smarkm switch (code) { 42229088Smarkm#ifdef LINEMODE 42329088Smarkm case TELOPT_LINEMODE: 42429088Smarkm /* 42529088Smarkm * Don't do anything unless client is asking us to change 42629088Smarkm * modes. 42729088Smarkm */ 42829088Smarkm uselinemode = (parm1 == WILL); 42929088Smarkm if (uselinemode != linemode) { 43029088Smarkm# ifdef KLUDGELINEMODE 43129088Smarkm /* 43229088Smarkm * If using kludge linemode, make sure that 43329088Smarkm * we can do what the client asks. 43429088Smarkm * We can not turn off linemode if alwayslinemode 43529088Smarkm * and the ICANON bit is set. 43629088Smarkm */ 43729088Smarkm if (lmodetype == KLUDGE_LINEMODE) { 43829088Smarkm if (alwayslinemode && tty_isediting()) { 43929088Smarkm uselinemode = 1; 44029088Smarkm } 44129088Smarkm } 44229088Smarkm 44329088Smarkm /* 44429088Smarkm * Quit now if we can't do it. 44529088Smarkm */ 44629088Smarkm if (uselinemode == linemode) 44729088Smarkm return; 44829088Smarkm 44929088Smarkm /* 45029088Smarkm * If using real linemode and linemode is being 45129088Smarkm * turned on, send along the edit mode mask. 45229088Smarkm */ 45329088Smarkm if (lmodetype == REAL_LINEMODE && uselinemode) 45429088Smarkm# else /* KLUDGELINEMODE */ 45529088Smarkm if (uselinemode) 45629088Smarkm# endif /* KLUDGELINEMODE */ 45729088Smarkm { 45829088Smarkm useeditmode = 0; 45929088Smarkm if (tty_isediting()) 46029088Smarkm useeditmode |= MODE_EDIT; 46129088Smarkm if (tty_istrapsig) 46229088Smarkm useeditmode |= MODE_TRAPSIG; 46329088Smarkm if (tty_issofttab()) 46429088Smarkm useeditmode |= MODE_SOFT_TAB; 46529088Smarkm if (tty_islitecho()) 46629088Smarkm useeditmode |= MODE_LIT_ECHO; 46729088Smarkm (void) sprintf(nfrontp, "%c%c%c%c%c%c%c", IAC, 46829088Smarkm SB, TELOPT_LINEMODE, LM_MODE, 46929088Smarkm useeditmode, IAC, SE); 47029088Smarkm nfrontp += 7; 47129088Smarkm editmode = useeditmode; 47229088Smarkm } 47329088Smarkm 47429088Smarkm 47529088Smarkm tty_setlinemode(uselinemode); 47629088Smarkm 47729088Smarkm linemode = uselinemode; 47829088Smarkm 47929088Smarkm if (!linemode) 48029088Smarkm send_will(TELOPT_ECHO, 1); 48129088Smarkm } 48229088Smarkm break; 48329088Smarkm 48429088Smarkm case LM_MODE: 48529088Smarkm { 48629088Smarkm register int ack, changed; 48729088Smarkm 48829088Smarkm /* 48929088Smarkm * Client has sent along a mode mask. If it agrees with 49029088Smarkm * what we are currently doing, ignore it; if not, it could 49129088Smarkm * be viewed as a request to change. Note that the server 49229088Smarkm * will change to the modes in an ack if it is different from 49329088Smarkm * what we currently have, but we will not ack the ack. 49429088Smarkm */ 49529088Smarkm useeditmode &= MODE_MASK; 49629088Smarkm ack = (useeditmode & MODE_ACK); 49729088Smarkm useeditmode &= ~MODE_ACK; 49829088Smarkm 49929181Smarkm if ((changed = (useeditmode ^ editmode))) { 50029088Smarkm /* 50129088Smarkm * This check is for a timing problem. If the 50229088Smarkm * state of the tty has changed (due to the user 50329088Smarkm * application) we need to process that info 50429088Smarkm * before we write in the state contained in the 50529088Smarkm * ack!!! This gets out the new MODE request, 50629088Smarkm * and when the ack to that command comes back 50729088Smarkm * we'll set it and be in the right mode. 50829088Smarkm */ 50929088Smarkm if (ack) 51029088Smarkm localstat(); 51129088Smarkm if (changed & MODE_EDIT) 51229088Smarkm tty_setedit(useeditmode & MODE_EDIT); 51329088Smarkm 51429088Smarkm if (changed & MODE_TRAPSIG) 51529088Smarkm tty_setsig(useeditmode & MODE_TRAPSIG); 51629088Smarkm 51729088Smarkm if (changed & MODE_SOFT_TAB) 51829088Smarkm tty_setsofttab(useeditmode & MODE_SOFT_TAB); 51929088Smarkm 52029088Smarkm if (changed & MODE_LIT_ECHO) 52129088Smarkm tty_setlitecho(useeditmode & MODE_LIT_ECHO); 52229088Smarkm 52329088Smarkm set_termbuf(); 52429088Smarkm 52529088Smarkm if (!ack) { 52629088Smarkm (void) sprintf(nfrontp, "%c%c%c%c%c%c%c", IAC, 52729088Smarkm SB, TELOPT_LINEMODE, LM_MODE, 52829088Smarkm useeditmode|MODE_ACK, 52929088Smarkm IAC, SE); 53029088Smarkm nfrontp += 7; 53129088Smarkm } 53229088Smarkm 53329088Smarkm editmode = useeditmode; 53429088Smarkm } 53529088Smarkm 53629088Smarkm break; 53729088Smarkm 53829088Smarkm } /* end of case LM_MODE */ 53929088Smarkm#endif /* LINEMODE */ 54029088Smarkm 54129088Smarkm case TELOPT_NAWS: 54229088Smarkm#ifdef TIOCSWINSZ 54329088Smarkm { 54429088Smarkm struct winsize ws; 54529088Smarkm 54629088Smarkm def_col = parm1; 54729088Smarkm def_row = parm2; 54829088Smarkm#ifdef LINEMODE 54929088Smarkm /* 55029088Smarkm * Defer changing window size until after terminal is 55129088Smarkm * initialized. 55229088Smarkm */ 55329088Smarkm if (terminit() == 0) 55429088Smarkm return; 55529088Smarkm#endif /* LINEMODE */ 55629088Smarkm 55729088Smarkm /* 55829088Smarkm * Change window size as requested by client. 55929088Smarkm */ 56029088Smarkm 56129088Smarkm ws.ws_col = parm1; 56229088Smarkm ws.ws_row = parm2; 56329088Smarkm (void) ioctl(pty, TIOCSWINSZ, (char *)&ws); 56429088Smarkm } 56529088Smarkm#endif /* TIOCSWINSZ */ 56629088Smarkm 56729088Smarkm break; 56829088Smarkm 56929088Smarkm case TELOPT_TSPEED: 57029088Smarkm { 57129088Smarkm def_tspeed = parm1; 57229088Smarkm def_rspeed = parm2; 57329088Smarkm#ifdef LINEMODE 57429088Smarkm /* 57529088Smarkm * Defer changing the terminal speed. 57629088Smarkm */ 57729088Smarkm if (terminit() == 0) 57829088Smarkm return; 57929088Smarkm#endif /* LINEMODE */ 58029088Smarkm /* 58129088Smarkm * Change terminal speed as requested by client. 58229088Smarkm * We set the receive speed first, so that if we can't 58372089Sasmodai * store separate receive and transmit speeds, the transmit 58429088Smarkm * speed will take precedence. 58529088Smarkm */ 58629088Smarkm tty_rspeed(parm2); 58729088Smarkm tty_tspeed(parm1); 58829088Smarkm set_termbuf(); 58929088Smarkm 59029088Smarkm break; 59129088Smarkm 59229088Smarkm } /* end of case TELOPT_TSPEED */ 59329088Smarkm 59429088Smarkm default: 59529088Smarkm /* What? */ 59629088Smarkm break; 59729088Smarkm } /* end of switch */ 59829088Smarkm 59929088Smarkm#if defined(CRAY2) && defined(UNICOS5) 60029088Smarkm /* 60129088Smarkm * Just in case of the likely event that we changed the pty state. 60229088Smarkm */ 60329088Smarkm rcv_ioctl(); 60429088Smarkm#endif /* defined(CRAY2) && defined(UNICOS5) */ 60529088Smarkm 60629088Smarkm netflush(); 60729088Smarkm 60829088Smarkm} /* end of clientstat */ 60929088Smarkm 61029088Smarkm#if defined(CRAY2) && defined(UNICOS5) 61129088Smarkm void 61229088Smarkmtermstat() 61329088Smarkm{ 61429088Smarkm needtermstat = 1; 61529088Smarkm} 61629088Smarkm 61729088Smarkm void 61829088Smarkm_termstat() 61929088Smarkm{ 62029088Smarkm needtermstat = 0; 62129088Smarkm init_termbuf(); 62229088Smarkm localstat(); 62329088Smarkm rcv_ioctl(); 62429088Smarkm} 62529088Smarkm#endif /* defined(CRAY2) && defined(UNICOS5) */ 62629088Smarkm 62729088Smarkm#ifdef LINEMODE 62829088Smarkm/* 62929088Smarkm * defer_terminit 63029088Smarkm * 63129088Smarkm * Some things should not be done until after the login process has started 63229088Smarkm * and all the pty modes are set to what they are supposed to be. This 63329088Smarkm * function is called when the pty state has been processed for the first time. 63429088Smarkm * It calls other functions that do things that were deferred in each module. 63529088Smarkm */ 63629088Smarkm void 63729088Smarkmdefer_terminit() 63829088Smarkm{ 63929088Smarkm 64029088Smarkm /* 64129088Smarkm * local stuff that got deferred. 64229088Smarkm */ 64329088Smarkm if (def_tspeed != -1) { 64429088Smarkm clientstat(TELOPT_TSPEED, def_tspeed, def_rspeed); 64529088Smarkm def_tspeed = def_rspeed = 0; 64629088Smarkm } 64729088Smarkm 64829088Smarkm#ifdef TIOCSWINSZ 64929088Smarkm if (def_col || def_row) { 65029088Smarkm struct winsize ws; 65129088Smarkm 65229088Smarkm memset((char *)&ws, 0, sizeof(ws)); 65329088Smarkm ws.ws_col = def_col; 65429088Smarkm ws.ws_row = def_row; 65529088Smarkm (void) ioctl(pty, TIOCSWINSZ, (char *)&ws); 65629088Smarkm } 65729088Smarkm#endif 65829088Smarkm 65929088Smarkm /* 66029088Smarkm * The only other module that currently defers anything. 66129088Smarkm */ 66229088Smarkm deferslc(); 66329088Smarkm 66429088Smarkm} /* end of defer_terminit */ 66529088Smarkm 66629088Smarkm/* 66729088Smarkm * terminit 66829088Smarkm * 66929088Smarkm * Returns true if the pty state has been processed yet. 67029088Smarkm */ 67129088Smarkm int 67229088Smarkmterminit() 67329088Smarkm{ 67429088Smarkm return(_terminit); 67529088Smarkm 67629088Smarkm} /* end of terminit */ 67729088Smarkm#endif /* LINEMODE */ 678