Home | History | Annotate | Line # | Download | only in telnetd
      1  1.14    perry /*	$NetBSD: termstat.c,v 1.14 2005/02/06 05:58:21 perry Exp $	*/
      2   1.5  thorpej 
      3   1.1      cgd /*
      4   1.3      cgd  * Copyright (c) 1989, 1993
      5   1.3      cgd  *	The Regents of the University of California.  All rights reserved.
      6   1.1      cgd  *
      7   1.1      cgd  * Redistribution and use in source and binary forms, with or without
      8   1.1      cgd  * modification, are permitted provided that the following conditions
      9   1.1      cgd  * are met:
     10   1.1      cgd  * 1. Redistributions of source code must retain the above copyright
     11   1.1      cgd  *    notice, this list of conditions and the following disclaimer.
     12   1.1      cgd  * 2. Redistributions in binary form must reproduce the above copyright
     13   1.1      cgd  *    notice, this list of conditions and the following disclaimer in the
     14   1.1      cgd  *    documentation and/or other materials provided with the distribution.
     15  1.13      agc  * 3. Neither the name of the University nor the names of its contributors
     16   1.1      cgd  *    may be used to endorse or promote products derived from this software
     17   1.1      cgd  *    without specific prior written permission.
     18   1.1      cgd  *
     19   1.1      cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     20   1.1      cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     21   1.1      cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     22   1.1      cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     23   1.1      cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     24   1.1      cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     25   1.1      cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     26   1.1      cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     27   1.1      cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     28   1.1      cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     29   1.1      cgd  * SUCH DAMAGE.
     30   1.1      cgd  */
     31   1.1      cgd 
     32   1.6      mrg #include <sys/cdefs.h>
     33   1.1      cgd #ifndef lint
     34   1.5  thorpej #if 0
     35   1.5  thorpej static char sccsid[] = "@(#)termstat.c	8.2 (Berkeley) 5/30/95";
     36   1.5  thorpej #else
     37  1.14    perry __RCSID("$NetBSD: termstat.c,v 1.14 2005/02/06 05:58:21 perry Exp $");
     38   1.5  thorpej #endif
     39   1.1      cgd #endif /* not lint */
     40   1.1      cgd 
     41   1.1      cgd #include "telnetd.h"
     42   1.1      cgd 
     43  1.12   itojun #ifdef ENCRYPTION
     44   1.7  thorpej #include <libtelnet/encrypt.h>
     45   1.7  thorpej #endif
     46   1.7  thorpej 
     47   1.1      cgd /*
     48   1.1      cgd  * local variables
     49   1.1      cgd  */
     50   1.1      cgd int def_tspeed = -1, def_rspeed = -1;
     51   1.1      cgd int def_row = 0, def_col = 0;
     52   1.1      cgd #ifdef	LINEMODE
     53   1.1      cgd static int _terminit = 0;
     54   1.1      cgd #endif	/* LINEMODE */
     55   1.1      cgd 
     56   1.1      cgd 
     57   1.1      cgd #ifdef	LINEMODE
     58   1.1      cgd /*
     59   1.1      cgd  * localstat
     60   1.1      cgd  *
     61   1.1      cgd  * This function handles all management of linemode.
     62   1.1      cgd  *
     63   1.1      cgd  * Linemode allows the client to do the local editing of data
     64   1.1      cgd  * and send only complete lines to the server.  Linemode state is
     65   1.1      cgd  * based on the state of the pty driver.  If the pty is set for
     66   1.1      cgd  * external processing, then we can use linemode.  Further, if we
     67   1.1      cgd  * can use real linemode, then we can look at the edit control bits
     68   1.1      cgd  * in the pty to determine what editing the client should do.
     69   1.1      cgd  *
     70   1.1      cgd  * Linemode support uses the following state flags to keep track of
     71   1.1      cgd  * current and desired linemode state.
     72   1.1      cgd  *	alwayslinemode : true if -l was specified on the telnetd
     73   1.1      cgd  * 	command line.  It means to have linemode on as much as
     74   1.1      cgd  *	possible.
     75   1.1      cgd  *
     76   1.1      cgd  * 	lmodetype: signifies whether the client can
     77   1.1      cgd  *	handle real linemode, or if use of kludgeomatic linemode
     78   1.1      cgd  *	is preferred.  It will be set to one of the following:
     79   1.1      cgd  *		REAL_LINEMODE : use linemode option
     80   1.3      cgd  *		NO_KLUDGE : don't initiate kludge linemode.
     81   1.1      cgd  *		KLUDGE_LINEMODE : use kludge linemode
     82   1.1      cgd  *		NO_LINEMODE : client is ignorant of linemode
     83   1.1      cgd  *
     84   1.1      cgd  *	linemode, uselinemode : linemode is true if linemode
     85   1.1      cgd  *	is currently on, uselinemode is the state that we wish
     86   1.1      cgd  *	to be in.  If another function wishes to turn linemode
     87   1.1      cgd  *	on or off, it sets or clears uselinemode.
     88   1.1      cgd  *
     89   1.1      cgd  *	editmode, useeditmode : like linemode/uselinemode, but
     90   1.1      cgd  *	these contain the edit mode states (edit and trapsig).
     91   1.1      cgd  *
     92   1.1      cgd  * The state variables correspond to some of the state information
     93   1.1      cgd  * in the pty.
     94   1.1      cgd  *	linemode:
     95   1.1      cgd  *		In real linemode, this corresponds to whether the pty
     96   1.1      cgd  *		expects external processing of incoming data.
     97   1.1      cgd  *		In kludge linemode, this more closely corresponds to the
     98   1.1      cgd  *		whether normal processing is on or not.  (ICANON in
     99   1.1      cgd  *		system V, or COOKED mode in BSD.)
    100   1.1      cgd  *		If the -l option was specified (alwayslinemode), then
    101   1.1      cgd  *		an attempt is made to force external processing on at
    102   1.1      cgd  *		all times.
    103   1.1      cgd  *
    104   1.1      cgd  * The following heuristics are applied to determine linemode
    105   1.1      cgd  * handling within the server.
    106   1.1      cgd  *	1) Early on in starting up the server, an attempt is made
    107   1.1      cgd  *	   to negotiate the linemode option.  If this succeeds
    108   1.1      cgd  *	   then lmodetype is set to REAL_LINEMODE and all linemode
    109   1.1      cgd  *	   processing occurs in the context of the linemode option.
    110   1.1      cgd  *	2) If the attempt to negotiate the linemode option failed,
    111   1.3      cgd  *	   and the "-k" (don't initiate kludge linemode) isn't set,
    112   1.1      cgd  *	   then we try to use kludge linemode.  We test for this
    113   1.1      cgd  *	   capability by sending "do Timing Mark".  If a positive
    114   1.1      cgd  *	   response comes back, then we assume that the client
    115   1.1      cgd  *	   understands kludge linemode (ech!) and the
    116   1.1      cgd  *	   lmodetype flag is set to KLUDGE_LINEMODE.
    117   1.1      cgd  *	3) Otherwise, linemode is not supported at all and
    118   1.1      cgd  *	   lmodetype remains set to NO_LINEMODE (which happens
    119   1.1      cgd  *	   to be 0 for convenience).
    120   1.1      cgd  *	4) At any time a command arrives that implies a higher
    121   1.1      cgd  *	   state of linemode support in the client, we move to that
    122   1.1      cgd  *	   linemode support.
    123   1.1      cgd  *
    124   1.1      cgd  * A short explanation of kludge linemode is in order here.
    125   1.1      cgd  *	1) The heuristic to determine support for kludge linemode
    126   1.1      cgd  *	   is to send a do timing mark.  We assume that a client
    127   1.1      cgd  *	   that supports timing marks also supports kludge linemode.
    128   1.1      cgd  *	   A risky proposition at best.
    129   1.1      cgd  *	2) Further negotiation of linemode is done by changing the
    130   1.1      cgd  *	   the server's state regarding SGA.  If server will SGA,
    131   1.1      cgd  *	   then linemode is off, if server won't SGA, then linemode
    132   1.1      cgd  *	   is on.
    133   1.1      cgd  */
    134  1.12   itojun void
    135  1.14    perry localstat(void)
    136   1.1      cgd {
    137   1.1      cgd 	int need_will_echo = 0;
    138   1.1      cgd 
    139   1.1      cgd 
    140   1.1      cgd 	/*
    141   1.1      cgd 	 * Check for state of BINARY options.
    142   1.1      cgd 	 */
    143   1.1      cgd 	if (tty_isbinaryin()) {
    144   1.1      cgd 		if (his_want_state_is_wont(TELOPT_BINARY))
    145   1.1      cgd 			send_do(TELOPT_BINARY, 1);
    146   1.1      cgd 	} else {
    147   1.1      cgd 		if (his_want_state_is_will(TELOPT_BINARY))
    148   1.1      cgd 			send_dont(TELOPT_BINARY, 1);
    149   1.1      cgd 	}
    150   1.1      cgd 
    151   1.1      cgd 	if (tty_isbinaryout()) {
    152   1.1      cgd 		if (my_want_state_is_wont(TELOPT_BINARY))
    153   1.1      cgd 			send_will(TELOPT_BINARY, 1);
    154   1.1      cgd 	} else {
    155   1.1      cgd 		if (my_want_state_is_will(TELOPT_BINARY))
    156   1.1      cgd 			send_wont(TELOPT_BINARY, 1);
    157   1.1      cgd 	}
    158   1.1      cgd 
    159   1.1      cgd 	/*
    160   1.1      cgd 	 * Check for changes to flow control if client supports it.
    161   1.1      cgd 	 */
    162   1.3      cgd 	flowstat();
    163   1.1      cgd 
    164   1.1      cgd 	/*
    165   1.1      cgd 	 * Check linemode on/off state
    166   1.1      cgd 	 */
    167   1.1      cgd 	uselinemode = tty_linemode();
    168   1.1      cgd 
    169   1.1      cgd 	/*
    170   1.1      cgd 	 * If alwayslinemode is on, and pty is changing to turn it off, then
    171   1.1      cgd 	 * force linemode back on.
    172   1.1      cgd 	 */
    173   1.1      cgd 	if (alwayslinemode && linemode && !uselinemode) {
    174   1.1      cgd 		uselinemode = 1;
    175   1.1      cgd 		tty_setlinemode(uselinemode);
    176   1.1      cgd 	}
    177   1.1      cgd 
    178   1.7  thorpej #ifdef	ENCRYPTION
    179   1.7  thorpej 	/*
    180   1.7  thorpej 	 * If the terminal is not echoing, but editing is enabled,
    181   1.7  thorpej 	 * something like password input is going to happen, so
    182   1.7  thorpej 	 * if we the other side is not currently sending encrypted
    183   1.7  thorpej 	 * data, ask the other side to start encrypting.
    184   1.7  thorpej 	 */
    185   1.7  thorpej 	if (his_state_is_will(TELOPT_ENCRYPT)) {
    186   1.7  thorpej 		static int enc_passwd = 0;
    187   1.7  thorpej 		if (uselinemode && !tty_isecho() && tty_isediting()
    188   1.7  thorpej 		    && (enc_passwd == 0) && !decrypt_input) {
    189   1.7  thorpej 			encrypt_send_request_start();
    190   1.7  thorpej 			enc_passwd = 1;
    191   1.7  thorpej 		} else if (enc_passwd) {
    192   1.7  thorpej 			encrypt_send_request_end();
    193   1.7  thorpej 			enc_passwd = 0;
    194   1.7  thorpej 		}
    195   1.7  thorpej 	}
    196   1.7  thorpej #endif	/* ENCRYPTION */
    197   1.1      cgd 
    198   1.1      cgd 	/*
    199   1.1      cgd 	 * Do echo mode handling as soon as we know what the
    200   1.1      cgd 	 * linemode is going to be.
    201   1.1      cgd 	 * If the pty has echo turned off, then tell the client that
    202   1.1      cgd 	 * the server will echo.  If echo is on, then the server
    203   1.1      cgd 	 * will echo if in character mode, but in linemode the
    204   1.1      cgd 	 * client should do local echoing.  The state machine will
    205   1.1      cgd 	 * not send anything if it is unnecessary, so don't worry
    206   1.1      cgd 	 * about that here.
    207   1.1      cgd 	 *
    208   1.1      cgd 	 * If we need to send the WILL ECHO (because echo is off),
    209   1.1      cgd 	 * then delay that until after we have changed the MODE.
    210   1.1      cgd 	 * This way, when the user is turning off both editing
    211   1.1      cgd 	 * and echo, the client will get editing turned off first.
    212   1.1      cgd 	 * This keeps the client from going into encryption mode
    213   1.1      cgd 	 * and then right back out if it is doing auto-encryption
    214   1.1      cgd 	 * when passwords are being typed.
    215   1.1      cgd 	 */
    216   1.1      cgd 	if (uselinemode) {
    217   1.1      cgd 		if (tty_isecho())
    218   1.1      cgd 			send_wont(TELOPT_ECHO, 1);
    219   1.1      cgd 		else
    220   1.1      cgd 			need_will_echo = 1;
    221   1.3      cgd #ifdef	KLUDGELINEMODE
    222   1.3      cgd 		if (lmodetype == KLUDGE_OK)
    223   1.3      cgd 			lmodetype = KLUDGE_LINEMODE;
    224   1.3      cgd #endif
    225   1.1      cgd 	}
    226   1.1      cgd 
    227   1.1      cgd 	/*
    228   1.1      cgd 	 * If linemode is being turned off, send appropriate
    229   1.1      cgd 	 * command and then we're all done.
    230   1.1      cgd 	 */
    231   1.1      cgd 	 if (!uselinemode && linemode) {
    232   1.1      cgd # ifdef	KLUDGELINEMODE
    233   1.1      cgd 		if (lmodetype == REAL_LINEMODE) {
    234   1.1      cgd # endif	/* KLUDGELINEMODE */
    235   1.1      cgd 			send_dont(TELOPT_LINEMODE, 1);
    236   1.1      cgd # ifdef	KLUDGELINEMODE
    237   1.1      cgd 		} else if (lmodetype == KLUDGE_LINEMODE)
    238   1.1      cgd 			send_will(TELOPT_SGA, 1);
    239   1.1      cgd # endif	/* KLUDGELINEMODE */
    240   1.1      cgd 		send_will(TELOPT_ECHO, 1);
    241   1.1      cgd 		linemode = uselinemode;
    242   1.1      cgd 		goto done;
    243   1.1      cgd 	}
    244   1.1      cgd 
    245   1.1      cgd # ifdef	KLUDGELINEMODE
    246   1.1      cgd 	/*
    247   1.1      cgd 	 * If using real linemode check edit modes for possible later use.
    248   1.1      cgd 	 * If we are in kludge linemode, do the SGA negotiation.
    249   1.1      cgd 	 */
    250   1.1      cgd 	if (lmodetype == REAL_LINEMODE) {
    251   1.1      cgd # endif	/* KLUDGELINEMODE */
    252   1.1      cgd 		useeditmode = 0;
    253   1.1      cgd 		if (tty_isediting())
    254   1.1      cgd 			useeditmode |= MODE_EDIT;
    255   1.1      cgd 		if (tty_istrapsig())
    256   1.1      cgd 			useeditmode |= MODE_TRAPSIG;
    257   1.1      cgd 		if (tty_issofttab())
    258   1.1      cgd 			useeditmode |= MODE_SOFT_TAB;
    259   1.1      cgd 		if (tty_islitecho())
    260   1.1      cgd 			useeditmode |= MODE_LIT_ECHO;
    261   1.1      cgd # ifdef	KLUDGELINEMODE
    262   1.1      cgd 	} else if (lmodetype == KLUDGE_LINEMODE) {
    263   1.1      cgd 		if (tty_isediting() && uselinemode)
    264   1.1      cgd 			send_wont(TELOPT_SGA, 1);
    265   1.1      cgd 		else
    266   1.1      cgd 			send_will(TELOPT_SGA, 1);
    267   1.1      cgd 	}
    268   1.1      cgd # endif	/* KLUDGELINEMODE */
    269   1.1      cgd 
    270   1.1      cgd 	/*
    271   1.1      cgd 	 * Negotiate linemode on if pty state has changed to turn it on.
    272   1.1      cgd 	 * Send appropriate command and send along edit mode, then all done.
    273   1.1      cgd 	 */
    274   1.1      cgd 	if (uselinemode && !linemode) {
    275   1.1      cgd # ifdef	KLUDGELINEMODE
    276   1.1      cgd 		if (lmodetype == KLUDGE_LINEMODE) {
    277   1.1      cgd 			send_wont(TELOPT_SGA, 1);
    278   1.1      cgd 		} else if (lmodetype == REAL_LINEMODE) {
    279   1.1      cgd # endif	/* KLUDGELINEMODE */
    280   1.1      cgd 			send_do(TELOPT_LINEMODE, 1);
    281   1.1      cgd 			/* send along edit modes */
    282   1.8   itojun 			(void) output_data("%c%c%c%c%c%c%c", IAC, SB,
    283   1.1      cgd 				TELOPT_LINEMODE, LM_MODE, useeditmode,
    284   1.1      cgd 				IAC, SE);
    285   1.1      cgd 			editmode = useeditmode;
    286   1.1      cgd # ifdef	KLUDGELINEMODE
    287   1.1      cgd 		}
    288   1.1      cgd # endif	/* KLUDGELINEMODE */
    289   1.1      cgd 		linemode = uselinemode;
    290   1.1      cgd 		goto done;
    291   1.1      cgd 	}
    292   1.1      cgd 
    293   1.1      cgd # ifdef	KLUDGELINEMODE
    294   1.1      cgd 	/*
    295   1.1      cgd 	 * None of what follows is of any value if not using
    296   1.1      cgd 	 * real linemode.
    297   1.1      cgd 	 */
    298   1.1      cgd 	if (lmodetype < REAL_LINEMODE)
    299   1.1      cgd 		goto done;
    300   1.1      cgd # endif	/* KLUDGELINEMODE */
    301   1.1      cgd 
    302   1.1      cgd 	if (linemode && his_state_is_will(TELOPT_LINEMODE)) {
    303   1.1      cgd 		/*
    304   1.1      cgd 		 * If edit mode changed, send edit mode.
    305   1.1      cgd 		 */
    306   1.1      cgd 		 if (useeditmode != editmode) {
    307   1.1      cgd 			/*
    308   1.1      cgd 			 * Send along appropriate edit mode mask.
    309   1.1      cgd 			 */
    310   1.8   itojun 			(void) output_data("%c%c%c%c%c%c%c", IAC, SB,
    311   1.1      cgd 				TELOPT_LINEMODE, LM_MODE, useeditmode,
    312   1.1      cgd 				IAC, SE);
    313   1.1      cgd 			editmode = useeditmode;
    314   1.1      cgd 		}
    315   1.4      jtk 
    316   1.1      cgd 
    317   1.1      cgd 		/*
    318   1.1      cgd 		 * Check for changes to special characters in use.
    319   1.1      cgd 		 */
    320   1.1      cgd 		start_slc(0);
    321   1.1      cgd 		check_slc();
    322   1.1      cgd 		(void) end_slc(0);
    323   1.1      cgd 	}
    324   1.1      cgd 
    325   1.1      cgd done:
    326   1.1      cgd 	if (need_will_echo)
    327   1.1      cgd 		send_will(TELOPT_ECHO, 1);
    328   1.1      cgd 	/*
    329   1.1      cgd 	 * Some things should be deferred until after the pty state has
    330   1.1      cgd 	 * been set by the local process.  Do those things that have been
    331   1.1      cgd 	 * deferred now.  This only happens once.
    332   1.1      cgd 	 */
    333   1.1      cgd 	if (_terminit == 0) {
    334   1.1      cgd 		_terminit = 1;
    335   1.1      cgd 		defer_terminit();
    336   1.1      cgd 	}
    337   1.1      cgd 
    338   1.1      cgd 	netflush();
    339   1.1      cgd 	set_termbuf();
    340   1.1      cgd 	return;
    341   1.1      cgd 
    342   1.1      cgd }  /* end of localstat */
    343   1.1      cgd #endif	/* LINEMODE */
    344   1.1      cgd 
    345   1.3      cgd /*
    346   1.3      cgd  * flowstat
    347   1.3      cgd  *
    348   1.3      cgd  * Check for changes to flow control
    349   1.3      cgd  */
    350  1.12   itojun void
    351  1.14    perry flowstat(void)
    352   1.3      cgd {
    353   1.3      cgd 	if (his_state_is_will(TELOPT_LFLOW)) {
    354   1.3      cgd 		if (tty_flowmode() != flowmode) {
    355   1.3      cgd 			flowmode = tty_flowmode();
    356   1.8   itojun 			(void) output_data("%c%c%c%c%c%c",
    357   1.3      cgd 					IAC, SB, TELOPT_LFLOW,
    358   1.3      cgd 					flowmode ? LFLOW_ON : LFLOW_OFF,
    359   1.3      cgd 					IAC, SE);
    360   1.3      cgd 		}
    361   1.3      cgd 		if (tty_restartany() != restartany) {
    362   1.3      cgd 			restartany = tty_restartany();
    363   1.8   itojun 			(void) output_data("%c%c%c%c%c%c",
    364   1.3      cgd 					IAC, SB, TELOPT_LFLOW,
    365   1.3      cgd 					restartany ? LFLOW_RESTART_ANY
    366   1.3      cgd 						   : LFLOW_RESTART_XON,
    367   1.3      cgd 					IAC, SE);
    368   1.3      cgd 		}
    369   1.3      cgd 	}
    370   1.3      cgd }
    371   1.1      cgd 
    372   1.1      cgd /*
    373   1.1      cgd  * clientstat
    374   1.1      cgd  *
    375   1.1      cgd  * Process linemode related requests from the client.
    376   1.1      cgd  * Client can request a change to only one of linemode, editmode or slc's
    377   1.1      cgd  * at a time, and if using kludge linemode, then only linemode may be
    378   1.1      cgd  * affected.
    379   1.1      cgd  */
    380  1.12   itojun void
    381  1.14    perry clientstat(int code, int parm1, int parm2)
    382   1.1      cgd {
    383   1.1      cgd 
    384   1.1      cgd 	/*
    385   1.1      cgd 	 * Get a copy of terminal characteristics.
    386   1.1      cgd 	 */
    387   1.1      cgd 	init_termbuf();
    388   1.1      cgd 
    389   1.1      cgd 	/*
    390   1.1      cgd 	 * Process request from client. code tells what it is.
    391   1.1      cgd 	 */
    392   1.1      cgd 	switch (code) {
    393   1.1      cgd #ifdef	LINEMODE
    394   1.1      cgd 	case TELOPT_LINEMODE:
    395   1.1      cgd 		/*
    396   1.1      cgd 		 * Don't do anything unless client is asking us to change
    397   1.1      cgd 		 * modes.
    398   1.1      cgd 		 */
    399   1.1      cgd 		uselinemode = (parm1 == WILL);
    400   1.1      cgd 		if (uselinemode != linemode) {
    401   1.1      cgd # ifdef	KLUDGELINEMODE
    402   1.1      cgd 			/*
    403   1.1      cgd 			 * If using kludge linemode, make sure that
    404   1.1      cgd 			 * we can do what the client asks.
    405   1.1      cgd 			 * We can not turn off linemode if alwayslinemode
    406   1.1      cgd 			 * and the ICANON bit is set.
    407   1.1      cgd 			 */
    408   1.1      cgd 			if (lmodetype == KLUDGE_LINEMODE) {
    409   1.1      cgd 				if (alwayslinemode && tty_isediting()) {
    410   1.1      cgd 					uselinemode = 1;
    411   1.1      cgd 				}
    412   1.1      cgd 			}
    413   1.4      jtk 
    414   1.1      cgd 			/*
    415   1.1      cgd 			 * Quit now if we can't do it.
    416   1.1      cgd 			 */
    417   1.1      cgd 			if (uselinemode == linemode)
    418   1.1      cgd 				return;
    419   1.1      cgd 
    420   1.1      cgd 			/*
    421   1.1      cgd 			 * If using real linemode and linemode is being
    422   1.1      cgd 			 * turned on, send along the edit mode mask.
    423   1.1      cgd 			 */
    424   1.1      cgd 			if (lmodetype == REAL_LINEMODE && uselinemode)
    425   1.1      cgd # else	/* KLUDGELINEMODE */
    426   1.1      cgd 			if (uselinemode)
    427   1.1      cgd # endif	/* KLUDGELINEMODE */
    428   1.1      cgd 			{
    429   1.1      cgd 				useeditmode = 0;
    430   1.1      cgd 				if (tty_isediting())
    431   1.1      cgd 					useeditmode |= MODE_EDIT;
    432  1.10      wiz 				if (tty_istrapsig())
    433   1.1      cgd 					useeditmode |= MODE_TRAPSIG;
    434   1.1      cgd 				if (tty_issofttab())
    435   1.1      cgd 					useeditmode |= MODE_SOFT_TAB;
    436   1.1      cgd 				if (tty_islitecho())
    437   1.1      cgd 					useeditmode |= MODE_LIT_ECHO;
    438   1.8   itojun 				(void) output_data("%c%c%c%c%c%c%c", IAC,
    439   1.1      cgd 					SB, TELOPT_LINEMODE, LM_MODE,
    440   1.1      cgd 							useeditmode, IAC, SE);
    441   1.1      cgd 				editmode = useeditmode;
    442   1.1      cgd 			}
    443   1.1      cgd 
    444   1.1      cgd 
    445   1.1      cgd 			tty_setlinemode(uselinemode);
    446   1.1      cgd 
    447   1.1      cgd 			linemode = uselinemode;
    448   1.1      cgd 
    449   1.3      cgd 			if (!linemode)
    450   1.3      cgd 				send_will(TELOPT_ECHO, 1);
    451   1.1      cgd 		}
    452   1.1      cgd 		break;
    453   1.4      jtk 
    454   1.1      cgd 	case LM_MODE:
    455   1.1      cgd 	    {
    456  1.14    perry 		int ack, changed;
    457   1.1      cgd 
    458   1.1      cgd 		/*
    459   1.1      cgd 		 * Client has sent along a mode mask.  If it agrees with
    460   1.1      cgd 		 * what we are currently doing, ignore it; if not, it could
    461   1.1      cgd 		 * be viewed as a request to change.  Note that the server
    462   1.1      cgd 		 * will change to the modes in an ack if it is different from
    463   1.1      cgd 		 * what we currently have, but we will not ack the ack.
    464   1.1      cgd 		 */
    465   1.1      cgd 		 useeditmode &= MODE_MASK;
    466   1.1      cgd 		 ack = (useeditmode & MODE_ACK);
    467   1.1      cgd 		 useeditmode &= ~MODE_ACK;
    468   1.1      cgd 
    469   1.6      mrg 		 if ((changed = (useeditmode ^ editmode))) {
    470   1.1      cgd 			/*
    471   1.1      cgd 			 * This check is for a timing problem.  If the
    472   1.1      cgd 			 * state of the tty has changed (due to the user
    473   1.1      cgd 			 * application) we need to process that info
    474   1.1      cgd 			 * before we write in the state contained in the
    475   1.1      cgd 			 * ack!!!  This gets out the new MODE request,
    476   1.1      cgd 			 * and when the ack to that command comes back
    477   1.1      cgd 			 * we'll set it and be in the right mode.
    478   1.1      cgd 			 */
    479   1.1      cgd 			if (ack)
    480   1.1      cgd 				localstat();
    481   1.1      cgd 			if (changed & MODE_EDIT)
    482   1.1      cgd 				tty_setedit(useeditmode & MODE_EDIT);
    483   1.1      cgd 
    484   1.1      cgd 			if (changed & MODE_TRAPSIG)
    485   1.1      cgd 				tty_setsig(useeditmode & MODE_TRAPSIG);
    486   1.1      cgd 
    487   1.1      cgd 			if (changed & MODE_SOFT_TAB)
    488   1.1      cgd 				tty_setsofttab(useeditmode & MODE_SOFT_TAB);
    489   1.1      cgd 
    490   1.1      cgd 			if (changed & MODE_LIT_ECHO)
    491   1.1      cgd 				tty_setlitecho(useeditmode & MODE_LIT_ECHO);
    492   1.1      cgd 
    493   1.1      cgd 			set_termbuf();
    494   1.1      cgd 
    495   1.1      cgd  			if (!ack) {
    496   1.8   itojun  				(void) output_data("%c%c%c%c%c%c%c", IAC,
    497   1.1      cgd 					SB, TELOPT_LINEMODE, LM_MODE,
    498   1.1      cgd  					useeditmode|MODE_ACK,
    499   1.1      cgd  					IAC, SE);
    500   1.1      cgd  			}
    501   1.4      jtk 
    502   1.1      cgd 			editmode = useeditmode;
    503   1.1      cgd 		}
    504   1.1      cgd 
    505   1.1      cgd 		break;
    506   1.1      cgd 
    507   1.1      cgd 	    }  /* end of case LM_MODE */
    508   1.1      cgd #endif	/* LINEMODE */
    509   1.1      cgd 
    510   1.1      cgd 	case TELOPT_NAWS:
    511   1.1      cgd 	    {
    512   1.1      cgd 		struct winsize ws;
    513   1.1      cgd 
    514   1.1      cgd 		def_col = parm1;
    515   1.1      cgd 		def_row = parm2;
    516   1.1      cgd #ifdef	LINEMODE
    517   1.1      cgd 		/*
    518   1.1      cgd 		 * Defer changing window size until after terminal is
    519   1.1      cgd 		 * initialized.
    520   1.1      cgd 		 */
    521   1.1      cgd 		if (terminit() == 0)
    522   1.1      cgd 			return;
    523   1.1      cgd #endif	/* LINEMODE */
    524   1.1      cgd 
    525   1.1      cgd 		/*
    526   1.1      cgd 		 * Change window size as requested by client.
    527   1.1      cgd 		 */
    528   1.1      cgd 
    529   1.1      cgd 		ws.ws_col = parm1;
    530   1.1      cgd 		ws.ws_row = parm2;
    531   1.1      cgd 		(void) ioctl(pty, TIOCSWINSZ, (char *)&ws);
    532   1.1      cgd 	    }
    533   1.4      jtk 
    534   1.1      cgd 		break;
    535   1.4      jtk 
    536   1.1      cgd 	case TELOPT_TSPEED:
    537   1.1      cgd 	    {
    538   1.1      cgd 		def_tspeed = parm1;
    539   1.1      cgd 		def_rspeed = parm2;
    540   1.1      cgd #ifdef	LINEMODE
    541   1.1      cgd 		/*
    542   1.1      cgd 		 * Defer changing the terminal speed.
    543   1.1      cgd 		 */
    544   1.1      cgd 		if (terminit() == 0)
    545   1.1      cgd 			return;
    546   1.1      cgd #endif	/* LINEMODE */
    547   1.1      cgd 		/*
    548   1.1      cgd 		 * Change terminal speed as requested by client.
    549   1.1      cgd 		 * We set the receive speed first, so that if we can't
    550   1.9      wiz 		 * store separate receive and transmit speeds, the transmit
    551   1.1      cgd 		 * speed will take precedence.
    552   1.1      cgd 		 */
    553   1.1      cgd 		tty_rspeed(parm2);
    554   1.1      cgd 		tty_tspeed(parm1);
    555   1.1      cgd 		set_termbuf();
    556   1.1      cgd 
    557   1.1      cgd 		break;
    558   1.1      cgd 
    559   1.1      cgd 	    }  /* end of case TELOPT_TSPEED */
    560   1.1      cgd 
    561   1.1      cgd 	default:
    562   1.1      cgd 		/* What? */
    563   1.1      cgd 		break;
    564   1.1      cgd 	}  /* end of switch */
    565   1.1      cgd 
    566   1.1      cgd 
    567   1.1      cgd 	netflush();
    568   1.1      cgd 
    569   1.1      cgd }  /* end of clientstat */
    570   1.1      cgd 
    571   1.1      cgd 
    572   1.1      cgd #ifdef	LINEMODE
    573   1.1      cgd /*
    574   1.1      cgd  * defer_terminit
    575   1.1      cgd  *
    576   1.1      cgd  * Some things should not be done until after the login process has started
    577   1.1      cgd  * and all the pty modes are set to what they are supposed to be.  This
    578   1.4      jtk  * function is called when the pty state has been processed for the first time.
    579   1.1      cgd  * It calls other functions that do things that were deferred in each module.
    580   1.1      cgd  */
    581  1.12   itojun void
    582  1.14    perry defer_terminit(void)
    583   1.1      cgd {
    584   1.1      cgd 
    585   1.1      cgd 	/*
    586   1.1      cgd 	 * local stuff that got deferred.
    587   1.1      cgd 	 */
    588   1.1      cgd 	if (def_tspeed != -1) {
    589   1.1      cgd 		clientstat(TELOPT_TSPEED, def_tspeed, def_rspeed);
    590   1.1      cgd 		def_tspeed = def_rspeed = 0;
    591   1.1      cgd 	}
    592   1.1      cgd 
    593   1.1      cgd 	if (def_col || def_row) {
    594   1.1      cgd 		struct winsize ws;
    595   1.1      cgd 
    596   1.4      jtk 		memset((char *)&ws, 0, sizeof(ws));
    597   1.1      cgd 		ws.ws_col = def_col;
    598   1.1      cgd 		ws.ws_row = def_row;
    599   1.1      cgd 		(void) ioctl(pty, TIOCSWINSZ, (char *)&ws);
    600   1.1      cgd 	}
    601   1.1      cgd 
    602   1.1      cgd 	/*
    603   1.1      cgd 	 * The only other module that currently defers anything.
    604   1.1      cgd 	 */
    605   1.1      cgd 	deferslc();
    606   1.1      cgd 
    607   1.1      cgd }  /* end of defer_terminit */
    608   1.1      cgd 
    609   1.1      cgd /*
    610   1.1      cgd  * terminit
    611   1.1      cgd  *
    612   1.1      cgd  * Returns true if the pty state has been processed yet.
    613   1.1      cgd  */
    614  1.12   itojun int
    615  1.14    perry terminit(void)
    616   1.1      cgd {
    617   1.3      cgd 	return(_terminit);
    618   1.1      cgd 
    619   1.1      cgd }  /* end of terminit */
    620   1.1      cgd #endif	/* LINEMODE */
    621