terminal.c revision 63248
129088Smarkm/*
229088Smarkm * Copyright (c) 1988, 1990, 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
3563248Speter#if 0
3629181Smarkmstatic const char sccsid[] = "@(#)terminal.c	8.2 (Berkeley) 2/16/95";
3763248Speter#else
3863248Speterstatic const char rcsid[] =
3963248Speter "$FreeBSD: head/contrib/telnet/telnet/terminal.c 63248 2000-07-16 05:48:49Z peter $";
4063248Speter#endif
4129088Smarkm#endif /* not lint */
4229088Smarkm
4329088Smarkm#include <arpa/telnet.h>
4429088Smarkm#include <sys/types.h>
4529088Smarkm
4629088Smarkm#include "ring.h"
4729088Smarkm
4829088Smarkm#include "externs.h"
4929088Smarkm#include "types.h"
5029088Smarkm
5129181Smarkm#if	defined(ENCRYPTION)
5229181Smarkm#include <libtelnet/encrypt.h>
5329181Smarkm#endif
5429181Smarkm
5529088SmarkmRing		ttyoring, ttyiring;
5629088Smarkmunsigned char	ttyobuf[2*BUFSIZ], ttyibuf[BUFSIZ];
5729088Smarkm
5829088Smarkmint termdata;			/* Debugging flag */
5929088Smarkm
6029088Smarkm#ifdef	USE_TERMIO
6129088Smarkm# ifndef VDISCARD
6229088Smarkmcc_t termFlushChar;
6329088Smarkm# endif
6429088Smarkm# ifndef VLNEXT
6529088Smarkmcc_t termLiteralNextChar;
6629088Smarkm# endif
6729088Smarkm# ifndef VSUSP
6829088Smarkmcc_t termSuspChar;
6929088Smarkm# endif
7029088Smarkm# ifndef VWERASE
7129088Smarkmcc_t termWerasChar;
7229088Smarkm# endif
7329088Smarkm# ifndef VREPRINT
7429088Smarkmcc_t termRprntChar;
7529088Smarkm# endif
7629088Smarkm# ifndef VSTART
7729088Smarkmcc_t termStartChar;
7829088Smarkm# endif
7929088Smarkm# ifndef VSTOP
8029088Smarkmcc_t termStopChar;
8129088Smarkm# endif
8229088Smarkm# ifndef VEOL
8329088Smarkmcc_t termForw1Char;
8429088Smarkm# endif
8529088Smarkm# ifndef VEOL2
8629088Smarkmcc_t termForw2Char;
8729088Smarkm# endif
8829088Smarkm# ifndef VSTATUS
8929088Smarkmcc_t termAytChar;
9029088Smarkm# endif
9129088Smarkm#else
9229088Smarkmcc_t termForw2Char;
9329088Smarkmcc_t termAytChar;
9429088Smarkm#endif
9529088Smarkm
9629088Smarkm/*
9729088Smarkm * initialize the terminal data structures.
9829088Smarkm */
9929088Smarkm
10029088Smarkm    void
10129088Smarkminit_terminal()
10229088Smarkm{
10329088Smarkm    if (ring_init(&ttyoring, ttyobuf, sizeof ttyobuf) != 1) {
10429088Smarkm	exit(1);
10529088Smarkm    }
10629088Smarkm    if (ring_init(&ttyiring, ttyibuf, sizeof ttyibuf) != 1) {
10729088Smarkm	exit(1);
10829088Smarkm    }
10929088Smarkm    autoflush = TerminalAutoFlush();
11029088Smarkm}
11129088Smarkm
11229088Smarkm
11329088Smarkm/*
11429088Smarkm *		Send as much data as possible to the terminal.
11529088Smarkm *
11629088Smarkm *		Return value:
11729088Smarkm *			-1: No useful work done, data waiting to go out.
11829088Smarkm *			 0: No data was waiting, so nothing was done.
11929088Smarkm *			 1: All waiting data was written out.
12029088Smarkm *			 n: All data - n was written out.
12129088Smarkm */
12229088Smarkm
12329088Smarkm
12429088Smarkm    int
12529088Smarkmttyflush(drop)
12629088Smarkm    int drop;
12729088Smarkm{
12829088Smarkm    register int n, n0, n1;
12929088Smarkm
13029088Smarkm    n0 = ring_full_count(&ttyoring);
13129088Smarkm    if ((n1 = n = ring_full_consecutive(&ttyoring)) > 0) {
13229088Smarkm	if (drop) {
13329088Smarkm	    TerminalFlushOutput();
13429088Smarkm	    /* we leave 'n' alone! */
13529088Smarkm	} else {
13629088Smarkm	    n = TerminalWrite(ttyoring.consume, n);
13729088Smarkm	}
13829088Smarkm    }
13929088Smarkm    if (n > 0) {
14029088Smarkm	if (termdata && n) {
14129088Smarkm	    Dump('>', ttyoring.consume, n);
14229088Smarkm	}
14329088Smarkm	/*
14429088Smarkm	 * If we wrote everything, and the full count is
14529088Smarkm	 * larger than what we wrote, then write the
14629088Smarkm	 * rest of the buffer.
14729088Smarkm	 */
14829088Smarkm	if (n1 == n && n0 > n) {
14929088Smarkm		n1 = n0 - n;
15029088Smarkm		if (!drop)
15129088Smarkm			n1 = TerminalWrite(ttyoring.bottom, n1);
15229088Smarkm		if (n1 > 0)
15329088Smarkm			n += n1;
15429088Smarkm	}
15529088Smarkm	ring_consumed(&ttyoring, n);
15629088Smarkm    }
15729088Smarkm    if (n < 0)
15829088Smarkm	return -1;
15929088Smarkm    if (n == n0) {
16029088Smarkm	if (n0)
16129088Smarkm	    return -1;
16229088Smarkm	return 0;
16329088Smarkm    }
16429088Smarkm    return n0 - n + 1;
16529088Smarkm}
16629088Smarkm
16729088Smarkm
16829088Smarkm/*
16929088Smarkm * These routines decides on what the mode should be (based on the values
17029088Smarkm * of various global variables).
17129088Smarkm */
17229088Smarkm
17329088Smarkm
17429088Smarkm    int
17529088Smarkmgetconnmode()
17629088Smarkm{
17729088Smarkm    extern int linemode;
17829088Smarkm    int mode = 0;
17929088Smarkm#ifdef	KLUDGELINEMODE
18029088Smarkm    extern int kludgelinemode;
18129088Smarkm#endif
18229088Smarkm
18329088Smarkm    if (In3270)
18429088Smarkm	return(MODE_FLOW);
18529088Smarkm
18629088Smarkm    if (my_want_state_is_dont(TELOPT_ECHO))
18729088Smarkm	mode |= MODE_ECHO;
18829088Smarkm
18929088Smarkm    if (localflow)
19029088Smarkm	mode |= MODE_FLOW;
19129088Smarkm
19229088Smarkm    if (my_want_state_is_will(TELOPT_BINARY))
19329088Smarkm	mode |= MODE_INBIN;
19429088Smarkm
19529088Smarkm    if (his_want_state_is_will(TELOPT_BINARY))
19629088Smarkm	mode |= MODE_OUTBIN;
19729088Smarkm
19829088Smarkm#ifdef	KLUDGELINEMODE
19929088Smarkm    if (kludgelinemode) {
20029088Smarkm	if (my_want_state_is_dont(TELOPT_SGA)) {
20129088Smarkm	    mode |= (MODE_TRAPSIG|MODE_EDIT);
20229088Smarkm	    if (dontlecho && (clocks.echotoggle > clocks.modenegotiated)) {
20329088Smarkm		mode &= ~MODE_ECHO;
20429088Smarkm	    }
20529088Smarkm	}
20629088Smarkm	return(mode);
20729088Smarkm    }
20829088Smarkm#endif
20929088Smarkm    if (my_want_state_is_will(TELOPT_LINEMODE))
21029088Smarkm	mode |= linemode;
21129088Smarkm    return(mode);
21229088Smarkm}
21329088Smarkm
21429088Smarkm    void
21529088Smarkmsetconnmode(force)
21629088Smarkm    int force;
21729088Smarkm{
21829088Smarkm#ifdef	ENCRYPTION
21929088Smarkm    static int enc_passwd = 0;
22029088Smarkm#endif	/* ENCRYPTION */
22129088Smarkm    register int newmode;
22229088Smarkm
22329088Smarkm    newmode = getconnmode()|(force?MODE_FORCE:0);
22429088Smarkm
22529088Smarkm    TerminalNewMode(newmode);
22629088Smarkm
22729088Smarkm#ifdef  ENCRYPTION
22829088Smarkm    if ((newmode & (MODE_ECHO|MODE_EDIT)) == MODE_EDIT) {
22929088Smarkm	if (my_want_state_is_will(TELOPT_ENCRYPT)
23029088Smarkm				&& (enc_passwd == 0) && !encrypt_output) {
23129088Smarkm	    encrypt_request_start(0, 0);
23229088Smarkm	    enc_passwd = 1;
23329088Smarkm	}
23429088Smarkm    } else {
23529088Smarkm	if (enc_passwd) {
23629088Smarkm	    encrypt_request_end();
23729088Smarkm	    enc_passwd = 0;
23829088Smarkm	}
23929088Smarkm    }
24029088Smarkm#endif	/* ENCRYPTION */
24129088Smarkm
24229088Smarkm}
24329088Smarkm
24429088Smarkm
24529088Smarkm    void
24629088Smarkmsetcommandmode()
24729088Smarkm{
24829088Smarkm    TerminalNewMode(-1);
24929088Smarkm}
250