Home | History | Annotate | Download | only in telnet
      1 /*
      2  * Copyright 1994-2002 Sun Microsystems, Inc.  All rights reserved.
      3  * Use is subject to license terms.
      4  */
      5 
      6 #pragma ident	"%Z%%M%	%I%	%E% SMI"
      7 
      8 /*
      9  * usr/src/cmd/cmd-inet/usr.bin/telnet/terminal.c
     10  */
     11 
     12 /*
     13  * Copyright (c) 1988, 1990, 1993
     14  *	The Regents of the University of California.  All rights reserved.
     15  *
     16  * Redistribution and use in source and binary forms, with or without
     17  * modification, are permitted provided that the following conditions
     18  * are met:
     19  * 1. Redistributions of source code must retain the above copyright
     20  *    notice, this list of conditions and the following disclaimer.
     21  * 2. Redistributions in binary form must reproduce the above copyright
     22  *    notice, this list of conditions and the following disclaimer in the
     23  *    documentation and/or other materials provided with the distribution.
     24  * 3. All advertising materials mentioning features or use of this software
     25  *    must display the following acknowledgement:
     26  *	This product includes software developed by the University of
     27  *	California, Berkeley and its contributors.
     28  * 4. Neither the name of the University nor the names of its contributors
     29  *    may be used to endorse or promote products derived from this software
     30  *    without specific prior written permission.
     31  *
     32  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     33  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     34  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     35  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     36  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     37  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     38  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     39  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     40  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     41  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     42  * SUCH DAMAGE.
     43  */
     44 
     45 #ifndef lint
     46 static char sccsid[] = "@(#)terminal.c	8.1 (Berkeley) 6/6/93";
     47 #endif /* not lint */
     48 
     49 #include <arpa/telnet.h>
     50 #include <sys/types.h>
     51 #include <errno.h>
     52 
     53 #include "ring.h"
     54 
     55 #include "externs.h"
     56 #include "types.h"
     57 
     58 Ring	ttyoring;
     59 Ring	ttyiring;
     60 static unsigned char ttyobuf[2*BUFSIZ];
     61 static unsigned char ttyibuf[BUFSIZ];
     62 
     63 int termdata;			/* Debugging flag */
     64 
     65 #ifdef	USE_TERMIO
     66 cc_t termAytChar;
     67 #else
     68 cc_t termForw2Char;
     69 cc_t termAytChar;
     70 #endif
     71 
     72 /*
     73  * initialize the terminal data structures.
     74  */
     75 
     76     void
     77 init_terminal()
     78 {
     79 	if (ring_init(&ttyoring, ttyobuf, sizeof (ttyobuf)) != 1) {
     80 		exit(1);
     81 	}
     82 	if (ring_init(&ttyiring, ttyibuf, sizeof (ttyibuf)) != 1) {
     83 		exit(1);
     84 	}
     85 	autoflush = 1;
     86 }
     87 
     88 
     89 /*
     90  *		Send as much data as possible to the terminal.
     91  *
     92  *		Return value:
     93  *			-2: Error occurred other than EWOULDBLOCK; see
     94  *			    'errno' for specifics
     95  *			-1: No useful work done, although data was waiting.
     96  *			    This may be due to EWOULDBLOCK error.
     97  *			 0: No data was waiting, so nothing was done.
     98  *			 1: All waiting data was written out.
     99  *			 n: Part of data was written.  'n' is the number
    100  *			    of bytes remaining which were not written.
    101  */
    102 
    103 int
    104 ttyflush(drop)
    105 	int drop;
    106 {
    107 	register int n, n0, n1;
    108 
    109 	n0 = ring_full_count(&ttyoring);
    110 	if ((n1 = n = ring_full_consecutive(&ttyoring)) > 0) {
    111 		if (drop) {
    112 			TerminalFlushOutput();
    113 			/* we leave 'n' alone! */
    114 		} else {
    115 			n = TerminalWrite((char *)ttyoring.consume, n);
    116 			if (n == -1 && errno != EWOULDBLOCK)
    117 				return (-2);
    118 		}
    119 	}
    120 	if (n > 0) {
    121 		if (termdata && n) {
    122 			Dump('>', ttyoring.consume, n);
    123 		}
    124 		/*
    125 		 * If we wrote everything, and the full count is
    126 		 * larger than what we wrote, then write the
    127 		 * rest of the buffer.
    128 		 */
    129 		if (n1 == n && n0 > n) {
    130 			n1 = n0 - n;
    131 			if (!drop) {
    132 				n1 = TerminalWrite((char *)ttyoring.bottom, n1);
    133 				if (n1 == -1) {
    134 					if (errno != EWOULDBLOCK)
    135 						return (-2);
    136 					n1 = 0;
    137 				}
    138 			}
    139 			n += n1;
    140 		}
    141 		ring_consumed(&ttyoring, n);
    142 	}
    143 	if (n < 0)
    144 		return (-1);
    145 
    146 	if (n == n0) {
    147 		if (n0)
    148 			return (-1);
    149 		return (0);
    150 	}
    151 	return (n0 - n + 1);
    152 }
    153 
    154 
    155 /*
    156  * These routines decides on what the mode should be (based on the values
    157  * of various global variables).
    158  */
    159 
    160 
    161 int
    162 getconnmode()
    163 {
    164 	extern int linemode;
    165 	int mode = 0;
    166 #ifdef	KLUDGELINEMODE
    167 	extern int kludgelinemode;
    168 #endif
    169 
    170 	if (my_want_state_is_dont(TELOPT_ECHO))
    171 		mode |= MODE_ECHO;
    172 
    173 	if (localflow)
    174 		mode |= MODE_FLOW;
    175 
    176 	if (my_want_state_is_will(TELOPT_BINARY))
    177 		mode |= MODE_INBIN;
    178 
    179 	if (my_want_state_is_do(TELOPT_BINARY))
    180 		mode |= MODE_OUTBIN;
    181 
    182 #ifdef	KLUDGELINEMODE
    183 	if (kludgelinemode) {
    184 		if (my_want_state_is_dont(TELOPT_SGA)) {
    185 			mode |= (MODE_TRAPSIG|MODE_EDIT);
    186 			if (dontlecho &&
    187 			    (clocks.echotoggle > clocks.modenegotiated)) {
    188 				mode &= ~MODE_ECHO;
    189 			}
    190 		}
    191 		return (mode);
    192 	}
    193 #endif
    194 	if (my_want_state_is_will(TELOPT_LINEMODE))
    195 		mode |= linemode;
    196 	return (mode);
    197 }
    198 
    199 void
    200 setconnmode(force)
    201 	int force;
    202 {
    203 	static int enc_passwd = 0;
    204 	register int newmode;
    205 
    206 	newmode = getconnmode()|(force?MODE_FORCE:0);
    207 
    208 	TerminalNewMode(newmode);
    209 
    210 	if ((newmode & (MODE_ECHO|MODE_EDIT)) == MODE_EDIT) {
    211 		if (my_want_state_is_will(TELOPT_ENCRYPT) &&
    212 		    (enc_passwd == 0) && !encrypt_output) {
    213 			encrypt_request_start(0, 0);
    214 			enc_passwd = 1;
    215 		}
    216 	} else {
    217 		if (enc_passwd) {
    218 			encrypt_request_end();
    219 			enc_passwd = 0;
    220 		}
    221 	}
    222 }
    223 
    224 
    225     void
    226 setcommandmode()
    227 {
    228 	TerminalNewMode(-1);
    229 }
    230