xref: /csrg-svn/libexec/getty/subr.c (revision 60091)
119061Sdist /*
236930Sbostic  * Copyright (c) 1983 The Regents of the University of California.
336930Sbostic  * All rights reserved.
436930Sbostic  *
542670Sbostic  * %sccs.include.redist.c%
619061Sdist  */
719061Sdist 
813796Ssam #ifndef lint
9*60091Sbostic static char sccsid[] = "@(#)subr.c	5.11 (Berkeley) 05/17/93";
1036930Sbostic #endif /* not lint */
1113796Ssam 
1213796Ssam /*
1313796Ssam  * Melbourne getty.
1413796Ssam  */
1542668Smarc #define USE_OLD_TTY
1613796Ssam #include <sgtty.h>
17*60091Sbostic #include <string.h>
1846671Sbostic #include <unistd.h>
19*60091Sbostic 
2013796Ssam #include "gettytab.h"
21*60091Sbostic #include "extern.h"
2213796Ssam 
2313796Ssam extern	struct sgttyb tmode;
2413796Ssam extern	struct tchars tc;
2513796Ssam extern	struct ltchars ltc;
2613796Ssam 
2713796Ssam /*
2813796Ssam  * Get a table entry.
2913796Ssam  */
30*60091Sbostic void
3113796Ssam gettable(name, buf, area)
3213796Ssam 	char *name, *buf, *area;
3313796Ssam {
3413796Ssam 	register struct gettystrs *sp;
3513796Ssam 	register struct gettynums *np;
3613796Ssam 	register struct gettyflags *fp;
3713796Ssam 	register n;
3813796Ssam 
3913796Ssam 	hopcount = 0;		/* new lookup, start fresh */
4013796Ssam 	if (getent(buf, name) != 1)
4113796Ssam 		return;
4213796Ssam 
4313796Ssam 	for (sp = gettystrs; sp->field; sp++)
4413796Ssam 		sp->value = getstr(sp->field, &area);
4513796Ssam 	for (np = gettynums; np->field; np++) {
4613796Ssam 		n = getnum(np->field);
4713796Ssam 		if (n == -1)
4813796Ssam 			np->set = 0;
4913796Ssam 		else {
5013796Ssam 			np->set = 1;
5113796Ssam 			np->value = n;
5213796Ssam 		}
5313796Ssam 	}
5413796Ssam 	for (fp = gettyflags; fp->field; fp++) {
5513796Ssam 		n = getflag(fp->field);
5613796Ssam 		if (n == -1)
5713796Ssam 			fp->set = 0;
5813796Ssam 		else {
5913796Ssam 			fp->set = 1;
6013796Ssam 			fp->value = n ^ fp->invrt;
6113796Ssam 		}
6213796Ssam 	}
6313796Ssam }
6413796Ssam 
65*60091Sbostic void
6613796Ssam gendefaults()
6713796Ssam {
6813796Ssam 	register struct gettystrs *sp;
6913796Ssam 	register struct gettynums *np;
7013796Ssam 	register struct gettyflags *fp;
7113796Ssam 
7213796Ssam 	for (sp = gettystrs; sp->field; sp++)
7313796Ssam 		if (sp->value)
7413796Ssam 			sp->defalt = sp->value;
7513796Ssam 	for (np = gettynums; np->field; np++)
7613796Ssam 		if (np->set)
7713796Ssam 			np->defalt = np->value;
7813796Ssam 	for (fp = gettyflags; fp->field; fp++)
7913796Ssam 		if (fp->set)
8013796Ssam 			fp->defalt = fp->value;
8113796Ssam 		else
8213796Ssam 			fp->defalt = fp->invrt;
8313796Ssam }
8413796Ssam 
85*60091Sbostic void
8613796Ssam setdefaults()
8713796Ssam {
8813796Ssam 	register struct gettystrs *sp;
8913796Ssam 	register struct gettynums *np;
9013796Ssam 	register struct gettyflags *fp;
9113796Ssam 
9213796Ssam 	for (sp = gettystrs; sp->field; sp++)
9313796Ssam 		if (!sp->value)
9413796Ssam 			sp->value = sp->defalt;
9513796Ssam 	for (np = gettynums; np->field; np++)
9613796Ssam 		if (!np->set)
9713796Ssam 			np->value = np->defalt;
9813796Ssam 	for (fp = gettyflags; fp->field; fp++)
9913796Ssam 		if (!fp->set)
10013796Ssam 			fp->value = fp->defalt;
10113796Ssam }
10213796Ssam 
10313796Ssam static char **
10413796Ssam charnames[] = {
10513796Ssam 	&ER, &KL, &IN, &QU, &XN, &XF, &ET, &BK,
10613796Ssam 	&SU, &DS, &RP, &FL, &WE, &LN, 0
10713796Ssam };
10813796Ssam 
10913796Ssam static char *
11013796Ssam charvars[] = {
11113796Ssam 	&tmode.sg_erase, &tmode.sg_kill, &tc.t_intrc,
11213796Ssam 	&tc.t_quitc, &tc.t_startc, &tc.t_stopc,
11313796Ssam 	&tc.t_eofc, &tc.t_brkc, &ltc.t_suspc,
11413796Ssam 	&ltc.t_dsuspc, &ltc.t_rprntc, &ltc.t_flushc,
11513796Ssam 	&ltc.t_werasc, &ltc.t_lnextc, 0
11613796Ssam };
11713796Ssam 
118*60091Sbostic void
11913796Ssam setchars()
12013796Ssam {
12113796Ssam 	register int i;
12213796Ssam 	register char *p;
12313796Ssam 
12413796Ssam 	for (i = 0; charnames[i]; i++) {
12513796Ssam 		p = *charnames[i];
12613796Ssam 		if (p && *p)
12713796Ssam 			*charvars[i] = *p;
12813796Ssam 		else
12919946Sedward 			*charvars[i] = '\377';
13013796Ssam 	}
13113796Ssam }
13213796Ssam 
13313796Ssam long
13413796Ssam setflags(n)
135*60091Sbostic 	int n;
13613796Ssam {
13713796Ssam 	register long f;
13813796Ssam 
13913796Ssam 	switch (n) {
14013796Ssam 	case 0:
14113796Ssam 		if (F0set)
14213796Ssam 			return(F0);
14313796Ssam 		break;
14413796Ssam 	case 1:
14513796Ssam 		if (F1set)
14613796Ssam 			return(F1);
14713796Ssam 		break;
14813796Ssam 	default:
14913796Ssam 		if (F2set)
15013796Ssam 			return(F2);
15113796Ssam 		break;
15213796Ssam 	}
15313796Ssam 
15413796Ssam 	f = 0;
15513796Ssam 
15613796Ssam 	if (AP)
15713796Ssam 		f |= ANYP;
15813796Ssam 	else if (OP)
15913796Ssam 		f |= ODDP;
16013796Ssam 	else if (EP)
16113796Ssam 		f |= EVENP;
16213796Ssam 
16313796Ssam 	if (UC)
16413796Ssam 		f |= LCASE;
16513796Ssam 
16613796Ssam 	if (NL)
16713796Ssam 		f |= CRMOD;
16813796Ssam 
16913796Ssam 	f |= delaybits();
17013796Ssam 
17113796Ssam 	if (n == 1) {		/* read mode flags */
17213796Ssam 		if (RW)
17313796Ssam 			f |= RAW;
17413796Ssam 		else
17513796Ssam 			f |= CBREAK;
17613796Ssam 		return (f);
17713796Ssam 	}
17813796Ssam 
17913796Ssam 	if (!HT)
18013796Ssam 		f |= XTABS;
18113796Ssam 
18213796Ssam 	if (n == 0)
18313796Ssam 		return (f);
18413796Ssam 
18513796Ssam 	if (CB)
18613796Ssam 		f |= CRTBS;
18713796Ssam 
18813796Ssam 	if (CE)
18913796Ssam 		f |= CRTERA;
19013796Ssam 
19116565Sralph 	if (CK)
19216565Sralph 		f |= CRTKIL;
19316565Sralph 
19413796Ssam 	if (PE)
19513796Ssam 		f |= PRTERA;
19613796Ssam 
19713796Ssam 	if (EC)
19813796Ssam 		f |= ECHO;
19913796Ssam 
20013796Ssam 	if (XC)
20113796Ssam 		f |= CTLECH;
20213796Ssam 
20325730Smckusick 	if (DX)
20425730Smckusick 		f |= DECCTQ;
20525730Smckusick 
20613796Ssam 	return (f);
20713796Ssam }
20813796Ssam 
20913796Ssam struct delayval {
21013796Ssam 	unsigned	delay;		/* delay in ms */
21113796Ssam 	int		bits;
21213796Ssam };
21313796Ssam 
21413796Ssam /*
21513796Ssam  * below are random guesses, I can't be bothered checking
21613796Ssam  */
21713796Ssam 
21813796Ssam struct delayval	crdelay[] = {
219*60091Sbostic 	{ 1,		CR1 },
220*60091Sbostic 	{ 2,		CR2 },
221*60091Sbostic 	{ 3,		CR3 },
222*60091Sbostic 	{ 83,		CR1 },
223*60091Sbostic 	{ 166,		CR2 },
224*60091Sbostic 	{ 0,		CR3 },
22513796Ssam };
22613796Ssam 
22713796Ssam struct delayval nldelay[] = {
228*60091Sbostic 	{ 1,		NL1 },		/* special, calculated */
229*60091Sbostic 	{ 2,		NL2 },
230*60091Sbostic 	{ 3,		NL3 },
231*60091Sbostic 	{ 100,		NL2 },
232*60091Sbostic 	{ 0,		NL3 },
23313796Ssam };
23413796Ssam 
23513796Ssam struct delayval	bsdelay[] = {
236*60091Sbostic 	{ 1,		BS1 },
237*60091Sbostic 	{ 0,		0 },
23813796Ssam };
23913796Ssam 
24013796Ssam struct delayval	ffdelay[] = {
241*60091Sbostic 	{ 1,		FF1 },
242*60091Sbostic 	{ 1750,		FF1 },
243*60091Sbostic 	{ 0,		FF1 },
24413796Ssam };
24513796Ssam 
24613796Ssam struct delayval	tbdelay[] = {
247*60091Sbostic 	{ 1,		 TAB1 },
248*60091Sbostic 	{ 2,		 TAB2 },
249*60091Sbostic 	{ 3,		XTABS },	/* this is expand tabs */
250*60091Sbostic 	{ 100,		 TAB1 },
251*60091Sbostic 	{ 0,		 TAB2 },
25213796Ssam };
25313796Ssam 
254*60091Sbostic int
25513796Ssam delaybits()
25613796Ssam {
257*60091Sbostic 	register int f;
25813796Ssam 
25913796Ssam 	f  = adelay(CD, crdelay);
26013796Ssam 	f |= adelay(ND, nldelay);
26113796Ssam 	f |= adelay(FD, ffdelay);
26213796Ssam 	f |= adelay(TD, tbdelay);
26313796Ssam 	f |= adelay(BD, bsdelay);
26413796Ssam 	return (f);
26513796Ssam }
26613796Ssam 
267*60091Sbostic int
26813796Ssam adelay(ms, dp)
26913796Ssam 	register ms;
27013796Ssam 	register struct delayval *dp;
27113796Ssam {
27213796Ssam 	if (ms == 0)
27313796Ssam 		return (0);
27413796Ssam 	while (dp->delay && ms > dp->delay)
27513796Ssam 		dp++;
27613796Ssam 	return (dp->bits);
27713796Ssam }
27813796Ssam 
27913796Ssam char	editedhost[32];
28013796Ssam 
281*60091Sbostic void
28213796Ssam edithost(pat)
28313796Ssam 	register char *pat;
28413796Ssam {
28513796Ssam 	register char *host = HN;
28613796Ssam 	register char *res = editedhost;
28713796Ssam 
28813796Ssam 	if (!pat)
28913796Ssam 		pat = "";
29013796Ssam 	while (*pat) {
29113796Ssam 		switch (*pat) {
29213796Ssam 
29313796Ssam 		case '#':
29413796Ssam 			if (*host)
29513796Ssam 				host++;
29613796Ssam 			break;
29713796Ssam 
29813796Ssam 		case '@':
29913796Ssam 			if (*host)
30013796Ssam 				*res++ = *host++;
30113796Ssam 			break;
30213796Ssam 
30313796Ssam 		default:
30413796Ssam 			*res++ = *pat;
30513796Ssam 			break;
30613796Ssam 
30713796Ssam 		}
30813796Ssam 		if (res == &editedhost[sizeof editedhost - 1]) {
30913796Ssam 			*res = '\0';
31013796Ssam 			return;
31113796Ssam 		}
31213796Ssam 		pat++;
31313796Ssam 	}
31413796Ssam 	if (*host)
31513796Ssam 		strncpy(res, host, sizeof editedhost - (res - editedhost) - 1);
31613796Ssam 	else
31713796Ssam 		*res = '\0';
31813796Ssam 	editedhost[sizeof editedhost - 1] = '\0';
31913796Ssam }
32013796Ssam 
32113796Ssam struct speedtab {
32213796Ssam 	int	speed;
32313796Ssam 	int	uxname;
32413796Ssam } speedtab[] = {
325*60091Sbostic 	{ 50,	  B50 },
326*60091Sbostic 	{ 75,	  B75 },
327*60091Sbostic 	{ 110,	 B110 },
328*60091Sbostic 	{ 134,	 B134 },
329*60091Sbostic 	{ 150,	 B150 },
330*60091Sbostic 	{ 200,	 B200 },
331*60091Sbostic 	{ 300,	 B300 },
332*60091Sbostic 	{ 600,	 B600 },
333*60091Sbostic 	{ 1200,	B1200 },
334*60091Sbostic 	{ 1800,	B1800 },
335*60091Sbostic 	{ 2400,	B2400 },
336*60091Sbostic 	{ 4800,	B4800 },
337*60091Sbostic 	{ 9600,	B9600 },
338*60091Sbostic 	{ 19200, EXTA },
339*60091Sbostic 	{ 19,	 EXTA },	/* for people who say 19.2K */
340*60091Sbostic 	{ 38400, EXTB },
341*60091Sbostic 	{ 38,	 EXTB },
342*60091Sbostic 	{ 7200,	 EXTB },	/* alternative */
343*60091Sbostic 	{ 0 }
34413796Ssam };
34513796Ssam 
346*60091Sbostic int
34713796Ssam speed(val)
348*60091Sbostic 	int val;
34913796Ssam {
35013796Ssam 	register struct speedtab *sp;
35113796Ssam 
35213796Ssam 	if (val <= 15)
35317925Sralph 		return (val);
35413796Ssam 
35513796Ssam 	for (sp = speedtab; sp->speed; sp++)
35613796Ssam 		if (sp->speed == val)
35713796Ssam 			return (sp->uxname);
35813796Ssam 
35913796Ssam 	return (B300);		/* default in impossible cases */
36013796Ssam }
36113796Ssam 
362*60091Sbostic void
36313796Ssam makeenv(env)
36413796Ssam 	char *env[];
36513796Ssam {
36613796Ssam 	static char termbuf[128] = "TERM=";
36713796Ssam 	register char *p, *q;
36813796Ssam 	register char **ep;
36913796Ssam 
37013796Ssam 	ep = env;
37113796Ssam 	if (TT && *TT) {
37213796Ssam 		strcat(termbuf, TT);
37313796Ssam 		*ep++ = termbuf;
37413796Ssam 	}
37513796Ssam 	if (p = EV) {
37613796Ssam 		q = p;
377*60091Sbostic 		while (q = strchr(q, ',')) {
37813796Ssam 			*q++ = '\0';
37913796Ssam 			*ep++ = p;
38013796Ssam 			p = q;
38113796Ssam 		}
38213796Ssam 		if (*p)
38313796Ssam 			*ep++ = p;
38413796Ssam 	}
38513796Ssam 	*ep = (char *)0;
38613796Ssam }
38713796Ssam 
38813796Ssam /*
38913796Ssam  * This speed select mechanism is written for the Develcon DATASWITCH.
39013796Ssam  * The Develcon sends a string of the form "B{speed}\n" at a predefined
39113796Ssam  * baud rate. This string indicates the user's actual speed.
39213796Ssam  * The routine below returns the terminal type mapped from derived speed.
39313796Ssam  */
39413796Ssam struct	portselect {
39513796Ssam 	char	*ps_baud;
39613796Ssam 	char	*ps_type;
39713796Ssam } portspeeds[] = {
39813796Ssam 	{ "B110",	"std.110" },
39913796Ssam 	{ "B134",	"std.134" },
40013796Ssam 	{ "B150",	"std.150" },
40113796Ssam 	{ "B300",	"std.300" },
40213796Ssam 	{ "B600",	"std.600" },
40313796Ssam 	{ "B1200",	"std.1200" },
40413796Ssam 	{ "B2400",	"std.2400" },
40513796Ssam 	{ "B4800",	"std.4800" },
40613796Ssam 	{ "B9600",	"std.9600" },
40725233Smckusick 	{ "B19200",	"std.19200" },
40813796Ssam 	{ 0 }
40913796Ssam };
41013796Ssam 
41113796Ssam char *
41213796Ssam portselector()
41313796Ssam {
41413796Ssam 	char c, baud[20], *type = "default";
41513796Ssam 	register struct portselect *ps;
41613796Ssam 	int len;
41713796Ssam 
41813796Ssam 	alarm(5*60);
41913796Ssam 	for (len = 0; len < sizeof (baud) - 1; len++) {
42046690Sbostic 		if (read(STDIN_FILENO, &c, 1) <= 0)
42113796Ssam 			break;
42213796Ssam 		c &= 0177;
42313796Ssam 		if (c == '\n' || c == '\r')
42413796Ssam 			break;
42513796Ssam 		if (c == 'B')
42613796Ssam 			len = 0;	/* in case of leading garbage */
42713796Ssam 		baud[len] = c;
42813796Ssam 	}
42913796Ssam 	baud[len] = '\0';
43013796Ssam 	for (ps = portspeeds; ps->ps_baud; ps++)
43113796Ssam 		if (strcmp(ps->ps_baud, baud) == 0) {
43213796Ssam 			type = ps->ps_type;
43313796Ssam 			break;
43413796Ssam 		}
43513796Ssam 	sleep(2);	/* wait for connection to complete */
43613796Ssam 	return (type);
43713796Ssam }
43817925Sralph 
43917925Sralph /*
44017925Sralph  * This auto-baud speed select mechanism is written for the Micom 600
44117925Sralph  * portselector. Selection is done by looking at how the character '\r'
44217925Sralph  * is garbled at the different speeds.
44317925Sralph  */
44417925Sralph #include <sys/time.h>
44517925Sralph 
44617925Sralph char *
44717925Sralph autobaud()
44817925Sralph {
44917925Sralph 	int rfds;
45017925Sralph 	struct timeval timeout;
45117925Sralph 	char c, *type = "9600-baud";
45217925Sralph 	int null = 0;
45317925Sralph 
45417925Sralph 	ioctl(0, TIOCFLUSH, &null);
45517925Sralph 	rfds = 1 << 0;
45617925Sralph 	timeout.tv_sec = 5;
45717925Sralph 	timeout.tv_usec = 0;
45846689Sbostic 	if (select(32, (fd_set *)&rfds, (fd_set *)NULL,
45946689Sbostic 	    (fd_set *)NULL, &timeout) <= 0)
46017925Sralph 		return (type);
46146690Sbostic 	if (read(STDIN_FILENO, &c, sizeof(char)) != sizeof(char))
46217925Sralph 		return (type);
46317925Sralph 	timeout.tv_sec = 0;
46417925Sralph 	timeout.tv_usec = 20;
46546689Sbostic 	(void) select(32, (fd_set *)NULL, (fd_set *)NULL,
46646689Sbostic 	    (fd_set *)NULL, &timeout);
46717925Sralph 	ioctl(0, TIOCFLUSH, &null);
46817925Sralph 	switch (c & 0377) {
46917925Sralph 
47017925Sralph 	case 0200:		/* 300-baud */
47117925Sralph 		type = "300-baud";
47217925Sralph 		break;
47317925Sralph 
47417925Sralph 	case 0346:		/* 1200-baud */
47517925Sralph 		type = "1200-baud";
47617925Sralph 		break;
47717925Sralph 
47817925Sralph 	case  015:		/* 2400-baud */
47917925Sralph 	case 0215:
48017925Sralph 		type = "2400-baud";
48117925Sralph 		break;
48217925Sralph 
48317925Sralph 	default:		/* 4800-baud */
48417925Sralph 		type = "4800-baud";
48517925Sralph 		break;
48617925Sralph 
48717925Sralph 	case 0377:		/* 9600-baud */
48817925Sralph 		type = "9600-baud";
48917925Sralph 		break;
49017925Sralph 	}
49117925Sralph 	return (type);
49217925Sralph }
493