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$";
401592Srgrimes#endif /* not lint */
411592Srgrimes
421592Srgrimes/*
431592Srgrimes * Melbourne getty.
441592Srgrimes */
4531331Scharnier#ifdef DEBUG
4631331Scharnier#include <stdio.h>
4731331Scharnier#endif
4815645Sjoerg#include <stdlib.h>
491592Srgrimes#include <string.h>
5015645Sjoerg#include <termios.h>
5131331Scharnier#include <unistd.h>
5215645Sjoerg#include <sys/ioctl.h>
5315645Sjoerg#include <sys/param.h>
5431331Scharnier#include <sys/time.h>
5525709Sdavidn#include <syslog.h>
5615645Sjoerg
571592Srgrimes#include "gettytab.h"
5815645Sjoerg#include "pathnames.h"
5915645Sjoerg#include "extern.h"
601592Srgrimes
611592Srgrimes
6215645Sjoerg
631592Srgrimes/*
641592Srgrimes * Get a table entry.
651592Srgrimes */
6615645Sjoergvoid
6790301Simpgettable(const char *name, char *buf)
681592Srgrimes{
6990301Simp	struct gettystrs *sp;
7090301Simp	struct gettynums *np;
7190301Simp	struct gettyflags *fp;
7215645Sjoerg	long n;
7325709Sdavidn	int l;
7425709Sdavidn	char *p;
7525709Sdavidn	char *msg = NULL;
7615645Sjoerg	const char *dba[2];
7725709Sdavidn
7825709Sdavidn	static int firsttime = 1;
7925709Sdavidn
8015645Sjoerg	dba[0] = _PATH_GETTYTAB;
8115645Sjoerg	dba[1] = 0;
821592Srgrimes
8325709Sdavidn	if (firsttime) {
8425709Sdavidn		/*
8525709Sdavidn		 * we need to strdup() anything in the strings array
8625709Sdavidn		 * initially in order to simplify things later
8725709Sdavidn		 */
8825709Sdavidn		for (sp = gettystrs; sp->field; sp++)
8925709Sdavidn			if (sp->value != NULL) {
9025709Sdavidn				/* handle these ones more carefully */
9125709Sdavidn				if (sp >= &gettystrs[4] && sp <= &gettystrs[6])
9225709Sdavidn					l = 2;
9325709Sdavidn				else
9425709Sdavidn					l = strlen(sp->value) + 1;
9525709Sdavidn				if ((p = malloc(l)) != NULL) {
9625709Sdavidn					strncpy(p, sp->value, l);
9725709Sdavidn					p[l-1] = '\0';
9825709Sdavidn				}
9925709Sdavidn				/*
10025709Sdavidn				 * replace, even if NULL, else we'll
10125709Sdavidn				 * have problems with free()ing static mem
10225709Sdavidn				 */
10325709Sdavidn				sp->value = p;
10425709Sdavidn			}
10525709Sdavidn		firsttime = 0;
10625709Sdavidn	}
10725709Sdavidn
10825709Sdavidn	switch (cgetent(&buf, (char **)dba, (char *)name)) {
10925709Sdavidn	case 1:
11025709Sdavidn		msg = "%s: couldn't resolve 'tc=' in gettytab '%s'";
11125709Sdavidn	case 0:
11225709Sdavidn		break;
11325709Sdavidn	case -1:
11425709Sdavidn		msg = "%s: unknown gettytab entry '%s'";
11525709Sdavidn		break;
11625709Sdavidn	case -2:
11725709Sdavidn		msg = "%s: retrieving gettytab entry '%s': %m";
11825709Sdavidn		break;
11925709Sdavidn	case -3:
12025709Sdavidn		msg = "%s: recursive 'tc=' reference gettytab entry '%s'";
12125709Sdavidn		break;
12225709Sdavidn	default:
12325709Sdavidn		msg = "%s: unexpected cgetent() error for entry '%s'";
12425709Sdavidn		break;
12525709Sdavidn	}
12625709Sdavidn
12725709Sdavidn	if (msg != NULL) {
12825709Sdavidn		syslog(LOG_ERR, msg, "getty", name);
1291592Srgrimes		return;
13025709Sdavidn	}
1311592Srgrimes
13225709Sdavidn	for (sp = gettystrs; sp->field; sp++) {
13329045Sdavidn		if ((l = cgetstr(buf, (char*)sp->field, &p)) >= 0) {
13425709Sdavidn			if (sp->value) {
13525709Sdavidn				/* prefer existing value */
13625709Sdavidn				if (strcmp(p, sp->value) != 0)
13725709Sdavidn					free(sp->value);
13825709Sdavidn				else {
13925709Sdavidn					free(p);
14025709Sdavidn					p = sp->value;
14125709Sdavidn				}
14225709Sdavidn			}
14325709Sdavidn			sp->value = p;
14425709Sdavidn		} else if (l == -1) {
14525709Sdavidn			free(sp->value);
14625709Sdavidn			sp->value = NULL;
14725709Sdavidn		}
14825709Sdavidn	}
14925709Sdavidn
1501592Srgrimes	for (np = gettynums; np->field; np++) {
15125709Sdavidn		if (cgetnum(buf, (char*)np->field, &n) == -1)
1521592Srgrimes			np->set = 0;
1531592Srgrimes		else {
1541592Srgrimes			np->set = 1;
1551592Srgrimes			np->value = n;
1561592Srgrimes		}
1571592Srgrimes	}
15825709Sdavidn
1591592Srgrimes	for (fp = gettyflags; fp->field; fp++) {
16025709Sdavidn		if (cgetcap(buf, (char *)fp->field, ':') == NULL)
1611592Srgrimes			fp->set = 0;
1621592Srgrimes		else {
1631592Srgrimes			fp->set = 1;
16415645Sjoerg			fp->value = 1 ^ fp->invrt;
1651592Srgrimes		}
1661592Srgrimes	}
16725709Sdavidn
16815645Sjoerg#ifdef DEBUG
16915645Sjoerg	printf("name=\"%s\", buf=\"%s\"\r\n", name, buf);
17015645Sjoerg	for (sp = gettystrs; sp->field; sp++)
17129045Sdavidn		printf("cgetstr: %s=%s\r\n", sp->field, sp->value);
17215645Sjoerg	for (np = gettynums; np->field; np++)
17315645Sjoerg		printf("cgetnum: %s=%d\r\n", np->field, np->value);
17415645Sjoerg	for (fp = gettyflags; fp->field; fp++)
17515645Sjoerg		printf("cgetflags: %s='%c' set='%c'\r\n", fp->field,
17615645Sjoerg		       fp->value + '0', fp->set + '0');
17715645Sjoerg#endif /* DEBUG */
1781592Srgrimes}
1791592Srgrimes
18015645Sjoergvoid
18190301Simpgendefaults(void)
1821592Srgrimes{
18390301Simp	struct gettystrs *sp;
18490301Simp	struct gettynums *np;
18590301Simp	struct gettyflags *fp;
1861592Srgrimes
1871592Srgrimes	for (sp = gettystrs; sp->field; sp++)
1881592Srgrimes		if (sp->value)
18925709Sdavidn			sp->defalt = strdup(sp->value);
1901592Srgrimes	for (np = gettynums; np->field; np++)
1911592Srgrimes		if (np->set)
1921592Srgrimes			np->defalt = np->value;
1931592Srgrimes	for (fp = gettyflags; fp->field; fp++)
1941592Srgrimes		if (fp->set)
1951592Srgrimes			fp->defalt = fp->value;
1961592Srgrimes		else
1971592Srgrimes			fp->defalt = fp->invrt;
1981592Srgrimes}
1991592Srgrimes
20015645Sjoergvoid
20190301Simpsetdefaults(void)
2021592Srgrimes{
20390301Simp	struct gettystrs *sp;
20490301Simp	struct gettynums *np;
20590301Simp	struct gettyflags *fp;
2061592Srgrimes
2071592Srgrimes	for (sp = gettystrs; sp->field; sp++)
2081592Srgrimes		if (!sp->value)
20925709Sdavidn			sp->value = !sp->defalt ? sp->defalt
21025709Sdavidn						: strdup(sp->defalt);
2111592Srgrimes	for (np = gettynums; np->field; np++)
2121592Srgrimes		if (!np->set)
2131592Srgrimes			np->value = np->defalt;
2141592Srgrimes	for (fp = gettyflags; fp->field; fp++)
2151592Srgrimes		if (!fp->set)
2161592Srgrimes			fp->value = fp->defalt;
2171592Srgrimes}
2181592Srgrimes
2191592Srgrimesstatic char **
2201592Srgrimescharnames[] = {
2211592Srgrimes	&ER, &KL, &IN, &QU, &XN, &XF, &ET, &BK,
2221592Srgrimes	&SU, &DS, &RP, &FL, &WE, &LN, 0
2231592Srgrimes};
2241592Srgrimes
2251592Srgrimesstatic char *
2261592Srgrimescharvars[] = {
22715645Sjoerg	&tmode.c_cc[VERASE], &tmode.c_cc[VKILL], &tmode.c_cc[VINTR],
22815645Sjoerg	&tmode.c_cc[VQUIT], &tmode.c_cc[VSTART], &tmode.c_cc[VSTOP],
22915645Sjoerg	&tmode.c_cc[VEOF], &tmode.c_cc[VEOL], &tmode.c_cc[VSUSP],
23015645Sjoerg	&tmode.c_cc[VDSUSP], &tmode.c_cc[VREPRINT], &tmode.c_cc[VDISCARD],
23115645Sjoerg	&tmode.c_cc[VWERASE], &tmode.c_cc[VLNEXT], 0
2321592Srgrimes};
2331592Srgrimes
23415645Sjoergvoid
23590301Simpsetchars(void)
2361592Srgrimes{
23790301Simp	int i;
23890301Simp	const char *p;
2391592Srgrimes
2401592Srgrimes	for (i = 0; charnames[i]; i++) {
2411592Srgrimes		p = *charnames[i];
2421592Srgrimes		if (p && *p)
2431592Srgrimes			*charvars[i] = *p;
2441592Srgrimes		else
24515645Sjoerg			*charvars[i] = _POSIX_VDISABLE;
2461592Srgrimes	}
2471592Srgrimes}
2481592Srgrimes
24915645Sjoerg/* Macros to clear/set/test flags. */
25015645Sjoerg#define	SET(t, f)	(t) |= (f)
25115645Sjoerg#define	CLR(t, f)	(t) &= ~(f)
25215645Sjoerg#define	ISSET(t, f)	((t) & (f))
25315645Sjoerg
25415645Sjoergvoid
25590301Simpset_flags(int n)
2561592Srgrimes{
25790301Simp	tcflag_t iflag, oflag, cflag, lflag;
2581592Srgrimes
2591592Srgrimes
26015645Sjoerg	switch (n) {
26115645Sjoerg	case 0:
26215645Sjoerg		if (C0set && I0set && L0set && O0set) {
26315645Sjoerg			tmode.c_cflag = C0;
26415645Sjoerg			tmode.c_iflag = I0;
26515645Sjoerg			tmode.c_lflag = L0;
26615645Sjoerg			tmode.c_oflag = O0;
26715645Sjoerg			return;
26815645Sjoerg		}
26915645Sjoerg		break;
27015645Sjoerg	case 1:
27115645Sjoerg		if (C1set && I1set && L1set && O1set) {
27215645Sjoerg			tmode.c_cflag = C1;
27315645Sjoerg			tmode.c_iflag = I1;
27415645Sjoerg			tmode.c_lflag = L1;
27515645Sjoerg			tmode.c_oflag = O1;
27615645Sjoerg			return;
27715645Sjoerg		}
27815645Sjoerg		break;
27915645Sjoerg	default:
28015645Sjoerg		if (C2set && I2set && L2set && O2set) {
28115645Sjoerg			tmode.c_cflag = C2;
28215645Sjoerg			tmode.c_iflag = I2;
28315645Sjoerg			tmode.c_lflag = L2;
28415645Sjoerg			tmode.c_oflag = O2;
28515645Sjoerg			return;
28615645Sjoerg		}
28715645Sjoerg		break;
28815645Sjoerg	}
2891592Srgrimes
29015645Sjoerg	iflag = omode.c_iflag;
29115645Sjoerg	oflag = omode.c_oflag;
29215645Sjoerg	cflag = omode.c_cflag;
29315645Sjoerg	lflag = omode.c_lflag;
2941592Srgrimes
29515645Sjoerg	if (NP) {
29615645Sjoerg		CLR(cflag, CSIZE|PARENB);
29715645Sjoerg		SET(cflag, CS8);
29815645Sjoerg		CLR(iflag, ISTRIP|INPCK|IGNPAR);
29915645Sjoerg	} else if (AP || EP || OP) {
30015645Sjoerg		CLR(cflag, CSIZE);
30115645Sjoerg		SET(cflag, CS7|PARENB);
30215645Sjoerg		SET(iflag, ISTRIP);
30315645Sjoerg		if (OP && !EP) {
30415645Sjoerg			SET(iflag, INPCK|IGNPAR);
30515645Sjoerg			SET(cflag, PARODD);
30615645Sjoerg			if (AP)
30715645Sjoerg				CLR(iflag, INPCK);
30815645Sjoerg		} else if (EP && !OP) {
30915645Sjoerg			SET(iflag, INPCK|IGNPAR);
31015645Sjoerg			CLR(cflag, PARODD);
31115645Sjoerg			if (AP)
31215645Sjoerg				CLR(iflag, INPCK);
31315645Sjoerg		} else if (AP || (EP && OP)) {
31415645Sjoerg			CLR(iflag, INPCK|IGNPAR);
31515645Sjoerg			CLR(cflag, PARODD);
31615645Sjoerg		}
31715645Sjoerg	} /* else, leave as is */
31815645Sjoerg
31915645Sjoerg#if 0
3201592Srgrimes	if (UC)
3211592Srgrimes		f |= LCASE;
32215645Sjoerg#endif
3231592Srgrimes
32415645Sjoerg	if (HC)
32515645Sjoerg		SET(cflag, HUPCL);
32615645Sjoerg	else
32715645Sjoerg		CLR(cflag, HUPCL);
3281592Srgrimes
32915645Sjoerg	if (MB)
33015645Sjoerg		SET(cflag, MDMBUF);
33115645Sjoerg	else
33215645Sjoerg		CLR(cflag, MDMBUF);
3331592Srgrimes
33422208Sdavidn	if (HW)
33522208Sdavidn		SET(cflag, CRTSCTS);
33622208Sdavidn	else
33722208Sdavidn		CLR(cflag, CRTSCTS);
33822208Sdavidn
33915645Sjoerg	if (NL) {
34015645Sjoerg		SET(iflag, ICRNL);
34115645Sjoerg		SET(oflag, ONLCR|OPOST);
34215645Sjoerg	} else {
34315645Sjoerg		CLR(iflag, ICRNL);
34415645Sjoerg		CLR(oflag, ONLCR);
3451592Srgrimes	}
3461592Srgrimes
3471592Srgrimes	if (!HT)
34815645Sjoerg		SET(oflag, OXTABS|OPOST);
34915645Sjoerg	else
35015645Sjoerg		CLR(oflag, OXTABS);
3511592Srgrimes
35215645Sjoerg#ifdef XXX_DELAY
35315645Sjoerg	SET(f, delaybits());
35415645Sjoerg#endif
35515645Sjoerg
35615645Sjoerg	if (n == 1) {		/* read mode flags */
35715645Sjoerg		if (RW) {
35815645Sjoerg			iflag = 0;
35915645Sjoerg			CLR(oflag, OPOST);
36015645Sjoerg			CLR(cflag, CSIZE|PARENB);
36115645Sjoerg			SET(cflag, CS8);
36215645Sjoerg			lflag = 0;
36315645Sjoerg		} else {
36415645Sjoerg			CLR(lflag, ICANON);
36515645Sjoerg		}
36615645Sjoerg		goto out;
36715645Sjoerg	}
36815645Sjoerg
3691592Srgrimes	if (n == 0)
37015645Sjoerg		goto out;
3711592Srgrimes
37215645Sjoerg#if 0
3731592Srgrimes	if (CB)
37415645Sjoerg		SET(f, CRTBS);
37515645Sjoerg#endif
3761592Srgrimes
3771592Srgrimes	if (CE)
37815645Sjoerg		SET(lflag, ECHOE);
37915645Sjoerg	else
38015645Sjoerg		CLR(lflag, ECHOE);
3811592Srgrimes
3821592Srgrimes	if (CK)
38315645Sjoerg		SET(lflag, ECHOKE);
38415645Sjoerg	else
38515645Sjoerg		CLR(lflag, ECHOKE);
3861592Srgrimes
3871592Srgrimes	if (PE)
38815645Sjoerg		SET(lflag, ECHOPRT);
38915645Sjoerg	else
39015645Sjoerg		CLR(lflag, ECHOPRT);
3911592Srgrimes
3921592Srgrimes	if (EC)
39315645Sjoerg		SET(lflag, ECHO);
39415645Sjoerg	else
39515645Sjoerg		CLR(lflag, ECHO);
3961592Srgrimes
3971592Srgrimes	if (XC)
39815645Sjoerg		SET(lflag, ECHOCTL);
39915645Sjoerg	else
40015645Sjoerg		CLR(lflag, ECHOCTL);
4011592Srgrimes
4021592Srgrimes	if (DX)
40315645Sjoerg		SET(lflag, IXANY);
40415645Sjoerg	else
40515645Sjoerg		CLR(lflag, IXANY);
4061592Srgrimes
40715645Sjoergout:
40815645Sjoerg	tmode.c_iflag = iflag;
40915645Sjoerg	tmode.c_oflag = oflag;
41015645Sjoerg	tmode.c_cflag = cflag;
41115645Sjoerg	tmode.c_lflag = lflag;
4121592Srgrimes}
4131592Srgrimes
41415645Sjoerg
41515645Sjoerg#ifdef XXX_DELAY
4161592Srgrimesstruct delayval {
4171592Srgrimes	unsigned	delay;		/* delay in ms */
4181592Srgrimes	int		bits;
4191592Srgrimes};
4201592Srgrimes
4211592Srgrimes/*
4221592Srgrimes * below are random guesses, I can't be bothered checking
4231592Srgrimes */
4241592Srgrimes
4251592Srgrimesstruct delayval	crdelay[] = {
42615645Sjoerg	{ 1,		CR1 },
42715645Sjoerg	{ 2,		CR2 },
42815645Sjoerg	{ 3,		CR3 },
42915645Sjoerg	{ 83,		CR1 },
43015645Sjoerg	{ 166,		CR2 },
43115645Sjoerg	{ 0,		CR3 },
4321592Srgrimes};
4331592Srgrimes
4341592Srgrimesstruct delayval nldelay[] = {
43515645Sjoerg	{ 1,		NL1 },		/* special, calculated */
43615645Sjoerg	{ 2,		NL2 },
43715645Sjoerg	{ 3,		NL3 },
43815645Sjoerg	{ 100,		NL2 },
43915645Sjoerg	{ 0,		NL3 },
4401592Srgrimes};
4411592Srgrimes
4421592Srgrimesstruct delayval	bsdelay[] = {
44315645Sjoerg	{ 1,		BS1 },
44415645Sjoerg	{ 0,		0 },
4451592Srgrimes};
4461592Srgrimes
4471592Srgrimesstruct delayval	ffdelay[] = {
44815645Sjoerg	{ 1,		FF1 },
44915645Sjoerg	{ 1750,		FF1 },
45015645Sjoerg	{ 0,		FF1 },
4511592Srgrimes};
4521592Srgrimes
4531592Srgrimesstruct delayval	tbdelay[] = {
45415645Sjoerg	{ 1,		TAB1 },
45515645Sjoerg	{ 2,		TAB2 },
45615645Sjoerg	{ 3,		XTABS },	/* this is expand tabs */
45715645Sjoerg	{ 100,		TAB1 },
45815645Sjoerg	{ 0,		TAB2 },
4591592Srgrimes};
4601592Srgrimes
46115645Sjoergint
46290301Simpdelaybits(void)
4631592Srgrimes{
46490301Simp	int f;
4651592Srgrimes
4661592Srgrimes	f  = adelay(CD, crdelay);
4671592Srgrimes	f |= adelay(ND, nldelay);
4681592Srgrimes	f |= adelay(FD, ffdelay);
4691592Srgrimes	f |= adelay(TD, tbdelay);
4701592Srgrimes	f |= adelay(BD, bsdelay);
4711592Srgrimes	return (f);
4721592Srgrimes}
4731592Srgrimes
47415645Sjoergint
47590301Simpadelay(int ms, struct delayval *dp)
4761592Srgrimes{
4771592Srgrimes	if (ms == 0)
4781592Srgrimes		return (0);
4791592Srgrimes	while (dp->delay && ms > dp->delay)
4801592Srgrimes		dp++;
4811592Srgrimes	return (dp->bits);
4821592Srgrimes}
48315645Sjoerg#endif
4841592Srgrimes
48515645Sjoergchar	editedhost[MAXHOSTNAMELEN];
4861592Srgrimes
48715645Sjoergvoid
48890301Simpedithost(const char *pat)
4891592Srgrimes{
49090301Simp	const char *host = HN;
49190301Simp	char *res = editedhost;
4921592Srgrimes
4931592Srgrimes	if (!pat)
4941592Srgrimes		pat = "";
4951592Srgrimes	while (*pat) {
4961592Srgrimes		switch (*pat) {
4971592Srgrimes
4981592Srgrimes		case '#':
4991592Srgrimes			if (*host)
5001592Srgrimes				host++;
5011592Srgrimes			break;
5021592Srgrimes
5031592Srgrimes		case '@':
5041592Srgrimes			if (*host)
5051592Srgrimes				*res++ = *host++;
5061592Srgrimes			break;
5071592Srgrimes
5081592Srgrimes		default:
5091592Srgrimes			*res++ = *pat;
5101592Srgrimes			break;
5111592Srgrimes
5121592Srgrimes		}
5131592Srgrimes		if (res == &editedhost[sizeof editedhost - 1]) {
5141592Srgrimes			*res = '\0';
5151592Srgrimes			return;
5161592Srgrimes		}
5171592Srgrimes		pat++;
5181592Srgrimes	}
5191592Srgrimes	if (*host)
5201592Srgrimes		strncpy(res, host, sizeof editedhost - (res - editedhost) - 1);
5211592Srgrimes	else
5221592Srgrimes		*res = '\0';
5231592Srgrimes	editedhost[sizeof editedhost - 1] = '\0';
5241592Srgrimes}
5251592Srgrimes
52615645Sjoergstatic struct speedtab {
5271592Srgrimes	int	speed;
5281592Srgrimes	int	uxname;
5291592Srgrimes} speedtab[] = {
53015645Sjoerg	{ 50,	B50 },
53115645Sjoerg	{ 75,	B75 },
53215645Sjoerg	{ 110,	B110 },
53315645Sjoerg	{ 134,	B134 },
53415645Sjoerg	{ 150,	B150 },
53515645Sjoerg	{ 200,	B200 },
53615645Sjoerg	{ 300,	B300 },
53715645Sjoerg	{ 600,	B600 },
53815645Sjoerg	{ 1200,	B1200 },
53915645Sjoerg	{ 1800,	B1800 },
54015645Sjoerg	{ 2400,	B2400 },
54115645Sjoerg	{ 4800,	B4800 },
54215645Sjoerg	{ 9600,	B9600 },
54315645Sjoerg	{ 19200, EXTA },
54415645Sjoerg	{ 19,	EXTA },		/* for people who say 19.2K */
54515645Sjoerg	{ 38400, EXTB },
54615645Sjoerg	{ 38,	EXTB },
54715645Sjoerg	{ 7200,	EXTB },		/* alternative */
54815645Sjoerg	{ 57600, B57600 },
54915645Sjoerg	{ 115200, B115200 },
55037817Sphk	{ 230400, B230400 },
55115645Sjoerg	{ 0 }
5521592Srgrimes};
5531592Srgrimes
55415645Sjoergint
55590301Simpspeed(int val)
5561592Srgrimes{
55790301Simp	struct speedtab *sp;
5581592Srgrimes
55937817Sphk	if (val <= B230400)
5601592Srgrimes		return (val);
5611592Srgrimes
5621592Srgrimes	for (sp = speedtab; sp->speed; sp++)
5631592Srgrimes		if (sp->speed == val)
5641592Srgrimes			return (sp->uxname);
5658870Srgrimes
5661592Srgrimes	return (B300);		/* default in impossible cases */
5671592Srgrimes}
5681592Srgrimes
56915645Sjoergvoid
57090301Simpmakeenv(char *env[])
5711592Srgrimes{
5721592Srgrimes	static char termbuf[128] = "TERM=";
57390301Simp	char *p, *q;
57490301Simp	char **ep;
5751592Srgrimes
5761592Srgrimes	ep = env;
5771592Srgrimes	if (TT && *TT) {
57875905Skris		strlcat(termbuf, TT, sizeof(termbuf));
5791592Srgrimes		*ep++ = termbuf;
5801592Srgrimes	}
58115645Sjoerg	if ((p = EV)) {
5821592Srgrimes		q = p;
58315645Sjoerg		while ((q = strchr(q, ','))) {
5841592Srgrimes			*q++ = '\0';
5851592Srgrimes			*ep++ = p;
5861592Srgrimes			p = q;
5871592Srgrimes		}
5881592Srgrimes		if (*p)
5891592Srgrimes			*ep++ = p;
5901592Srgrimes	}
5911592Srgrimes	*ep = (char *)0;
5921592Srgrimes}
5931592Srgrimes
5941592Srgrimes/*
5951592Srgrimes * This speed select mechanism is written for the Develcon DATASWITCH.
5961592Srgrimes * The Develcon sends a string of the form "B{speed}\n" at a predefined
5971592Srgrimes * baud rate. This string indicates the user's actual speed.
5981592Srgrimes * The routine below returns the terminal type mapped from derived speed.
5991592Srgrimes */
6001592Srgrimesstruct	portselect {
60115645Sjoerg	const char	*ps_baud;
60215645Sjoerg	const char	*ps_type;
6031592Srgrimes} portspeeds[] = {
6041592Srgrimes	{ "B110",	"std.110" },
6051592Srgrimes	{ "B134",	"std.134" },
6061592Srgrimes	{ "B150",	"std.150" },
6071592Srgrimes	{ "B300",	"std.300" },
6081592Srgrimes	{ "B600",	"std.600" },
6091592Srgrimes	{ "B1200",	"std.1200" },
6101592Srgrimes	{ "B2400",	"std.2400" },
6111592Srgrimes	{ "B4800",	"std.4800" },
6121592Srgrimes	{ "B9600",	"std.9600" },
6131592Srgrimes	{ "B19200",	"std.19200" },
6141592Srgrimes	{ 0 }
6151592Srgrimes};
6161592Srgrimes
61715645Sjoergconst char *
61890301Simpportselector(void)
6191592Srgrimes{
62015645Sjoerg	char c, baud[20];
62115645Sjoerg	const char *type = "default";
62290301Simp	struct portselect *ps;
6231592Srgrimes	int len;
6241592Srgrimes
6251592Srgrimes	alarm(5*60);
6261592Srgrimes	for (len = 0; len < sizeof (baud) - 1; len++) {
6271592Srgrimes		if (read(STDIN_FILENO, &c, 1) <= 0)
6281592Srgrimes			break;
6291592Srgrimes		c &= 0177;
6301592Srgrimes		if (c == '\n' || c == '\r')
6311592Srgrimes			break;
6321592Srgrimes		if (c == 'B')
6331592Srgrimes			len = 0;	/* in case of leading garbage */
6341592Srgrimes		baud[len] = c;
6351592Srgrimes	}
6361592Srgrimes	baud[len] = '\0';
6371592Srgrimes	for (ps = portspeeds; ps->ps_baud; ps++)
6381592Srgrimes		if (strcmp(ps->ps_baud, baud) == 0) {
6391592Srgrimes			type = ps->ps_type;
6401592Srgrimes			break;
6411592Srgrimes		}
6421592Srgrimes	sleep(2);	/* wait for connection to complete */
6431592Srgrimes	return (type);
6441592Srgrimes}
6451592Srgrimes
6461592Srgrimes/*
6471592Srgrimes * This auto-baud speed select mechanism is written for the Micom 600
6481592Srgrimes * portselector. Selection is done by looking at how the character '\r'
6491592Srgrimes * is garbled at the different speeds.
6501592Srgrimes */
65115645Sjoergconst char *
65290301Simpautobaud(void)
6531592Srgrimes{
6541592Srgrimes	int rfds;
6551592Srgrimes	struct timeval timeout;
65615645Sjoerg	char c;
65715645Sjoerg	const char *type = "9600-baud";
6581592Srgrimes
65915645Sjoerg	(void)tcflush(0, TCIOFLUSH);
6601592Srgrimes	rfds = 1 << 0;
6611592Srgrimes	timeout.tv_sec = 5;
6621592Srgrimes	timeout.tv_usec = 0;
6631592Srgrimes	if (select(32, (fd_set *)&rfds, (fd_set *)NULL,
6641592Srgrimes	    (fd_set *)NULL, &timeout) <= 0)
6651592Srgrimes		return (type);
6661592Srgrimes	if (read(STDIN_FILENO, &c, sizeof(char)) != sizeof(char))
6671592Srgrimes		return (type);
6681592Srgrimes	timeout.tv_sec = 0;
6691592Srgrimes	timeout.tv_usec = 20;
6701592Srgrimes	(void) select(32, (fd_set *)NULL, (fd_set *)NULL,
6711592Srgrimes	    (fd_set *)NULL, &timeout);
67215645Sjoerg	(void)tcflush(0, TCIOFLUSH);
6731592Srgrimes	switch (c & 0377) {
6741592Srgrimes
6751592Srgrimes	case 0200:		/* 300-baud */
6761592Srgrimes		type = "300-baud";
6771592Srgrimes		break;
6781592Srgrimes
6791592Srgrimes	case 0346:		/* 1200-baud */
6801592Srgrimes		type = "1200-baud";
6811592Srgrimes		break;
6821592Srgrimes
6831592Srgrimes	case  015:		/* 2400-baud */
6841592Srgrimes	case 0215:
6851592Srgrimes		type = "2400-baud";
6861592Srgrimes		break;
6871592Srgrimes
6881592Srgrimes	default:		/* 4800-baud */
6891592Srgrimes		type = "4800-baud";
6901592Srgrimes		break;
6911592Srgrimes
6921592Srgrimes	case 0377:		/* 9600-baud */
6931592Srgrimes		type = "9600-baud";
6941592Srgrimes		break;
6951592Srgrimes	}
6961592Srgrimes	return (type);
6971592Srgrimes}
698