subr.c revision 29045
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
3515645Sjoerg/*static char sccsid[] = "from: @(#)subr.c	8.1 (Berkeley) 6/4/93";*/
3629045Sdavidnstatic char rcsid[] = "$Id: subr.c,v 1.11 1997/09/01 10:06:05 davidn Exp $";
371592Srgrimes#endif /* not lint */
381592Srgrimes
391592Srgrimes/*
401592Srgrimes * Melbourne getty.
411592Srgrimes */
4215645Sjoerg#define COMPAT_43
4315645Sjoerg#include <stdlib.h>
442286Sjkh#include <unistd.h>
451592Srgrimes#include <string.h>
4615645Sjoerg#include <termios.h>
4715645Sjoerg#include <sys/ioctl.h>
4815645Sjoerg#include <sys/param.h>
4925709Sdavidn#include <syslog.h>
5015645Sjoerg#ifdef DEBUG
5115645Sjoerg#include <stdio.h>
5215645Sjoerg#endif
5315645Sjoerg
541592Srgrimes#include "gettytab.h"
5515645Sjoerg#include "pathnames.h"
5615645Sjoerg#include "extern.h"
571592Srgrimes
581592Srgrimes
5915645Sjoerg#ifdef COMPAT_43
6015645Sjoergstatic void	compatflags __P((long));
6115645Sjoerg#endif
6215645Sjoerg
631592Srgrimes/*
641592Srgrimes * Get a table entry.
651592Srgrimes */
6615645Sjoergvoid
6715645Sjoerggettable(name, buf)
6815645Sjoerg	const char *name;
6915645Sjoerg	char *buf;
701592Srgrimes{
711592Srgrimes	register struct gettystrs *sp;
721592Srgrimes	register struct gettynums *np;
731592Srgrimes	register struct gettyflags *fp;
7415645Sjoerg	long n;
7525709Sdavidn	int l;
7625709Sdavidn	char *p;
7725709Sdavidn	char *msg = NULL;
7815645Sjoerg	const char *dba[2];
7925709Sdavidn
8025709Sdavidn	static int firsttime = 1;
8125709Sdavidn
8215645Sjoerg	dba[0] = _PATH_GETTYTAB;
8315645Sjoerg	dba[1] = 0;
841592Srgrimes
8525709Sdavidn	if (firsttime) {
8625709Sdavidn		/*
8725709Sdavidn		 * we need to strdup() anything in the strings array
8825709Sdavidn		 * initially in order to simplify things later
8925709Sdavidn		 */
9025709Sdavidn		for (sp = gettystrs; sp->field; sp++)
9125709Sdavidn			if (sp->value != NULL) {
9225709Sdavidn				/* handle these ones more carefully */
9325709Sdavidn				if (sp >= &gettystrs[4] && sp <= &gettystrs[6])
9425709Sdavidn					l = 2;
9525709Sdavidn				else
9625709Sdavidn					l = strlen(sp->value) + 1;
9725709Sdavidn				if ((p = malloc(l)) != NULL) {
9825709Sdavidn					strncpy(p, sp->value, l);
9925709Sdavidn					p[l-1] = '\0';
10025709Sdavidn				}
10125709Sdavidn				/*
10225709Sdavidn				 * replace, even if NULL, else we'll
10325709Sdavidn				 * have problems with free()ing static mem
10425709Sdavidn				 */
10525709Sdavidn				sp->value = p;
10625709Sdavidn			}
10725709Sdavidn		firsttime = 0;
10825709Sdavidn	}
10925709Sdavidn
11025709Sdavidn	switch (cgetent(&buf, (char **)dba, (char *)name)) {
11125709Sdavidn	case 1:
11225709Sdavidn		msg = "%s: couldn't resolve 'tc=' in gettytab '%s'";
11325709Sdavidn	case 0:
11425709Sdavidn		break;
11525709Sdavidn	case -1:
11625709Sdavidn		msg = "%s: unknown gettytab entry '%s'";
11725709Sdavidn		break;
11825709Sdavidn	case -2:
11925709Sdavidn		msg = "%s: retrieving gettytab entry '%s': %m";
12025709Sdavidn		break;
12125709Sdavidn	case -3:
12225709Sdavidn		msg = "%s: recursive 'tc=' reference gettytab entry '%s'";
12325709Sdavidn		break;
12425709Sdavidn	default:
12525709Sdavidn		msg = "%s: unexpected cgetent() error for entry '%s'";
12625709Sdavidn		break;
12725709Sdavidn	}
12825709Sdavidn
12925709Sdavidn	if (msg != NULL) {
13025709Sdavidn		syslog(LOG_ERR, msg, "getty", name);
1311592Srgrimes		return;
13225709Sdavidn	}
1331592Srgrimes
13425709Sdavidn	for (sp = gettystrs; sp->field; sp++) {
13529045Sdavidn		if ((l = cgetstr(buf, (char*)sp->field, &p)) >= 0) {
13625709Sdavidn			if (sp->value) {
13725709Sdavidn				/* prefer existing value */
13825709Sdavidn				if (strcmp(p, sp->value) != 0)
13925709Sdavidn					free(sp->value);
14025709Sdavidn				else {
14125709Sdavidn					free(p);
14225709Sdavidn					p = sp->value;
14325709Sdavidn				}
14425709Sdavidn			}
14525709Sdavidn			sp->value = p;
14625709Sdavidn		} else if (l == -1) {
14725709Sdavidn			free(sp->value);
14825709Sdavidn			sp->value = NULL;
14925709Sdavidn		}
15025709Sdavidn	}
15125709Sdavidn
1521592Srgrimes	for (np = gettynums; np->field; np++) {
15325709Sdavidn		if (cgetnum(buf, (char*)np->field, &n) == -1)
1541592Srgrimes			np->set = 0;
1551592Srgrimes		else {
1561592Srgrimes			np->set = 1;
1571592Srgrimes			np->value = n;
1581592Srgrimes		}
1591592Srgrimes	}
16025709Sdavidn
1611592Srgrimes	for (fp = gettyflags; fp->field; fp++) {
16225709Sdavidn		if (cgetcap(buf, (char *)fp->field, ':') == NULL)
1631592Srgrimes			fp->set = 0;
1641592Srgrimes		else {
1651592Srgrimes			fp->set = 1;
16615645Sjoerg			fp->value = 1 ^ fp->invrt;
1671592Srgrimes		}
1681592Srgrimes	}
16925709Sdavidn
17015645Sjoerg#ifdef DEBUG
17115645Sjoerg	printf("name=\"%s\", buf=\"%s\"\r\n", name, buf);
17215645Sjoerg	for (sp = gettystrs; sp->field; sp++)
17329045Sdavidn		printf("cgetstr: %s=%s\r\n", sp->field, sp->value);
17415645Sjoerg	for (np = gettynums; np->field; np++)
17515645Sjoerg		printf("cgetnum: %s=%d\r\n", np->field, np->value);
17615645Sjoerg	for (fp = gettyflags; fp->field; fp++)
17715645Sjoerg		printf("cgetflags: %s='%c' set='%c'\r\n", fp->field,
17815645Sjoerg		       fp->value + '0', fp->set + '0');
17915645Sjoerg#endif /* DEBUG */
1801592Srgrimes}
1811592Srgrimes
18215645Sjoergvoid
1831592Srgrimesgendefaults()
1841592Srgrimes{
1851592Srgrimes	register struct gettystrs *sp;
1861592Srgrimes	register struct gettynums *np;
1871592Srgrimes	register struct gettyflags *fp;
1881592Srgrimes
1891592Srgrimes	for (sp = gettystrs; sp->field; sp++)
1901592Srgrimes		if (sp->value)
19125709Sdavidn			sp->defalt = strdup(sp->value);
1921592Srgrimes	for (np = gettynums; np->field; np++)
1931592Srgrimes		if (np->set)
1941592Srgrimes			np->defalt = np->value;
1951592Srgrimes	for (fp = gettyflags; fp->field; fp++)
1961592Srgrimes		if (fp->set)
1971592Srgrimes			fp->defalt = fp->value;
1981592Srgrimes		else
1991592Srgrimes			fp->defalt = fp->invrt;
2001592Srgrimes}
2011592Srgrimes
20215645Sjoergvoid
2031592Srgrimessetdefaults()
2041592Srgrimes{
2051592Srgrimes	register struct gettystrs *sp;
2061592Srgrimes	register struct gettynums *np;
2071592Srgrimes	register struct gettyflags *fp;
2081592Srgrimes
2091592Srgrimes	for (sp = gettystrs; sp->field; sp++)
2101592Srgrimes		if (!sp->value)
21125709Sdavidn			sp->value = !sp->defalt ? sp->defalt
21225709Sdavidn						: strdup(sp->defalt);
2131592Srgrimes	for (np = gettynums; np->field; np++)
2141592Srgrimes		if (!np->set)
2151592Srgrimes			np->value = np->defalt;
2161592Srgrimes	for (fp = gettyflags; fp->field; fp++)
2171592Srgrimes		if (!fp->set)
2181592Srgrimes			fp->value = fp->defalt;
2191592Srgrimes}
2201592Srgrimes
2211592Srgrimesstatic char **
2221592Srgrimescharnames[] = {
2231592Srgrimes	&ER, &KL, &IN, &QU, &XN, &XF, &ET, &BK,
2241592Srgrimes	&SU, &DS, &RP, &FL, &WE, &LN, 0
2251592Srgrimes};
2261592Srgrimes
2271592Srgrimesstatic char *
2281592Srgrimescharvars[] = {
22915645Sjoerg	&tmode.c_cc[VERASE], &tmode.c_cc[VKILL], &tmode.c_cc[VINTR],
23015645Sjoerg	&tmode.c_cc[VQUIT], &tmode.c_cc[VSTART], &tmode.c_cc[VSTOP],
23115645Sjoerg	&tmode.c_cc[VEOF], &tmode.c_cc[VEOL], &tmode.c_cc[VSUSP],
23215645Sjoerg	&tmode.c_cc[VDSUSP], &tmode.c_cc[VREPRINT], &tmode.c_cc[VDISCARD],
23315645Sjoerg	&tmode.c_cc[VWERASE], &tmode.c_cc[VLNEXT], 0
2341592Srgrimes};
2351592Srgrimes
23615645Sjoergvoid
2371592Srgrimessetchars()
2381592Srgrimes{
2391592Srgrimes	register int i;
24015645Sjoerg	register const char *p;
2411592Srgrimes
2421592Srgrimes	for (i = 0; charnames[i]; i++) {
2431592Srgrimes		p = *charnames[i];
2441592Srgrimes		if (p && *p)
2451592Srgrimes			*charvars[i] = *p;
2461592Srgrimes		else
24715645Sjoerg			*charvars[i] = _POSIX_VDISABLE;
2481592Srgrimes	}
2491592Srgrimes}
2501592Srgrimes
25115645Sjoerg/* Macros to clear/set/test flags. */
25215645Sjoerg#define	SET(t, f)	(t) |= (f)
25315645Sjoerg#define	CLR(t, f)	(t) &= ~(f)
25415645Sjoerg#define	ISSET(t, f)	((t) & (f))
25515645Sjoerg
25615645Sjoergvoid
2571592Srgrimessetflags(n)
25815645Sjoerg	int n;
2591592Srgrimes{
26015645Sjoerg	register tcflag_t iflag, oflag, cflag, lflag;
2611592Srgrimes
26215645Sjoerg#ifdef COMPAT_43
2631592Srgrimes	switch (n) {
2641592Srgrimes	case 0:
26515645Sjoerg		if (F0set) {
26615645Sjoerg			compatflags(F0);
26715645Sjoerg			return;
26815645Sjoerg		}
2691592Srgrimes		break;
2701592Srgrimes	case 1:
27115645Sjoerg		if (F1set) {
27215645Sjoerg			compatflags(F1);
27315645Sjoerg			return;
27415645Sjoerg		}
2751592Srgrimes		break;
2761592Srgrimes	default:
27715645Sjoerg		if (F2set) {
27815645Sjoerg			compatflags(F2);
27915645Sjoerg			return;
28015645Sjoerg		}
2811592Srgrimes		break;
2821592Srgrimes	}
28315645Sjoerg#endif
2841592Srgrimes
28515645Sjoerg	switch (n) {
28615645Sjoerg	case 0:
28715645Sjoerg		if (C0set && I0set && L0set && O0set) {
28815645Sjoerg			tmode.c_cflag = C0;
28915645Sjoerg			tmode.c_iflag = I0;
29015645Sjoerg			tmode.c_lflag = L0;
29115645Sjoerg			tmode.c_oflag = O0;
29215645Sjoerg			return;
29315645Sjoerg		}
29415645Sjoerg		break;
29515645Sjoerg	case 1:
29615645Sjoerg		if (C1set && I1set && L1set && O1set) {
29715645Sjoerg			tmode.c_cflag = C1;
29815645Sjoerg			tmode.c_iflag = I1;
29915645Sjoerg			tmode.c_lflag = L1;
30015645Sjoerg			tmode.c_oflag = O1;
30115645Sjoerg			return;
30215645Sjoerg		}
30315645Sjoerg		break;
30415645Sjoerg	default:
30515645Sjoerg		if (C2set && I2set && L2set && O2set) {
30615645Sjoerg			tmode.c_cflag = C2;
30715645Sjoerg			tmode.c_iflag = I2;
30815645Sjoerg			tmode.c_lflag = L2;
30915645Sjoerg			tmode.c_oflag = O2;
31015645Sjoerg			return;
31115645Sjoerg		}
31215645Sjoerg		break;
31315645Sjoerg	}
3141592Srgrimes
31515645Sjoerg	iflag = omode.c_iflag;
31615645Sjoerg	oflag = omode.c_oflag;
31715645Sjoerg	cflag = omode.c_cflag;
31815645Sjoerg	lflag = omode.c_lflag;
3191592Srgrimes
32015645Sjoerg	if (NP) {
32115645Sjoerg		CLR(cflag, CSIZE|PARENB);
32215645Sjoerg		SET(cflag, CS8);
32315645Sjoerg		CLR(iflag, ISTRIP|INPCK|IGNPAR);
32415645Sjoerg	} else if (AP || EP || OP) {
32515645Sjoerg		CLR(cflag, CSIZE);
32615645Sjoerg		SET(cflag, CS7|PARENB);
32715645Sjoerg		SET(iflag, ISTRIP);
32815645Sjoerg		if (OP && !EP) {
32915645Sjoerg			SET(iflag, INPCK|IGNPAR);
33015645Sjoerg			SET(cflag, PARODD);
33115645Sjoerg			if (AP)
33215645Sjoerg				CLR(iflag, INPCK);
33315645Sjoerg		} else if (EP && !OP) {
33415645Sjoerg			SET(iflag, INPCK|IGNPAR);
33515645Sjoerg			CLR(cflag, PARODD);
33615645Sjoerg			if (AP)
33715645Sjoerg				CLR(iflag, INPCK);
33815645Sjoerg		} else if (AP || (EP && OP)) {
33915645Sjoerg			CLR(iflag, INPCK|IGNPAR);
34015645Sjoerg			CLR(cflag, PARODD);
34115645Sjoerg		}
34215645Sjoerg	} /* else, leave as is */
34315645Sjoerg
34415645Sjoerg#if 0
3451592Srgrimes	if (UC)
3461592Srgrimes		f |= LCASE;
34715645Sjoerg#endif
3481592Srgrimes
34915645Sjoerg	if (HC)
35015645Sjoerg		SET(cflag, HUPCL);
35115645Sjoerg	else
35215645Sjoerg		CLR(cflag, HUPCL);
3531592Srgrimes
35415645Sjoerg	if (MB)
35515645Sjoerg		SET(cflag, MDMBUF);
35615645Sjoerg	else
35715645Sjoerg		CLR(cflag, MDMBUF);
3581592Srgrimes
35922208Sdavidn	if (HW)
36022208Sdavidn		SET(cflag, CRTSCTS);
36122208Sdavidn	else
36222208Sdavidn		CLR(cflag, CRTSCTS);
36322208Sdavidn
36415645Sjoerg	if (NL) {
36515645Sjoerg		SET(iflag, ICRNL);
36615645Sjoerg		SET(oflag, ONLCR|OPOST);
36715645Sjoerg	} else {
36815645Sjoerg		CLR(iflag, ICRNL);
36915645Sjoerg		CLR(oflag, ONLCR);
3701592Srgrimes	}
3711592Srgrimes
3721592Srgrimes	if (!HT)
37315645Sjoerg		SET(oflag, OXTABS|OPOST);
37415645Sjoerg	else
37515645Sjoerg		CLR(oflag, OXTABS);
3761592Srgrimes
37715645Sjoerg#ifdef XXX_DELAY
37815645Sjoerg	SET(f, delaybits());
37915645Sjoerg#endif
38015645Sjoerg
38115645Sjoerg	if (n == 1) {		/* read mode flags */
38215645Sjoerg		if (RW) {
38315645Sjoerg			iflag = 0;
38415645Sjoerg			CLR(oflag, OPOST);
38515645Sjoerg			CLR(cflag, CSIZE|PARENB);
38615645Sjoerg			SET(cflag, CS8);
38715645Sjoerg			lflag = 0;
38815645Sjoerg		} else {
38915645Sjoerg			CLR(lflag, ICANON);
39015645Sjoerg		}
39115645Sjoerg		goto out;
39215645Sjoerg	}
39315645Sjoerg
3941592Srgrimes	if (n == 0)
39515645Sjoerg		goto out;
3961592Srgrimes
39715645Sjoerg#if 0
3981592Srgrimes	if (CB)
39915645Sjoerg		SET(f, CRTBS);
40015645Sjoerg#endif
4011592Srgrimes
4021592Srgrimes	if (CE)
40315645Sjoerg		SET(lflag, ECHOE);
40415645Sjoerg	else
40515645Sjoerg		CLR(lflag, ECHOE);
4061592Srgrimes
4071592Srgrimes	if (CK)
40815645Sjoerg		SET(lflag, ECHOKE);
40915645Sjoerg	else
41015645Sjoerg		CLR(lflag, ECHOKE);
4111592Srgrimes
4121592Srgrimes	if (PE)
41315645Sjoerg		SET(lflag, ECHOPRT);
41415645Sjoerg	else
41515645Sjoerg		CLR(lflag, ECHOPRT);
4161592Srgrimes
4171592Srgrimes	if (EC)
41815645Sjoerg		SET(lflag, ECHO);
41915645Sjoerg	else
42015645Sjoerg		CLR(lflag, ECHO);
4211592Srgrimes
4221592Srgrimes	if (XC)
42315645Sjoerg		SET(lflag, ECHOCTL);
42415645Sjoerg	else
42515645Sjoerg		CLR(lflag, ECHOCTL);
4261592Srgrimes
4271592Srgrimes	if (DX)
42815645Sjoerg		SET(lflag, IXANY);
42915645Sjoerg	else
43015645Sjoerg		CLR(lflag, IXANY);
4311592Srgrimes
43215645Sjoergout:
43315645Sjoerg	tmode.c_iflag = iflag;
43415645Sjoerg	tmode.c_oflag = oflag;
43515645Sjoerg	tmode.c_cflag = cflag;
43615645Sjoerg	tmode.c_lflag = lflag;
4371592Srgrimes}
4381592Srgrimes
43915645Sjoerg#ifdef COMPAT_43
44015645Sjoerg/*
44115645Sjoerg * Old TTY => termios, snatched from <sys/kern/tty_compat.c>
44215645Sjoerg */
44315645Sjoergvoid
44415645Sjoergcompatflags(flags)
44515645Sjoergregister long flags;
44615645Sjoerg{
44715645Sjoerg	register 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
6121592Srgrimesdelaybits()
6131592Srgrimes{
61415645Sjoerg	register 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
6251592Srgrimesadelay(ms, dp)
6261592Srgrimes	register ms;
6271592Srgrimes	register struct delayval *dp;
6281592Srgrimes{
6291592Srgrimes	if (ms == 0)
6301592Srgrimes		return (0);
6311592Srgrimes	while (dp->delay && ms > dp->delay)
6321592Srgrimes		dp++;
6331592Srgrimes	return (dp->bits);
6341592Srgrimes}
63515645Sjoerg#endif
6361592Srgrimes
63715645Sjoergchar	editedhost[MAXHOSTNAMELEN];
6381592Srgrimes
63915645Sjoergvoid
6401592Srgrimesedithost(pat)
64115645Sjoerg	register const char *pat;
6421592Srgrimes{
64315645Sjoerg	register const char *host = HN;
6441592Srgrimes	register char *res = editedhost;
6451592Srgrimes
6461592Srgrimes	if (!pat)
6471592Srgrimes		pat = "";
6481592Srgrimes	while (*pat) {
6491592Srgrimes		switch (*pat) {
6501592Srgrimes
6511592Srgrimes		case '#':
6521592Srgrimes			if (*host)
6531592Srgrimes				host++;
6541592Srgrimes			break;
6551592Srgrimes
6561592Srgrimes		case '@':
6571592Srgrimes			if (*host)
6581592Srgrimes				*res++ = *host++;
6591592Srgrimes			break;
6601592Srgrimes
6611592Srgrimes		default:
6621592Srgrimes			*res++ = *pat;
6631592Srgrimes			break;
6641592Srgrimes
6651592Srgrimes		}
6661592Srgrimes		if (res == &editedhost[sizeof editedhost - 1]) {
6671592Srgrimes			*res = '\0';
6681592Srgrimes			return;
6691592Srgrimes		}
6701592Srgrimes		pat++;
6711592Srgrimes	}
6721592Srgrimes	if (*host)
6731592Srgrimes		strncpy(res, host, sizeof editedhost - (res - editedhost) - 1);
6741592Srgrimes	else
6751592Srgrimes		*res = '\0';
6761592Srgrimes	editedhost[sizeof editedhost - 1] = '\0';
6771592Srgrimes}
6781592Srgrimes
67915645Sjoergstatic struct speedtab {
6801592Srgrimes	int	speed;
6811592Srgrimes	int	uxname;
6821592Srgrimes} speedtab[] = {
68315645Sjoerg	{ 50,	B50 },
68415645Sjoerg	{ 75,	B75 },
68515645Sjoerg	{ 110,	B110 },
68615645Sjoerg	{ 134,	B134 },
68715645Sjoerg	{ 150,	B150 },
68815645Sjoerg	{ 200,	B200 },
68915645Sjoerg	{ 300,	B300 },
69015645Sjoerg	{ 600,	B600 },
69115645Sjoerg	{ 1200,	B1200 },
69215645Sjoerg	{ 1800,	B1800 },
69315645Sjoerg	{ 2400,	B2400 },
69415645Sjoerg	{ 4800,	B4800 },
69515645Sjoerg	{ 9600,	B9600 },
69615645Sjoerg	{ 19200, EXTA },
69715645Sjoerg	{ 19,	EXTA },		/* for people who say 19.2K */
69815645Sjoerg	{ 38400, EXTB },
69915645Sjoerg	{ 38,	EXTB },
70015645Sjoerg	{ 7200,	EXTB },		/* alternative */
70115645Sjoerg	{ 57600, B57600 },
70215645Sjoerg	{ 115200, B115200 },
70315645Sjoerg	{ 0 }
7041592Srgrimes};
7051592Srgrimes
70615645Sjoergint
7071592Srgrimesspeed(val)
70815645Sjoerg	int val;
7091592Srgrimes{
7101592Srgrimes	register struct speedtab *sp;
7111592Srgrimes
7129651Sache	if (val <= B115200)
7131592Srgrimes		return (val);
7141592Srgrimes
7151592Srgrimes	for (sp = speedtab; sp->speed; sp++)
7161592Srgrimes		if (sp->speed == val)
7171592Srgrimes			return (sp->uxname);
7188870Srgrimes
7191592Srgrimes	return (B300);		/* default in impossible cases */
7201592Srgrimes}
7211592Srgrimes
72215645Sjoergvoid
7231592Srgrimesmakeenv(env)
7241592Srgrimes	char *env[];
7251592Srgrimes{
7261592Srgrimes	static char termbuf[128] = "TERM=";
7271592Srgrimes	register char *p, *q;
7281592Srgrimes	register char **ep;
7291592Srgrimes
7301592Srgrimes	ep = env;
7311592Srgrimes	if (TT && *TT) {
7321592Srgrimes		strcat(termbuf, TT);
7331592Srgrimes		*ep++ = termbuf;
7341592Srgrimes	}
73515645Sjoerg	if ((p = EV)) {
7361592Srgrimes		q = p;
73715645Sjoerg		while ((q = strchr(q, ','))) {
7381592Srgrimes			*q++ = '\0';
7391592Srgrimes			*ep++ = p;
7401592Srgrimes			p = q;
7411592Srgrimes		}
7421592Srgrimes		if (*p)
7431592Srgrimes			*ep++ = p;
7441592Srgrimes	}
7451592Srgrimes	*ep = (char *)0;
7461592Srgrimes}
7471592Srgrimes
7481592Srgrimes/*
7491592Srgrimes * This speed select mechanism is written for the Develcon DATASWITCH.
7501592Srgrimes * The Develcon sends a string of the form "B{speed}\n" at a predefined
7511592Srgrimes * baud rate. This string indicates the user's actual speed.
7521592Srgrimes * The routine below returns the terminal type mapped from derived speed.
7531592Srgrimes */
7541592Srgrimesstruct	portselect {
75515645Sjoerg	const char	*ps_baud;
75615645Sjoerg	const char	*ps_type;
7571592Srgrimes} portspeeds[] = {
7581592Srgrimes	{ "B110",	"std.110" },
7591592Srgrimes	{ "B134",	"std.134" },
7601592Srgrimes	{ "B150",	"std.150" },
7611592Srgrimes	{ "B300",	"std.300" },
7621592Srgrimes	{ "B600",	"std.600" },
7631592Srgrimes	{ "B1200",	"std.1200" },
7641592Srgrimes	{ "B2400",	"std.2400" },
7651592Srgrimes	{ "B4800",	"std.4800" },
7661592Srgrimes	{ "B9600",	"std.9600" },
7671592Srgrimes	{ "B19200",	"std.19200" },
7681592Srgrimes	{ 0 }
7691592Srgrimes};
7701592Srgrimes
77115645Sjoergconst char *
7721592Srgrimesportselector()
7731592Srgrimes{
77415645Sjoerg	char c, baud[20];
77515645Sjoerg	const char *type = "default";
7761592Srgrimes	register struct portselect *ps;
7771592Srgrimes	int len;
7781592Srgrimes
7791592Srgrimes	alarm(5*60);
7801592Srgrimes	for (len = 0; len < sizeof (baud) - 1; len++) {
7811592Srgrimes		if (read(STDIN_FILENO, &c, 1) <= 0)
7821592Srgrimes			break;
7831592Srgrimes		c &= 0177;
7841592Srgrimes		if (c == '\n' || c == '\r')
7851592Srgrimes			break;
7861592Srgrimes		if (c == 'B')
7871592Srgrimes			len = 0;	/* in case of leading garbage */
7881592Srgrimes		baud[len] = c;
7891592Srgrimes	}
7901592Srgrimes	baud[len] = '\0';
7911592Srgrimes	for (ps = portspeeds; ps->ps_baud; ps++)
7921592Srgrimes		if (strcmp(ps->ps_baud, baud) == 0) {
7931592Srgrimes			type = ps->ps_type;
7941592Srgrimes			break;
7951592Srgrimes		}
7961592Srgrimes	sleep(2);	/* wait for connection to complete */
7971592Srgrimes	return (type);
7981592Srgrimes}
7991592Srgrimes
8001592Srgrimes/*
8011592Srgrimes * This auto-baud speed select mechanism is written for the Micom 600
8021592Srgrimes * portselector. Selection is done by looking at how the character '\r'
8031592Srgrimes * is garbled at the different speeds.
8041592Srgrimes */
8051592Srgrimes#include <sys/time.h>
8061592Srgrimes
80715645Sjoergconst char *
8081592Srgrimesautobaud()
8091592Srgrimes{
8101592Srgrimes	int rfds;
8111592Srgrimes	struct timeval timeout;
81215645Sjoerg	char c;
81315645Sjoerg	const char *type = "9600-baud";
8141592Srgrimes
81515645Sjoerg	(void)tcflush(0, TCIOFLUSH);
8161592Srgrimes	rfds = 1 << 0;
8171592Srgrimes	timeout.tv_sec = 5;
8181592Srgrimes	timeout.tv_usec = 0;
8191592Srgrimes	if (select(32, (fd_set *)&rfds, (fd_set *)NULL,
8201592Srgrimes	    (fd_set *)NULL, &timeout) <= 0)
8211592Srgrimes		return (type);
8221592Srgrimes	if (read(STDIN_FILENO, &c, sizeof(char)) != sizeof(char))
8231592Srgrimes		return (type);
8241592Srgrimes	timeout.tv_sec = 0;
8251592Srgrimes	timeout.tv_usec = 20;
8261592Srgrimes	(void) select(32, (fd_set *)NULL, (fd_set *)NULL,
8271592Srgrimes	    (fd_set *)NULL, &timeout);
82815645Sjoerg	(void)tcflush(0, TCIOFLUSH);
8291592Srgrimes	switch (c & 0377) {
8301592Srgrimes
8311592Srgrimes	case 0200:		/* 300-baud */
8321592Srgrimes		type = "300-baud";
8331592Srgrimes		break;
8341592Srgrimes
8351592Srgrimes	case 0346:		/* 1200-baud */
8361592Srgrimes		type = "1200-baud";
8371592Srgrimes		break;
8381592Srgrimes
8391592Srgrimes	case  015:		/* 2400-baud */
8401592Srgrimes	case 0215:
8411592Srgrimes		type = "2400-baud";
8421592Srgrimes		break;
8431592Srgrimes
8441592Srgrimes	default:		/* 4800-baud */
8451592Srgrimes		type = "4800-baud";
8461592Srgrimes		break;
8471592Srgrimes
8481592Srgrimes	case 0377:		/* 9600-baud */
8491592Srgrimes		type = "9600-baud";
8501592Srgrimes		break;
8511592Srgrimes	}
8521592Srgrimes	return (type);
8531592Srgrimes}
854