xref: /csrg-svn/libexec/getty/subr.c (revision 60499)
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*60499Selan static char sccsid[] = "@(#)subr.c	5.12 (Berkeley) 05/27/93";
1036930Sbostic #endif /* not lint */
1113796Ssam 
1213796Ssam /*
1313796Ssam  * Melbourne getty.
1413796Ssam  */
1542668Smarc #define USE_OLD_TTY
16*60499Selan #include <stdlib.h>
1713796Ssam #include <sgtty.h>
1860091Sbostic #include <string.h>
1946671Sbostic #include <unistd.h>
2060091Sbostic 
2113796Ssam #include "gettytab.h"
2260091Sbostic #include "extern.h"
23*60499Selan #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
33*60499Selan gettable(name, buf)
34*60499Selan 	char *name, *buf;
3513796Ssam {
3613796Ssam 	register struct gettystrs *sp;
3713796Ssam 	register struct gettynums *np;
3813796Ssam 	register struct gettyflags *fp;
39*60499Selan 	long n;
40*60499Selan 	char *dba[2];
41*60499Selan 	dba[0] = _PATH_GETTYTAB;
42*60499Selan 	dba[1] = 0;
4313796Ssam 
44*60499Selan 	if (cgetent(&buf, dba, name) != 0)
4513796Ssam 		return;
4613796Ssam 
47*60499Selan 	for (sp = gettystrs; sp->field; sp++)
48*60499Selan 		cgetstr(buf, sp->field, &sp->value);
4913796Ssam 	for (np = gettynums; np->field; np++) {
50*60499Selan 		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++) {
58*60499Selan 		if (cgetcap(buf, fp->field, ':') == NULL)
5913796Ssam 			fp->set = 0;
6013796Ssam 		else {
6113796Ssam 			fp->set = 1;
62*60499Selan 			fp->value = 1 ^ fp->invrt;
6313796Ssam 		}
6413796Ssam 	}
65*60499Selan #define DEBUG
66*60499Selan #ifdef DEBUG
67*60499Selan 	printf("name=\"%s\", buf=\"%s\"\n", name, buf);
68*60499Selan 	for (sp = gettystrs; sp->field; sp++)
69*60499Selan 		printf("cgetstr: %s=%s\n", sp->field, sp->value);
70*60499Selan 	for (np = gettynums; np->field; np++)
71*60499Selan 		printf("cgetnum: %s=%d\n", np->field, np->value);
72*60499Selan 	for (fp = gettyflags; fp->field; fp++)
73*60499Selan 		printf("cgetflags: %s='%c' set='%c'\n", fp->field,
74*60499Selan 		       fp->value + '0', fp->set + '0');
75*60499Selan 	exit(1);
76*60499Selan #endif /* DEBUG */
7713796Ssam }
7813796Ssam 
7960091Sbostic void
8013796Ssam gendefaults()
8113796Ssam {
8213796Ssam 	register struct gettystrs *sp;
8313796Ssam 	register struct gettynums *np;
8413796Ssam 	register struct gettyflags *fp;
8513796Ssam 
8613796Ssam 	for (sp = gettystrs; sp->field; sp++)
8713796Ssam 		if (sp->value)
8813796Ssam 			sp->defalt = sp->value;
8913796Ssam 	for (np = gettynums; np->field; np++)
9013796Ssam 		if (np->set)
9113796Ssam 			np->defalt = np->value;
9213796Ssam 	for (fp = gettyflags; fp->field; fp++)
9313796Ssam 		if (fp->set)
9413796Ssam 			fp->defalt = fp->value;
9513796Ssam 		else
9613796Ssam 			fp->defalt = fp->invrt;
9713796Ssam }
9813796Ssam 
9960091Sbostic void
10013796Ssam setdefaults()
10113796Ssam {
10213796Ssam 	register struct gettystrs *sp;
10313796Ssam 	register struct gettynums *np;
10413796Ssam 	register struct gettyflags *fp;
10513796Ssam 
10613796Ssam 	for (sp = gettystrs; sp->field; sp++)
10713796Ssam 		if (!sp->value)
10813796Ssam 			sp->value = sp->defalt;
10913796Ssam 	for (np = gettynums; np->field; np++)
11013796Ssam 		if (!np->set)
11113796Ssam 			np->value = np->defalt;
11213796Ssam 	for (fp = gettyflags; fp->field; fp++)
11313796Ssam 		if (!fp->set)
11413796Ssam 			fp->value = fp->defalt;
11513796Ssam }
11613796Ssam 
11713796Ssam static char **
11813796Ssam charnames[] = {
11913796Ssam 	&ER, &KL, &IN, &QU, &XN, &XF, &ET, &BK,
12013796Ssam 	&SU, &DS, &RP, &FL, &WE, &LN, 0
12113796Ssam };
12213796Ssam 
12313796Ssam static char *
12413796Ssam charvars[] = {
12513796Ssam 	&tmode.sg_erase, &tmode.sg_kill, &tc.t_intrc,
12613796Ssam 	&tc.t_quitc, &tc.t_startc, &tc.t_stopc,
12713796Ssam 	&tc.t_eofc, &tc.t_brkc, &ltc.t_suspc,
12813796Ssam 	&ltc.t_dsuspc, &ltc.t_rprntc, &ltc.t_flushc,
12913796Ssam 	&ltc.t_werasc, &ltc.t_lnextc, 0
13013796Ssam };
13113796Ssam 
13260091Sbostic void
13313796Ssam setchars()
13413796Ssam {
13513796Ssam 	register int i;
13613796Ssam 	register char *p;
13713796Ssam 
13813796Ssam 	for (i = 0; charnames[i]; i++) {
13913796Ssam 		p = *charnames[i];
14013796Ssam 		if (p && *p)
14113796Ssam 			*charvars[i] = *p;
14213796Ssam 		else
14319946Sedward 			*charvars[i] = '\377';
14413796Ssam 	}
14513796Ssam }
14613796Ssam 
14713796Ssam long
14813796Ssam setflags(n)
14960091Sbostic 	int n;
15013796Ssam {
15113796Ssam 	register long f;
15213796Ssam 
15313796Ssam 	switch (n) {
15413796Ssam 	case 0:
15513796Ssam 		if (F0set)
15613796Ssam 			return(F0);
15713796Ssam 		break;
15813796Ssam 	case 1:
15913796Ssam 		if (F1set)
16013796Ssam 			return(F1);
16113796Ssam 		break;
16213796Ssam 	default:
16313796Ssam 		if (F2set)
16413796Ssam 			return(F2);
16513796Ssam 		break;
16613796Ssam 	}
16713796Ssam 
16813796Ssam 	f = 0;
16913796Ssam 
17013796Ssam 	if (AP)
17113796Ssam 		f |= ANYP;
17213796Ssam 	else if (OP)
17313796Ssam 		f |= ODDP;
17413796Ssam 	else if (EP)
17513796Ssam 		f |= EVENP;
17613796Ssam 
17713796Ssam 	if (UC)
17813796Ssam 		f |= LCASE;
17913796Ssam 
18013796Ssam 	if (NL)
18113796Ssam 		f |= CRMOD;
18213796Ssam 
18313796Ssam 	f |= delaybits();
18413796Ssam 
18513796Ssam 	if (n == 1) {		/* read mode flags */
18613796Ssam 		if (RW)
18713796Ssam 			f |= RAW;
18813796Ssam 		else
18913796Ssam 			f |= CBREAK;
19013796Ssam 		return (f);
19113796Ssam 	}
19213796Ssam 
19313796Ssam 	if (!HT)
19413796Ssam 		f |= XTABS;
19513796Ssam 
19613796Ssam 	if (n == 0)
19713796Ssam 		return (f);
19813796Ssam 
19913796Ssam 	if (CB)
20013796Ssam 		f |= CRTBS;
20113796Ssam 
20213796Ssam 	if (CE)
20313796Ssam 		f |= CRTERA;
20413796Ssam 
20516565Sralph 	if (CK)
20616565Sralph 		f |= CRTKIL;
20716565Sralph 
20813796Ssam 	if (PE)
20913796Ssam 		f |= PRTERA;
21013796Ssam 
21113796Ssam 	if (EC)
21213796Ssam 		f |= ECHO;
21313796Ssam 
21413796Ssam 	if (XC)
21513796Ssam 		f |= CTLECH;
21613796Ssam 
21725730Smckusick 	if (DX)
21825730Smckusick 		f |= DECCTQ;
21925730Smckusick 
22013796Ssam 	return (f);
22113796Ssam }
22213796Ssam 
22313796Ssam struct delayval {
22413796Ssam 	unsigned	delay;		/* delay in ms */
22513796Ssam 	int		bits;
22613796Ssam };
22713796Ssam 
22813796Ssam /*
22913796Ssam  * below are random guesses, I can't be bothered checking
23013796Ssam  */
23113796Ssam 
23213796Ssam struct delayval	crdelay[] = {
23360091Sbostic 	{ 1,		CR1 },
23460091Sbostic 	{ 2,		CR2 },
23560091Sbostic 	{ 3,		CR3 },
23660091Sbostic 	{ 83,		CR1 },
23760091Sbostic 	{ 166,		CR2 },
23860091Sbostic 	{ 0,		CR3 },
23913796Ssam };
24013796Ssam 
24113796Ssam struct delayval nldelay[] = {
24260091Sbostic 	{ 1,		NL1 },		/* special, calculated */
24360091Sbostic 	{ 2,		NL2 },
24460091Sbostic 	{ 3,		NL3 },
24560091Sbostic 	{ 100,		NL2 },
24660091Sbostic 	{ 0,		NL3 },
24713796Ssam };
24813796Ssam 
24913796Ssam struct delayval	bsdelay[] = {
25060091Sbostic 	{ 1,		BS1 },
25160091Sbostic 	{ 0,		0 },
25213796Ssam };
25313796Ssam 
25413796Ssam struct delayval	ffdelay[] = {
25560091Sbostic 	{ 1,		FF1 },
25660091Sbostic 	{ 1750,		FF1 },
25760091Sbostic 	{ 0,		FF1 },
25813796Ssam };
25913796Ssam 
26013796Ssam struct delayval	tbdelay[] = {
26160091Sbostic 	{ 1,		 TAB1 },
26260091Sbostic 	{ 2,		 TAB2 },
26360091Sbostic 	{ 3,		XTABS },	/* this is expand tabs */
26460091Sbostic 	{ 100,		 TAB1 },
26560091Sbostic 	{ 0,		 TAB2 },
26613796Ssam };
26713796Ssam 
26860091Sbostic int
26913796Ssam delaybits()
27013796Ssam {
27160091Sbostic 	register int f;
27213796Ssam 
27313796Ssam 	f  = adelay(CD, crdelay);
27413796Ssam 	f |= adelay(ND, nldelay);
27513796Ssam 	f |= adelay(FD, ffdelay);
27613796Ssam 	f |= adelay(TD, tbdelay);
27713796Ssam 	f |= adelay(BD, bsdelay);
27813796Ssam 	return (f);
27913796Ssam }
28013796Ssam 
28160091Sbostic int
28213796Ssam adelay(ms, dp)
28313796Ssam 	register ms;
28413796Ssam 	register struct delayval *dp;
28513796Ssam {
28613796Ssam 	if (ms == 0)
28713796Ssam 		return (0);
28813796Ssam 	while (dp->delay && ms > dp->delay)
28913796Ssam 		dp++;
29013796Ssam 	return (dp->bits);
29113796Ssam }
29213796Ssam 
29313796Ssam char	editedhost[32];
29413796Ssam 
29560091Sbostic void
29613796Ssam edithost(pat)
29713796Ssam 	register char *pat;
29813796Ssam {
29913796Ssam 	register char *host = HN;
30013796Ssam 	register char *res = editedhost;
30113796Ssam 
30213796Ssam 	if (!pat)
30313796Ssam 		pat = "";
30413796Ssam 	while (*pat) {
30513796Ssam 		switch (*pat) {
30613796Ssam 
30713796Ssam 		case '#':
30813796Ssam 			if (*host)
30913796Ssam 				host++;
31013796Ssam 			break;
31113796Ssam 
31213796Ssam 		case '@':
31313796Ssam 			if (*host)
31413796Ssam 				*res++ = *host++;
31513796Ssam 			break;
31613796Ssam 
31713796Ssam 		default:
31813796Ssam 			*res++ = *pat;
31913796Ssam 			break;
32013796Ssam 
32113796Ssam 		}
32213796Ssam 		if (res == &editedhost[sizeof editedhost - 1]) {
32313796Ssam 			*res = '\0';
32413796Ssam 			return;
32513796Ssam 		}
32613796Ssam 		pat++;
32713796Ssam 	}
32813796Ssam 	if (*host)
32913796Ssam 		strncpy(res, host, sizeof editedhost - (res - editedhost) - 1);
33013796Ssam 	else
33113796Ssam 		*res = '\0';
33213796Ssam 	editedhost[sizeof editedhost - 1] = '\0';
33313796Ssam }
33413796Ssam 
33513796Ssam struct speedtab {
33613796Ssam 	int	speed;
33713796Ssam 	int	uxname;
33813796Ssam } speedtab[] = {
33960091Sbostic 	{ 50,	  B50 },
34060091Sbostic 	{ 75,	  B75 },
34160091Sbostic 	{ 110,	 B110 },
34260091Sbostic 	{ 134,	 B134 },
34360091Sbostic 	{ 150,	 B150 },
34460091Sbostic 	{ 200,	 B200 },
34560091Sbostic 	{ 300,	 B300 },
34660091Sbostic 	{ 600,	 B600 },
34760091Sbostic 	{ 1200,	B1200 },
34860091Sbostic 	{ 1800,	B1800 },
34960091Sbostic 	{ 2400,	B2400 },
35060091Sbostic 	{ 4800,	B4800 },
35160091Sbostic 	{ 9600,	B9600 },
35260091Sbostic 	{ 19200, EXTA },
35360091Sbostic 	{ 19,	 EXTA },	/* for people who say 19.2K */
35460091Sbostic 	{ 38400, EXTB },
35560091Sbostic 	{ 38,	 EXTB },
35660091Sbostic 	{ 7200,	 EXTB },	/* alternative */
35760091Sbostic 	{ 0 }
35813796Ssam };
35913796Ssam 
36060091Sbostic int
36113796Ssam speed(val)
36260091Sbostic 	int val;
36313796Ssam {
36413796Ssam 	register struct speedtab *sp;
36513796Ssam 
36613796Ssam 	if (val <= 15)
36717925Sralph 		return (val);
36813796Ssam 
36913796Ssam 	for (sp = speedtab; sp->speed; sp++)
37013796Ssam 		if (sp->speed == val)
37113796Ssam 			return (sp->uxname);
37213796Ssam 
37313796Ssam 	return (B300);		/* default in impossible cases */
37413796Ssam }
37513796Ssam 
37660091Sbostic void
37713796Ssam makeenv(env)
37813796Ssam 	char *env[];
37913796Ssam {
38013796Ssam 	static char termbuf[128] = "TERM=";
38113796Ssam 	register char *p, *q;
38213796Ssam 	register char **ep;
38313796Ssam 
38413796Ssam 	ep = env;
38513796Ssam 	if (TT && *TT) {
38613796Ssam 		strcat(termbuf, TT);
38713796Ssam 		*ep++ = termbuf;
38813796Ssam 	}
38913796Ssam 	if (p = EV) {
39013796Ssam 		q = p;
39160091Sbostic 		while (q = strchr(q, ',')) {
39213796Ssam 			*q++ = '\0';
39313796Ssam 			*ep++ = p;
39413796Ssam 			p = q;
39513796Ssam 		}
39613796Ssam 		if (*p)
39713796Ssam 			*ep++ = p;
39813796Ssam 	}
39913796Ssam 	*ep = (char *)0;
40013796Ssam }
40113796Ssam 
40213796Ssam /*
40313796Ssam  * This speed select mechanism is written for the Develcon DATASWITCH.
40413796Ssam  * The Develcon sends a string of the form "B{speed}\n" at a predefined
40513796Ssam  * baud rate. This string indicates the user's actual speed.
40613796Ssam  * The routine below returns the terminal type mapped from derived speed.
40713796Ssam  */
40813796Ssam struct	portselect {
40913796Ssam 	char	*ps_baud;
41013796Ssam 	char	*ps_type;
41113796Ssam } portspeeds[] = {
41213796Ssam 	{ "B110",	"std.110" },
41313796Ssam 	{ "B134",	"std.134" },
41413796Ssam 	{ "B150",	"std.150" },
41513796Ssam 	{ "B300",	"std.300" },
41613796Ssam 	{ "B600",	"std.600" },
41713796Ssam 	{ "B1200",	"std.1200" },
41813796Ssam 	{ "B2400",	"std.2400" },
41913796Ssam 	{ "B4800",	"std.4800" },
42013796Ssam 	{ "B9600",	"std.9600" },
42125233Smckusick 	{ "B19200",	"std.19200" },
42213796Ssam 	{ 0 }
42313796Ssam };
42413796Ssam 
42513796Ssam char *
42613796Ssam portselector()
42713796Ssam {
42813796Ssam 	char c, baud[20], *type = "default";
42913796Ssam 	register struct portselect *ps;
43013796Ssam 	int len;
43113796Ssam 
43213796Ssam 	alarm(5*60);
43313796Ssam 	for (len = 0; len < sizeof (baud) - 1; len++) {
43446690Sbostic 		if (read(STDIN_FILENO, &c, 1) <= 0)
43513796Ssam 			break;
43613796Ssam 		c &= 0177;
43713796Ssam 		if (c == '\n' || c == '\r')
43813796Ssam 			break;
43913796Ssam 		if (c == 'B')
44013796Ssam 			len = 0;	/* in case of leading garbage */
44113796Ssam 		baud[len] = c;
44213796Ssam 	}
44313796Ssam 	baud[len] = '\0';
44413796Ssam 	for (ps = portspeeds; ps->ps_baud; ps++)
44513796Ssam 		if (strcmp(ps->ps_baud, baud) == 0) {
44613796Ssam 			type = ps->ps_type;
44713796Ssam 			break;
44813796Ssam 		}
44913796Ssam 	sleep(2);	/* wait for connection to complete */
45013796Ssam 	return (type);
45113796Ssam }
45217925Sralph 
45317925Sralph /*
45417925Sralph  * This auto-baud speed select mechanism is written for the Micom 600
45517925Sralph  * portselector. Selection is done by looking at how the character '\r'
45617925Sralph  * is garbled at the different speeds.
45717925Sralph  */
45817925Sralph #include <sys/time.h>
45917925Sralph 
46017925Sralph char *
46117925Sralph autobaud()
46217925Sralph {
46317925Sralph 	int rfds;
46417925Sralph 	struct timeval timeout;
46517925Sralph 	char c, *type = "9600-baud";
46617925Sralph 	int null = 0;
46717925Sralph 
46817925Sralph 	ioctl(0, TIOCFLUSH, &null);
46917925Sralph 	rfds = 1 << 0;
47017925Sralph 	timeout.tv_sec = 5;
47117925Sralph 	timeout.tv_usec = 0;
47246689Sbostic 	if (select(32, (fd_set *)&rfds, (fd_set *)NULL,
47346689Sbostic 	    (fd_set *)NULL, &timeout) <= 0)
47417925Sralph 		return (type);
47546690Sbostic 	if (read(STDIN_FILENO, &c, sizeof(char)) != sizeof(char))
47617925Sralph 		return (type);
47717925Sralph 	timeout.tv_sec = 0;
47817925Sralph 	timeout.tv_usec = 20;
47946689Sbostic 	(void) select(32, (fd_set *)NULL, (fd_set *)NULL,
48046689Sbostic 	    (fd_set *)NULL, &timeout);
48117925Sralph 	ioctl(0, TIOCFLUSH, &null);
48217925Sralph 	switch (c & 0377) {
48317925Sralph 
48417925Sralph 	case 0200:		/* 300-baud */
48517925Sralph 		type = "300-baud";
48617925Sralph 		break;
48717925Sralph 
48817925Sralph 	case 0346:		/* 1200-baud */
48917925Sralph 		type = "1200-baud";
49017925Sralph 		break;
49117925Sralph 
49217925Sralph 	case  015:		/* 2400-baud */
49317925Sralph 	case 0215:
49417925Sralph 		type = "2400-baud";
49517925Sralph 		break;
49617925Sralph 
49717925Sralph 	default:		/* 4800-baud */
49817925Sralph 		type = "4800-baud";
49917925Sralph 		break;
50017925Sralph 
50117925Sralph 	case 0377:		/* 9600-baud */
50217925Sralph 		type = "9600-baud";
50317925Sralph 		break;
50417925Sralph 	}
50517925Sralph 	return (type);
50617925Sralph }
507