subr.c revision 90301
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 90301 2002-02-06 16:38:40Z imp $";
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
6490301Simpstatic void	compatflags(long);
6515645Sjoerg#endif
6615645Sjoerg
671592Srgrimes/*
681592Srgrimes * Get a table entry.
691592Srgrimes */
7015645Sjoergvoid
7190301Simpgettable(const char *name, char *buf)
721592Srgrimes{
7390301Simp	struct gettystrs *sp;
7490301Simp	struct gettynums *np;
7590301Simp	struct gettyflags *fp;
7615645Sjoerg	long n;
7725709Sdavidn	int l;
7825709Sdavidn	char *p;
7925709Sdavidn	char *msg = NULL;
8015645Sjoerg	const char *dba[2];
8125709Sdavidn
8225709Sdavidn	static int firsttime = 1;
8325709Sdavidn
8415645Sjoerg	dba[0] = _PATH_GETTYTAB;
8515645Sjoerg	dba[1] = 0;
861592Srgrimes
8725709Sdavidn	if (firsttime) {
8825709Sdavidn		/*
8925709Sdavidn		 * we need to strdup() anything in the strings array
9025709Sdavidn		 * initially in order to simplify things later
9125709Sdavidn		 */
9225709Sdavidn		for (sp = gettystrs; sp->field; sp++)
9325709Sdavidn			if (sp->value != NULL) {
9425709Sdavidn				/* handle these ones more carefully */
9525709Sdavidn				if (sp >= &gettystrs[4] && sp <= &gettystrs[6])
9625709Sdavidn					l = 2;
9725709Sdavidn				else
9825709Sdavidn					l = strlen(sp->value) + 1;
9925709Sdavidn				if ((p = malloc(l)) != NULL) {
10025709Sdavidn					strncpy(p, sp->value, l);
10125709Sdavidn					p[l-1] = '\0';
10225709Sdavidn				}
10325709Sdavidn				/*
10425709Sdavidn				 * replace, even if NULL, else we'll
10525709Sdavidn				 * have problems with free()ing static mem
10625709Sdavidn				 */
10725709Sdavidn				sp->value = p;
10825709Sdavidn			}
10925709Sdavidn		firsttime = 0;
11025709Sdavidn	}
11125709Sdavidn
11225709Sdavidn	switch (cgetent(&buf, (char **)dba, (char *)name)) {
11325709Sdavidn	case 1:
11425709Sdavidn		msg = "%s: couldn't resolve 'tc=' in gettytab '%s'";
11525709Sdavidn	case 0:
11625709Sdavidn		break;
11725709Sdavidn	case -1:
11825709Sdavidn		msg = "%s: unknown gettytab entry '%s'";
11925709Sdavidn		break;
12025709Sdavidn	case -2:
12125709Sdavidn		msg = "%s: retrieving gettytab entry '%s': %m";
12225709Sdavidn		break;
12325709Sdavidn	case -3:
12425709Sdavidn		msg = "%s: recursive 'tc=' reference gettytab entry '%s'";
12525709Sdavidn		break;
12625709Sdavidn	default:
12725709Sdavidn		msg = "%s: unexpected cgetent() error for entry '%s'";
12825709Sdavidn		break;
12925709Sdavidn	}
13025709Sdavidn
13125709Sdavidn	if (msg != NULL) {
13225709Sdavidn		syslog(LOG_ERR, msg, "getty", name);
1331592Srgrimes		return;
13425709Sdavidn	}
1351592Srgrimes
13625709Sdavidn	for (sp = gettystrs; sp->field; sp++) {
13729045Sdavidn		if ((l = cgetstr(buf, (char*)sp->field, &p)) >= 0) {
13825709Sdavidn			if (sp->value) {
13925709Sdavidn				/* prefer existing value */
14025709Sdavidn				if (strcmp(p, sp->value) != 0)
14125709Sdavidn					free(sp->value);
14225709Sdavidn				else {
14325709Sdavidn					free(p);
14425709Sdavidn					p = sp->value;
14525709Sdavidn				}
14625709Sdavidn			}
14725709Sdavidn			sp->value = p;
14825709Sdavidn		} else if (l == -1) {
14925709Sdavidn			free(sp->value);
15025709Sdavidn			sp->value = NULL;
15125709Sdavidn		}
15225709Sdavidn	}
15325709Sdavidn
1541592Srgrimes	for (np = gettynums; np->field; np++) {
15525709Sdavidn		if (cgetnum(buf, (char*)np->field, &n) == -1)
1561592Srgrimes			np->set = 0;
1571592Srgrimes		else {
1581592Srgrimes			np->set = 1;
1591592Srgrimes			np->value = n;
1601592Srgrimes		}
1611592Srgrimes	}
16225709Sdavidn
1631592Srgrimes	for (fp = gettyflags; fp->field; fp++) {
16425709Sdavidn		if (cgetcap(buf, (char *)fp->field, ':') == NULL)
1651592Srgrimes			fp->set = 0;
1661592Srgrimes		else {
1671592Srgrimes			fp->set = 1;
16815645Sjoerg			fp->value = 1 ^ fp->invrt;
1691592Srgrimes		}
1701592Srgrimes	}
17125709Sdavidn
17215645Sjoerg#ifdef DEBUG
17315645Sjoerg	printf("name=\"%s\", buf=\"%s\"\r\n", name, buf);
17415645Sjoerg	for (sp = gettystrs; sp->field; sp++)
17529045Sdavidn		printf("cgetstr: %s=%s\r\n", sp->field, sp->value);
17615645Sjoerg	for (np = gettynums; np->field; np++)
17715645Sjoerg		printf("cgetnum: %s=%d\r\n", np->field, np->value);
17815645Sjoerg	for (fp = gettyflags; fp->field; fp++)
17915645Sjoerg		printf("cgetflags: %s='%c' set='%c'\r\n", fp->field,
18015645Sjoerg		       fp->value + '0', fp->set + '0');
18115645Sjoerg#endif /* DEBUG */
1821592Srgrimes}
1831592Srgrimes
18415645Sjoergvoid
18590301Simpgendefaults(void)
1861592Srgrimes{
18790301Simp	struct gettystrs *sp;
18890301Simp	struct gettynums *np;
18990301Simp	struct gettyflags *fp;
1901592Srgrimes
1911592Srgrimes	for (sp = gettystrs; sp->field; sp++)
1921592Srgrimes		if (sp->value)
19325709Sdavidn			sp->defalt = strdup(sp->value);
1941592Srgrimes	for (np = gettynums; np->field; np++)
1951592Srgrimes		if (np->set)
1961592Srgrimes			np->defalt = np->value;
1971592Srgrimes	for (fp = gettyflags; fp->field; fp++)
1981592Srgrimes		if (fp->set)
1991592Srgrimes			fp->defalt = fp->value;
2001592Srgrimes		else
2011592Srgrimes			fp->defalt = fp->invrt;
2021592Srgrimes}
2031592Srgrimes
20415645Sjoergvoid
20590301Simpsetdefaults(void)
2061592Srgrimes{
20790301Simp	struct gettystrs *sp;
20890301Simp	struct gettynums *np;
20990301Simp	struct gettyflags *fp;
2101592Srgrimes
2111592Srgrimes	for (sp = gettystrs; sp->field; sp++)
2121592Srgrimes		if (!sp->value)
21325709Sdavidn			sp->value = !sp->defalt ? sp->defalt
21425709Sdavidn						: strdup(sp->defalt);
2151592Srgrimes	for (np = gettynums; np->field; np++)
2161592Srgrimes		if (!np->set)
2171592Srgrimes			np->value = np->defalt;
2181592Srgrimes	for (fp = gettyflags; fp->field; fp++)
2191592Srgrimes		if (!fp->set)
2201592Srgrimes			fp->value = fp->defalt;
2211592Srgrimes}
2221592Srgrimes
2231592Srgrimesstatic char **
2241592Srgrimescharnames[] = {
2251592Srgrimes	&ER, &KL, &IN, &QU, &XN, &XF, &ET, &BK,
2261592Srgrimes	&SU, &DS, &RP, &FL, &WE, &LN, 0
2271592Srgrimes};
2281592Srgrimes
2291592Srgrimesstatic char *
2301592Srgrimescharvars[] = {
23115645Sjoerg	&tmode.c_cc[VERASE], &tmode.c_cc[VKILL], &tmode.c_cc[VINTR],
23215645Sjoerg	&tmode.c_cc[VQUIT], &tmode.c_cc[VSTART], &tmode.c_cc[VSTOP],
23315645Sjoerg	&tmode.c_cc[VEOF], &tmode.c_cc[VEOL], &tmode.c_cc[VSUSP],
23415645Sjoerg	&tmode.c_cc[VDSUSP], &tmode.c_cc[VREPRINT], &tmode.c_cc[VDISCARD],
23515645Sjoerg	&tmode.c_cc[VWERASE], &tmode.c_cc[VLNEXT], 0
2361592Srgrimes};
2371592Srgrimes
23815645Sjoergvoid
23990301Simpsetchars(void)
2401592Srgrimes{
24190301Simp	int i;
24290301Simp	const char *p;
2431592Srgrimes
2441592Srgrimes	for (i = 0; charnames[i]; i++) {
2451592Srgrimes		p = *charnames[i];
2461592Srgrimes		if (p && *p)
2471592Srgrimes			*charvars[i] = *p;
2481592Srgrimes		else
24915645Sjoerg			*charvars[i] = _POSIX_VDISABLE;
2501592Srgrimes	}
2511592Srgrimes}
2521592Srgrimes
25315645Sjoerg/* Macros to clear/set/test flags. */
25415645Sjoerg#define	SET(t, f)	(t) |= (f)
25515645Sjoerg#define	CLR(t, f)	(t) &= ~(f)
25615645Sjoerg#define	ISSET(t, f)	((t) & (f))
25715645Sjoerg
25815645Sjoergvoid
25990301Simpset_flags(int n)
2601592Srgrimes{
26190301Simp	tcflag_t iflag, oflag, cflag, lflag;
2621592Srgrimes
26315645Sjoerg#ifdef COMPAT_43
2641592Srgrimes	switch (n) {
2651592Srgrimes	case 0:
26615645Sjoerg		if (F0set) {
26715645Sjoerg			compatflags(F0);
26815645Sjoerg			return;
26915645Sjoerg		}
2701592Srgrimes		break;
2711592Srgrimes	case 1:
27215645Sjoerg		if (F1set) {
27315645Sjoerg			compatflags(F1);
27415645Sjoerg			return;
27515645Sjoerg		}
2761592Srgrimes		break;
2771592Srgrimes	default:
27815645Sjoerg		if (F2set) {
27915645Sjoerg			compatflags(F2);
28015645Sjoerg			return;
28115645Sjoerg		}
2821592Srgrimes		break;
2831592Srgrimes	}
28415645Sjoerg#endif
2851592Srgrimes
28615645Sjoerg	switch (n) {
28715645Sjoerg	case 0:
28815645Sjoerg		if (C0set && I0set && L0set && O0set) {
28915645Sjoerg			tmode.c_cflag = C0;
29015645Sjoerg			tmode.c_iflag = I0;
29115645Sjoerg			tmode.c_lflag = L0;
29215645Sjoerg			tmode.c_oflag = O0;
29315645Sjoerg			return;
29415645Sjoerg		}
29515645Sjoerg		break;
29615645Sjoerg	case 1:
29715645Sjoerg		if (C1set && I1set && L1set && O1set) {
29815645Sjoerg			tmode.c_cflag = C1;
29915645Sjoerg			tmode.c_iflag = I1;
30015645Sjoerg			tmode.c_lflag = L1;
30115645Sjoerg			tmode.c_oflag = O1;
30215645Sjoerg			return;
30315645Sjoerg		}
30415645Sjoerg		break;
30515645Sjoerg	default:
30615645Sjoerg		if (C2set && I2set && L2set && O2set) {
30715645Sjoerg			tmode.c_cflag = C2;
30815645Sjoerg			tmode.c_iflag = I2;
30915645Sjoerg			tmode.c_lflag = L2;
31015645Sjoerg			tmode.c_oflag = O2;
31115645Sjoerg			return;
31215645Sjoerg		}
31315645Sjoerg		break;
31415645Sjoerg	}
3151592Srgrimes
31615645Sjoerg	iflag = omode.c_iflag;
31715645Sjoerg	oflag = omode.c_oflag;
31815645Sjoerg	cflag = omode.c_cflag;
31915645Sjoerg	lflag = omode.c_lflag;
3201592Srgrimes
32115645Sjoerg	if (NP) {
32215645Sjoerg		CLR(cflag, CSIZE|PARENB);
32315645Sjoerg		SET(cflag, CS8);
32415645Sjoerg		CLR(iflag, ISTRIP|INPCK|IGNPAR);
32515645Sjoerg	} else if (AP || EP || OP) {
32615645Sjoerg		CLR(cflag, CSIZE);
32715645Sjoerg		SET(cflag, CS7|PARENB);
32815645Sjoerg		SET(iflag, ISTRIP);
32915645Sjoerg		if (OP && !EP) {
33015645Sjoerg			SET(iflag, INPCK|IGNPAR);
33115645Sjoerg			SET(cflag, PARODD);
33215645Sjoerg			if (AP)
33315645Sjoerg				CLR(iflag, INPCK);
33415645Sjoerg		} else if (EP && !OP) {
33515645Sjoerg			SET(iflag, INPCK|IGNPAR);
33615645Sjoerg			CLR(cflag, PARODD);
33715645Sjoerg			if (AP)
33815645Sjoerg				CLR(iflag, INPCK);
33915645Sjoerg		} else if (AP || (EP && OP)) {
34015645Sjoerg			CLR(iflag, INPCK|IGNPAR);
34115645Sjoerg			CLR(cflag, PARODD);
34215645Sjoerg		}
34315645Sjoerg	} /* else, leave as is */
34415645Sjoerg
34515645Sjoerg#if 0
3461592Srgrimes	if (UC)
3471592Srgrimes		f |= LCASE;
34815645Sjoerg#endif
3491592Srgrimes
35015645Sjoerg	if (HC)
35115645Sjoerg		SET(cflag, HUPCL);
35215645Sjoerg	else
35315645Sjoerg		CLR(cflag, HUPCL);
3541592Srgrimes
35515645Sjoerg	if (MB)
35615645Sjoerg		SET(cflag, MDMBUF);
35715645Sjoerg	else
35815645Sjoerg		CLR(cflag, MDMBUF);
3591592Srgrimes
36022208Sdavidn	if (HW)
36122208Sdavidn		SET(cflag, CRTSCTS);
36222208Sdavidn	else
36322208Sdavidn		CLR(cflag, CRTSCTS);
36422208Sdavidn
36515645Sjoerg	if (NL) {
36615645Sjoerg		SET(iflag, ICRNL);
36715645Sjoerg		SET(oflag, ONLCR|OPOST);
36815645Sjoerg	} else {
36915645Sjoerg		CLR(iflag, ICRNL);
37015645Sjoerg		CLR(oflag, ONLCR);
3711592Srgrimes	}
3721592Srgrimes
3731592Srgrimes	if (!HT)
37415645Sjoerg		SET(oflag, OXTABS|OPOST);
37515645Sjoerg	else
37615645Sjoerg		CLR(oflag, OXTABS);
3771592Srgrimes
37815645Sjoerg#ifdef XXX_DELAY
37915645Sjoerg	SET(f, delaybits());
38015645Sjoerg#endif
38115645Sjoerg
38215645Sjoerg	if (n == 1) {		/* read mode flags */
38315645Sjoerg		if (RW) {
38415645Sjoerg			iflag = 0;
38515645Sjoerg			CLR(oflag, OPOST);
38615645Sjoerg			CLR(cflag, CSIZE|PARENB);
38715645Sjoerg			SET(cflag, CS8);
38815645Sjoerg			lflag = 0;
38915645Sjoerg		} else {
39015645Sjoerg			CLR(lflag, ICANON);
39115645Sjoerg		}
39215645Sjoerg		goto out;
39315645Sjoerg	}
39415645Sjoerg
3951592Srgrimes	if (n == 0)
39615645Sjoerg		goto out;
3971592Srgrimes
39815645Sjoerg#if 0
3991592Srgrimes	if (CB)
40015645Sjoerg		SET(f, CRTBS);
40115645Sjoerg#endif
4021592Srgrimes
4031592Srgrimes	if (CE)
40415645Sjoerg		SET(lflag, ECHOE);
40515645Sjoerg	else
40615645Sjoerg		CLR(lflag, ECHOE);
4071592Srgrimes
4081592Srgrimes	if (CK)
40915645Sjoerg		SET(lflag, ECHOKE);
41015645Sjoerg	else
41115645Sjoerg		CLR(lflag, ECHOKE);
4121592Srgrimes
4131592Srgrimes	if (PE)
41415645Sjoerg		SET(lflag, ECHOPRT);
41515645Sjoerg	else
41615645Sjoerg		CLR(lflag, ECHOPRT);
4171592Srgrimes
4181592Srgrimes	if (EC)
41915645Sjoerg		SET(lflag, ECHO);
42015645Sjoerg	else
42115645Sjoerg		CLR(lflag, ECHO);
4221592Srgrimes
4231592Srgrimes	if (XC)
42415645Sjoerg		SET(lflag, ECHOCTL);
42515645Sjoerg	else
42615645Sjoerg		CLR(lflag, ECHOCTL);
4271592Srgrimes
4281592Srgrimes	if (DX)
42915645Sjoerg		SET(lflag, IXANY);
43015645Sjoerg	else
43115645Sjoerg		CLR(lflag, IXANY);
4321592Srgrimes
43315645Sjoergout:
43415645Sjoerg	tmode.c_iflag = iflag;
43515645Sjoerg	tmode.c_oflag = oflag;
43615645Sjoerg	tmode.c_cflag = cflag;
43715645Sjoerg	tmode.c_lflag = lflag;
4381592Srgrimes}
4391592Srgrimes
44015645Sjoerg#ifdef COMPAT_43
44115645Sjoerg/*
44215645Sjoerg * Old TTY => termios, snatched from <sys/kern/tty_compat.c>
44315645Sjoerg */
44415645Sjoergvoid
44590301Simpcompatflags(long flags)
44615645Sjoerg{
44790301Simp	tcflag_t iflag, oflag, cflag, lflag;
44815645Sjoerg
44915645Sjoerg	iflag = BRKINT|ICRNL|IMAXBEL|IXON|IXANY;
45015645Sjoerg	oflag = OPOST|ONLCR|OXTABS;
45115645Sjoerg	cflag = CREAD;
45215645Sjoerg	lflag = ICANON|ISIG|IEXTEN;
45315645Sjoerg
45415645Sjoerg	if (ISSET(flags, TANDEM))
45515645Sjoerg		SET(iflag, IXOFF);
45615645Sjoerg	else
45715645Sjoerg		CLR(iflag, IXOFF);
45815645Sjoerg	if (ISSET(flags, ECHO))
45915645Sjoerg		SET(lflag, ECHO);
46015645Sjoerg	else
46115645Sjoerg		CLR(lflag, ECHO);
46215645Sjoerg	if (ISSET(flags, CRMOD)) {
46315645Sjoerg		SET(iflag, ICRNL);
46415645Sjoerg		SET(oflag, ONLCR);
46515645Sjoerg	} else {
46615645Sjoerg		CLR(iflag, ICRNL);
46715645Sjoerg		CLR(oflag, ONLCR);
46815645Sjoerg	}
46915645Sjoerg	if (ISSET(flags, XTABS))
47015645Sjoerg		SET(oflag, OXTABS);
47115645Sjoerg	else
47215645Sjoerg		CLR(oflag, OXTABS);
47315645Sjoerg
47415645Sjoerg
47515645Sjoerg	if (ISSET(flags, RAW)) {
47615645Sjoerg		iflag &= IXOFF;
47715645Sjoerg		CLR(lflag, ISIG|ICANON|IEXTEN);
47815645Sjoerg		CLR(cflag, PARENB);
47915645Sjoerg	} else {
48015645Sjoerg		SET(iflag, BRKINT|IXON|IMAXBEL);
48115645Sjoerg		SET(lflag, ISIG|IEXTEN);
48215645Sjoerg		if (ISSET(flags, CBREAK))
48315645Sjoerg			CLR(lflag, ICANON);
48415645Sjoerg		else
48515645Sjoerg			SET(lflag, ICANON);
48615645Sjoerg		switch (ISSET(flags, ANYP)) {
48715645Sjoerg		case 0:
48815645Sjoerg			CLR(cflag, PARENB);
48915645Sjoerg			break;
49015645Sjoerg		case ANYP:
49115645Sjoerg			SET(cflag, PARENB);
49215645Sjoerg			CLR(iflag, INPCK);
49315645Sjoerg			break;
49415645Sjoerg		case EVENP:
49515645Sjoerg			SET(cflag, PARENB);
49615645Sjoerg			SET(iflag, INPCK);
49715645Sjoerg			CLR(cflag, PARODD);
49815645Sjoerg			break;
49915645Sjoerg		case ODDP:
50015645Sjoerg			SET(cflag, PARENB);
50115645Sjoerg			SET(iflag, INPCK);
50215645Sjoerg			SET(cflag, PARODD);
50315645Sjoerg			break;
50415645Sjoerg		}
50515645Sjoerg	}
50615645Sjoerg
50715645Sjoerg	/* Nothing we can do with CRTBS. */
50815645Sjoerg	if (ISSET(flags, PRTERA))
50915645Sjoerg		SET(lflag, ECHOPRT);
51015645Sjoerg	else
51115645Sjoerg		CLR(lflag, ECHOPRT);
51215645Sjoerg	if (ISSET(flags, CRTERA))
51315645Sjoerg		SET(lflag, ECHOE);
51415645Sjoerg	else
51515645Sjoerg		CLR(lflag, ECHOE);
51615645Sjoerg	/* Nothing we can do with TILDE. */
51715645Sjoerg	if (ISSET(flags, MDMBUF))
51815645Sjoerg		SET(cflag, MDMBUF);
51915645Sjoerg	else
52015645Sjoerg		CLR(cflag, MDMBUF);
52115645Sjoerg	if (ISSET(flags, NOHANG))
52215645Sjoerg		CLR(cflag, HUPCL);
52315645Sjoerg	else
52415645Sjoerg		SET(cflag, HUPCL);
52515645Sjoerg	if (ISSET(flags, CRTKIL))
52615645Sjoerg		SET(lflag, ECHOKE);
52715645Sjoerg	else
52815645Sjoerg		CLR(lflag, ECHOKE);
52915645Sjoerg	if (ISSET(flags, CTLECH))
53015645Sjoerg		SET(lflag, ECHOCTL);
53115645Sjoerg	else
53215645Sjoerg		CLR(lflag, ECHOCTL);
53315645Sjoerg	if (!ISSET(flags, DECCTQ))
53415645Sjoerg		SET(iflag, IXANY);
53515645Sjoerg	else
53615645Sjoerg		CLR(iflag, IXANY);
53715645Sjoerg	CLR(lflag, TOSTOP|FLUSHO|PENDIN|NOFLSH);
53815645Sjoerg	SET(lflag, ISSET(flags, TOSTOP|FLUSHO|PENDIN|NOFLSH));
53915645Sjoerg
54015645Sjoerg	if (ISSET(flags, RAW|LITOUT|PASS8)) {
54115645Sjoerg		CLR(cflag, CSIZE);
54215645Sjoerg		SET(cflag, CS8);
54315645Sjoerg		if (!ISSET(flags, RAW|PASS8))
54415645Sjoerg			SET(iflag, ISTRIP);
54515645Sjoerg		else
54615645Sjoerg			CLR(iflag, ISTRIP);
54715645Sjoerg		if (!ISSET(flags, RAW|LITOUT))
54815645Sjoerg			SET(oflag, OPOST);
54915645Sjoerg		else
55015645Sjoerg			CLR(oflag, OPOST);
55115645Sjoerg	} else {
55215645Sjoerg		CLR(cflag, CSIZE);
55315645Sjoerg		SET(cflag, CS7);
55415645Sjoerg		SET(iflag, ISTRIP);
55515645Sjoerg		SET(oflag, OPOST);
55615645Sjoerg	}
55715645Sjoerg
55815645Sjoerg	tmode.c_iflag = iflag;
55915645Sjoerg	tmode.c_oflag = oflag;
56015645Sjoerg	tmode.c_cflag = cflag;
56115645Sjoerg	tmode.c_lflag = lflag;
56215645Sjoerg}
56315645Sjoerg#endif
56415645Sjoerg
56515645Sjoerg#ifdef XXX_DELAY
5661592Srgrimesstruct delayval {
5671592Srgrimes	unsigned	delay;		/* delay in ms */
5681592Srgrimes	int		bits;
5691592Srgrimes};
5701592Srgrimes
5711592Srgrimes/*
5721592Srgrimes * below are random guesses, I can't be bothered checking
5731592Srgrimes */
5741592Srgrimes
5751592Srgrimesstruct delayval	crdelay[] = {
57615645Sjoerg	{ 1,		CR1 },
57715645Sjoerg	{ 2,		CR2 },
57815645Sjoerg	{ 3,		CR3 },
57915645Sjoerg	{ 83,		CR1 },
58015645Sjoerg	{ 166,		CR2 },
58115645Sjoerg	{ 0,		CR3 },
5821592Srgrimes};
5831592Srgrimes
5841592Srgrimesstruct delayval nldelay[] = {
58515645Sjoerg	{ 1,		NL1 },		/* special, calculated */
58615645Sjoerg	{ 2,		NL2 },
58715645Sjoerg	{ 3,		NL3 },
58815645Sjoerg	{ 100,		NL2 },
58915645Sjoerg	{ 0,		NL3 },
5901592Srgrimes};
5911592Srgrimes
5921592Srgrimesstruct delayval	bsdelay[] = {
59315645Sjoerg	{ 1,		BS1 },
59415645Sjoerg	{ 0,		0 },
5951592Srgrimes};
5961592Srgrimes
5971592Srgrimesstruct delayval	ffdelay[] = {
59815645Sjoerg	{ 1,		FF1 },
59915645Sjoerg	{ 1750,		FF1 },
60015645Sjoerg	{ 0,		FF1 },
6011592Srgrimes};
6021592Srgrimes
6031592Srgrimesstruct delayval	tbdelay[] = {
60415645Sjoerg	{ 1,		TAB1 },
60515645Sjoerg	{ 2,		TAB2 },
60615645Sjoerg	{ 3,		XTABS },	/* this is expand tabs */
60715645Sjoerg	{ 100,		TAB1 },
60815645Sjoerg	{ 0,		TAB2 },
6091592Srgrimes};
6101592Srgrimes
61115645Sjoergint
61290301Simpdelaybits(void)
6131592Srgrimes{
61490301Simp	int f;
6151592Srgrimes
6161592Srgrimes	f  = adelay(CD, crdelay);
6171592Srgrimes	f |= adelay(ND, nldelay);
6181592Srgrimes	f |= adelay(FD, ffdelay);
6191592Srgrimes	f |= adelay(TD, tbdelay);
6201592Srgrimes	f |= adelay(BD, bsdelay);
6211592Srgrimes	return (f);
6221592Srgrimes}
6231592Srgrimes
62415645Sjoergint
62590301Simpadelay(int ms, struct delayval *dp)
6261592Srgrimes{
6271592Srgrimes	if (ms == 0)
6281592Srgrimes		return (0);
6291592Srgrimes	while (dp->delay && ms > dp->delay)
6301592Srgrimes		dp++;
6311592Srgrimes	return (dp->bits);
6321592Srgrimes}
63315645Sjoerg#endif
6341592Srgrimes
63515645Sjoergchar	editedhost[MAXHOSTNAMELEN];
6361592Srgrimes
63715645Sjoergvoid
63890301Simpedithost(const char *pat)
6391592Srgrimes{
64090301Simp	const char *host = HN;
64190301Simp	char *res = editedhost;
6421592Srgrimes
6431592Srgrimes	if (!pat)
6441592Srgrimes		pat = "";
6451592Srgrimes	while (*pat) {
6461592Srgrimes		switch (*pat) {
6471592Srgrimes
6481592Srgrimes		case '#':
6491592Srgrimes			if (*host)
6501592Srgrimes				host++;
6511592Srgrimes			break;
6521592Srgrimes
6531592Srgrimes		case '@':
6541592Srgrimes			if (*host)
6551592Srgrimes				*res++ = *host++;
6561592Srgrimes			break;
6571592Srgrimes
6581592Srgrimes		default:
6591592Srgrimes			*res++ = *pat;
6601592Srgrimes			break;
6611592Srgrimes
6621592Srgrimes		}
6631592Srgrimes		if (res == &editedhost[sizeof editedhost - 1]) {
6641592Srgrimes			*res = '\0';
6651592Srgrimes			return;
6661592Srgrimes		}
6671592Srgrimes		pat++;
6681592Srgrimes	}
6691592Srgrimes	if (*host)
6701592Srgrimes		strncpy(res, host, sizeof editedhost - (res - editedhost) - 1);
6711592Srgrimes	else
6721592Srgrimes		*res = '\0';
6731592Srgrimes	editedhost[sizeof editedhost - 1] = '\0';
6741592Srgrimes}
6751592Srgrimes
67615645Sjoergstatic struct speedtab {
6771592Srgrimes	int	speed;
6781592Srgrimes	int	uxname;
6791592Srgrimes} speedtab[] = {
68015645Sjoerg	{ 50,	B50 },
68115645Sjoerg	{ 75,	B75 },
68215645Sjoerg	{ 110,	B110 },
68315645Sjoerg	{ 134,	B134 },
68415645Sjoerg	{ 150,	B150 },
68515645Sjoerg	{ 200,	B200 },
68615645Sjoerg	{ 300,	B300 },
68715645Sjoerg	{ 600,	B600 },
68815645Sjoerg	{ 1200,	B1200 },
68915645Sjoerg	{ 1800,	B1800 },
69015645Sjoerg	{ 2400,	B2400 },
69115645Sjoerg	{ 4800,	B4800 },
69215645Sjoerg	{ 9600,	B9600 },
69315645Sjoerg	{ 19200, EXTA },
69415645Sjoerg	{ 19,	EXTA },		/* for people who say 19.2K */
69515645Sjoerg	{ 38400, EXTB },
69615645Sjoerg	{ 38,	EXTB },
69715645Sjoerg	{ 7200,	EXTB },		/* alternative */
69815645Sjoerg	{ 57600, B57600 },
69915645Sjoerg	{ 115200, B115200 },
70037817Sphk	{ 230400, B230400 },
70115645Sjoerg	{ 0 }
7021592Srgrimes};
7031592Srgrimes
70415645Sjoergint
70590301Simpspeed(int val)
7061592Srgrimes{
70790301Simp	struct speedtab *sp;
7081592Srgrimes
70937817Sphk	if (val <= B230400)
7101592Srgrimes		return (val);
7111592Srgrimes
7121592Srgrimes	for (sp = speedtab; sp->speed; sp++)
7131592Srgrimes		if (sp->speed == val)
7141592Srgrimes			return (sp->uxname);
7158870Srgrimes
7161592Srgrimes	return (B300);		/* default in impossible cases */
7171592Srgrimes}
7181592Srgrimes
71915645Sjoergvoid
72090301Simpmakeenv(char *env[])
7211592Srgrimes{
7221592Srgrimes	static char termbuf[128] = "TERM=";
72390301Simp	char *p, *q;
72490301Simp	char **ep;
7251592Srgrimes
7261592Srgrimes	ep = env;
7271592Srgrimes	if (TT && *TT) {
72875905Skris		strlcat(termbuf, TT, sizeof(termbuf));
7291592Srgrimes		*ep++ = termbuf;
7301592Srgrimes	}
73115645Sjoerg	if ((p = EV)) {
7321592Srgrimes		q = p;
73315645Sjoerg		while ((q = strchr(q, ','))) {
7341592Srgrimes			*q++ = '\0';
7351592Srgrimes			*ep++ = p;
7361592Srgrimes			p = q;
7371592Srgrimes		}
7381592Srgrimes		if (*p)
7391592Srgrimes			*ep++ = p;
7401592Srgrimes	}
7411592Srgrimes	*ep = (char *)0;
7421592Srgrimes}
7431592Srgrimes
7441592Srgrimes/*
7451592Srgrimes * This speed select mechanism is written for the Develcon DATASWITCH.
7461592Srgrimes * The Develcon sends a string of the form "B{speed}\n" at a predefined
7471592Srgrimes * baud rate. This string indicates the user's actual speed.
7481592Srgrimes * The routine below returns the terminal type mapped from derived speed.
7491592Srgrimes */
7501592Srgrimesstruct	portselect {
75115645Sjoerg	const char	*ps_baud;
75215645Sjoerg	const char	*ps_type;
7531592Srgrimes} portspeeds[] = {
7541592Srgrimes	{ "B110",	"std.110" },
7551592Srgrimes	{ "B134",	"std.134" },
7561592Srgrimes	{ "B150",	"std.150" },
7571592Srgrimes	{ "B300",	"std.300" },
7581592Srgrimes	{ "B600",	"std.600" },
7591592Srgrimes	{ "B1200",	"std.1200" },
7601592Srgrimes	{ "B2400",	"std.2400" },
7611592Srgrimes	{ "B4800",	"std.4800" },
7621592Srgrimes	{ "B9600",	"std.9600" },
7631592Srgrimes	{ "B19200",	"std.19200" },
7641592Srgrimes	{ 0 }
7651592Srgrimes};
7661592Srgrimes
76715645Sjoergconst char *
76890301Simpportselector(void)
7691592Srgrimes{
77015645Sjoerg	char c, baud[20];
77115645Sjoerg	const char *type = "default";
77290301Simp	struct portselect *ps;
7731592Srgrimes	int len;
7741592Srgrimes
7751592Srgrimes	alarm(5*60);
7761592Srgrimes	for (len = 0; len < sizeof (baud) - 1; len++) {
7771592Srgrimes		if (read(STDIN_FILENO, &c, 1) <= 0)
7781592Srgrimes			break;
7791592Srgrimes		c &= 0177;
7801592Srgrimes		if (c == '\n' || c == '\r')
7811592Srgrimes			break;
7821592Srgrimes		if (c == 'B')
7831592Srgrimes			len = 0;	/* in case of leading garbage */
7841592Srgrimes		baud[len] = c;
7851592Srgrimes	}
7861592Srgrimes	baud[len] = '\0';
7871592Srgrimes	for (ps = portspeeds; ps->ps_baud; ps++)
7881592Srgrimes		if (strcmp(ps->ps_baud, baud) == 0) {
7891592Srgrimes			type = ps->ps_type;
7901592Srgrimes			break;
7911592Srgrimes		}
7921592Srgrimes	sleep(2);	/* wait for connection to complete */
7931592Srgrimes	return (type);
7941592Srgrimes}
7951592Srgrimes
7961592Srgrimes/*
7971592Srgrimes * This auto-baud speed select mechanism is written for the Micom 600
7981592Srgrimes * portselector. Selection is done by looking at how the character '\r'
7991592Srgrimes * is garbled at the different speeds.
8001592Srgrimes */
80115645Sjoergconst char *
80290301Simpautobaud(void)
8031592Srgrimes{
8041592Srgrimes	int rfds;
8051592Srgrimes	struct timeval timeout;
80615645Sjoerg	char c;
80715645Sjoerg	const char *type = "9600-baud";
8081592Srgrimes
80915645Sjoerg	(void)tcflush(0, TCIOFLUSH);
8101592Srgrimes	rfds = 1 << 0;
8111592Srgrimes	timeout.tv_sec = 5;
8121592Srgrimes	timeout.tv_usec = 0;
8131592Srgrimes	if (select(32, (fd_set *)&rfds, (fd_set *)NULL,
8141592Srgrimes	    (fd_set *)NULL, &timeout) <= 0)
8151592Srgrimes		return (type);
8161592Srgrimes	if (read(STDIN_FILENO, &c, sizeof(char)) != sizeof(char))
8171592Srgrimes		return (type);
8181592Srgrimes	timeout.tv_sec = 0;
8191592Srgrimes	timeout.tv_usec = 20;
8201592Srgrimes	(void) select(32, (fd_set *)NULL, (fd_set *)NULL,
8211592Srgrimes	    (fd_set *)NULL, &timeout);
82215645Sjoerg	(void)tcflush(0, TCIOFLUSH);
8231592Srgrimes	switch (c & 0377) {
8241592Srgrimes
8251592Srgrimes	case 0200:		/* 300-baud */
8261592Srgrimes		type = "300-baud";
8271592Srgrimes		break;
8281592Srgrimes
8291592Srgrimes	case 0346:		/* 1200-baud */
8301592Srgrimes		type = "1200-baud";
8311592Srgrimes		break;
8321592Srgrimes
8331592Srgrimes	case  015:		/* 2400-baud */
8341592Srgrimes	case 0215:
8351592Srgrimes		type = "2400-baud";
8361592Srgrimes		break;
8371592Srgrimes
8381592Srgrimes	default:		/* 4800-baud */
8391592Srgrimes		type = "4800-baud";
8401592Srgrimes		break;
8411592Srgrimes
8421592Srgrimes	case 0377:		/* 9600-baud */
8431592Srgrimes		type = "9600-baud";
8441592Srgrimes		break;
8451592Srgrimes	}
8461592Srgrimes	return (type);
8471592Srgrimes}
848