xref: /csrg-svn/libexec/getty/main.c (revision 25954)
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*25954Sbloom static char sccsid[] = "@(#)main.c	5.5 (Berkeley) 01/23/86";
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)
133*25954Sbloom 	    strcpy(ttyn, ttyname(0));
13418543Sralph 	else {
135*25954Sbloom 	    strcpy(ttyn, dev);
136*25954Sbloom 	    strncat(ttyn, argv[2], sizeof(ttyn)-sizeof(dev));
137*25954Sbloom 	    if (strcmp(argv[0], "+") != 0) {
13818543Sralph 		chown(ttyn, 0, 0);
13918543Sralph 		chmod(ttyn, 0622);
14025553Smckusick 		/*
14125553Smckusick 		 * Delay the open so DTR stays down long enough to be detected.
14225553Smckusick 		 */
14325553Smckusick 		sleep(2);
14418543Sralph 		while (open(ttyn, O_RDWR) != 0) {
14518543Sralph 			if (repcnt % 10 == 0) {
14624895Seric 				syslog(LOG_ERR, "%s: %m", ttyn);
14718543Sralph 				closelog();
14818543Sralph 			}
14918543Sralph 			repcnt++;
15018543Sralph 			sleep(60);
15118543Sralph 		}
15218543Sralph 		signal(SIGHUP, SIG_IGN);
15318543Sralph 		vhangup();
15418543Sralph 		(void) open(ttyn, O_RDWR);
15518543Sralph 		close(0);
15618543Sralph 		dup(1);
15718543Sralph 		dup(0);
15818543Sralph 		signal(SIGHUP, SIG_DFL);
159*25954Sbloom 	    }
16018543Sralph 	}
16118543Sralph 
16213795Ssam 	gettable("default", defent, defstrs);
16313795Ssam 	gendefaults();
16413795Ssam 	tname = "default";
16513795Ssam 	if (argc > 1)
16613795Ssam 		tname = argv[1];
16713795Ssam 	for (;;) {
16813795Ssam 		int ldisp = OTTYDISC;
16913795Ssam 
17013795Ssam 		gettable(tname, tabent, tabstrs);
17113828Skre 		if (OPset || EPset || APset)
17213828Skre 			APset++, OPset++, EPset++;
17313795Ssam 		setdefaults();
17413795Ssam 		ioctl(0, TIOCFLUSH, 0);		/* clear out the crap */
17513795Ssam 		if (IS)
17613795Ssam 			tmode.sg_ispeed = speed(IS);
17713795Ssam 		else if (SP)
17813795Ssam 			tmode.sg_ispeed = speed(SP);
17913795Ssam 		if (OS)
18013795Ssam 			tmode.sg_ospeed = speed(OS);
18113795Ssam 		else if (SP)
18213795Ssam 			tmode.sg_ospeed = speed(SP);
18313795Ssam 		tmode.sg_flags = setflags(0);
18413795Ssam 		ioctl(0, TIOCSETP, &tmode);
18513795Ssam 		setchars();
18613795Ssam 		ioctl(0, TIOCSETC, &tc);
18713795Ssam 		ioctl(0, TIOCSETD, &ldisp);
18813795Ssam 		if (HC)
18913795Ssam 			ioctl(0, TIOCHPCL, 0);
19018543Sralph 		if (AB) {
19118543Sralph 			extern char *autobaud();
19218543Sralph 
19318543Sralph 			tname = autobaud();
19418543Sralph 			continue;
19518543Sralph 		}
19613795Ssam 		if (PS) {
19713795Ssam 			tname = portselector();
19813795Ssam 			continue;
19913795Ssam 		}
20013795Ssam 		if (CL && *CL)
20113795Ssam 			putpad(CL);
20213795Ssam 		edithost(HE);
20313795Ssam 		if (IM && *IM)
20413795Ssam 			putf(IM);
20513795Ssam 		if (setjmp(timeout)) {
20613795Ssam 			tmode.sg_ispeed = tmode.sg_ospeed = 0;
20713795Ssam 			ioctl(0, TIOCSETP, &tmode);
20813795Ssam 			exit(1);
20913795Ssam 		}
21013795Ssam 		if (TO) {
21113795Ssam 			signal(SIGALRM, dingdong);
21213795Ssam 			alarm(TO);
21313795Ssam 		}
21413795Ssam 		if (getname()) {
21518543Sralph 			register int i;
21618543Sralph 
21718543Sralph 			oflush();
21813795Ssam 			alarm(0);
21913795Ssam 			signal(SIGALRM, SIG_DFL);
22013831Ssam 			if (!(upper || lower || digit))
22113795Ssam 				continue;
22213795Ssam 			allflags = setflags(2);
22313795Ssam 			tmode.sg_flags = allflags & 0xffff;
22413795Ssam 			allflags >>= 16;
22513795Ssam 			if (crmod || NL)
22613795Ssam 				tmode.sg_flags |= CRMOD;
22713795Ssam 			if (upper || UC)
22813795Ssam 				tmode.sg_flags |= LCASE;
22913795Ssam 			if (lower || LC)
23013795Ssam 				tmode.sg_flags &= ~LCASE;
23113795Ssam 			ioctl(0, TIOCSETP, &tmode);
23213795Ssam 			ioctl(0, TIOCSLTC, &ltc);
23313795Ssam 			ioctl(0, TIOCLSET, &allflags);
23413828Skre 			signal(SIGINT, SIG_DFL);
23518543Sralph 			for (i = 0; environ[i] != (char *)0; i++)
23618543Sralph 				env[i] = environ[i];
23718543Sralph 			makeenv(&env[i]);
23818543Sralph 			execle(LO, "login", "-p", name, (char *) 0, env);
23913795Ssam 			exit(1);
24013795Ssam 		}
24113795Ssam 		alarm(0);
24213795Ssam 		signal(SIGALRM, SIG_DFL);
24313828Skre 		signal(SIGINT, SIG_IGN);
24413795Ssam 		if (NX && *NX)
24513795Ssam 			tname = NX;
24613795Ssam 	}
24713795Ssam }
24813795Ssam 
24913795Ssam getname()
25013795Ssam {
25113795Ssam 	register char *np;
25213795Ssam 	register c;
25313795Ssam 	char cs;
25413795Ssam 
25513828Skre 	/*
25613831Ssam 	 * Interrupt may happen if we use CBREAK mode
25713828Skre 	 */
25813828Skre 	if (setjmp(intrupt)) {
25913828Skre 		signal(SIGINT, SIG_IGN);
26013828Skre 		return (0);
26113828Skre 	}
26213828Skre 	signal(SIGINT, interrupt);
26313795Ssam 	tmode.sg_flags = setflags(0);
26413795Ssam 	ioctl(0, TIOCSETP, &tmode);
26513795Ssam 	tmode.sg_flags = setflags(1);
26613795Ssam 	prompt();
26713885Ssam 	if (PF > 0) {
26814322Ssam 		oflush();
26913885Ssam 		sleep(PF);
27013885Ssam 		PF = 0;
27113885Ssam 	}
27213795Ssam 	ioctl(0, TIOCSETP, &tmode);
27313795Ssam 	crmod = 0;
27413795Ssam 	upper = 0;
27513795Ssam 	lower = 0;
27613795Ssam 	digit = 0;
27713795Ssam 	np = name;
27813795Ssam 	for (;;) {
27913828Skre 		oflush();
28013795Ssam 		if (read(0, &cs, 1) <= 0)
28113795Ssam 			exit(0);
28213795Ssam 		if ((c = cs&0177) == 0)
28313795Ssam 			return (0);
28413831Ssam 		if (c == EOT)
28513795Ssam 			exit(1);
28618543Sralph 		if (c == '\r' || c == '\n' || np >= &name[sizeof name]) {
28718543Sralph 			putf("\r\n");
28813795Ssam 			break;
28918543Sralph 		}
29013831Ssam 		if (c >= 'a' && c <= 'z')
29113795Ssam 			lower++;
29218543Sralph 		else if (c >= 'A' && c <= 'Z')
29313795Ssam 			upper++;
29418543Sralph 		else if (c == ERASE || c == '#' || c == '\b') {
29513795Ssam 			if (np > name) {
29613795Ssam 				np--;
29713795Ssam 				if (tmode.sg_ospeed >= B1200)
29813795Ssam 					puts("\b \b");
29913795Ssam 				else
30013795Ssam 					putchr(cs);
30113795Ssam 			}
30213795Ssam 			continue;
30313831Ssam 		} else if (c == KILL || c == '@') {
30413795Ssam 			putchr(cs);
30513795Ssam 			putchr('\r');
30613795Ssam 			if (tmode.sg_ospeed < B1200)
30713795Ssam 				putchr('\n');
30813795Ssam 			/* this is the way they do it down under ... */
30913795Ssam 			else if (np > name)
31013795Ssam 				puts("                                     \r");
31113795Ssam 			prompt();
31213795Ssam 			np = name;
31313795Ssam 			continue;
31418543Sralph 		} else if (c >= '0' && c <= '9')
31513795Ssam 			digit++;
31618543Sralph 		if (IG && (c <= ' ' || c > 0176))
31713795Ssam 			continue;
31813795Ssam 		*np++ = c;
31913795Ssam 		putchr(cs);
32013795Ssam 	}
32113828Skre 	signal(SIGINT, SIG_IGN);
32213795Ssam 	*np = 0;
32313795Ssam 	if (c == '\r')
32413795Ssam 		crmod++;
32513795Ssam 	if (upper && !lower && !LC || UC)
32613795Ssam 		for (np = name; *np; np++)
32713795Ssam 			if (isupper(*np))
32813795Ssam 				*np = tolower(*np);
32913795Ssam 	return (1);
33013795Ssam }
33113795Ssam 
33213795Ssam static
33313795Ssam short	tmspc10[] = {
33413795Ssam 	0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5, 15
33513795Ssam };
33613795Ssam 
33713795Ssam putpad(s)
33813795Ssam 	register char *s;
33913795Ssam {
34013795Ssam 	register pad = 0;
34113795Ssam 	register mspc10;
34213795Ssam 
34313795Ssam 	if (isdigit(*s)) {
34413795Ssam 		while (isdigit(*s)) {
34513795Ssam 			pad *= 10;
34613795Ssam 			pad += *s++ - '0';
34713795Ssam 		}
34813795Ssam 		pad *= 10;
34913795Ssam 		if (*s == '.' && isdigit(s[1])) {
35013795Ssam 			pad += s[1] - '0';
35113795Ssam 			s += 2;
35213795Ssam 		}
35313795Ssam 	}
35413795Ssam 
35513795Ssam 	puts(s);
35613795Ssam 	/*
35713795Ssam 	 * If no delay needed, or output speed is
35813795Ssam 	 * not comprehensible, then don't try to delay.
35913795Ssam 	 */
36013795Ssam 	if (pad == 0)
36113795Ssam 		return;
36213795Ssam 	if (tmode.sg_ospeed <= 0 ||
36313795Ssam 	    tmode.sg_ospeed >= (sizeof tmspc10 / sizeof tmspc10[0]))
36413795Ssam 		return;
36513795Ssam 
36613795Ssam 	/*
36713795Ssam 	 * Round up by a half a character frame,
36813795Ssam 	 * and then do the delay.
36913795Ssam 	 * Too bad there are no user program accessible programmed delays.
37013795Ssam 	 * Transmitting pad characters slows many
37113795Ssam 	 * terminals down and also loads the system.
37213795Ssam 	 */
37313795Ssam 	mspc10 = tmspc10[tmode.sg_ospeed];
37413795Ssam 	pad += mspc10 / 2;
37513795Ssam 	for (pad /= mspc10; pad > 0; pad--)
37613795Ssam 		putchr(*PC);
37713795Ssam }
37813795Ssam 
37913795Ssam puts(s)
38013795Ssam 	register char *s;
38113795Ssam {
38213795Ssam 
38313795Ssam 	while (*s)
38413795Ssam 		putchr(*s++);
38513795Ssam }
38613795Ssam 
38713828Skre char	outbuf[OBUFSIZ];
38813828Skre int	obufcnt = 0;
38913828Skre 
39013795Ssam putchr(cc)
39113795Ssam {
39213795Ssam 	char c;
39313795Ssam 
39413795Ssam 	c = cc;
39513795Ssam 	c |= partab[c&0177] & 0200;
39613795Ssam 	if (OP)
39713795Ssam 		c ^= 0200;
39813828Skre 	if (!UB) {
39913828Skre 		outbuf[obufcnt++] = c;
40013828Skre 		if (obufcnt >= OBUFSIZ)
40113828Skre 			oflush();
40213828Skre 	} else
40313828Skre 		write(1, &c, 1);
40413795Ssam }
40513795Ssam 
40613828Skre oflush()
40713828Skre {
40813828Skre 	if (obufcnt)
40913828Skre 		write(1, outbuf, obufcnt);
41013828Skre 	obufcnt = 0;
41113828Skre }
41213828Skre 
41313795Ssam prompt()
41413795Ssam {
41513795Ssam 
41613795Ssam 	putf(LM);
41713795Ssam 	if (CO)
41813795Ssam 		putchr('\n');
41913795Ssam }
42013795Ssam 
42113795Ssam putf(cp)
42213795Ssam 	register char *cp;
42313795Ssam {
42418543Sralph 	char *ttyn, *slash;
42518543Sralph 	char datebuffer[60];
42613795Ssam 	extern char editedhost[];
42718543Sralph 	extern char *ttyname(), *rindex();
42813795Ssam 
42913795Ssam 	while (*cp) {
43013795Ssam 		if (*cp != '%') {
43113795Ssam 			putchr(*cp++);
43213795Ssam 			continue;
43313795Ssam 		}
43413795Ssam 		switch (*++cp) {
43513795Ssam 
43618543Sralph 		case 't':
43718543Sralph 			ttyn = ttyname(0);
43818543Sralph 			slash = rindex(ttyn, '/');
43918543Sralph 			if (slash == (char *) 0)
44018543Sralph 				puts(ttyn);
44118543Sralph 			else
44218543Sralph 				puts(&slash[1]);
44318543Sralph 			break;
44418543Sralph 
44513795Ssam 		case 'h':
44613795Ssam 			puts(editedhost);
44713795Ssam 			break;
44813795Ssam 
44918543Sralph 		case 'd':
45018543Sralph 			get_date(datebuffer);
45118543Sralph 			puts(datebuffer);
45215713Sralph 			break;
45315713Sralph 
45413795Ssam 		case '%':
45513795Ssam 			putchr('%');
45613795Ssam 			break;
45713795Ssam 		}
45813795Ssam 		cp++;
45913795Ssam 	}
46013795Ssam }
461