xref: /csrg-svn/libexec/getty/subr.c (revision 61431)
119061Sdist /*
2*61431Sbostic  * Copyright (c) 1983, 1993
3*61431Sbostic  *	The Regents of the University of California.  All rights reserved.
436930Sbostic  *
542670Sbostic  * %sccs.include.redist.c%
619061Sdist  */
719061Sdist 
813796Ssam #ifndef lint
9*61431Sbostic static char sccsid[] = "@(#)subr.c	8.1 (Berkeley) 06/04/93";
1036930Sbostic #endif /* not lint */
1113796Ssam 
1213796Ssam /*
1313796Ssam  * Melbourne getty.
1413796Ssam  */
1542668Smarc #define USE_OLD_TTY
1660499Selan #include <stdlib.h>
1713796Ssam #include <sgtty.h>
1860091Sbostic #include <string.h>
1946671Sbostic #include <unistd.h>
2060091Sbostic 
2113796Ssam #include "gettytab.h"
2260091Sbostic #include "extern.h"
2360499Selan #include "pathnames.h"
2413796Ssam 
2513796Ssam extern	struct sgttyb tmode;
2613796Ssam extern	struct tchars tc;
2713796Ssam extern	struct ltchars ltc;
2813796Ssam 
2913796Ssam /*
3013796Ssam  * Get a table entry.
3113796Ssam  */
3260091Sbostic void
gettable(name,buf)3360499Selan gettable(name, buf)
3460499Selan 	char *name, *buf;
3513796Ssam {
3613796Ssam 	register struct gettystrs *sp;
3713796Ssam 	register struct gettynums *np;
3813796Ssam 	register struct gettyflags *fp;
3960499Selan 	long n;
4060499Selan 	char *dba[2];
4160499Selan 	dba[0] = _PATH_GETTYTAB;
4260499Selan 	dba[1] = 0;
4313796Ssam 
4460499Selan 	if (cgetent(&buf, dba, name) != 0)
4513796Ssam 		return;
4613796Ssam 
4760499Selan 	for (sp = gettystrs; sp->field; sp++)
4860499Selan 		cgetstr(buf, sp->field, &sp->value);
4913796Ssam 	for (np = gettynums; np->field; np++) {
5060499Selan 		if (cgetnum(buf, np->field, &n) == -1)
5113796Ssam 			np->set = 0;
5213796Ssam 		else {
5313796Ssam 			np->set = 1;
5413796Ssam 			np->value = n;
5513796Ssam 		}
5613796Ssam 	}
5713796Ssam 	for (fp = gettyflags; fp->field; fp++) {
5860499Selan 		if (cgetcap(buf, fp->field, ':') == NULL)
5913796Ssam 			fp->set = 0;
6013796Ssam 		else {
6113796Ssam 			fp->set = 1;
6260499Selan 			fp->value = 1 ^ fp->invrt;
6313796Ssam 		}
6413796Ssam 	}
6560499Selan #ifdef DEBUG
6660499Selan 	printf("name=\"%s\", buf=\"%s\"\n", name, buf);
6760499Selan 	for (sp = gettystrs; sp->field; sp++)
6860499Selan 		printf("cgetstr: %s=%s\n", sp->field, sp->value);
6960499Selan 	for (np = gettynums; np->field; np++)
7060499Selan 		printf("cgetnum: %s=%d\n", np->field, np->value);
7160499Selan 	for (fp = gettyflags; fp->field; fp++)
7260499Selan 		printf("cgetflags: %s='%c' set='%c'\n", fp->field,
7360499Selan 		       fp->value + '0', fp->set + '0');
7460499Selan 	exit(1);
7560499Selan #endif /* DEBUG */
7613796Ssam }
7713796Ssam 
7860091Sbostic void
gendefaults()7913796Ssam gendefaults()
8013796Ssam {
8113796Ssam 	register struct gettystrs *sp;
8213796Ssam 	register struct gettynums *np;
8313796Ssam 	register struct gettyflags *fp;
8413796Ssam 
8513796Ssam 	for (sp = gettystrs; sp->field; sp++)
8613796Ssam 		if (sp->value)
8713796Ssam 			sp->defalt = sp->value;
8813796Ssam 	for (np = gettynums; np->field; np++)
8913796Ssam 		if (np->set)
9013796Ssam 			np->defalt = np->value;
9113796Ssam 	for (fp = gettyflags; fp->field; fp++)
9213796Ssam 		if (fp->set)
9313796Ssam 			fp->defalt = fp->value;
9413796Ssam 		else
9513796Ssam 			fp->defalt = fp->invrt;
9613796Ssam }
9713796Ssam 
9860091Sbostic void
setdefaults()9913796Ssam setdefaults()
10013796Ssam {
10113796Ssam 	register struct gettystrs *sp;
10213796Ssam 	register struct gettynums *np;
10313796Ssam 	register struct gettyflags *fp;
10413796Ssam 
10513796Ssam 	for (sp = gettystrs; sp->field; sp++)
10613796Ssam 		if (!sp->value)
10713796Ssam 			sp->value = sp->defalt;
10813796Ssam 	for (np = gettynums; np->field; np++)
10913796Ssam 		if (!np->set)
11013796Ssam 			np->value = np->defalt;
11113796Ssam 	for (fp = gettyflags; fp->field; fp++)
11213796Ssam 		if (!fp->set)
11313796Ssam 			fp->value = fp->defalt;
11413796Ssam }
11513796Ssam 
11613796Ssam static char **
11713796Ssam charnames[] = {
11813796Ssam 	&ER, &KL, &IN, &QU, &XN, &XF, &ET, &BK,
11913796Ssam 	&SU, &DS, &RP, &FL, &WE, &LN, 0
12013796Ssam };
12113796Ssam 
12213796Ssam static char *
12313796Ssam charvars[] = {
12413796Ssam 	&tmode.sg_erase, &tmode.sg_kill, &tc.t_intrc,
12513796Ssam 	&tc.t_quitc, &tc.t_startc, &tc.t_stopc,
12613796Ssam 	&tc.t_eofc, &tc.t_brkc, &ltc.t_suspc,
12713796Ssam 	&ltc.t_dsuspc, &ltc.t_rprntc, &ltc.t_flushc,
12813796Ssam 	&ltc.t_werasc, &ltc.t_lnextc, 0
12913796Ssam };
13013796Ssam 
13160091Sbostic void
setchars()13213796Ssam setchars()
13313796Ssam {
13413796Ssam 	register int i;
13513796Ssam 	register char *p;
13613796Ssam 
13713796Ssam 	for (i = 0; charnames[i]; i++) {
13813796Ssam 		p = *charnames[i];
13913796Ssam 		if (p && *p)
14013796Ssam 			*charvars[i] = *p;
14113796Ssam 		else
14219946Sedward 			*charvars[i] = '\377';
14313796Ssam 	}
14413796Ssam }
14513796Ssam 
14613796Ssam long
setflags(n)14713796Ssam setflags(n)
14860091Sbostic 	int n;
14913796Ssam {
15013796Ssam 	register long f;
15113796Ssam 
15213796Ssam 	switch (n) {
15313796Ssam 	case 0:
15413796Ssam 		if (F0set)
15513796Ssam 			return(F0);
15613796Ssam 		break;
15713796Ssam 	case 1:
15813796Ssam 		if (F1set)
15913796Ssam 			return(F1);
16013796Ssam 		break;
16113796Ssam 	default:
16213796Ssam 		if (F2set)
16313796Ssam 			return(F2);
16413796Ssam 		break;
16513796Ssam 	}
16613796Ssam 
16713796Ssam 	f = 0;
16813796Ssam 
16913796Ssam 	if (AP)
17013796Ssam 		f |= ANYP;
17113796Ssam 	else if (OP)
17213796Ssam 		f |= ODDP;
17313796Ssam 	else if (EP)
17413796Ssam 		f |= EVENP;
17513796Ssam 
17613796Ssam 	if (UC)
17713796Ssam 		f |= LCASE;
17813796Ssam 
17913796Ssam 	if (NL)
18013796Ssam 		f |= CRMOD;
18113796Ssam 
18213796Ssam 	f |= delaybits();
18313796Ssam 
18413796Ssam 	if (n == 1) {		/* read mode flags */
18513796Ssam 		if (RW)
18613796Ssam 			f |= RAW;
18713796Ssam 		else
18813796Ssam 			f |= CBREAK;
18913796Ssam 		return (f);
19013796Ssam 	}
19113796Ssam 
19213796Ssam 	if (!HT)
19313796Ssam 		f |= XTABS;
19413796Ssam 
19513796Ssam 	if (n == 0)
19613796Ssam 		return (f);
19713796Ssam 
19813796Ssam 	if (CB)
19913796Ssam 		f |= CRTBS;
20013796Ssam 
20113796Ssam 	if (CE)
20213796Ssam 		f |= CRTERA;
20313796Ssam 
20416565Sralph 	if (CK)
20516565Sralph 		f |= CRTKIL;
20616565Sralph 
20713796Ssam 	if (PE)
20813796Ssam 		f |= PRTERA;
20913796Ssam 
21013796Ssam 	if (EC)
21113796Ssam 		f |= ECHO;
21213796Ssam 
21313796Ssam 	if (XC)
21413796Ssam 		f |= CTLECH;
21513796Ssam 
21625730Smckusick 	if (DX)
21725730Smckusick 		f |= DECCTQ;
21825730Smckusick 
21913796Ssam 	return (f);
22013796Ssam }
22113796Ssam 
22213796Ssam struct delayval {
22313796Ssam 	unsigned	delay;		/* delay in ms */
22413796Ssam 	int		bits;
22513796Ssam };
22613796Ssam 
22713796Ssam /*
22813796Ssam  * below are random guesses, I can't be bothered checking
22913796Ssam  */
23013796Ssam 
23113796Ssam struct delayval	crdelay[] = {
23260091Sbostic 	{ 1,		CR1 },
23360091Sbostic 	{ 2,		CR2 },
23460091Sbostic 	{ 3,		CR3 },
23560091Sbostic 	{ 83,		CR1 },
23660091Sbostic 	{ 166,		CR2 },
23760091Sbostic 	{ 0,		CR3 },
23813796Ssam };
23913796Ssam 
24013796Ssam struct delayval nldelay[] = {
24160091Sbostic 	{ 1,		NL1 },		/* special, calculated */
24260091Sbostic 	{ 2,		NL2 },
24360091Sbostic 	{ 3,		NL3 },
24460091Sbostic 	{ 100,		NL2 },
24560091Sbostic 	{ 0,		NL3 },
24613796Ssam };
24713796Ssam 
24813796Ssam struct delayval	bsdelay[] = {
24960091Sbostic 	{ 1,		BS1 },
25060091Sbostic 	{ 0,		0 },
25113796Ssam };
25213796Ssam 
25313796Ssam struct delayval	ffdelay[] = {
25460091Sbostic 	{ 1,		FF1 },
25560091Sbostic 	{ 1750,		FF1 },
25660091Sbostic 	{ 0,		FF1 },
25713796Ssam };
25813796Ssam 
25913796Ssam struct delayval	tbdelay[] = {
26060091Sbostic 	{ 1,		 TAB1 },
26160091Sbostic 	{ 2,		 TAB2 },
26260091Sbostic 	{ 3,		XTABS },	/* this is expand tabs */
26360091Sbostic 	{ 100,		 TAB1 },
26460091Sbostic 	{ 0,		 TAB2 },
26513796Ssam };
26613796Ssam 
26760091Sbostic int
delaybits()26813796Ssam delaybits()
26913796Ssam {
27060091Sbostic 	register int f;
27113796Ssam 
27213796Ssam 	f  = adelay(CD, crdelay);
27313796Ssam 	f |= adelay(ND, nldelay);
27413796Ssam 	f |= adelay(FD, ffdelay);
27513796Ssam 	f |= adelay(TD, tbdelay);
27613796Ssam 	f |= adelay(BD, bsdelay);
27713796Ssam 	return (f);
27813796Ssam }
27913796Ssam 
28060091Sbostic int
adelay(ms,dp)28113796Ssam adelay(ms, dp)
28213796Ssam 	register ms;
28313796Ssam 	register struct delayval *dp;
28413796Ssam {
28513796Ssam 	if (ms == 0)
28613796Ssam 		return (0);
28713796Ssam 	while (dp->delay && ms > dp->delay)
28813796Ssam 		dp++;
28913796Ssam 	return (dp->bits);
29013796Ssam }
29113796Ssam 
29213796Ssam char	editedhost[32];
29313796Ssam 
29460091Sbostic void
edithost(pat)29513796Ssam edithost(pat)
29613796Ssam 	register char *pat;
29713796Ssam {
29813796Ssam 	register char *host = HN;
29913796Ssam 	register char *res = editedhost;
30013796Ssam 
30113796Ssam 	if (!pat)
30213796Ssam 		pat = "";
30313796Ssam 	while (*pat) {
30413796Ssam 		switch (*pat) {
30513796Ssam 
30613796Ssam 		case '#':
30713796Ssam 			if (*host)
30813796Ssam 				host++;
30913796Ssam 			break;
31013796Ssam 
31113796Ssam 		case '@':
31213796Ssam 			if (*host)
31313796Ssam 				*res++ = *host++;
31413796Ssam 			break;
31513796Ssam 
31613796Ssam 		default:
31713796Ssam 			*res++ = *pat;
31813796Ssam 			break;
31913796Ssam 
32013796Ssam 		}
32113796Ssam 		if (res == &editedhost[sizeof editedhost - 1]) {
32213796Ssam 			*res = '\0';
32313796Ssam 			return;
32413796Ssam 		}
32513796Ssam 		pat++;
32613796Ssam 	}
32713796Ssam 	if (*host)
32813796Ssam 		strncpy(res, host, sizeof editedhost - (res - editedhost) - 1);
32913796Ssam 	else
33013796Ssam 		*res = '\0';
33113796Ssam 	editedhost[sizeof editedhost - 1] = '\0';
33213796Ssam }
33313796Ssam 
33413796Ssam struct speedtab {
33513796Ssam 	int	speed;
33613796Ssam 	int	uxname;
33713796Ssam } speedtab[] = {
33860091Sbostic 	{ 50,	  B50 },
33960091Sbostic 	{ 75,	  B75 },
34060091Sbostic 	{ 110,	 B110 },
34160091Sbostic 	{ 134,	 B134 },
34260091Sbostic 	{ 150,	 B150 },
34360091Sbostic 	{ 200,	 B200 },
34460091Sbostic 	{ 300,	 B300 },
34560091Sbostic 	{ 600,	 B600 },
34660091Sbostic 	{ 1200,	B1200 },
34760091Sbostic 	{ 1800,	B1800 },
34860091Sbostic 	{ 2400,	B2400 },
34960091Sbostic 	{ 4800,	B4800 },
35060091Sbostic 	{ 9600,	B9600 },
35160091Sbostic 	{ 19200, EXTA },
35260091Sbostic 	{ 19,	 EXTA },	/* for people who say 19.2K */
35360091Sbostic 	{ 38400, EXTB },
35460091Sbostic 	{ 38,	 EXTB },
35560091Sbostic 	{ 7200,	 EXTB },	/* alternative */
35660091Sbostic 	{ 0 }
35713796Ssam };
35813796Ssam 
35960091Sbostic int
speed(val)36013796Ssam speed(val)
36160091Sbostic 	int val;
36213796Ssam {
36313796Ssam 	register struct speedtab *sp;
36413796Ssam 
36513796Ssam 	if (val <= 15)
36617925Sralph 		return (val);
36713796Ssam 
36813796Ssam 	for (sp = speedtab; sp->speed; sp++)
36913796Ssam 		if (sp->speed == val)
37013796Ssam 			return (sp->uxname);
37113796Ssam 
37213796Ssam 	return (B300);		/* default in impossible cases */
37313796Ssam }
37413796Ssam 
37560091Sbostic void
makeenv(env)37613796Ssam makeenv(env)
37713796Ssam 	char *env[];
37813796Ssam {
37913796Ssam 	static char termbuf[128] = "TERM=";
38013796Ssam 	register char *p, *q;
38113796Ssam 	register char **ep;
38213796Ssam 
38313796Ssam 	ep = env;
38413796Ssam 	if (TT && *TT) {
38513796Ssam 		strcat(termbuf, TT);
38613796Ssam 		*ep++ = termbuf;
38713796Ssam 	}
38813796Ssam 	if (p = EV) {
38913796Ssam 		q = p;
39060091Sbostic 		while (q = strchr(q, ',')) {
39113796Ssam 			*q++ = '\0';
39213796Ssam 			*ep++ = p;
39313796Ssam 			p = q;
39413796Ssam 		}
39513796Ssam 		if (*p)
39613796Ssam 			*ep++ = p;
39713796Ssam 	}
39813796Ssam 	*ep = (char *)0;
39913796Ssam }
40013796Ssam 
40113796Ssam /*
40213796Ssam  * This speed select mechanism is written for the Develcon DATASWITCH.
40313796Ssam  * The Develcon sends a string of the form "B{speed}\n" at a predefined
40413796Ssam  * baud rate. This string indicates the user's actual speed.
40513796Ssam  * The routine below returns the terminal type mapped from derived speed.
40613796Ssam  */
40713796Ssam struct	portselect {
40813796Ssam 	char	*ps_baud;
40913796Ssam 	char	*ps_type;
41013796Ssam } portspeeds[] = {
41113796Ssam 	{ "B110",	"std.110" },
41213796Ssam 	{ "B134",	"std.134" },
41313796Ssam 	{ "B150",	"std.150" },
41413796Ssam 	{ "B300",	"std.300" },
41513796Ssam 	{ "B600",	"std.600" },
41613796Ssam 	{ "B1200",	"std.1200" },
41713796Ssam 	{ "B2400",	"std.2400" },
41813796Ssam 	{ "B4800",	"std.4800" },
41913796Ssam 	{ "B9600",	"std.9600" },
42025233Smckusick 	{ "B19200",	"std.19200" },
42113796Ssam 	{ 0 }
42213796Ssam };
42313796Ssam 
42413796Ssam char *
portselector()42513796Ssam portselector()
42613796Ssam {
42713796Ssam 	char c, baud[20], *type = "default";
42813796Ssam 	register struct portselect *ps;
42913796Ssam 	int len;
43013796Ssam 
43113796Ssam 	alarm(5*60);
43213796Ssam 	for (len = 0; len < sizeof (baud) - 1; len++) {
43346690Sbostic 		if (read(STDIN_FILENO, &c, 1) <= 0)
43413796Ssam 			break;
43513796Ssam 		c &= 0177;
43613796Ssam 		if (c == '\n' || c == '\r')
43713796Ssam 			break;
43813796Ssam 		if (c == 'B')
43913796Ssam 			len = 0;	/* in case of leading garbage */
44013796Ssam 		baud[len] = c;
44113796Ssam 	}
44213796Ssam 	baud[len] = '\0';
44313796Ssam 	for (ps = portspeeds; ps->ps_baud; ps++)
44413796Ssam 		if (strcmp(ps->ps_baud, baud) == 0) {
44513796Ssam 			type = ps->ps_type;
44613796Ssam 			break;
44713796Ssam 		}
44813796Ssam 	sleep(2);	/* wait for connection to complete */
44913796Ssam 	return (type);
45013796Ssam }
45117925Sralph 
45217925Sralph /*
45317925Sralph  * This auto-baud speed select mechanism is written for the Micom 600
45417925Sralph  * portselector. Selection is done by looking at how the character '\r'
45517925Sralph  * is garbled at the different speeds.
45617925Sralph  */
45717925Sralph #include <sys/time.h>
45817925Sralph 
45917925Sralph char *
autobaud()46017925Sralph autobaud()
46117925Sralph {
46217925Sralph 	int rfds;
46317925Sralph 	struct timeval timeout;
46417925Sralph 	char c, *type = "9600-baud";
46517925Sralph 	int null = 0;
46617925Sralph 
46717925Sralph 	ioctl(0, TIOCFLUSH, &null);
46817925Sralph 	rfds = 1 << 0;
46917925Sralph 	timeout.tv_sec = 5;
47017925Sralph 	timeout.tv_usec = 0;
47146689Sbostic 	if (select(32, (fd_set *)&rfds, (fd_set *)NULL,
47246689Sbostic 	    (fd_set *)NULL, &timeout) <= 0)
47317925Sralph 		return (type);
47446690Sbostic 	if (read(STDIN_FILENO, &c, sizeof(char)) != sizeof(char))
47517925Sralph 		return (type);
47617925Sralph 	timeout.tv_sec = 0;
47717925Sralph 	timeout.tv_usec = 20;
47846689Sbostic 	(void) select(32, (fd_set *)NULL, (fd_set *)NULL,
47946689Sbostic 	    (fd_set *)NULL, &timeout);
48017925Sralph 	ioctl(0, TIOCFLUSH, &null);
48117925Sralph 	switch (c & 0377) {
48217925Sralph 
48317925Sralph 	case 0200:		/* 300-baud */
48417925Sralph 		type = "300-baud";
48517925Sralph 		break;
48617925Sralph 
48717925Sralph 	case 0346:		/* 1200-baud */
48817925Sralph 		type = "1200-baud";
48917925Sralph 		break;
49017925Sralph 
49117925Sralph 	case  015:		/* 2400-baud */
49217925Sralph 	case 0215:
49317925Sralph 		type = "2400-baud";
49417925Sralph 		break;
49517925Sralph 
49617925Sralph 	default:		/* 4800-baud */
49717925Sralph 		type = "4800-baud";
49817925Sralph 		break;
49917925Sralph 
50017925Sralph 	case 0377:		/* 9600-baud */
50117925Sralph 		type = "9600-baud";
50217925Sralph 		break;
50317925Sralph 	}
50417925Sralph 	return (type);
50517925Sralph }
506