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
34114630Sobrien#if 0
3529088Smarkm#ifndef lint
3629181Smarkmstatic const char sccsid[] = "@(#)terminal.c	8.2 (Berkeley) 2/16/95";
3763248Speter#endif
38114630Sobrien#endif
39114630Sobrien#include <sys/cdefs.h>
40114630Sobrien__FBSDID("$FreeBSD$");
4129088Smarkm
4229088Smarkm#include <arpa/telnet.h>
4329088Smarkm#include <sys/types.h>
4429088Smarkm
4596385Salfred#include <stdlib.h>
4696385Salfred
4729088Smarkm#include "ring.h"
4829088Smarkm
4929088Smarkm#include "externs.h"
5029088Smarkm#include "types.h"
5129088Smarkm
5287139Smarkm#ifdef	ENCRYPTION
5329181Smarkm#include <libtelnet/encrypt.h>
5429181Smarkm#endif
5529181Smarkm
5629088SmarkmRing		ttyoring, ttyiring;
5729088Smarkmunsigned char	ttyobuf[2*BUFSIZ], ttyibuf[BUFSIZ];
5829088Smarkm
5929088Smarkmint termdata;			/* Debugging flag */
6029088Smarkm
6129088Smarkm#ifdef	USE_TERMIO
6229088Smarkm# ifndef VDISCARD
6329088Smarkmcc_t termFlushChar;
6429088Smarkm# endif
6529088Smarkm# ifndef VLNEXT
6629088Smarkmcc_t termLiteralNextChar;
6729088Smarkm# endif
6829088Smarkm# ifndef VSUSP
6929088Smarkmcc_t termSuspChar;
7029088Smarkm# endif
7129088Smarkm# ifndef VWERASE
7229088Smarkmcc_t termWerasChar;
7329088Smarkm# endif
7429088Smarkm# ifndef VREPRINT
7529088Smarkmcc_t termRprntChar;
7629088Smarkm# endif
7729088Smarkm# ifndef VSTART
7829088Smarkmcc_t termStartChar;
7929088Smarkm# endif
8029088Smarkm# ifndef VSTOP
8129088Smarkmcc_t termStopChar;
8229088Smarkm# endif
8329088Smarkm# ifndef VEOL
8429088Smarkmcc_t termForw1Char;
8529088Smarkm# endif
8629088Smarkm# ifndef VEOL2
8729088Smarkmcc_t termForw2Char;
8829088Smarkm# endif
8929088Smarkm# ifndef VSTATUS
9029088Smarkmcc_t termAytChar;
9129088Smarkm# endif
9229088Smarkm#else
9329088Smarkmcc_t termForw2Char;
9429088Smarkmcc_t termAytChar;
9529088Smarkm#endif
9629088Smarkm
9729088Smarkm/*
9829088Smarkm * initialize the terminal data structures.
9929088Smarkm */
10029088Smarkm
10187139Smarkmvoid
10287139Smarkminit_terminal(void)
10329088Smarkm{
10429088Smarkm    if (ring_init(&ttyoring, ttyobuf, sizeof ttyobuf) != 1) {
10529088Smarkm	exit(1);
10629088Smarkm    }
10729088Smarkm    if (ring_init(&ttyiring, ttyibuf, sizeof ttyibuf) != 1) {
10829088Smarkm	exit(1);
10929088Smarkm    }
11029088Smarkm    autoflush = TerminalAutoFlush();
11129088Smarkm}
11229088Smarkm
11329088Smarkm/*
114207449Sjilles *		Send as much data as possible to the terminal, else exits if
115207449Sjilles *		it encounters a permanent failure when writing to the tty.
11629088Smarkm *
11729088Smarkm *		Return value:
11829088Smarkm *			-1: No useful work done, data waiting to go out.
11929088Smarkm *			 0: No data was waiting, so nothing was done.
12029088Smarkm *			 1: All waiting data was written out.
12129088Smarkm *			 n: All data - n was written out.
12229088Smarkm */
12329088Smarkm
12487139Smarkmint
12587139Smarkmttyflush(int drop)
12629088Smarkm{
12787139Smarkm    int n, n0, n1;
12829088Smarkm
12929088Smarkm    n0 = ring_full_count(&ttyoring);
13029088Smarkm    if ((n1 = n = ring_full_consecutive(&ttyoring)) > 0) {
13129088Smarkm	if (drop) {
13229088Smarkm	    TerminalFlushOutput();
13329088Smarkm	    /* we leave 'n' alone! */
13429088Smarkm	} else {
13529088Smarkm	    n = TerminalWrite(ttyoring.consume, n);
13629088Smarkm	}
13729088Smarkm    }
13829088Smarkm    if (n > 0) {
13929088Smarkm	if (termdata && n) {
14029088Smarkm	    Dump('>', ttyoring.consume, n);
14129088Smarkm	}
14229088Smarkm	/*
14329088Smarkm	 * If we wrote everything, and the full count is
14429088Smarkm	 * larger than what we wrote, then write the
14529088Smarkm	 * rest of the buffer.
14629088Smarkm	 */
14729088Smarkm	if (n1 == n && n0 > n) {
14829088Smarkm		n1 = n0 - n;
14929088Smarkm		if (!drop)
15029088Smarkm			n1 = TerminalWrite(ttyoring.bottom, n1);
15129088Smarkm		if (n1 > 0)
15229088Smarkm			n += n1;
15329088Smarkm	}
15429088Smarkm	ring_consumed(&ttyoring, n);
15529088Smarkm    }
156207449Sjilles    if (n < 0) {
157207449Sjilles	if (errno == EAGAIN || errno == EINTR) {
158207449Sjilles	    return -1;
159207449Sjilles	} else {
160207449Sjilles	    ring_consumed(&ttyoring, ring_full_count(&ttyoring));
161207449Sjilles	    setconnmode(0);
162207449Sjilles	    setcommandmode();
163207449Sjilles	    NetClose(net);
164207449Sjilles	    fprintf(stderr, "Write error on local output.\n");
165207449Sjilles	    exit(1);
166207449Sjilles	}
16729088Smarkm	return -1;
168207449Sjilles    }
16929088Smarkm    if (n == n0) {
17029088Smarkm	if (n0)
17129088Smarkm	    return -1;
17229088Smarkm	return 0;
17329088Smarkm    }
17429088Smarkm    return n0 - n + 1;
17529088Smarkm}
17629088Smarkm
17729088Smarkm
17829088Smarkm/*
17929088Smarkm * These routines decides on what the mode should be (based on the values
18029088Smarkm * of various global variables).
18129088Smarkm */
18229088Smarkm
18329088Smarkm
18487139Smarkmint
18587139Smarkmgetconnmode(void)
18629088Smarkm{
18729088Smarkm    extern int linemode;
18829088Smarkm    int mode = 0;
18929088Smarkm#ifdef	KLUDGELINEMODE
19029088Smarkm    extern int kludgelinemode;
19129088Smarkm#endif
19229088Smarkm
19329088Smarkm    if (my_want_state_is_dont(TELOPT_ECHO))
19429088Smarkm	mode |= MODE_ECHO;
19529088Smarkm
19629088Smarkm    if (localflow)
19729088Smarkm	mode |= MODE_FLOW;
19829088Smarkm
19929088Smarkm    if (my_want_state_is_will(TELOPT_BINARY))
20029088Smarkm	mode |= MODE_INBIN;
20129088Smarkm
20229088Smarkm    if (his_want_state_is_will(TELOPT_BINARY))
20329088Smarkm	mode |= MODE_OUTBIN;
20429088Smarkm
20529088Smarkm#ifdef	KLUDGELINEMODE
20629088Smarkm    if (kludgelinemode) {
20729088Smarkm	if (my_want_state_is_dont(TELOPT_SGA)) {
20829088Smarkm	    mode |= (MODE_TRAPSIG|MODE_EDIT);
20929088Smarkm	    if (dontlecho && (clocks.echotoggle > clocks.modenegotiated)) {
21029088Smarkm		mode &= ~MODE_ECHO;
21129088Smarkm	    }
21229088Smarkm	}
21329088Smarkm	return(mode);
21429088Smarkm    }
21529088Smarkm#endif
21629088Smarkm    if (my_want_state_is_will(TELOPT_LINEMODE))
21729088Smarkm	mode |= linemode;
21829088Smarkm    return(mode);
21929088Smarkm}
22029088Smarkm
22187139Smarkmvoid
22287139Smarkmsetconnmode(int force)
22329088Smarkm{
22429088Smarkm#ifdef	ENCRYPTION
22529088Smarkm    static int enc_passwd = 0;
22629088Smarkm#endif	/* ENCRYPTION */
22787139Smarkm    int newmode;
22829088Smarkm
22929088Smarkm    newmode = getconnmode()|(force?MODE_FORCE:0);
23029088Smarkm
23129088Smarkm    TerminalNewMode(newmode);
23229088Smarkm
23329088Smarkm#ifdef  ENCRYPTION
23429088Smarkm    if ((newmode & (MODE_ECHO|MODE_EDIT)) == MODE_EDIT) {
23529088Smarkm	if (my_want_state_is_will(TELOPT_ENCRYPT)
23629088Smarkm				&& (enc_passwd == 0) && !encrypt_output) {
23729088Smarkm	    encrypt_request_start(0, 0);
23829088Smarkm	    enc_passwd = 1;
23929088Smarkm	}
24029088Smarkm    } else {
24129088Smarkm	if (enc_passwd) {
24229088Smarkm	    encrypt_request_end();
24329088Smarkm	    enc_passwd = 0;
24429088Smarkm	}
24529088Smarkm    }
24629088Smarkm#endif	/* ENCRYPTION */
24729088Smarkm
24829088Smarkm}
24929088Smarkm
25087139Smarkmvoid
25187139Smarkmsetcommandmode(void)
25229088Smarkm{
25329088Smarkm    TerminalNewMode(-1);
25429088Smarkm}
255