xref: /csrg-svn/libexec/getty/main.c (revision 18543)
113795Ssam #ifndef lint
2*18543Sralph static char sccsid[] = "@(#)main.c	4.7 (Berkeley) 85/04/01";
313795Ssam #endif
413795Ssam 
513795Ssam /*
613795Ssam  * getty -- adapt to terminal speed on dialup, and call login
713795Ssam  *
813795Ssam  * Melbourne getty, June 83, kre.
913795Ssam  */
1013795Ssam 
1113795Ssam #include <sgtty.h>
1213795Ssam #include <signal.h>
1313795Ssam #include <ctype.h>
1413795Ssam #include <setjmp.h>
15*18543Sralph #include <syslog.h>
16*18543Sralph #include <sys/file.h>
1713795Ssam #include "gettytab.h"
1813795Ssam 
19*18543Sralph extern	char **environ;
20*18543Sralph 
2113795Ssam struct	sgttyb tmode = {
2213795Ssam 	0, 0, CERASE, CKILL, 0
2313795Ssam };
2413795Ssam struct	tchars tc = {
2513795Ssam 	CINTR, CQUIT, CSTART,
2613795Ssam 	CSTOP, CEOF, CBRK,
2713795Ssam };
2813795Ssam struct	ltchars ltc = {
2913795Ssam 	CSUSP, CDSUSP, CRPRNT,
3013795Ssam 	CFLUSH, CWERASE, CLNEXT
3113795Ssam };
3213795Ssam 
3313795Ssam int	crmod;
3413795Ssam int	upper;
3513795Ssam int	lower;
3613795Ssam int	digit;
3713795Ssam 
3813795Ssam char	hostname[32];
3913795Ssam char	name[16];
40*18543Sralph char	dev[] = "/dev/";
41*18543Sralph char	ctty[] = "/dev/console";
42*18543Sralph char	ttyn[32];
4313795Ssam char	*portselector();
44*18543Sralph char	*ttyname();
4513795Ssam 
4613828Skre #define	OBUFSIZ		128
4713795Ssam #define	TABBUFSIZ	512
4813795Ssam 
4913795Ssam char	defent[TABBUFSIZ];
5013795Ssam char	defstrs[TABBUFSIZ];
5113795Ssam char	tabent[TABBUFSIZ];
5213795Ssam char	tabstrs[TABBUFSIZ];
5313795Ssam 
5413795Ssam char	*env[128];
5513795Ssam 
5613795Ssam char partab[] = {
5713795Ssam 	0001,0201,0201,0001,0201,0001,0001,0201,
5813795Ssam 	0202,0004,0003,0205,0005,0206,0201,0001,
5913795Ssam 	0201,0001,0001,0201,0001,0201,0201,0001,
6013795Ssam 	0001,0201,0201,0001,0201,0001,0001,0201,
6113795Ssam 	0200,0000,0000,0200,0000,0200,0200,0000,
6213795Ssam 	0000,0200,0200,0000,0200,0000,0000,0200,
6313795Ssam 	0000,0200,0200,0000,0200,0000,0000,0200,
6413795Ssam 	0200,0000,0000,0200,0000,0200,0200,0000,
6513795Ssam 	0200,0000,0000,0200,0000,0200,0200,0000,
6613795Ssam 	0000,0200,0200,0000,0200,0000,0000,0200,
6713795Ssam 	0000,0200,0200,0000,0200,0000,0000,0200,
6813795Ssam 	0200,0000,0000,0200,0000,0200,0200,0000,
6913795Ssam 	0000,0200,0200,0000,0200,0000,0000,0200,
7013795Ssam 	0200,0000,0000,0200,0000,0200,0200,0000,
7113795Ssam 	0200,0000,0000,0200,0000,0200,0200,0000,
7213795Ssam 	0000,0200,0200,0000,0200,0000,0000,0201
7313795Ssam };
7413795Ssam 
7513795Ssam #define	ERASE	tmode.sg_erase
7613795Ssam #define	KILL	tmode.sg_kill
7713795Ssam #define	EOT	tc.t_eofc
7813795Ssam 
7913795Ssam jmp_buf timeout;
8013795Ssam 
8113795Ssam dingdong()
8213795Ssam {
8313795Ssam 
8413795Ssam 	alarm(0);
8513795Ssam 	signal(SIGALRM, SIG_DFL);
8613795Ssam 	longjmp(timeout, 1);
8713795Ssam }
8813795Ssam 
8913828Skre jmp_buf	intrupt;
9013828Skre 
9113828Skre interrupt()
9213828Skre {
9313828Skre 
9413828Skre 	signal(SIGINT, interrupt);
9513828Skre 	longjmp(intrupt, 1);
9613828Skre }
9713828Skre 
9813795Ssam main(argc, argv)
9913795Ssam 	char *argv[];
10013795Ssam {
10113795Ssam 	char *tname;
10213795Ssam 	long allflags;
103*18543Sralph 	int repcnt = 0;
10413795Ssam 
10513828Skre 	signal(SIGINT, SIG_IGN);
10613795Ssam /*
10713795Ssam 	signal(SIGQUIT, SIG_DFL);
10813795Ssam */
109*18543Sralph 	openlog("getty", LOG_ODELAY|LOG_CONS, 0);
11013795Ssam 	gethostname(hostname, sizeof(hostname));
11113795Ssam 	if (hostname[0] == '\0')
11213795Ssam 		strcpy(hostname, "Amnesiac");
113*18543Sralph 	/*
114*18543Sralph 	 * The following is a work around for vhangup interactions
115*18543Sralph 	 * which cause great problems getting window systems started.
116*18543Sralph 	 * If the tty line is "-", we do the old style getty presuming
117*18543Sralph 	 * that the file descriptors are already set up for us.
118*18543Sralph 	 * J. Gettys - MIT Project Athena.
119*18543Sralph 	 */
120*18543Sralph 	if (argc <= 2 || strcmp(argv[2], "-") == 0)
121*18543Sralph 		strcpy(ttyn, ttyname(0));
122*18543Sralph 	else {
123*18543Sralph 		strcpy(ttyn, dev);
124*18543Sralph 		strncat(ttyn, argv[2], sizeof(ttyn)-sizeof(dev));
125*18543Sralph 		chown(ttyn, 0, 0);
126*18543Sralph 		chmod(ttyn, 0622);
127*18543Sralph 		while (open(ttyn, O_RDWR) != 0) {
128*18543Sralph 			if (repcnt % 10 == 0) {
129*18543Sralph 				syslog(LOG_FAIL, "%s: %m", ttyn);
130*18543Sralph 				closelog();
131*18543Sralph 			}
132*18543Sralph 			repcnt++;
133*18543Sralph 			sleep(60);
134*18543Sralph 		}
135*18543Sralph 		signal(SIGHUP, SIG_IGN);
136*18543Sralph 		vhangup();
137*18543Sralph 		(void) open(ttyn, O_RDWR);
138*18543Sralph 		close(0);
139*18543Sralph 		dup(1);
140*18543Sralph 		dup(0);
141*18543Sralph 		signal(SIGHUP, SIG_DFL);
142*18543Sralph 	}
143*18543Sralph 
14413795Ssam 	gettable("default", defent, defstrs);
14513795Ssam 	gendefaults();
14613795Ssam 	tname = "default";
14713795Ssam 	if (argc > 1)
14813795Ssam 		tname = argv[1];
14913795Ssam 	for (;;) {
15013795Ssam 		int ldisp = OTTYDISC;
15113795Ssam 
15213795Ssam 		gettable(tname, tabent, tabstrs);
15313828Skre 		if (OPset || EPset || APset)
15413828Skre 			APset++, OPset++, EPset++;
15513795Ssam 		setdefaults();
15613795Ssam 		ioctl(0, TIOCFLUSH, 0);		/* clear out the crap */
15713795Ssam 		if (IS)
15813795Ssam 			tmode.sg_ispeed = speed(IS);
15913795Ssam 		else if (SP)
16013795Ssam 			tmode.sg_ispeed = speed(SP);
16113795Ssam 		if (OS)
16213795Ssam 			tmode.sg_ospeed = speed(OS);
16313795Ssam 		else if (SP)
16413795Ssam 			tmode.sg_ospeed = speed(SP);
16513795Ssam 		tmode.sg_flags = setflags(0);
16613795Ssam 		ioctl(0, TIOCSETP, &tmode);
16713795Ssam 		setchars();
16813795Ssam 		ioctl(0, TIOCSETC, &tc);
16913795Ssam 		ioctl(0, TIOCSETD, &ldisp);
17013795Ssam 		if (HC)
17113795Ssam 			ioctl(0, TIOCHPCL, 0);
172*18543Sralph 		if (AB) {
173*18543Sralph 			extern char *autobaud();
174*18543Sralph 
175*18543Sralph 			tname = autobaud();
176*18543Sralph 			continue;
177*18543Sralph 		}
17813795Ssam 		if (PS) {
17913795Ssam 			tname = portselector();
18013795Ssam 			continue;
18113795Ssam 		}
18213795Ssam 		if (CL && *CL)
18313795Ssam 			putpad(CL);
18413795Ssam 		edithost(HE);
18513795Ssam 		if (IM && *IM)
18613795Ssam 			putf(IM);
18713795Ssam 		if (setjmp(timeout)) {
18813795Ssam 			tmode.sg_ispeed = tmode.sg_ospeed = 0;
18913795Ssam 			ioctl(0, TIOCSETP, &tmode);
19013795Ssam 			exit(1);
19113795Ssam 		}
19213795Ssam 		if (TO) {
19313795Ssam 			signal(SIGALRM, dingdong);
19413795Ssam 			alarm(TO);
19513795Ssam 		}
19613795Ssam 		if (getname()) {
197*18543Sralph 			register int i;
198*18543Sralph 
199*18543Sralph 			oflush();
20013795Ssam 			alarm(0);
20113795Ssam 			signal(SIGALRM, SIG_DFL);
20213831Ssam 			if (!(upper || lower || digit))
20313795Ssam 				continue;
20413795Ssam 			allflags = setflags(2);
20513795Ssam 			tmode.sg_flags = allflags & 0xffff;
20613795Ssam 			allflags >>= 16;
20713795Ssam 			if (crmod || NL)
20813795Ssam 				tmode.sg_flags |= CRMOD;
20913795Ssam 			if (upper || UC)
21013795Ssam 				tmode.sg_flags |= LCASE;
21113795Ssam 			if (lower || LC)
21213795Ssam 				tmode.sg_flags &= ~LCASE;
21313795Ssam 			ioctl(0, TIOCSETP, &tmode);
21413795Ssam 			ioctl(0, TIOCSLTC, &ltc);
21513795Ssam 			ioctl(0, TIOCLSET, &allflags);
21613828Skre 			signal(SIGINT, SIG_DFL);
217*18543Sralph 			for (i = 0; environ[i] != (char *)0; i++)
218*18543Sralph 				env[i] = environ[i];
219*18543Sralph 			makeenv(&env[i]);
220*18543Sralph 			execle(LO, "login", "-p", name, (char *) 0, env);
22113795Ssam 			exit(1);
22213795Ssam 		}
22313795Ssam 		alarm(0);
22413795Ssam 		signal(SIGALRM, SIG_DFL);
22513828Skre 		signal(SIGINT, SIG_IGN);
22613795Ssam 		if (NX && *NX)
22713795Ssam 			tname = NX;
22813795Ssam 	}
22913795Ssam }
23013795Ssam 
23113795Ssam getname()
23213795Ssam {
23313795Ssam 	register char *np;
23413795Ssam 	register c;
23513795Ssam 	char cs;
23613795Ssam 
23713828Skre 	/*
23813831Ssam 	 * Interrupt may happen if we use CBREAK mode
23913828Skre 	 */
24013828Skre 	if (setjmp(intrupt)) {
24113828Skre 		signal(SIGINT, SIG_IGN);
24213828Skre 		return (0);
24313828Skre 	}
24413828Skre 	signal(SIGINT, interrupt);
24513795Ssam 	tmode.sg_flags = setflags(0);
24613795Ssam 	ioctl(0, TIOCSETP, &tmode);
24713795Ssam 	tmode.sg_flags = setflags(1);
24813795Ssam 	prompt();
24913885Ssam 	if (PF > 0) {
25014322Ssam 		oflush();
25113885Ssam 		sleep(PF);
25213885Ssam 		PF = 0;
25313885Ssam 	}
25413795Ssam 	ioctl(0, TIOCSETP, &tmode);
25513795Ssam 	crmod = 0;
25613795Ssam 	upper = 0;
25713795Ssam 	lower = 0;
25813795Ssam 	digit = 0;
25913795Ssam 	np = name;
26013795Ssam 	for (;;) {
26113828Skre 		oflush();
26213795Ssam 		if (read(0, &cs, 1) <= 0)
26313795Ssam 			exit(0);
26413795Ssam 		if ((c = cs&0177) == 0)
26513795Ssam 			return (0);
26613831Ssam 		if (c == EOT)
26713795Ssam 			exit(1);
268*18543Sralph 		if (c == '\r' || c == '\n' || np >= &name[sizeof name]) {
269*18543Sralph 			putf("\r\n");
27013795Ssam 			break;
271*18543Sralph 		}
27213831Ssam 		if (c >= 'a' && c <= 'z')
27313795Ssam 			lower++;
274*18543Sralph 		else if (c >= 'A' && c <= 'Z')
27513795Ssam 			upper++;
276*18543Sralph 		else if (c == ERASE || c == '#' || c == '\b') {
27713795Ssam 			if (np > name) {
27813795Ssam 				np--;
27913795Ssam 				if (tmode.sg_ospeed >= B1200)
28013795Ssam 					puts("\b \b");
28113795Ssam 				else
28213795Ssam 					putchr(cs);
28313795Ssam 			}
28413795Ssam 			continue;
28513831Ssam 		} else if (c == KILL || c == '@') {
28613795Ssam 			putchr(cs);
28713795Ssam 			putchr('\r');
28813795Ssam 			if (tmode.sg_ospeed < B1200)
28913795Ssam 				putchr('\n');
29013795Ssam 			/* this is the way they do it down under ... */
29113795Ssam 			else if (np > name)
29213795Ssam 				puts("                                     \r");
29313795Ssam 			prompt();
29413795Ssam 			np = name;
29513795Ssam 			continue;
296*18543Sralph 		} else if (c >= '0' && c <= '9')
29713795Ssam 			digit++;
298*18543Sralph 		if (IG && (c <= ' ' || c > 0176))
29913795Ssam 			continue;
30013795Ssam 		*np++ = c;
30113795Ssam 		putchr(cs);
30213795Ssam 	}
30313828Skre 	signal(SIGINT, SIG_IGN);
30413795Ssam 	*np = 0;
30513795Ssam 	if (c == '\r')
30613795Ssam 		crmod++;
30713795Ssam 	if (upper && !lower && !LC || UC)
30813795Ssam 		for (np = name; *np; np++)
30913795Ssam 			if (isupper(*np))
31013795Ssam 				*np = tolower(*np);
31113795Ssam 	return (1);
31213795Ssam }
31313795Ssam 
31413795Ssam static
31513795Ssam short	tmspc10[] = {
31613795Ssam 	0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5, 15
31713795Ssam };
31813795Ssam 
31913795Ssam putpad(s)
32013795Ssam 	register char *s;
32113795Ssam {
32213795Ssam 	register pad = 0;
32313795Ssam 	register mspc10;
32413795Ssam 
32513795Ssam 	if (isdigit(*s)) {
32613795Ssam 		while (isdigit(*s)) {
32713795Ssam 			pad *= 10;
32813795Ssam 			pad += *s++ - '0';
32913795Ssam 		}
33013795Ssam 		pad *= 10;
33113795Ssam 		if (*s == '.' && isdigit(s[1])) {
33213795Ssam 			pad += s[1] - '0';
33313795Ssam 			s += 2;
33413795Ssam 		}
33513795Ssam 	}
33613795Ssam 
33713795Ssam 	puts(s);
33813795Ssam 	/*
33913795Ssam 	 * If no delay needed, or output speed is
34013795Ssam 	 * not comprehensible, then don't try to delay.
34113795Ssam 	 */
34213795Ssam 	if (pad == 0)
34313795Ssam 		return;
34413795Ssam 	if (tmode.sg_ospeed <= 0 ||
34513795Ssam 	    tmode.sg_ospeed >= (sizeof tmspc10 / sizeof tmspc10[0]))
34613795Ssam 		return;
34713795Ssam 
34813795Ssam 	/*
34913795Ssam 	 * Round up by a half a character frame,
35013795Ssam 	 * and then do the delay.
35113795Ssam 	 * Too bad there are no user program accessible programmed delays.
35213795Ssam 	 * Transmitting pad characters slows many
35313795Ssam 	 * terminals down and also loads the system.
35413795Ssam 	 */
35513795Ssam 	mspc10 = tmspc10[tmode.sg_ospeed];
35613795Ssam 	pad += mspc10 / 2;
35713795Ssam 	for (pad /= mspc10; pad > 0; pad--)
35813795Ssam 		putchr(*PC);
35913795Ssam }
36013795Ssam 
36113795Ssam puts(s)
36213795Ssam 	register char *s;
36313795Ssam {
36413795Ssam 
36513795Ssam 	while (*s)
36613795Ssam 		putchr(*s++);
36713795Ssam }
36813795Ssam 
36913828Skre char	outbuf[OBUFSIZ];
37013828Skre int	obufcnt = 0;
37113828Skre 
37213795Ssam putchr(cc)
37313795Ssam {
37413795Ssam 	char c;
37513795Ssam 
37613795Ssam 	c = cc;
37713795Ssam 	c |= partab[c&0177] & 0200;
37813795Ssam 	if (OP)
37913795Ssam 		c ^= 0200;
38013828Skre 	if (!UB) {
38113828Skre 		outbuf[obufcnt++] = c;
38213828Skre 		if (obufcnt >= OBUFSIZ)
38313828Skre 			oflush();
38413828Skre 	} else
38513828Skre 		write(1, &c, 1);
38613795Ssam }
38713795Ssam 
38813828Skre oflush()
38913828Skre {
39013828Skre 	if (obufcnt)
39113828Skre 		write(1, outbuf, obufcnt);
39213828Skre 	obufcnt = 0;
39313828Skre }
39413828Skre 
39513795Ssam prompt()
39613795Ssam {
39713795Ssam 
39813795Ssam 	putf(LM);
39913795Ssam 	if (CO)
40013795Ssam 		putchr('\n');
40113795Ssam }
40213795Ssam 
40313795Ssam putf(cp)
40413795Ssam 	register char *cp;
40513795Ssam {
406*18543Sralph 	char *ttyn, *slash;
407*18543Sralph 	char datebuffer[60];
40813795Ssam 	extern char editedhost[];
409*18543Sralph 	extern char *ttyname(), *rindex();
41013795Ssam 
41113795Ssam 	while (*cp) {
41213795Ssam 		if (*cp != '%') {
41313795Ssam 			putchr(*cp++);
41413795Ssam 			continue;
41513795Ssam 		}
41613795Ssam 		switch (*++cp) {
41713795Ssam 
418*18543Sralph 		case 't':
419*18543Sralph 			ttyn = ttyname(0);
420*18543Sralph 			slash = rindex(ttyn, '/');
421*18543Sralph 			if (slash == (char *) 0)
422*18543Sralph 				puts(ttyn);
423*18543Sralph 			else
424*18543Sralph 				puts(&slash[1]);
425*18543Sralph 			break;
426*18543Sralph 
42713795Ssam 		case 'h':
42813795Ssam 			puts(editedhost);
42913795Ssam 			break;
43013795Ssam 
431*18543Sralph 		case 'd':
432*18543Sralph 			get_date(datebuffer);
433*18543Sralph 			puts(datebuffer);
43415713Sralph 			break;
43515713Sralph 
43613795Ssam 		case '%':
43713795Ssam 			putchr('%');
43813795Ssam 			break;
43913795Ssam 		}
44013795Ssam 		cp++;
44113795Ssam 	}
44213795Ssam }
443