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.
13262435Sbrueffer * 3. Neither the name of the University nor the names of its contributors
141592Srgrimes *    may be used to endorse or promote products derived from this software
151592Srgrimes *    without specific prior written permission.
161592Srgrimes *
171592Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
181592Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
191592Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
201592Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
211592Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
221592Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
231592Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
241592Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
251592Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
261592Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
271592Srgrimes * SUCH DAMAGE.
281592Srgrimes */
291592Srgrimes
301592Srgrimes#ifndef lint
3131331Scharnier#if 0
3231331Scharnierstatic char sccsid[] = "@(#)from: subr.c	8.1 (Berkeley) 6/4/93";
3331331Scharnier#endif
3431331Scharnierstatic const char rcsid[] =
3550476Speter  "$FreeBSD$";
361592Srgrimes#endif /* not lint */
371592Srgrimes
381592Srgrimes/*
391592Srgrimes * Melbourne getty.
401592Srgrimes */
4115645Sjoerg#include <stdlib.h>
421592Srgrimes#include <string.h>
4315645Sjoerg#include <termios.h>
4431331Scharnier#include <unistd.h>
4515645Sjoerg#include <sys/ioctl.h>
4615645Sjoerg#include <sys/param.h>
4731331Scharnier#include <sys/time.h>
4825709Sdavidn#include <syslog.h>
4915645Sjoerg
501592Srgrimes#include "gettytab.h"
5115645Sjoerg#include "pathnames.h"
5215645Sjoerg#include "extern.h"
531592Srgrimes
541592Srgrimes
5515645Sjoerg
561592Srgrimes/*
571592Srgrimes * Get a table entry.
581592Srgrimes */
5915645Sjoergvoid
6090301Simpgettable(const char *name, char *buf)
611592Srgrimes{
6290301Simp	struct gettystrs *sp;
6390301Simp	struct gettynums *np;
6490301Simp	struct gettyflags *fp;
6515645Sjoerg	long n;
6625709Sdavidn	int l;
6725709Sdavidn	char *p;
6825709Sdavidn	char *msg = NULL;
6915645Sjoerg	const char *dba[2];
7025709Sdavidn
7125709Sdavidn	static int firsttime = 1;
7225709Sdavidn
7315645Sjoerg	dba[0] = _PATH_GETTYTAB;
7415645Sjoerg	dba[1] = 0;
751592Srgrimes
7625709Sdavidn	if (firsttime) {
7725709Sdavidn		/*
7825709Sdavidn		 * we need to strdup() anything in the strings array
7925709Sdavidn		 * initially in order to simplify things later
8025709Sdavidn		 */
8125709Sdavidn		for (sp = gettystrs; sp->field; sp++)
8225709Sdavidn			if (sp->value != NULL) {
8325709Sdavidn				/* handle these ones more carefully */
8425709Sdavidn				if (sp >= &gettystrs[4] && sp <= &gettystrs[6])
8525709Sdavidn					l = 2;
8625709Sdavidn				else
8725709Sdavidn					l = strlen(sp->value) + 1;
8825709Sdavidn				if ((p = malloc(l)) != NULL) {
8925709Sdavidn					strncpy(p, sp->value, l);
9025709Sdavidn					p[l-1] = '\0';
9125709Sdavidn				}
9225709Sdavidn				/*
9325709Sdavidn				 * replace, even if NULL, else we'll
9425709Sdavidn				 * have problems with free()ing static mem
9525709Sdavidn				 */
9625709Sdavidn				sp->value = p;
9725709Sdavidn			}
9825709Sdavidn		firsttime = 0;
9925709Sdavidn	}
10025709Sdavidn
10125709Sdavidn	switch (cgetent(&buf, (char **)dba, (char *)name)) {
10225709Sdavidn	case 1:
10325709Sdavidn		msg = "%s: couldn't resolve 'tc=' in gettytab '%s'";
10425709Sdavidn	case 0:
10525709Sdavidn		break;
10625709Sdavidn	case -1:
10725709Sdavidn		msg = "%s: unknown gettytab entry '%s'";
10825709Sdavidn		break;
10925709Sdavidn	case -2:
11025709Sdavidn		msg = "%s: retrieving gettytab entry '%s': %m";
11125709Sdavidn		break;
11225709Sdavidn	case -3:
11325709Sdavidn		msg = "%s: recursive 'tc=' reference gettytab entry '%s'";
11425709Sdavidn		break;
11525709Sdavidn	default:
11625709Sdavidn		msg = "%s: unexpected cgetent() error for entry '%s'";
11725709Sdavidn		break;
11825709Sdavidn	}
11925709Sdavidn
12025709Sdavidn	if (msg != NULL) {
12125709Sdavidn		syslog(LOG_ERR, msg, "getty", name);
1221592Srgrimes		return;
12325709Sdavidn	}
1241592Srgrimes
12525709Sdavidn	for (sp = gettystrs; sp->field; sp++) {
12629045Sdavidn		if ((l = cgetstr(buf, (char*)sp->field, &p)) >= 0) {
12725709Sdavidn			if (sp->value) {
12825709Sdavidn				/* prefer existing value */
12925709Sdavidn				if (strcmp(p, sp->value) != 0)
13025709Sdavidn					free(sp->value);
13125709Sdavidn				else {
13225709Sdavidn					free(p);
13325709Sdavidn					p = sp->value;
13425709Sdavidn				}
13525709Sdavidn			}
13625709Sdavidn			sp->value = p;
13725709Sdavidn		} else if (l == -1) {
13825709Sdavidn			free(sp->value);
13925709Sdavidn			sp->value = NULL;
14025709Sdavidn		}
14125709Sdavidn	}
14225709Sdavidn
1431592Srgrimes	for (np = gettynums; np->field; np++) {
14425709Sdavidn		if (cgetnum(buf, (char*)np->field, &n) == -1)
1451592Srgrimes			np->set = 0;
1461592Srgrimes		else {
1471592Srgrimes			np->set = 1;
1481592Srgrimes			np->value = n;
1491592Srgrimes		}
1501592Srgrimes	}
15125709Sdavidn
1521592Srgrimes	for (fp = gettyflags; fp->field; fp++) {
15325709Sdavidn		if (cgetcap(buf, (char *)fp->field, ':') == NULL)
1541592Srgrimes			fp->set = 0;
1551592Srgrimes		else {
1561592Srgrimes			fp->set = 1;
15715645Sjoerg			fp->value = 1 ^ fp->invrt;
1581592Srgrimes		}
1591592Srgrimes	}
1601592Srgrimes}
1611592Srgrimes
16215645Sjoergvoid
16390301Simpgendefaults(void)
1641592Srgrimes{
16590301Simp	struct gettystrs *sp;
16690301Simp	struct gettynums *np;
16790301Simp	struct gettyflags *fp;
1681592Srgrimes
1691592Srgrimes	for (sp = gettystrs; sp->field; sp++)
1701592Srgrimes		if (sp->value)
17125709Sdavidn			sp->defalt = strdup(sp->value);
1721592Srgrimes	for (np = gettynums; np->field; np++)
1731592Srgrimes		if (np->set)
1741592Srgrimes			np->defalt = np->value;
1751592Srgrimes	for (fp = gettyflags; fp->field; fp++)
1761592Srgrimes		if (fp->set)
1771592Srgrimes			fp->defalt = fp->value;
1781592Srgrimes		else
1791592Srgrimes			fp->defalt = fp->invrt;
1801592Srgrimes}
1811592Srgrimes
18215645Sjoergvoid
18390301Simpsetdefaults(void)
1841592Srgrimes{
18590301Simp	struct gettystrs *sp;
18690301Simp	struct gettynums *np;
18790301Simp	struct gettyflags *fp;
1881592Srgrimes
1891592Srgrimes	for (sp = gettystrs; sp->field; sp++)
1901592Srgrimes		if (!sp->value)
19125709Sdavidn			sp->value = !sp->defalt ? sp->defalt
19225709Sdavidn						: strdup(sp->defalt);
1931592Srgrimes	for (np = gettynums; np->field; np++)
1941592Srgrimes		if (!np->set)
1951592Srgrimes			np->value = np->defalt;
1961592Srgrimes	for (fp = gettyflags; fp->field; fp++)
1971592Srgrimes		if (!fp->set)
1981592Srgrimes			fp->value = fp->defalt;
1991592Srgrimes}
2001592Srgrimes
2011592Srgrimesstatic char **
2021592Srgrimescharnames[] = {
2031592Srgrimes	&ER, &KL, &IN, &QU, &XN, &XF, &ET, &BK,
2041592Srgrimes	&SU, &DS, &RP, &FL, &WE, &LN, 0
2051592Srgrimes};
2061592Srgrimes
2071592Srgrimesstatic char *
2081592Srgrimescharvars[] = {
20915645Sjoerg	&tmode.c_cc[VERASE], &tmode.c_cc[VKILL], &tmode.c_cc[VINTR],
21015645Sjoerg	&tmode.c_cc[VQUIT], &tmode.c_cc[VSTART], &tmode.c_cc[VSTOP],
21115645Sjoerg	&tmode.c_cc[VEOF], &tmode.c_cc[VEOL], &tmode.c_cc[VSUSP],
21215645Sjoerg	&tmode.c_cc[VDSUSP], &tmode.c_cc[VREPRINT], &tmode.c_cc[VDISCARD],
21315645Sjoerg	&tmode.c_cc[VWERASE], &tmode.c_cc[VLNEXT], 0
2141592Srgrimes};
2151592Srgrimes
21615645Sjoergvoid
21790301Simpsetchars(void)
2181592Srgrimes{
21990301Simp	int i;
22090301Simp	const char *p;
2211592Srgrimes
2221592Srgrimes	for (i = 0; charnames[i]; i++) {
2231592Srgrimes		p = *charnames[i];
2241592Srgrimes		if (p && *p)
2251592Srgrimes			*charvars[i] = *p;
2261592Srgrimes		else
22715645Sjoerg			*charvars[i] = _POSIX_VDISABLE;
2281592Srgrimes	}
2291592Srgrimes}
2301592Srgrimes
23115645Sjoerg/* Macros to clear/set/test flags. */
23215645Sjoerg#define	SET(t, f)	(t) |= (f)
23315645Sjoerg#define	CLR(t, f)	(t) &= ~(f)
23415645Sjoerg#define	ISSET(t, f)	((t) & (f))
23515645Sjoerg
23615645Sjoergvoid
23790301Simpset_flags(int n)
2381592Srgrimes{
23990301Simp	tcflag_t iflag, oflag, cflag, lflag;
2401592Srgrimes
2411592Srgrimes
24215645Sjoerg	switch (n) {
24315645Sjoerg	case 0:
24415645Sjoerg		if (C0set && I0set && L0set && O0set) {
24515645Sjoerg			tmode.c_cflag = C0;
24615645Sjoerg			tmode.c_iflag = I0;
24715645Sjoerg			tmode.c_lflag = L0;
24815645Sjoerg			tmode.c_oflag = O0;
24915645Sjoerg			return;
25015645Sjoerg		}
25115645Sjoerg		break;
25215645Sjoerg	case 1:
25315645Sjoerg		if (C1set && I1set && L1set && O1set) {
25415645Sjoerg			tmode.c_cflag = C1;
25515645Sjoerg			tmode.c_iflag = I1;
25615645Sjoerg			tmode.c_lflag = L1;
25715645Sjoerg			tmode.c_oflag = O1;
25815645Sjoerg			return;
25915645Sjoerg		}
26015645Sjoerg		break;
26115645Sjoerg	default:
26215645Sjoerg		if (C2set && I2set && L2set && O2set) {
26315645Sjoerg			tmode.c_cflag = C2;
26415645Sjoerg			tmode.c_iflag = I2;
26515645Sjoerg			tmode.c_lflag = L2;
26615645Sjoerg			tmode.c_oflag = O2;
26715645Sjoerg			return;
26815645Sjoerg		}
26915645Sjoerg		break;
27015645Sjoerg	}
2711592Srgrimes
27215645Sjoerg	iflag = omode.c_iflag;
27315645Sjoerg	oflag = omode.c_oflag;
27415645Sjoerg	cflag = omode.c_cflag;
27515645Sjoerg	lflag = omode.c_lflag;
2761592Srgrimes
27715645Sjoerg	if (NP) {
27815645Sjoerg		CLR(cflag, CSIZE|PARENB);
27915645Sjoerg		SET(cflag, CS8);
28015645Sjoerg		CLR(iflag, ISTRIP|INPCK|IGNPAR);
28115645Sjoerg	} else if (AP || EP || OP) {
28215645Sjoerg		CLR(cflag, CSIZE);
28315645Sjoerg		SET(cflag, CS7|PARENB);
28415645Sjoerg		SET(iflag, ISTRIP);
28515645Sjoerg		if (OP && !EP) {
28615645Sjoerg			SET(iflag, INPCK|IGNPAR);
28715645Sjoerg			SET(cflag, PARODD);
28815645Sjoerg			if (AP)
28915645Sjoerg				CLR(iflag, INPCK);
29015645Sjoerg		} else if (EP && !OP) {
29115645Sjoerg			SET(iflag, INPCK|IGNPAR);
29215645Sjoerg			CLR(cflag, PARODD);
29315645Sjoerg			if (AP)
29415645Sjoerg				CLR(iflag, INPCK);
29515645Sjoerg		} else if (AP || (EP && OP)) {
29615645Sjoerg			CLR(iflag, INPCK|IGNPAR);
29715645Sjoerg			CLR(cflag, PARODD);
29815645Sjoerg		}
29915645Sjoerg	} /* else, leave as is */
30015645Sjoerg
30115645Sjoerg#if 0
3021592Srgrimes	if (UC)
3031592Srgrimes		f |= LCASE;
30415645Sjoerg#endif
3051592Srgrimes
30615645Sjoerg	if (HC)
30715645Sjoerg		SET(cflag, HUPCL);
30815645Sjoerg	else
30915645Sjoerg		CLR(cflag, HUPCL);
3101592Srgrimes
31115645Sjoerg	if (MB)
31215645Sjoerg		SET(cflag, MDMBUF);
31315645Sjoerg	else
31415645Sjoerg		CLR(cflag, MDMBUF);
3151592Srgrimes
31622208Sdavidn	if (HW)
31722208Sdavidn		SET(cflag, CRTSCTS);
31822208Sdavidn	else
31922208Sdavidn		CLR(cflag, CRTSCTS);
32022208Sdavidn
32115645Sjoerg	if (NL) {
32215645Sjoerg		SET(iflag, ICRNL);
32315645Sjoerg		SET(oflag, ONLCR|OPOST);
32415645Sjoerg	} else {
32515645Sjoerg		CLR(iflag, ICRNL);
32615645Sjoerg		CLR(oflag, ONLCR);
3271592Srgrimes	}
3281592Srgrimes
3291592Srgrimes	if (!HT)
33015645Sjoerg		SET(oflag, OXTABS|OPOST);
33115645Sjoerg	else
33215645Sjoerg		CLR(oflag, OXTABS);
3331592Srgrimes
33415645Sjoerg#ifdef XXX_DELAY
33515645Sjoerg	SET(f, delaybits());
33615645Sjoerg#endif
33715645Sjoerg
33815645Sjoerg	if (n == 1) {		/* read mode flags */
33915645Sjoerg		if (RW) {
34015645Sjoerg			iflag = 0;
34115645Sjoerg			CLR(oflag, OPOST);
34215645Sjoerg			CLR(cflag, CSIZE|PARENB);
34315645Sjoerg			SET(cflag, CS8);
34415645Sjoerg			lflag = 0;
34515645Sjoerg		} else {
34615645Sjoerg			CLR(lflag, ICANON);
34715645Sjoerg		}
34815645Sjoerg		goto out;
34915645Sjoerg	}
35015645Sjoerg
3511592Srgrimes	if (n == 0)
35215645Sjoerg		goto out;
3531592Srgrimes
35415645Sjoerg#if 0
3551592Srgrimes	if (CB)
35615645Sjoerg		SET(f, CRTBS);
35715645Sjoerg#endif
3581592Srgrimes
3591592Srgrimes	if (CE)
36015645Sjoerg		SET(lflag, ECHOE);
36115645Sjoerg	else
36215645Sjoerg		CLR(lflag, ECHOE);
3631592Srgrimes
3641592Srgrimes	if (CK)
36515645Sjoerg		SET(lflag, ECHOKE);
36615645Sjoerg	else
36715645Sjoerg		CLR(lflag, ECHOKE);
3681592Srgrimes
3691592Srgrimes	if (PE)
37015645Sjoerg		SET(lflag, ECHOPRT);
37115645Sjoerg	else
37215645Sjoerg		CLR(lflag, ECHOPRT);
3731592Srgrimes
3741592Srgrimes	if (EC)
37515645Sjoerg		SET(lflag, ECHO);
37615645Sjoerg	else
37715645Sjoerg		CLR(lflag, ECHO);
3781592Srgrimes
3791592Srgrimes	if (XC)
38015645Sjoerg		SET(lflag, ECHOCTL);
38115645Sjoerg	else
38215645Sjoerg		CLR(lflag, ECHOCTL);
3831592Srgrimes
3841592Srgrimes	if (DX)
38515645Sjoerg		SET(lflag, IXANY);
38615645Sjoerg	else
38715645Sjoerg		CLR(lflag, IXANY);
3881592Srgrimes
38915645Sjoergout:
39015645Sjoerg	tmode.c_iflag = iflag;
39115645Sjoerg	tmode.c_oflag = oflag;
39215645Sjoerg	tmode.c_cflag = cflag;
39315645Sjoerg	tmode.c_lflag = lflag;
3941592Srgrimes}
3951592Srgrimes
39615645Sjoerg
39715645Sjoerg#ifdef XXX_DELAY
3981592Srgrimesstruct delayval {
3991592Srgrimes	unsigned	delay;		/* delay in ms */
4001592Srgrimes	int		bits;
4011592Srgrimes};
4021592Srgrimes
4031592Srgrimes/*
4041592Srgrimes * below are random guesses, I can't be bothered checking
4051592Srgrimes */
4061592Srgrimes
4071592Srgrimesstruct delayval	crdelay[] = {
40815645Sjoerg	{ 1,		CR1 },
40915645Sjoerg	{ 2,		CR2 },
41015645Sjoerg	{ 3,		CR3 },
41115645Sjoerg	{ 83,		CR1 },
41215645Sjoerg	{ 166,		CR2 },
41315645Sjoerg	{ 0,		CR3 },
4141592Srgrimes};
4151592Srgrimes
4161592Srgrimesstruct delayval nldelay[] = {
41715645Sjoerg	{ 1,		NL1 },		/* special, calculated */
41815645Sjoerg	{ 2,		NL2 },
41915645Sjoerg	{ 3,		NL3 },
42015645Sjoerg	{ 100,		NL2 },
42115645Sjoerg	{ 0,		NL3 },
4221592Srgrimes};
4231592Srgrimes
4241592Srgrimesstruct delayval	bsdelay[] = {
42515645Sjoerg	{ 1,		BS1 },
42615645Sjoerg	{ 0,		0 },
4271592Srgrimes};
4281592Srgrimes
4291592Srgrimesstruct delayval	ffdelay[] = {
43015645Sjoerg	{ 1,		FF1 },
43115645Sjoerg	{ 1750,		FF1 },
43215645Sjoerg	{ 0,		FF1 },
4331592Srgrimes};
4341592Srgrimes
4351592Srgrimesstruct delayval	tbdelay[] = {
43615645Sjoerg	{ 1,		TAB1 },
43715645Sjoerg	{ 2,		TAB2 },
43815645Sjoerg	{ 3,		XTABS },	/* this is expand tabs */
43915645Sjoerg	{ 100,		TAB1 },
44015645Sjoerg	{ 0,		TAB2 },
4411592Srgrimes};
4421592Srgrimes
44315645Sjoergint
44490301Simpdelaybits(void)
4451592Srgrimes{
44690301Simp	int f;
4471592Srgrimes
4481592Srgrimes	f  = adelay(CD, crdelay);
4491592Srgrimes	f |= adelay(ND, nldelay);
4501592Srgrimes	f |= adelay(FD, ffdelay);
4511592Srgrimes	f |= adelay(TD, tbdelay);
4521592Srgrimes	f |= adelay(BD, bsdelay);
4531592Srgrimes	return (f);
4541592Srgrimes}
4551592Srgrimes
45615645Sjoergint
45790301Simpadelay(int ms, struct delayval *dp)
4581592Srgrimes{
4591592Srgrimes	if (ms == 0)
4601592Srgrimes		return (0);
4611592Srgrimes	while (dp->delay && ms > dp->delay)
4621592Srgrimes		dp++;
4631592Srgrimes	return (dp->bits);
4641592Srgrimes}
46515645Sjoerg#endif
4661592Srgrimes
46715645Sjoergchar	editedhost[MAXHOSTNAMELEN];
4681592Srgrimes
46915645Sjoergvoid
47090301Simpedithost(const char *pat)
4711592Srgrimes{
47290301Simp	const char *host = HN;
47390301Simp	char *res = editedhost;
4741592Srgrimes
4751592Srgrimes	if (!pat)
4761592Srgrimes		pat = "";
4771592Srgrimes	while (*pat) {
4781592Srgrimes		switch (*pat) {
4791592Srgrimes
4801592Srgrimes		case '#':
4811592Srgrimes			if (*host)
4821592Srgrimes				host++;
4831592Srgrimes			break;
4841592Srgrimes
4851592Srgrimes		case '@':
4861592Srgrimes			if (*host)
4871592Srgrimes				*res++ = *host++;
4881592Srgrimes			break;
4891592Srgrimes
4901592Srgrimes		default:
4911592Srgrimes			*res++ = *pat;
4921592Srgrimes			break;
4931592Srgrimes
4941592Srgrimes		}
4951592Srgrimes		if (res == &editedhost[sizeof editedhost - 1]) {
4961592Srgrimes			*res = '\0';
4971592Srgrimes			return;
4981592Srgrimes		}
4991592Srgrimes		pat++;
5001592Srgrimes	}
5011592Srgrimes	if (*host)
5021592Srgrimes		strncpy(res, host, sizeof editedhost - (res - editedhost) - 1);
5031592Srgrimes	else
5041592Srgrimes		*res = '\0';
5051592Srgrimes	editedhost[sizeof editedhost - 1] = '\0';
5061592Srgrimes}
5071592Srgrimes
50815645Sjoergstatic struct speedtab {
5091592Srgrimes	int	speed;
5101592Srgrimes	int	uxname;
5111592Srgrimes} speedtab[] = {
51215645Sjoerg	{ 50,	B50 },
51315645Sjoerg	{ 75,	B75 },
51415645Sjoerg	{ 110,	B110 },
51515645Sjoerg	{ 134,	B134 },
51615645Sjoerg	{ 150,	B150 },
51715645Sjoerg	{ 200,	B200 },
51815645Sjoerg	{ 300,	B300 },
51915645Sjoerg	{ 600,	B600 },
52015645Sjoerg	{ 1200,	B1200 },
52115645Sjoerg	{ 1800,	B1800 },
52215645Sjoerg	{ 2400,	B2400 },
52315645Sjoerg	{ 4800,	B4800 },
52415645Sjoerg	{ 9600,	B9600 },
52515645Sjoerg	{ 19200, EXTA },
52615645Sjoerg	{ 19,	EXTA },		/* for people who say 19.2K */
52715645Sjoerg	{ 38400, EXTB },
52815645Sjoerg	{ 38,	EXTB },
52915645Sjoerg	{ 7200,	EXTB },		/* alternative */
53015645Sjoerg	{ 57600, B57600 },
53115645Sjoerg	{ 115200, B115200 },
53237817Sphk	{ 230400, B230400 },
53315645Sjoerg	{ 0 }
5341592Srgrimes};
5351592Srgrimes
53615645Sjoergint
53790301Simpspeed(int val)
5381592Srgrimes{
53990301Simp	struct speedtab *sp;
5401592Srgrimes
54137817Sphk	if (val <= B230400)
5421592Srgrimes		return (val);
5431592Srgrimes
5441592Srgrimes	for (sp = speedtab; sp->speed; sp++)
5451592Srgrimes		if (sp->speed == val)
5461592Srgrimes			return (sp->uxname);
5478870Srgrimes
5481592Srgrimes	return (B300);		/* default in impossible cases */
5491592Srgrimes}
5501592Srgrimes
55115645Sjoergvoid
55290301Simpmakeenv(char *env[])
5531592Srgrimes{
5541592Srgrimes	static char termbuf[128] = "TERM=";
55590301Simp	char *p, *q;
55690301Simp	char **ep;
5571592Srgrimes
5581592Srgrimes	ep = env;
5591592Srgrimes	if (TT && *TT) {
56075905Skris		strlcat(termbuf, TT, sizeof(termbuf));
5611592Srgrimes		*ep++ = termbuf;
5621592Srgrimes	}
56315645Sjoerg	if ((p = EV)) {
5641592Srgrimes		q = p;
56515645Sjoerg		while ((q = strchr(q, ','))) {
5661592Srgrimes			*q++ = '\0';
5671592Srgrimes			*ep++ = p;
5681592Srgrimes			p = q;
5691592Srgrimes		}
5701592Srgrimes		if (*p)
5711592Srgrimes			*ep++ = p;
5721592Srgrimes	}
5731592Srgrimes	*ep = (char *)0;
5741592Srgrimes}
5751592Srgrimes
5761592Srgrimes/*
5771592Srgrimes * This speed select mechanism is written for the Develcon DATASWITCH.
5781592Srgrimes * The Develcon sends a string of the form "B{speed}\n" at a predefined
5791592Srgrimes * baud rate. This string indicates the user's actual speed.
5801592Srgrimes * The routine below returns the terminal type mapped from derived speed.
5811592Srgrimes */
5821592Srgrimesstruct	portselect {
58315645Sjoerg	const char	*ps_baud;
58415645Sjoerg	const char	*ps_type;
5851592Srgrimes} portspeeds[] = {
5861592Srgrimes	{ "B110",	"std.110" },
5871592Srgrimes	{ "B134",	"std.134" },
5881592Srgrimes	{ "B150",	"std.150" },
5891592Srgrimes	{ "B300",	"std.300" },
5901592Srgrimes	{ "B600",	"std.600" },
5911592Srgrimes	{ "B1200",	"std.1200" },
5921592Srgrimes	{ "B2400",	"std.2400" },
5931592Srgrimes	{ "B4800",	"std.4800" },
5941592Srgrimes	{ "B9600",	"std.9600" },
5951592Srgrimes	{ "B19200",	"std.19200" },
5961592Srgrimes	{ 0 }
5971592Srgrimes};
5981592Srgrimes
59915645Sjoergconst char *
60090301Simpportselector(void)
6011592Srgrimes{
60215645Sjoerg	char c, baud[20];
60315645Sjoerg	const char *type = "default";
60490301Simp	struct portselect *ps;
6051592Srgrimes	int len;
6061592Srgrimes
6071592Srgrimes	alarm(5*60);
6081592Srgrimes	for (len = 0; len < sizeof (baud) - 1; len++) {
6091592Srgrimes		if (read(STDIN_FILENO, &c, 1) <= 0)
6101592Srgrimes			break;
6111592Srgrimes		c &= 0177;
6121592Srgrimes		if (c == '\n' || c == '\r')
6131592Srgrimes			break;
6141592Srgrimes		if (c == 'B')
6151592Srgrimes			len = 0;	/* in case of leading garbage */
6161592Srgrimes		baud[len] = c;
6171592Srgrimes	}
6181592Srgrimes	baud[len] = '\0';
6191592Srgrimes	for (ps = portspeeds; ps->ps_baud; ps++)
6201592Srgrimes		if (strcmp(ps->ps_baud, baud) == 0) {
6211592Srgrimes			type = ps->ps_type;
6221592Srgrimes			break;
6231592Srgrimes		}
6241592Srgrimes	sleep(2);	/* wait for connection to complete */
6251592Srgrimes	return (type);
6261592Srgrimes}
6271592Srgrimes
6281592Srgrimes/*
6291592Srgrimes * This auto-baud speed select mechanism is written for the Micom 600
6301592Srgrimes * portselector. Selection is done by looking at how the character '\r'
6311592Srgrimes * is garbled at the different speeds.
6321592Srgrimes */
63315645Sjoergconst char *
63490301Simpautobaud(void)
6351592Srgrimes{
6361592Srgrimes	int rfds;
6371592Srgrimes	struct timeval timeout;
63815645Sjoerg	char c;
63915645Sjoerg	const char *type = "9600-baud";
6401592Srgrimes
64115645Sjoerg	(void)tcflush(0, TCIOFLUSH);
6421592Srgrimes	rfds = 1 << 0;
6431592Srgrimes	timeout.tv_sec = 5;
6441592Srgrimes	timeout.tv_usec = 0;
6451592Srgrimes	if (select(32, (fd_set *)&rfds, (fd_set *)NULL,
6461592Srgrimes	    (fd_set *)NULL, &timeout) <= 0)
6471592Srgrimes		return (type);
6481592Srgrimes	if (read(STDIN_FILENO, &c, sizeof(char)) != sizeof(char))
6491592Srgrimes		return (type);
6501592Srgrimes	timeout.tv_sec = 0;
6511592Srgrimes	timeout.tv_usec = 20;
6521592Srgrimes	(void) select(32, (fd_set *)NULL, (fd_set *)NULL,
6531592Srgrimes	    (fd_set *)NULL, &timeout);
65415645Sjoerg	(void)tcflush(0, TCIOFLUSH);
6551592Srgrimes	switch (c & 0377) {
6561592Srgrimes
6571592Srgrimes	case 0200:		/* 300-baud */
6581592Srgrimes		type = "300-baud";
6591592Srgrimes		break;
6601592Srgrimes
6611592Srgrimes	case 0346:		/* 1200-baud */
6621592Srgrimes		type = "1200-baud";
6631592Srgrimes		break;
6641592Srgrimes
6651592Srgrimes	case  015:		/* 2400-baud */
6661592Srgrimes	case 0215:
6671592Srgrimes		type = "2400-baud";
6681592Srgrimes		break;
6691592Srgrimes
6701592Srgrimes	default:		/* 4800-baud */
6711592Srgrimes		type = "4800-baud";
6721592Srgrimes		break;
6731592Srgrimes
6741592Srgrimes	case 0377:		/* 9600-baud */
6751592Srgrimes		type = "9600-baud";
6761592Srgrimes		break;
6771592Srgrimes	}
6781592Srgrimes	return (type);
6791592Srgrimes}
680