subr.c revision 75905
11592Srgrimes/*
215645Sjoerg * Copyright (c) 1983, 1993
315645Sjoerg *	The Regents of the University of California.  All rights reserved.
41592Srgrimes *
51592Srgrimes * Redistribution and use in source and binary forms, with or without
61592Srgrimes * modification, are permitted provided that the following conditions
71592Srgrimes * are met:
81592Srgrimes * 1. Redistributions of source code must retain the above copyright
91592Srgrimes *    notice, this list of conditions and the following disclaimer.
101592Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111592Srgrimes *    notice, this list of conditions and the following disclaimer in the
121592Srgrimes *    documentation and/or other materials provided with the distribution.
131592Srgrimes * 3. All advertising materials mentioning features or use of this software
141592Srgrimes *    must display the following acknowledgement:
151592Srgrimes *	This product includes software developed by the University of
161592Srgrimes *	California, Berkeley and its contributors.
171592Srgrimes * 4. Neither the name of the University nor the names of its contributors
181592Srgrimes *    may be used to endorse or promote products derived from this software
191592Srgrimes *    without specific prior written permission.
201592Srgrimes *
211592Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
221592Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
231592Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
241592Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
251592Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
261592Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
271592Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
281592Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
291592Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
301592Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
311592Srgrimes * SUCH DAMAGE.
321592Srgrimes */
331592Srgrimes
341592Srgrimes#ifndef lint
3531331Scharnier#if 0
3631331Scharnierstatic char sccsid[] = "@(#)from: subr.c	8.1 (Berkeley) 6/4/93";
3731331Scharnier#endif
3831331Scharnierstatic const char rcsid[] =
3950476Speter  "$FreeBSD: head/libexec/getty/subr.c 75905 2001-04-24 10:33:46Z kris $";
401592Srgrimes#endif /* not lint */
411592Srgrimes
421592Srgrimes/*
431592Srgrimes * Melbourne getty.
441592Srgrimes */
4515645Sjoerg#define COMPAT_43
4631331Scharnier#ifdef DEBUG
4731331Scharnier#include <stdio.h>
4831331Scharnier#endif
4915645Sjoerg#include <stdlib.h>
501592Srgrimes#include <string.h>
5115645Sjoerg#include <termios.h>
5231331Scharnier#include <unistd.h>
5315645Sjoerg#include <sys/ioctl.h>
5415645Sjoerg#include <sys/param.h>
5531331Scharnier#include <sys/time.h>
5625709Sdavidn#include <syslog.h>
5715645Sjoerg
581592Srgrimes#include "gettytab.h"
5915645Sjoerg#include "pathnames.h"
6015645Sjoerg#include "extern.h"
611592Srgrimes
621592Srgrimes
6315645Sjoerg#ifdef COMPAT_43
6415645Sjoergstatic void	compatflags __P((long));
6515645Sjoerg#endif
6615645Sjoerg
671592Srgrimes/*
681592Srgrimes * Get a table entry.
691592Srgrimes */
7015645Sjoergvoid
7115645Sjoerggettable(name, buf)
7215645Sjoerg	const char *name;
7315645Sjoerg	char *buf;
741592Srgrimes{
751592Srgrimes	register struct gettystrs *sp;
761592Srgrimes	register struct gettynums *np;
771592Srgrimes	register struct gettyflags *fp;
7815645Sjoerg	long n;
7925709Sdavidn	int l;
8025709Sdavidn	char *p;
8125709Sdavidn	char *msg = NULL;
8215645Sjoerg	const char *dba[2];
8325709Sdavidn
8425709Sdavidn	static int firsttime = 1;
8525709Sdavidn
8615645Sjoerg	dba[0] = _PATH_GETTYTAB;
8715645Sjoerg	dba[1] = 0;
881592Srgrimes
8925709Sdavidn	if (firsttime) {
9025709Sdavidn		/*
9125709Sdavidn		 * we need to strdup() anything in the strings array
9225709Sdavidn		 * initially in order to simplify things later
9325709Sdavidn		 */
9425709Sdavidn		for (sp = gettystrs; sp->field; sp++)
9525709Sdavidn			if (sp->value != NULL) {
9625709Sdavidn				/* handle these ones more carefully */
9725709Sdavidn				if (sp >= &gettystrs[4] && sp <= &gettystrs[6])
9825709Sdavidn					l = 2;
9925709Sdavidn				else
10025709Sdavidn					l = strlen(sp->value) + 1;
10125709Sdavidn				if ((p = malloc(l)) != NULL) {
10225709Sdavidn					strncpy(p, sp->value, l);
10325709Sdavidn					p[l-1] = '\0';
10425709Sdavidn				}
10525709Sdavidn				/*
10625709Sdavidn				 * replace, even if NULL, else we'll
10725709Sdavidn				 * have problems with free()ing static mem
10825709Sdavidn				 */
10925709Sdavidn				sp->value = p;
11025709Sdavidn			}
11125709Sdavidn		firsttime = 0;
11225709Sdavidn	}
11325709Sdavidn
11425709Sdavidn	switch (cgetent(&buf, (char **)dba, (char *)name)) {
11525709Sdavidn	case 1:
11625709Sdavidn		msg = "%s: couldn't resolve 'tc=' in gettytab '%s'";
11725709Sdavidn	case 0:
11825709Sdavidn		break;
11925709Sdavidn	case -1:
12025709Sdavidn		msg = "%s: unknown gettytab entry '%s'";
12125709Sdavidn		break;
12225709Sdavidn	case -2:
12325709Sdavidn		msg = "%s: retrieving gettytab entry '%s': %m";
12425709Sdavidn		break;
12525709Sdavidn	case -3:
12625709Sdavidn		msg = "%s: recursive 'tc=' reference gettytab entry '%s'";
12725709Sdavidn		break;
12825709Sdavidn	default:
12925709Sdavidn		msg = "%s: unexpected cgetent() error for entry '%s'";
13025709Sdavidn		break;
13125709Sdavidn	}
13225709Sdavidn
13325709Sdavidn	if (msg != NULL) {
13425709Sdavidn		syslog(LOG_ERR, msg, "getty", name);
1351592Srgrimes		return;
13625709Sdavidn	}
1371592Srgrimes
13825709Sdavidn	for (sp = gettystrs; sp->field; sp++) {
13929045Sdavidn		if ((l = cgetstr(buf, (char*)sp->field, &p)) >= 0) {
14025709Sdavidn			if (sp->value) {
14125709Sdavidn				/* prefer existing value */
14225709Sdavidn				if (strcmp(p, sp->value) != 0)
14325709Sdavidn					free(sp->value);
14425709Sdavidn				else {
14525709Sdavidn					free(p);
14625709Sdavidn					p = sp->value;
14725709Sdavidn				}
14825709Sdavidn			}
14925709Sdavidn			sp->value = p;
15025709Sdavidn		} else if (l == -1) {
15125709Sdavidn			free(sp->value);
15225709Sdavidn			sp->value = NULL;
15325709Sdavidn		}
15425709Sdavidn	}
15525709Sdavidn
1561592Srgrimes	for (np = gettynums; np->field; np++) {
15725709Sdavidn		if (cgetnum(buf, (char*)np->field, &n) == -1)
1581592Srgrimes			np->set = 0;
1591592Srgrimes		else {
1601592Srgrimes			np->set = 1;
1611592Srgrimes			np->value = n;
1621592Srgrimes		}
1631592Srgrimes	}
16425709Sdavidn
1651592Srgrimes	for (fp = gettyflags; fp->field; fp++) {
16625709Sdavidn		if (cgetcap(buf, (char *)fp->field, ':') == NULL)
1671592Srgrimes			fp->set = 0;
1681592Srgrimes		else {
1691592Srgrimes			fp->set = 1;
17015645Sjoerg			fp->value = 1 ^ fp->invrt;
1711592Srgrimes		}
1721592Srgrimes	}
17325709Sdavidn
17415645Sjoerg#ifdef DEBUG
17515645Sjoerg	printf("name=\"%s\", buf=\"%s\"\r\n", name, buf);
17615645Sjoerg	for (sp = gettystrs; sp->field; sp++)
17729045Sdavidn		printf("cgetstr: %s=%s\r\n", sp->field, sp->value);
17815645Sjoerg	for (np = gettynums; np->field; np++)
17915645Sjoerg		printf("cgetnum: %s=%d\r\n", np->field, np->value);
18015645Sjoerg	for (fp = gettyflags; fp->field; fp++)
18115645Sjoerg		printf("cgetflags: %s='%c' set='%c'\r\n", fp->field,
18215645Sjoerg		       fp->value + '0', fp->set + '0');
18315645Sjoerg#endif /* DEBUG */
1841592Srgrimes}
1851592Srgrimes
18615645Sjoergvoid
1871592Srgrimesgendefaults()
1881592Srgrimes{
1891592Srgrimes	register struct gettystrs *sp;
1901592Srgrimes	register struct gettynums *np;
1911592Srgrimes	register struct gettyflags *fp;
1921592Srgrimes
1931592Srgrimes	for (sp = gettystrs; sp->field; sp++)
1941592Srgrimes		if (sp->value)
19525709Sdavidn			sp->defalt = strdup(sp->value);
1961592Srgrimes	for (np = gettynums; np->field; np++)
1971592Srgrimes		if (np->set)
1981592Srgrimes			np->defalt = np->value;
1991592Srgrimes	for (fp = gettyflags; fp->field; fp++)
2001592Srgrimes		if (fp->set)
2011592Srgrimes			fp->defalt = fp->value;
2021592Srgrimes		else
2031592Srgrimes			fp->defalt = fp->invrt;
2041592Srgrimes}
2051592Srgrimes
20615645Sjoergvoid
2071592Srgrimessetdefaults()
2081592Srgrimes{
2091592Srgrimes	register struct gettystrs *sp;
2101592Srgrimes	register struct gettynums *np;
2111592Srgrimes	register struct gettyflags *fp;
2121592Srgrimes
2131592Srgrimes	for (sp = gettystrs; sp->field; sp++)
2141592Srgrimes		if (!sp->value)
21525709Sdavidn			sp->value = !sp->defalt ? sp->defalt
21625709Sdavidn						: strdup(sp->defalt);
2171592Srgrimes	for (np = gettynums; np->field; np++)
2181592Srgrimes		if (!np->set)
2191592Srgrimes			np->value = np->defalt;
2201592Srgrimes	for (fp = gettyflags; fp->field; fp++)
2211592Srgrimes		if (!fp->set)
2221592Srgrimes			fp->value = fp->defalt;
2231592Srgrimes}
2241592Srgrimes
2251592Srgrimesstatic char **
2261592Srgrimescharnames[] = {
2271592Srgrimes	&ER, &KL, &IN, &QU, &XN, &XF, &ET, &BK,
2281592Srgrimes	&SU, &DS, &RP, &FL, &WE, &LN, 0
2291592Srgrimes};
2301592Srgrimes
2311592Srgrimesstatic char *
2321592Srgrimescharvars[] = {
23315645Sjoerg	&tmode.c_cc[VERASE], &tmode.c_cc[VKILL], &tmode.c_cc[VINTR],
23415645Sjoerg	&tmode.c_cc[VQUIT], &tmode.c_cc[VSTART], &tmode.c_cc[VSTOP],
23515645Sjoerg	&tmode.c_cc[VEOF], &tmode.c_cc[VEOL], &tmode.c_cc[VSUSP],
23615645Sjoerg	&tmode.c_cc[VDSUSP], &tmode.c_cc[VREPRINT], &tmode.c_cc[VDISCARD],
23715645Sjoerg	&tmode.c_cc[VWERASE], &tmode.c_cc[VLNEXT], 0
2381592Srgrimes};
2391592Srgrimes
24015645Sjoergvoid
2411592Srgrimessetchars()
2421592Srgrimes{
2431592Srgrimes	register int i;
24415645Sjoerg	register const char *p;
2451592Srgrimes
2461592Srgrimes	for (i = 0; charnames[i]; i++) {
2471592Srgrimes		p = *charnames[i];
2481592Srgrimes		if (p && *p)
2491592Srgrimes			*charvars[i] = *p;
2501592Srgrimes		else
25115645Sjoerg			*charvars[i] = _POSIX_VDISABLE;
2521592Srgrimes	}
2531592Srgrimes}
2541592Srgrimes
25515645Sjoerg/* Macros to clear/set/test flags. */
25615645Sjoerg#define	SET(t, f)	(t) |= (f)
25715645Sjoerg#define	CLR(t, f)	(t) &= ~(f)
25815645Sjoerg#define	ISSET(t, f)	((t) & (f))
25915645Sjoerg
26015645Sjoergvoid
26156725Sbdeset_flags(n)
26215645Sjoerg	int n;
2631592Srgrimes{
26415645Sjoerg	register tcflag_t iflag, oflag, cflag, lflag;
2651592Srgrimes
26615645Sjoerg#ifdef COMPAT_43
2671592Srgrimes	switch (n) {
2681592Srgrimes	case 0:
26915645Sjoerg		if (F0set) {
27015645Sjoerg			compatflags(F0);
27115645Sjoerg			return;
27215645Sjoerg		}
2731592Srgrimes		break;
2741592Srgrimes	case 1:
27515645Sjoerg		if (F1set) {
27615645Sjoerg			compatflags(F1);
27715645Sjoerg			return;
27815645Sjoerg		}
2791592Srgrimes		break;
2801592Srgrimes	default:
28115645Sjoerg		if (F2set) {
28215645Sjoerg			compatflags(F2);
28315645Sjoerg			return;
28415645Sjoerg		}
2851592Srgrimes		break;
2861592Srgrimes	}
28715645Sjoerg#endif
2881592Srgrimes
28915645Sjoerg	switch (n) {
29015645Sjoerg	case 0:
29115645Sjoerg		if (C0set && I0set && L0set && O0set) {
29215645Sjoerg			tmode.c_cflag = C0;
29315645Sjoerg			tmode.c_iflag = I0;
29415645Sjoerg			tmode.c_lflag = L0;
29515645Sjoerg			tmode.c_oflag = O0;
29615645Sjoerg			return;
29715645Sjoerg		}
29815645Sjoerg		break;
29915645Sjoerg	case 1:
30015645Sjoerg		if (C1set && I1set && L1set && O1set) {
30115645Sjoerg			tmode.c_cflag = C1;
30215645Sjoerg			tmode.c_iflag = I1;
30315645Sjoerg			tmode.c_lflag = L1;
30415645Sjoerg			tmode.c_oflag = O1;
30515645Sjoerg			return;
30615645Sjoerg		}
30715645Sjoerg		break;
30815645Sjoerg	default:
30915645Sjoerg		if (C2set && I2set && L2set && O2set) {
31015645Sjoerg			tmode.c_cflag = C2;
31115645Sjoerg			tmode.c_iflag = I2;
31215645Sjoerg			tmode.c_lflag = L2;
31315645Sjoerg			tmode.c_oflag = O2;
31415645Sjoerg			return;
31515645Sjoerg		}
31615645Sjoerg		break;
31715645Sjoerg	}
3181592Srgrimes
31915645Sjoerg	iflag = omode.c_iflag;
32015645Sjoerg	oflag = omode.c_oflag;
32115645Sjoerg	cflag = omode.c_cflag;
32215645Sjoerg	lflag = omode.c_lflag;
3231592Srgrimes
32415645Sjoerg	if (NP) {
32515645Sjoerg		CLR(cflag, CSIZE|PARENB);
32615645Sjoerg		SET(cflag, CS8);
32715645Sjoerg		CLR(iflag, ISTRIP|INPCK|IGNPAR);
32815645Sjoerg	} else if (AP || EP || OP) {
32915645Sjoerg		CLR(cflag, CSIZE);
33015645Sjoerg		SET(cflag, CS7|PARENB);
33115645Sjoerg		SET(iflag, ISTRIP);
33215645Sjoerg		if (OP && !EP) {
33315645Sjoerg			SET(iflag, INPCK|IGNPAR);
33415645Sjoerg			SET(cflag, PARODD);
33515645Sjoerg			if (AP)
33615645Sjoerg				CLR(iflag, INPCK);
33715645Sjoerg		} else if (EP && !OP) {
33815645Sjoerg			SET(iflag, INPCK|IGNPAR);
33915645Sjoerg			CLR(cflag, PARODD);
34015645Sjoerg			if (AP)
34115645Sjoerg				CLR(iflag, INPCK);
34215645Sjoerg		} else if (AP || (EP && OP)) {
34315645Sjoerg			CLR(iflag, INPCK|IGNPAR);
34415645Sjoerg			CLR(cflag, PARODD);
34515645Sjoerg		}
34615645Sjoerg	} /* else, leave as is */
34715645Sjoerg
34815645Sjoerg#if 0
3491592Srgrimes	if (UC)
3501592Srgrimes		f |= LCASE;
35115645Sjoerg#endif
3521592Srgrimes
35315645Sjoerg	if (HC)
35415645Sjoerg		SET(cflag, HUPCL);
35515645Sjoerg	else
35615645Sjoerg		CLR(cflag, HUPCL);
3571592Srgrimes
35815645Sjoerg	if (MB)
35915645Sjoerg		SET(cflag, MDMBUF);
36015645Sjoerg	else
36115645Sjoerg		CLR(cflag, MDMBUF);
3621592Srgrimes
36322208Sdavidn	if (HW)
36422208Sdavidn		SET(cflag, CRTSCTS);
36522208Sdavidn	else
36622208Sdavidn		CLR(cflag, CRTSCTS);
36722208Sdavidn
36815645Sjoerg	if (NL) {
36915645Sjoerg		SET(iflag, ICRNL);
37015645Sjoerg		SET(oflag, ONLCR|OPOST);
37115645Sjoerg	} else {
37215645Sjoerg		CLR(iflag, ICRNL);
37315645Sjoerg		CLR(oflag, ONLCR);
3741592Srgrimes	}
3751592Srgrimes
3761592Srgrimes	if (!HT)
37715645Sjoerg		SET(oflag, OXTABS|OPOST);
37815645Sjoerg	else
37915645Sjoerg		CLR(oflag, OXTABS);
3801592Srgrimes
38115645Sjoerg#ifdef XXX_DELAY
38215645Sjoerg	SET(f, delaybits());
38315645Sjoerg#endif
38415645Sjoerg
38515645Sjoerg	if (n == 1) {		/* read mode flags */
38615645Sjoerg		if (RW) {
38715645Sjoerg			iflag = 0;
38815645Sjoerg			CLR(oflag, OPOST);
38915645Sjoerg			CLR(cflag, CSIZE|PARENB);
39015645Sjoerg			SET(cflag, CS8);
39115645Sjoerg			lflag = 0;
39215645Sjoerg		} else {
39315645Sjoerg			CLR(lflag, ICANON);
39415645Sjoerg		}
39515645Sjoerg		goto out;
39615645Sjoerg	}
39715645Sjoerg
3981592Srgrimes	if (n == 0)
39915645Sjoerg		goto out;
4001592Srgrimes
40115645Sjoerg#if 0
4021592Srgrimes	if (CB)
40315645Sjoerg		SET(f, CRTBS);
40415645Sjoerg#endif
4051592Srgrimes
4061592Srgrimes	if (CE)
40715645Sjoerg		SET(lflag, ECHOE);
40815645Sjoerg	else
40915645Sjoerg		CLR(lflag, ECHOE);
4101592Srgrimes
4111592Srgrimes	if (CK)
41215645Sjoerg		SET(lflag, ECHOKE);
41315645Sjoerg	else
41415645Sjoerg		CLR(lflag, ECHOKE);
4151592Srgrimes
4161592Srgrimes	if (PE)
41715645Sjoerg		SET(lflag, ECHOPRT);
41815645Sjoerg	else
41915645Sjoerg		CLR(lflag, ECHOPRT);
4201592Srgrimes
4211592Srgrimes	if (EC)
42215645Sjoerg		SET(lflag, ECHO);
42315645Sjoerg	else
42415645Sjoerg		CLR(lflag, ECHO);
4251592Srgrimes
4261592Srgrimes	if (XC)
42715645Sjoerg		SET(lflag, ECHOCTL);
42815645Sjoerg	else
42915645Sjoerg		CLR(lflag, ECHOCTL);
4301592Srgrimes
4311592Srgrimes	if (DX)
43215645Sjoerg		SET(lflag, IXANY);
43315645Sjoerg	else
43415645Sjoerg		CLR(lflag, IXANY);
4351592Srgrimes
43615645Sjoergout:
43715645Sjoerg	tmode.c_iflag = iflag;
43815645Sjoerg	tmode.c_oflag = oflag;
43915645Sjoerg	tmode.c_cflag = cflag;
44015645Sjoerg	tmode.c_lflag = lflag;
4411592Srgrimes}
4421592Srgrimes
44315645Sjoerg#ifdef COMPAT_43
44415645Sjoerg/*
44515645Sjoerg * Old TTY => termios, snatched from <sys/kern/tty_compat.c>
44615645Sjoerg */
44715645Sjoergvoid
44815645Sjoergcompatflags(flags)
44915645Sjoergregister long flags;
45015645Sjoerg{
45115645Sjoerg	register tcflag_t iflag, oflag, cflag, lflag;
45215645Sjoerg
45315645Sjoerg	iflag = BRKINT|ICRNL|IMAXBEL|IXON|IXANY;
45415645Sjoerg	oflag = OPOST|ONLCR|OXTABS;
45515645Sjoerg	cflag = CREAD;
45615645Sjoerg	lflag = ICANON|ISIG|IEXTEN;
45715645Sjoerg
45815645Sjoerg	if (ISSET(flags, TANDEM))
45915645Sjoerg		SET(iflag, IXOFF);
46015645Sjoerg	else
46115645Sjoerg		CLR(iflag, IXOFF);
46215645Sjoerg	if (ISSET(flags, ECHO))
46315645Sjoerg		SET(lflag, ECHO);
46415645Sjoerg	else
46515645Sjoerg		CLR(lflag, ECHO);
46615645Sjoerg	if (ISSET(flags, CRMOD)) {
46715645Sjoerg		SET(iflag, ICRNL);
46815645Sjoerg		SET(oflag, ONLCR);
46915645Sjoerg	} else {
47015645Sjoerg		CLR(iflag, ICRNL);
47115645Sjoerg		CLR(oflag, ONLCR);
47215645Sjoerg	}
47315645Sjoerg	if (ISSET(flags, XTABS))
47415645Sjoerg		SET(oflag, OXTABS);
47515645Sjoerg	else
47615645Sjoerg		CLR(oflag, OXTABS);
47715645Sjoerg
47815645Sjoerg
47915645Sjoerg	if (ISSET(flags, RAW)) {
48015645Sjoerg		iflag &= IXOFF;
48115645Sjoerg		CLR(lflag, ISIG|ICANON|IEXTEN);
48215645Sjoerg		CLR(cflag, PARENB);
48315645Sjoerg	} else {
48415645Sjoerg		SET(iflag, BRKINT|IXON|IMAXBEL);
48515645Sjoerg		SET(lflag, ISIG|IEXTEN);
48615645Sjoerg		if (ISSET(flags, CBREAK))
48715645Sjoerg			CLR(lflag, ICANON);
48815645Sjoerg		else
48915645Sjoerg			SET(lflag, ICANON);
49015645Sjoerg		switch (ISSET(flags, ANYP)) {
49115645Sjoerg		case 0:
49215645Sjoerg			CLR(cflag, PARENB);
49315645Sjoerg			break;
49415645Sjoerg		case ANYP:
49515645Sjoerg			SET(cflag, PARENB);
49615645Sjoerg			CLR(iflag, INPCK);
49715645Sjoerg			break;
49815645Sjoerg		case EVENP:
49915645Sjoerg			SET(cflag, PARENB);
50015645Sjoerg			SET(iflag, INPCK);
50115645Sjoerg			CLR(cflag, PARODD);
50215645Sjoerg			break;
50315645Sjoerg		case ODDP:
50415645Sjoerg			SET(cflag, PARENB);
50515645Sjoerg			SET(iflag, INPCK);
50615645Sjoerg			SET(cflag, PARODD);
50715645Sjoerg			break;
50815645Sjoerg		}
50915645Sjoerg	}
51015645Sjoerg
51115645Sjoerg	/* Nothing we can do with CRTBS. */
51215645Sjoerg	if (ISSET(flags, PRTERA))
51315645Sjoerg		SET(lflag, ECHOPRT);
51415645Sjoerg	else
51515645Sjoerg		CLR(lflag, ECHOPRT);
51615645Sjoerg	if (ISSET(flags, CRTERA))
51715645Sjoerg		SET(lflag, ECHOE);
51815645Sjoerg	else
51915645Sjoerg		CLR(lflag, ECHOE);
52015645Sjoerg	/* Nothing we can do with TILDE. */
52115645Sjoerg	if (ISSET(flags, MDMBUF))
52215645Sjoerg		SET(cflag, MDMBUF);
52315645Sjoerg	else
52415645Sjoerg		CLR(cflag, MDMBUF);
52515645Sjoerg	if (ISSET(flags, NOHANG))
52615645Sjoerg		CLR(cflag, HUPCL);
52715645Sjoerg	else
52815645Sjoerg		SET(cflag, HUPCL);
52915645Sjoerg	if (ISSET(flags, CRTKIL))
53015645Sjoerg		SET(lflag, ECHOKE);
53115645Sjoerg	else
53215645Sjoerg		CLR(lflag, ECHOKE);
53315645Sjoerg	if (ISSET(flags, CTLECH))
53415645Sjoerg		SET(lflag, ECHOCTL);
53515645Sjoerg	else
53615645Sjoerg		CLR(lflag, ECHOCTL);
53715645Sjoerg	if (!ISSET(flags, DECCTQ))
53815645Sjoerg		SET(iflag, IXANY);
53915645Sjoerg	else
54015645Sjoerg		CLR(iflag, IXANY);
54115645Sjoerg	CLR(lflag, TOSTOP|FLUSHO|PENDIN|NOFLSH);
54215645Sjoerg	SET(lflag, ISSET(flags, TOSTOP|FLUSHO|PENDIN|NOFLSH));
54315645Sjoerg
54415645Sjoerg	if (ISSET(flags, RAW|LITOUT|PASS8)) {
54515645Sjoerg		CLR(cflag, CSIZE);
54615645Sjoerg		SET(cflag, CS8);
54715645Sjoerg		if (!ISSET(flags, RAW|PASS8))
54815645Sjoerg			SET(iflag, ISTRIP);
54915645Sjoerg		else
55015645Sjoerg			CLR(iflag, ISTRIP);
55115645Sjoerg		if (!ISSET(flags, RAW|LITOUT))
55215645Sjoerg			SET(oflag, OPOST);
55315645Sjoerg		else
55415645Sjoerg			CLR(oflag, OPOST);
55515645Sjoerg	} else {
55615645Sjoerg		CLR(cflag, CSIZE);
55715645Sjoerg		SET(cflag, CS7);
55815645Sjoerg		SET(iflag, ISTRIP);
55915645Sjoerg		SET(oflag, OPOST);
56015645Sjoerg	}
56115645Sjoerg
56215645Sjoerg	tmode.c_iflag = iflag;
56315645Sjoerg	tmode.c_oflag = oflag;
56415645Sjoerg	tmode.c_cflag = cflag;
56515645Sjoerg	tmode.c_lflag = lflag;
56615645Sjoerg}
56715645Sjoerg#endif
56815645Sjoerg
56915645Sjoerg#ifdef XXX_DELAY
5701592Srgrimesstruct delayval {
5711592Srgrimes	unsigned	delay;		/* delay in ms */
5721592Srgrimes	int		bits;
5731592Srgrimes};
5741592Srgrimes
5751592Srgrimes/*
5761592Srgrimes * below are random guesses, I can't be bothered checking
5771592Srgrimes */
5781592Srgrimes
5791592Srgrimesstruct delayval	crdelay[] = {
58015645Sjoerg	{ 1,		CR1 },
58115645Sjoerg	{ 2,		CR2 },
58215645Sjoerg	{ 3,		CR3 },
58315645Sjoerg	{ 83,		CR1 },
58415645Sjoerg	{ 166,		CR2 },
58515645Sjoerg	{ 0,		CR3 },
5861592Srgrimes};
5871592Srgrimes
5881592Srgrimesstruct delayval nldelay[] = {
58915645Sjoerg	{ 1,		NL1 },		/* special, calculated */
59015645Sjoerg	{ 2,		NL2 },
59115645Sjoerg	{ 3,		NL3 },
59215645Sjoerg	{ 100,		NL2 },
59315645Sjoerg	{ 0,		NL3 },
5941592Srgrimes};
5951592Srgrimes
5961592Srgrimesstruct delayval	bsdelay[] = {
59715645Sjoerg	{ 1,		BS1 },
59815645Sjoerg	{ 0,		0 },
5991592Srgrimes};
6001592Srgrimes
6011592Srgrimesstruct delayval	ffdelay[] = {
60215645Sjoerg	{ 1,		FF1 },
60315645Sjoerg	{ 1750,		FF1 },
60415645Sjoerg	{ 0,		FF1 },
6051592Srgrimes};
6061592Srgrimes
6071592Srgrimesstruct delayval	tbdelay[] = {
60815645Sjoerg	{ 1,		TAB1 },
60915645Sjoerg	{ 2,		TAB2 },
61015645Sjoerg	{ 3,		XTABS },	/* this is expand tabs */
61115645Sjoerg	{ 100,		TAB1 },
61215645Sjoerg	{ 0,		TAB2 },
6131592Srgrimes};
6141592Srgrimes
61515645Sjoergint
6161592Srgrimesdelaybits()
6171592Srgrimes{
61815645Sjoerg	register int f;
6191592Srgrimes
6201592Srgrimes	f  = adelay(CD, crdelay);
6211592Srgrimes	f |= adelay(ND, nldelay);
6221592Srgrimes	f |= adelay(FD, ffdelay);
6231592Srgrimes	f |= adelay(TD, tbdelay);
6241592Srgrimes	f |= adelay(BD, bsdelay);
6251592Srgrimes	return (f);
6261592Srgrimes}
6271592Srgrimes
62815645Sjoergint
6291592Srgrimesadelay(ms, dp)
6301592Srgrimes	register ms;
6311592Srgrimes	register struct delayval *dp;
6321592Srgrimes{
6331592Srgrimes	if (ms == 0)
6341592Srgrimes		return (0);
6351592Srgrimes	while (dp->delay && ms > dp->delay)
6361592Srgrimes		dp++;
6371592Srgrimes	return (dp->bits);
6381592Srgrimes}
63915645Sjoerg#endif
6401592Srgrimes
64115645Sjoergchar	editedhost[MAXHOSTNAMELEN];
6421592Srgrimes
64315645Sjoergvoid
6441592Srgrimesedithost(pat)
64515645Sjoerg	register const char *pat;
6461592Srgrimes{
64715645Sjoerg	register const char *host = HN;
6481592Srgrimes	register char *res = editedhost;
6491592Srgrimes
6501592Srgrimes	if (!pat)
6511592Srgrimes		pat = "";
6521592Srgrimes	while (*pat) {
6531592Srgrimes		switch (*pat) {
6541592Srgrimes
6551592Srgrimes		case '#':
6561592Srgrimes			if (*host)
6571592Srgrimes				host++;
6581592Srgrimes			break;
6591592Srgrimes
6601592Srgrimes		case '@':
6611592Srgrimes			if (*host)
6621592Srgrimes				*res++ = *host++;
6631592Srgrimes			break;
6641592Srgrimes
6651592Srgrimes		default:
6661592Srgrimes			*res++ = *pat;
6671592Srgrimes			break;
6681592Srgrimes
6691592Srgrimes		}
6701592Srgrimes		if (res == &editedhost[sizeof editedhost - 1]) {
6711592Srgrimes			*res = '\0';
6721592Srgrimes			return;
6731592Srgrimes		}
6741592Srgrimes		pat++;
6751592Srgrimes	}
6761592Srgrimes	if (*host)
6771592Srgrimes		strncpy(res, host, sizeof editedhost - (res - editedhost) - 1);
6781592Srgrimes	else
6791592Srgrimes		*res = '\0';
6801592Srgrimes	editedhost[sizeof editedhost - 1] = '\0';
6811592Srgrimes}
6821592Srgrimes
68315645Sjoergstatic struct speedtab {
6841592Srgrimes	int	speed;
6851592Srgrimes	int	uxname;
6861592Srgrimes} speedtab[] = {
68715645Sjoerg	{ 50,	B50 },
68815645Sjoerg	{ 75,	B75 },
68915645Sjoerg	{ 110,	B110 },
69015645Sjoerg	{ 134,	B134 },
69115645Sjoerg	{ 150,	B150 },
69215645Sjoerg	{ 200,	B200 },
69315645Sjoerg	{ 300,	B300 },
69415645Sjoerg	{ 600,	B600 },
69515645Sjoerg	{ 1200,	B1200 },
69615645Sjoerg	{ 1800,	B1800 },
69715645Sjoerg	{ 2400,	B2400 },
69815645Sjoerg	{ 4800,	B4800 },
69915645Sjoerg	{ 9600,	B9600 },
70015645Sjoerg	{ 19200, EXTA },
70115645Sjoerg	{ 19,	EXTA },		/* for people who say 19.2K */
70215645Sjoerg	{ 38400, EXTB },
70315645Sjoerg	{ 38,	EXTB },
70415645Sjoerg	{ 7200,	EXTB },		/* alternative */
70515645Sjoerg	{ 57600, B57600 },
70615645Sjoerg	{ 115200, B115200 },
70737817Sphk	{ 230400, B230400 },
70815645Sjoerg	{ 0 }
7091592Srgrimes};
7101592Srgrimes
71115645Sjoergint
7121592Srgrimesspeed(val)
71315645Sjoerg	int val;
7141592Srgrimes{
7151592Srgrimes	register struct speedtab *sp;
7161592Srgrimes
71737817Sphk	if (val <= B230400)
7181592Srgrimes		return (val);
7191592Srgrimes
7201592Srgrimes	for (sp = speedtab; sp->speed; sp++)
7211592Srgrimes		if (sp->speed == val)
7221592Srgrimes			return (sp->uxname);
7238870Srgrimes
7241592Srgrimes	return (B300);		/* default in impossible cases */
7251592Srgrimes}
7261592Srgrimes
72715645Sjoergvoid
7281592Srgrimesmakeenv(env)
7291592Srgrimes	char *env[];
7301592Srgrimes{
7311592Srgrimes	static char termbuf[128] = "TERM=";
7321592Srgrimes	register char *p, *q;
7331592Srgrimes	register char **ep;
7341592Srgrimes
7351592Srgrimes	ep = env;
7361592Srgrimes	if (TT && *TT) {
73775905Skris		strlcat(termbuf, TT, sizeof(termbuf));
7381592Srgrimes		*ep++ = termbuf;
7391592Srgrimes	}
74015645Sjoerg	if ((p = EV)) {
7411592Srgrimes		q = p;
74215645Sjoerg		while ((q = strchr(q, ','))) {
7431592Srgrimes			*q++ = '\0';
7441592Srgrimes			*ep++ = p;
7451592Srgrimes			p = q;
7461592Srgrimes		}
7471592Srgrimes		if (*p)
7481592Srgrimes			*ep++ = p;
7491592Srgrimes	}
7501592Srgrimes	*ep = (char *)0;
7511592Srgrimes}
7521592Srgrimes
7531592Srgrimes/*
7541592Srgrimes * This speed select mechanism is written for the Develcon DATASWITCH.
7551592Srgrimes * The Develcon sends a string of the form "B{speed}\n" at a predefined
7561592Srgrimes * baud rate. This string indicates the user's actual speed.
7571592Srgrimes * The routine below returns the terminal type mapped from derived speed.
7581592Srgrimes */
7591592Srgrimesstruct	portselect {
76015645Sjoerg	const char	*ps_baud;
76115645Sjoerg	const char	*ps_type;
7621592Srgrimes} portspeeds[] = {
7631592Srgrimes	{ "B110",	"std.110" },
7641592Srgrimes	{ "B134",	"std.134" },
7651592Srgrimes	{ "B150",	"std.150" },
7661592Srgrimes	{ "B300",	"std.300" },
7671592Srgrimes	{ "B600",	"std.600" },
7681592Srgrimes	{ "B1200",	"std.1200" },
7691592Srgrimes	{ "B2400",	"std.2400" },
7701592Srgrimes	{ "B4800",	"std.4800" },
7711592Srgrimes	{ "B9600",	"std.9600" },
7721592Srgrimes	{ "B19200",	"std.19200" },
7731592Srgrimes	{ 0 }
7741592Srgrimes};
7751592Srgrimes
77615645Sjoergconst char *
7771592Srgrimesportselector()
7781592Srgrimes{
77915645Sjoerg	char c, baud[20];
78015645Sjoerg	const char *type = "default";
7811592Srgrimes	register struct portselect *ps;
7821592Srgrimes	int len;
7831592Srgrimes
7841592Srgrimes	alarm(5*60);
7851592Srgrimes	for (len = 0; len < sizeof (baud) - 1; len++) {
7861592Srgrimes		if (read(STDIN_FILENO, &c, 1) <= 0)
7871592Srgrimes			break;
7881592Srgrimes		c &= 0177;
7891592Srgrimes		if (c == '\n' || c == '\r')
7901592Srgrimes			break;
7911592Srgrimes		if (c == 'B')
7921592Srgrimes			len = 0;	/* in case of leading garbage */
7931592Srgrimes		baud[len] = c;
7941592Srgrimes	}
7951592Srgrimes	baud[len] = '\0';
7961592Srgrimes	for (ps = portspeeds; ps->ps_baud; ps++)
7971592Srgrimes		if (strcmp(ps->ps_baud, baud) == 0) {
7981592Srgrimes			type = ps->ps_type;
7991592Srgrimes			break;
8001592Srgrimes		}
8011592Srgrimes	sleep(2);	/* wait for connection to complete */
8021592Srgrimes	return (type);
8031592Srgrimes}
8041592Srgrimes
8051592Srgrimes/*
8061592Srgrimes * This auto-baud speed select mechanism is written for the Micom 600
8071592Srgrimes * portselector. Selection is done by looking at how the character '\r'
8081592Srgrimes * is garbled at the different speeds.
8091592Srgrimes */
81015645Sjoergconst char *
8111592Srgrimesautobaud()
8121592Srgrimes{
8131592Srgrimes	int rfds;
8141592Srgrimes	struct timeval timeout;
81515645Sjoerg	char c;
81615645Sjoerg	const char *type = "9600-baud";
8171592Srgrimes
81815645Sjoerg	(void)tcflush(0, TCIOFLUSH);
8191592Srgrimes	rfds = 1 << 0;
8201592Srgrimes	timeout.tv_sec = 5;
8211592Srgrimes	timeout.tv_usec = 0;
8221592Srgrimes	if (select(32, (fd_set *)&rfds, (fd_set *)NULL,
8231592Srgrimes	    (fd_set *)NULL, &timeout) <= 0)
8241592Srgrimes		return (type);
8251592Srgrimes	if (read(STDIN_FILENO, &c, sizeof(char)) != sizeof(char))
8261592Srgrimes		return (type);
8271592Srgrimes	timeout.tv_sec = 0;
8281592Srgrimes	timeout.tv_usec = 20;
8291592Srgrimes	(void) select(32, (fd_set *)NULL, (fd_set *)NULL,
8301592Srgrimes	    (fd_set *)NULL, &timeout);
83115645Sjoerg	(void)tcflush(0, TCIOFLUSH);
8321592Srgrimes	switch (c & 0377) {
8331592Srgrimes
8341592Srgrimes	case 0200:		/* 300-baud */
8351592Srgrimes		type = "300-baud";
8361592Srgrimes		break;
8371592Srgrimes
8381592Srgrimes	case 0346:		/* 1200-baud */
8391592Srgrimes		type = "1200-baud";
8401592Srgrimes		break;
8411592Srgrimes
8421592Srgrimes	case  015:		/* 2400-baud */
8431592Srgrimes	case 0215:
8441592Srgrimes		type = "2400-baud";
8451592Srgrimes		break;
8461592Srgrimes
8471592Srgrimes	default:		/* 4800-baud */
8481592Srgrimes		type = "4800-baud";
8491592Srgrimes		break;
8501592Srgrimes
8511592Srgrimes	case 0377:		/* 9600-baud */
8521592Srgrimes		type = "9600-baud";
8531592Srgrimes		break;
8541592Srgrimes	}
8551592Srgrimes	return (type);
8561592Srgrimes}
857