xref: /csrg-svn/libexec/getty/main.c (revision 25553)
119054Sdist /*
219054Sdist  * Copyright (c) 1980 Regents of the University of California.
319054Sdist  * All rights reserved.  The Berkeley software License Agreement
419054Sdist  * specifies the terms and conditions for redistribution.
519054Sdist  */
619054Sdist 
713795Ssam #ifndef lint
819054Sdist char copyright[] =
919054Sdist "@(#) Copyright (c) 1980 Regents of the University of California.\n\
1019054Sdist  All rights reserved.\n";
1119054Sdist #endif not lint
1213795Ssam 
1319054Sdist #ifndef lint
14*25553Smckusick static char sccsid[] = "@(#)main.c	5.4 (Berkeley) 11/30/85";
1519054Sdist #endif not lint
1619054Sdist 
1713795Ssam /*
1813795Ssam  * getty -- adapt to terminal speed on dialup, and call login
1913795Ssam  *
2013795Ssam  * Melbourne getty, June 83, kre.
2113795Ssam  */
2213795Ssam 
2313795Ssam #include <sgtty.h>
2413795Ssam #include <signal.h>
2513795Ssam #include <ctype.h>
2613795Ssam #include <setjmp.h>
2718543Sralph #include <syslog.h>
2818543Sralph #include <sys/file.h>
2913795Ssam #include "gettytab.h"
3013795Ssam 
3118543Sralph extern	char **environ;
3218543Sralph 
3313795Ssam struct	sgttyb tmode = {
3413795Ssam 	0, 0, CERASE, CKILL, 0
3513795Ssam };
3613795Ssam struct	tchars tc = {
3713795Ssam 	CINTR, CQUIT, CSTART,
3813795Ssam 	CSTOP, CEOF, CBRK,
3913795Ssam };
4013795Ssam struct	ltchars ltc = {
4113795Ssam 	CSUSP, CDSUSP, CRPRNT,
4213795Ssam 	CFLUSH, CWERASE, CLNEXT
4313795Ssam };
4413795Ssam 
4513795Ssam int	crmod;
4613795Ssam int	upper;
4713795Ssam int	lower;
4813795Ssam int	digit;
4913795Ssam 
5013795Ssam char	hostname[32];
5113795Ssam char	name[16];
5218543Sralph char	dev[] = "/dev/";
5318543Sralph char	ctty[] = "/dev/console";
5418543Sralph char	ttyn[32];
5513795Ssam char	*portselector();
5618543Sralph char	*ttyname();
5713795Ssam 
5813828Skre #define	OBUFSIZ		128
5913795Ssam #define	TABBUFSIZ	512
6013795Ssam 
6113795Ssam char	defent[TABBUFSIZ];
6213795Ssam char	defstrs[TABBUFSIZ];
6313795Ssam char	tabent[TABBUFSIZ];
6413795Ssam char	tabstrs[TABBUFSIZ];
6513795Ssam 
6613795Ssam char	*env[128];
6713795Ssam 
6813795Ssam char partab[] = {
6913795Ssam 	0001,0201,0201,0001,0201,0001,0001,0201,
7013795Ssam 	0202,0004,0003,0205,0005,0206,0201,0001,
7113795Ssam 	0201,0001,0001,0201,0001,0201,0201,0001,
7213795Ssam 	0001,0201,0201,0001,0201,0001,0001,0201,
7313795Ssam 	0200,0000,0000,0200,0000,0200,0200,0000,
7413795Ssam 	0000,0200,0200,0000,0200,0000,0000,0200,
7513795Ssam 	0000,0200,0200,0000,0200,0000,0000,0200,
7613795Ssam 	0200,0000,0000,0200,0000,0200,0200,0000,
7713795Ssam 	0200,0000,0000,0200,0000,0200,0200,0000,
7813795Ssam 	0000,0200,0200,0000,0200,0000,0000,0200,
7913795Ssam 	0000,0200,0200,0000,0200,0000,0000,0200,
8013795Ssam 	0200,0000,0000,0200,0000,0200,0200,0000,
8113795Ssam 	0000,0200,0200,0000,0200,0000,0000,0200,
8213795Ssam 	0200,0000,0000,0200,0000,0200,0200,0000,
8313795Ssam 	0200,0000,0000,0200,0000,0200,0200,0000,
8413795Ssam 	0000,0200,0200,0000,0200,0000,0000,0201
8513795Ssam };
8613795Ssam 
8713795Ssam #define	ERASE	tmode.sg_erase
8813795Ssam #define	KILL	tmode.sg_kill
8913795Ssam #define	EOT	tc.t_eofc
9013795Ssam 
9113795Ssam jmp_buf timeout;
9213795Ssam 
9313795Ssam dingdong()
9413795Ssam {
9513795Ssam 
9613795Ssam 	alarm(0);
9713795Ssam 	signal(SIGALRM, SIG_DFL);
9813795Ssam 	longjmp(timeout, 1);
9913795Ssam }
10013795Ssam 
10113828Skre jmp_buf	intrupt;
10213828Skre 
10313828Skre interrupt()
10413828Skre {
10513828Skre 
10613828Skre 	signal(SIGINT, interrupt);
10713828Skre 	longjmp(intrupt, 1);
10813828Skre }
10913828Skre 
11013795Ssam main(argc, argv)
11113795Ssam 	char *argv[];
11213795Ssam {
11313795Ssam 	char *tname;
11413795Ssam 	long allflags;
11518543Sralph 	int repcnt = 0;
11613795Ssam 
11713828Skre 	signal(SIGINT, SIG_IGN);
11813795Ssam /*
11913795Ssam 	signal(SIGQUIT, SIG_DFL);
12013795Ssam */
12124890Seric 	openlog("getty", LOG_ODELAY|LOG_CONS, LOG_AUTH);
12213795Ssam 	gethostname(hostname, sizeof(hostname));
12313795Ssam 	if (hostname[0] == '\0')
12413795Ssam 		strcpy(hostname, "Amnesiac");
12518543Sralph 	/*
12618543Sralph 	 * The following is a work around for vhangup interactions
12718543Sralph 	 * which cause great problems getting window systems started.
12818543Sralph 	 * If the tty line is "-", we do the old style getty presuming
12918543Sralph 	 * that the file descriptors are already set up for us.
13018543Sralph 	 * J. Gettys - MIT Project Athena.
13118543Sralph 	 */
13218543Sralph 	if (argc <= 2 || strcmp(argv[2], "-") == 0)
13318543Sralph 		strcpy(ttyn, ttyname(0));
13418543Sralph 	else {
13518543Sralph 		strcpy(ttyn, dev);
13618543Sralph 		strncat(ttyn, argv[2], sizeof(ttyn)-sizeof(dev));
13718543Sralph 		chown(ttyn, 0, 0);
13818543Sralph 		chmod(ttyn, 0622);
139*25553Smckusick 		/*
140*25553Smckusick 		 * Delay the open so DTR stays down long enough to be detected.
141*25553Smckusick 		 */
142*25553Smckusick 		sleep(2);
14318543Sralph 		while (open(ttyn, O_RDWR) != 0) {
14418543Sralph 			if (repcnt % 10 == 0) {
14524895Seric 				syslog(LOG_ERR, "%s: %m", ttyn);
14618543Sralph 				closelog();
14718543Sralph 			}
14818543Sralph 			repcnt++;
14918543Sralph 			sleep(60);
15018543Sralph 		}
15118543Sralph 		signal(SIGHUP, SIG_IGN);
15218543Sralph 		vhangup();
15318543Sralph 		(void) open(ttyn, O_RDWR);
15418543Sralph 		close(0);
15518543Sralph 		dup(1);
15618543Sralph 		dup(0);
15718543Sralph 		signal(SIGHUP, SIG_DFL);
15818543Sralph 	}
15918543Sralph 
16013795Ssam 	gettable("default", defent, defstrs);
16113795Ssam 	gendefaults();
16213795Ssam 	tname = "default";
16313795Ssam 	if (argc > 1)
16413795Ssam 		tname = argv[1];
16513795Ssam 	for (;;) {
16613795Ssam 		int ldisp = OTTYDISC;
16713795Ssam 
16813795Ssam 		gettable(tname, tabent, tabstrs);
16913828Skre 		if (OPset || EPset || APset)
17013828Skre 			APset++, OPset++, EPset++;
17113795Ssam 		setdefaults();
17213795Ssam 		ioctl(0, TIOCFLUSH, 0);		/* clear out the crap */
17313795Ssam 		if (IS)
17413795Ssam 			tmode.sg_ispeed = speed(IS);
17513795Ssam 		else if (SP)
17613795Ssam 			tmode.sg_ispeed = speed(SP);
17713795Ssam 		if (OS)
17813795Ssam 			tmode.sg_ospeed = speed(OS);
17913795Ssam 		else if (SP)
18013795Ssam 			tmode.sg_ospeed = speed(SP);
18113795Ssam 		tmode.sg_flags = setflags(0);
18213795Ssam 		ioctl(0, TIOCSETP, &tmode);
18313795Ssam 		setchars();
18413795Ssam 		ioctl(0, TIOCSETC, &tc);
18513795Ssam 		ioctl(0, TIOCSETD, &ldisp);
18613795Ssam 		if (HC)
18713795Ssam 			ioctl(0, TIOCHPCL, 0);
18818543Sralph 		if (AB) {
18918543Sralph 			extern char *autobaud();
19018543Sralph 
19118543Sralph 			tname = autobaud();
19218543Sralph 			continue;
19318543Sralph 		}
19413795Ssam 		if (PS) {
19513795Ssam 			tname = portselector();
19613795Ssam 			continue;
19713795Ssam 		}
19813795Ssam 		if (CL && *CL)
19913795Ssam 			putpad(CL);
20013795Ssam 		edithost(HE);
20113795Ssam 		if (IM && *IM)
20213795Ssam 			putf(IM);
20313795Ssam 		if (setjmp(timeout)) {
20413795Ssam 			tmode.sg_ispeed = tmode.sg_ospeed = 0;
20513795Ssam 			ioctl(0, TIOCSETP, &tmode);
20613795Ssam 			exit(1);
20713795Ssam 		}
20813795Ssam 		if (TO) {
20913795Ssam 			signal(SIGALRM, dingdong);
21013795Ssam 			alarm(TO);
21113795Ssam 		}
21213795Ssam 		if (getname()) {
21318543Sralph 			register int i;
21418543Sralph 
21518543Sralph 			oflush();
21613795Ssam 			alarm(0);
21713795Ssam 			signal(SIGALRM, SIG_DFL);
21813831Ssam 			if (!(upper || lower || digit))
21913795Ssam 				continue;
22013795Ssam 			allflags = setflags(2);
22113795Ssam 			tmode.sg_flags = allflags & 0xffff;
22213795Ssam 			allflags >>= 16;
22313795Ssam 			if (crmod || NL)
22413795Ssam 				tmode.sg_flags |= CRMOD;
22513795Ssam 			if (upper || UC)
22613795Ssam 				tmode.sg_flags |= LCASE;
22713795Ssam 			if (lower || LC)
22813795Ssam 				tmode.sg_flags &= ~LCASE;
22913795Ssam 			ioctl(0, TIOCSETP, &tmode);
23013795Ssam 			ioctl(0, TIOCSLTC, &ltc);
23113795Ssam 			ioctl(0, TIOCLSET, &allflags);
23213828Skre 			signal(SIGINT, SIG_DFL);
23318543Sralph 			for (i = 0; environ[i] != (char *)0; i++)
23418543Sralph 				env[i] = environ[i];
23518543Sralph 			makeenv(&env[i]);
23618543Sralph 			execle(LO, "login", "-p", name, (char *) 0, env);
23713795Ssam 			exit(1);
23813795Ssam 		}
23913795Ssam 		alarm(0);
24013795Ssam 		signal(SIGALRM, SIG_DFL);
24113828Skre 		signal(SIGINT, SIG_IGN);
24213795Ssam 		if (NX && *NX)
24313795Ssam 			tname = NX;
24413795Ssam 	}
24513795Ssam }
24613795Ssam 
24713795Ssam getname()
24813795Ssam {
24913795Ssam 	register char *np;
25013795Ssam 	register c;
25113795Ssam 	char cs;
25213795Ssam 
25313828Skre 	/*
25413831Ssam 	 * Interrupt may happen if we use CBREAK mode
25513828Skre 	 */
25613828Skre 	if (setjmp(intrupt)) {
25713828Skre 		signal(SIGINT, SIG_IGN);
25813828Skre 		return (0);
25913828Skre 	}
26013828Skre 	signal(SIGINT, interrupt);
26113795Ssam 	tmode.sg_flags = setflags(0);
26213795Ssam 	ioctl(0, TIOCSETP, &tmode);
26313795Ssam 	tmode.sg_flags = setflags(1);
26413795Ssam 	prompt();
26513885Ssam 	if (PF > 0) {
26614322Ssam 		oflush();
26713885Ssam 		sleep(PF);
26813885Ssam 		PF = 0;
26913885Ssam 	}
27013795Ssam 	ioctl(0, TIOCSETP, &tmode);
27113795Ssam 	crmod = 0;
27213795Ssam 	upper = 0;
27313795Ssam 	lower = 0;
27413795Ssam 	digit = 0;
27513795Ssam 	np = name;
27613795Ssam 	for (;;) {
27713828Skre 		oflush();
27813795Ssam 		if (read(0, &cs, 1) <= 0)
27913795Ssam 			exit(0);
28013795Ssam 		if ((c = cs&0177) == 0)
28113795Ssam 			return (0);
28213831Ssam 		if (c == EOT)
28313795Ssam 			exit(1);
28418543Sralph 		if (c == '\r' || c == '\n' || np >= &name[sizeof name]) {
28518543Sralph 			putf("\r\n");
28613795Ssam 			break;
28718543Sralph 		}
28813831Ssam 		if (c >= 'a' && c <= 'z')
28913795Ssam 			lower++;
29018543Sralph 		else if (c >= 'A' && c <= 'Z')
29113795Ssam 			upper++;
29218543Sralph 		else if (c == ERASE || c == '#' || c == '\b') {
29313795Ssam 			if (np > name) {
29413795Ssam 				np--;
29513795Ssam 				if (tmode.sg_ospeed >= B1200)
29613795Ssam 					puts("\b \b");
29713795Ssam 				else
29813795Ssam 					putchr(cs);
29913795Ssam 			}
30013795Ssam 			continue;
30113831Ssam 		} else if (c == KILL || c == '@') {
30213795Ssam 			putchr(cs);
30313795Ssam 			putchr('\r');
30413795Ssam 			if (tmode.sg_ospeed < B1200)
30513795Ssam 				putchr('\n');
30613795Ssam 			/* this is the way they do it down under ... */
30713795Ssam 			else if (np > name)
30813795Ssam 				puts("                                     \r");
30913795Ssam 			prompt();
31013795Ssam 			np = name;
31113795Ssam 			continue;
31218543Sralph 		} else if (c >= '0' && c <= '9')
31313795Ssam 			digit++;
31418543Sralph 		if (IG && (c <= ' ' || c > 0176))
31513795Ssam 			continue;
31613795Ssam 		*np++ = c;
31713795Ssam 		putchr(cs);
31813795Ssam 	}
31913828Skre 	signal(SIGINT, SIG_IGN);
32013795Ssam 	*np = 0;
32113795Ssam 	if (c == '\r')
32213795Ssam 		crmod++;
32313795Ssam 	if (upper && !lower && !LC || UC)
32413795Ssam 		for (np = name; *np; np++)
32513795Ssam 			if (isupper(*np))
32613795Ssam 				*np = tolower(*np);
32713795Ssam 	return (1);
32813795Ssam }
32913795Ssam 
33013795Ssam static
33113795Ssam short	tmspc10[] = {
33213795Ssam 	0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5, 15
33313795Ssam };
33413795Ssam 
33513795Ssam putpad(s)
33613795Ssam 	register char *s;
33713795Ssam {
33813795Ssam 	register pad = 0;
33913795Ssam 	register mspc10;
34013795Ssam 
34113795Ssam 	if (isdigit(*s)) {
34213795Ssam 		while (isdigit(*s)) {
34313795Ssam 			pad *= 10;
34413795Ssam 			pad += *s++ - '0';
34513795Ssam 		}
34613795Ssam 		pad *= 10;
34713795Ssam 		if (*s == '.' && isdigit(s[1])) {
34813795Ssam 			pad += s[1] - '0';
34913795Ssam 			s += 2;
35013795Ssam 		}
35113795Ssam 	}
35213795Ssam 
35313795Ssam 	puts(s);
35413795Ssam 	/*
35513795Ssam 	 * If no delay needed, or output speed is
35613795Ssam 	 * not comprehensible, then don't try to delay.
35713795Ssam 	 */
35813795Ssam 	if (pad == 0)
35913795Ssam 		return;
36013795Ssam 	if (tmode.sg_ospeed <= 0 ||
36113795Ssam 	    tmode.sg_ospeed >= (sizeof tmspc10 / sizeof tmspc10[0]))
36213795Ssam 		return;
36313795Ssam 
36413795Ssam 	/*
36513795Ssam 	 * Round up by a half a character frame,
36613795Ssam 	 * and then do the delay.
36713795Ssam 	 * Too bad there are no user program accessible programmed delays.
36813795Ssam 	 * Transmitting pad characters slows many
36913795Ssam 	 * terminals down and also loads the system.
37013795Ssam 	 */
37113795Ssam 	mspc10 = tmspc10[tmode.sg_ospeed];
37213795Ssam 	pad += mspc10 / 2;
37313795Ssam 	for (pad /= mspc10; pad > 0; pad--)
37413795Ssam 		putchr(*PC);
37513795Ssam }
37613795Ssam 
37713795Ssam puts(s)
37813795Ssam 	register char *s;
37913795Ssam {
38013795Ssam 
38113795Ssam 	while (*s)
38213795Ssam 		putchr(*s++);
38313795Ssam }
38413795Ssam 
38513828Skre char	outbuf[OBUFSIZ];
38613828Skre int	obufcnt = 0;
38713828Skre 
38813795Ssam putchr(cc)
38913795Ssam {
39013795Ssam 	char c;
39113795Ssam 
39213795Ssam 	c = cc;
39313795Ssam 	c |= partab[c&0177] & 0200;
39413795Ssam 	if (OP)
39513795Ssam 		c ^= 0200;
39613828Skre 	if (!UB) {
39713828Skre 		outbuf[obufcnt++] = c;
39813828Skre 		if (obufcnt >= OBUFSIZ)
39913828Skre 			oflush();
40013828Skre 	} else
40113828Skre 		write(1, &c, 1);
40213795Ssam }
40313795Ssam 
40413828Skre oflush()
40513828Skre {
40613828Skre 	if (obufcnt)
40713828Skre 		write(1, outbuf, obufcnt);
40813828Skre 	obufcnt = 0;
40913828Skre }
41013828Skre 
41113795Ssam prompt()
41213795Ssam {
41313795Ssam 
41413795Ssam 	putf(LM);
41513795Ssam 	if (CO)
41613795Ssam 		putchr('\n');
41713795Ssam }
41813795Ssam 
41913795Ssam putf(cp)
42013795Ssam 	register char *cp;
42113795Ssam {
42218543Sralph 	char *ttyn, *slash;
42318543Sralph 	char datebuffer[60];
42413795Ssam 	extern char editedhost[];
42518543Sralph 	extern char *ttyname(), *rindex();
42613795Ssam 
42713795Ssam 	while (*cp) {
42813795Ssam 		if (*cp != '%') {
42913795Ssam 			putchr(*cp++);
43013795Ssam 			continue;
43113795Ssam 		}
43213795Ssam 		switch (*++cp) {
43313795Ssam 
43418543Sralph 		case 't':
43518543Sralph 			ttyn = ttyname(0);
43618543Sralph 			slash = rindex(ttyn, '/');
43718543Sralph 			if (slash == (char *) 0)
43818543Sralph 				puts(ttyn);
43918543Sralph 			else
44018543Sralph 				puts(&slash[1]);
44118543Sralph 			break;
44218543Sralph 
44313795Ssam 		case 'h':
44413795Ssam 			puts(editedhost);
44513795Ssam 			break;
44613795Ssam 
44718543Sralph 		case 'd':
44818543Sralph 			get_date(datebuffer);
44918543Sralph 			puts(datebuffer);
45015713Sralph 			break;
45115713Sralph 
45213795Ssam 		case '%':
45313795Ssam 			putchr('%');
45413795Ssam 			break;
45513795Ssam 		}
45613795Ssam 		cp++;
45713795Ssam 	}
45813795Ssam }
459