xref: /csrg-svn/libexec/getty/main.c (revision 44567)
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*44567Smarc static char sccsid[] = "@(#)main.c	5.10 (Berkeley) 06/28/90";
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 
2342459Smarc #define USE_OLD_TTY
2442459Smarc #include <sys/param.h>
2542459Smarc #include <sys/signal.h>
2642459Smarc #include <sys/file.h>
2713795Ssam #include <sgtty.h>
2813795Ssam #include <ctype.h>
2913795Ssam #include <setjmp.h>
3018543Sralph #include <syslog.h>
3142459Smarc #include <ctype.h>
3213795Ssam #include "gettytab.h"
3342459Smarc #include "pathnames.h"
3413795Ssam 
3518543Sralph extern	char **environ;
3618543Sralph 
3713795Ssam struct	sgttyb tmode = {
3813795Ssam 	0, 0, CERASE, CKILL, 0
3913795Ssam };
4013795Ssam struct	tchars tc = {
4113795Ssam 	CINTR, CQUIT, CSTART,
4213795Ssam 	CSTOP, CEOF, CBRK,
4313795Ssam };
4413795Ssam struct	ltchars ltc = {
4513795Ssam 	CSUSP, CDSUSP, CRPRNT,
4613795Ssam 	CFLUSH, CWERASE, CLNEXT
4713795Ssam };
4813795Ssam 
4913795Ssam int	crmod;
5013795Ssam int	upper;
5113795Ssam int	lower;
5213795Ssam int	digit;
5313795Ssam 
5442459Smarc char	hostname[MAXHOSTNAMELEN];
5513795Ssam char	name[16];
5642459Smarc char	dev[] = _PATH_DEV;
5718543Sralph char	ttyn[32];
5813795Ssam char	*portselector();
5918543Sralph char	*ttyname();
6013795Ssam 
6113828Skre #define	OBUFSIZ		128
6213795Ssam #define	TABBUFSIZ	512
6313795Ssam 
6413795Ssam char	defent[TABBUFSIZ];
6513795Ssam char	defstrs[TABBUFSIZ];
6613795Ssam char	tabent[TABBUFSIZ];
6713795Ssam char	tabstrs[TABBUFSIZ];
6813795Ssam 
6913795Ssam char	*env[128];
7013795Ssam 
7113795Ssam char partab[] = {
7213795Ssam 	0001,0201,0201,0001,0201,0001,0001,0201,
7313795Ssam 	0202,0004,0003,0205,0005,0206,0201,0001,
7413795Ssam 	0201,0001,0001,0201,0001,0201,0201,0001,
7513795Ssam 	0001,0201,0201,0001,0201,0001,0001,0201,
7613795Ssam 	0200,0000,0000,0200,0000,0200,0200,0000,
7713795Ssam 	0000,0200,0200,0000,0200,0000,0000,0200,
7813795Ssam 	0000,0200,0200,0000,0200,0000,0000,0200,
7913795Ssam 	0200,0000,0000,0200,0000,0200,0200,0000,
8013795Ssam 	0200,0000,0000,0200,0000,0200,0200,0000,
8113795Ssam 	0000,0200,0200,0000,0200,0000,0000,0200,
8213795Ssam 	0000,0200,0200,0000,0200,0000,0000,0200,
8313795Ssam 	0200,0000,0000,0200,0000,0200,0200,0000,
8413795Ssam 	0000,0200,0200,0000,0200,0000,0000,0200,
8513795Ssam 	0200,0000,0000,0200,0000,0200,0200,0000,
8613795Ssam 	0200,0000,0000,0200,0000,0200,0200,0000,
8713795Ssam 	0000,0200,0200,0000,0200,0000,0000,0201
8813795Ssam };
8913795Ssam 
9013795Ssam #define	ERASE	tmode.sg_erase
9113795Ssam #define	KILL	tmode.sg_kill
9213795Ssam #define	EOT	tc.t_eofc
9313795Ssam 
9413795Ssam jmp_buf timeout;
9513795Ssam 
9613795Ssam dingdong()
9713795Ssam {
9813795Ssam 
9913795Ssam 	alarm(0);
10013795Ssam 	signal(SIGALRM, SIG_DFL);
10113795Ssam 	longjmp(timeout, 1);
10213795Ssam }
10313795Ssam 
10413828Skre jmp_buf	intrupt;
10513828Skre 
10613828Skre interrupt()
10713828Skre {
10813828Skre 
10913828Skre 	signal(SIGINT, interrupt);
11013828Skre 	longjmp(intrupt, 1);
11113828Skre }
11213828Skre 
11313795Ssam main(argc, argv)
11413795Ssam 	char *argv[];
11513795Ssam {
11613795Ssam 	char *tname;
11713795Ssam 	long allflags;
11818543Sralph 	int repcnt = 0;
11913795Ssam 
12013828Skre 	signal(SIGINT, SIG_IGN);
12113795Ssam /*
12213795Ssam 	signal(SIGQUIT, SIG_DFL);
12313795Ssam */
12424890Seric 	openlog("getty", LOG_ODELAY|LOG_CONS, LOG_AUTH);
12513795Ssam 	gethostname(hostname, sizeof(hostname));
12613795Ssam 	if (hostname[0] == '\0')
12713795Ssam 		strcpy(hostname, "Amnesiac");
12818543Sralph 	/*
12918543Sralph 	 * The following is a work around for vhangup interactions
13018543Sralph 	 * which cause great problems getting window systems started.
13118543Sralph 	 * If the tty line is "-", we do the old style getty presuming
13218543Sralph 	 * that the file descriptors are already set up for us.
13318543Sralph 	 * J. Gettys - MIT Project Athena.
13418543Sralph 	 */
13518543Sralph 	if (argc <= 2 || strcmp(argv[2], "-") == 0)
13625954Sbloom 	    strcpy(ttyn, ttyname(0));
13718543Sralph 	else {
138*44567Smarc 	    int i;
139*44567Smarc 
14025954Sbloom 	    strcpy(ttyn, dev);
14125954Sbloom 	    strncat(ttyn, argv[2], sizeof(ttyn)-sizeof(dev));
14225954Sbloom 	    if (strcmp(argv[0], "+") != 0) {
14318543Sralph 		chown(ttyn, 0, 0);
144*44567Smarc 		chmod(ttyn, 0600);
145*44567Smarc 		revoke(ttyn);
14625553Smckusick 		/*
14725553Smckusick 		 * Delay the open so DTR stays down long enough to be detected.
14825553Smckusick 		 */
14925553Smckusick 		sleep(2);
150*44567Smarc 		while ((i = open(ttyn, O_RDWR)) == -1) {
15118543Sralph 			if (repcnt % 10 == 0) {
15224895Seric 				syslog(LOG_ERR, "%s: %m", ttyn);
15318543Sralph 				closelog();
15418543Sralph 			}
15518543Sralph 			repcnt++;
15618543Sralph 			sleep(60);
15718543Sralph 		}
158*44567Smarc 		login_tty(i);
15925954Sbloom 	    }
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;
16932209Sbostic 		int off = 0;
17013795Ssam 
17113795Ssam 		gettable(tname, tabent, tabstrs);
17213828Skre 		if (OPset || EPset || APset)
17313828Skre 			APset++, OPset++, EPset++;
17413795Ssam 		setdefaults();
17513795Ssam 		ioctl(0, TIOCFLUSH, 0);		/* clear out the crap */
17632209Sbostic 		ioctl(0, FIONBIO, &off);	/* turn off non-blocking mode */
17732209Sbostic 		ioctl(0, FIOASYNC, &off);	/* ditto for asynchronous mode */
17813795Ssam 		if (IS)
17913795Ssam 			tmode.sg_ispeed = speed(IS);
18013795Ssam 		else if (SP)
18113795Ssam 			tmode.sg_ispeed = speed(SP);
18213795Ssam 		if (OS)
18313795Ssam 			tmode.sg_ospeed = speed(OS);
18413795Ssam 		else if (SP)
18513795Ssam 			tmode.sg_ospeed = speed(SP);
18613795Ssam 		tmode.sg_flags = setflags(0);
18713795Ssam 		ioctl(0, TIOCSETP, &tmode);
18813795Ssam 		setchars();
18913795Ssam 		ioctl(0, TIOCSETC, &tc);
19013795Ssam 		ioctl(0, TIOCSETD, &ldisp);
19113795Ssam 		if (HC)
19213795Ssam 			ioctl(0, TIOCHPCL, 0);
19318543Sralph 		if (AB) {
19418543Sralph 			extern char *autobaud();
19518543Sralph 
19618543Sralph 			tname = autobaud();
19718543Sralph 			continue;
19818543Sralph 		}
19913795Ssam 		if (PS) {
20013795Ssam 			tname = portselector();
20113795Ssam 			continue;
20213795Ssam 		}
20313795Ssam 		if (CL && *CL)
20413795Ssam 			putpad(CL);
20513795Ssam 		edithost(HE);
20613795Ssam 		if (IM && *IM)
20713795Ssam 			putf(IM);
20813795Ssam 		if (setjmp(timeout)) {
20913795Ssam 			tmode.sg_ispeed = tmode.sg_ospeed = 0;
21013795Ssam 			ioctl(0, TIOCSETP, &tmode);
21113795Ssam 			exit(1);
21213795Ssam 		}
21313795Ssam 		if (TO) {
21413795Ssam 			signal(SIGALRM, dingdong);
21513795Ssam 			alarm(TO);
21613795Ssam 		}
21713795Ssam 		if (getname()) {
21818543Sralph 			register int i;
21918543Sralph 
22018543Sralph 			oflush();
22113795Ssam 			alarm(0);
22213795Ssam 			signal(SIGALRM, SIG_DFL);
22332308Sbostic 			if (name[0] == '-') {
22442459Smarc 				puts("user names may not start with '-'.");
22532308Sbostic 				continue;
22632308Sbostic 			}
22713831Ssam 			if (!(upper || lower || digit))
22813795Ssam 				continue;
22913795Ssam 			allflags = setflags(2);
23013795Ssam 			tmode.sg_flags = allflags & 0xffff;
23113795Ssam 			allflags >>= 16;
23213795Ssam 			if (crmod || NL)
23313795Ssam 				tmode.sg_flags |= CRMOD;
23413795Ssam 			if (upper || UC)
23513795Ssam 				tmode.sg_flags |= LCASE;
23613795Ssam 			if (lower || LC)
23713795Ssam 				tmode.sg_flags &= ~LCASE;
23813795Ssam 			ioctl(0, TIOCSETP, &tmode);
23913795Ssam 			ioctl(0, TIOCSLTC, &ltc);
24013795Ssam 			ioctl(0, TIOCLSET, &allflags);
24113828Skre 			signal(SIGINT, SIG_DFL);
24218543Sralph 			for (i = 0; environ[i] != (char *)0; i++)
24318543Sralph 				env[i] = environ[i];
24418543Sralph 			makeenv(&env[i]);
24518543Sralph 			execle(LO, "login", "-p", name, (char *) 0, env);
24632209Sbostic 			syslog(LOG_ERR, "%s: %m", LO);
24713795Ssam 			exit(1);
24813795Ssam 		}
24913795Ssam 		alarm(0);
25013795Ssam 		signal(SIGALRM, SIG_DFL);
25113828Skre 		signal(SIGINT, SIG_IGN);
25213795Ssam 		if (NX && *NX)
25313795Ssam 			tname = NX;
25413795Ssam 	}
25513795Ssam }
25613795Ssam 
25713795Ssam getname()
25813795Ssam {
25913795Ssam 	register char *np;
26013795Ssam 	register c;
26113795Ssam 	char cs;
26213795Ssam 
26313828Skre 	/*
26413831Ssam 	 * Interrupt may happen if we use CBREAK mode
26513828Skre 	 */
26613828Skre 	if (setjmp(intrupt)) {
26713828Skre 		signal(SIGINT, SIG_IGN);
26813828Skre 		return (0);
26913828Skre 	}
27013828Skre 	signal(SIGINT, interrupt);
27113795Ssam 	tmode.sg_flags = setflags(0);
27213795Ssam 	ioctl(0, TIOCSETP, &tmode);
27313795Ssam 	tmode.sg_flags = setflags(1);
27413795Ssam 	prompt();
27513885Ssam 	if (PF > 0) {
27614322Ssam 		oflush();
27713885Ssam 		sleep(PF);
27813885Ssam 		PF = 0;
27913885Ssam 	}
28013795Ssam 	ioctl(0, TIOCSETP, &tmode);
28113795Ssam 	crmod = 0;
28213795Ssam 	upper = 0;
28313795Ssam 	lower = 0;
28413795Ssam 	digit = 0;
28513795Ssam 	np = name;
28613795Ssam 	for (;;) {
28713828Skre 		oflush();
28813795Ssam 		if (read(0, &cs, 1) <= 0)
28913795Ssam 			exit(0);
29013795Ssam 		if ((c = cs&0177) == 0)
29113795Ssam 			return (0);
29213831Ssam 		if (c == EOT)
29313795Ssam 			exit(1);
29418543Sralph 		if (c == '\r' || c == '\n' || np >= &name[sizeof name]) {
29518543Sralph 			putf("\r\n");
29613795Ssam 			break;
29718543Sralph 		}
29842459Smarc 		if (islower(c))
29913795Ssam 			lower++;
30042459Smarc 		else if (isupper(c))
30113795Ssam 			upper++;
30218543Sralph 		else if (c == ERASE || c == '#' || c == '\b') {
30313795Ssam 			if (np > name) {
30413795Ssam 				np--;
30513795Ssam 				if (tmode.sg_ospeed >= B1200)
30613795Ssam 					puts("\b \b");
30713795Ssam 				else
30813795Ssam 					putchr(cs);
30913795Ssam 			}
31013795Ssam 			continue;
31113831Ssam 		} else if (c == KILL || c == '@') {
31213795Ssam 			putchr(cs);
31313795Ssam 			putchr('\r');
31413795Ssam 			if (tmode.sg_ospeed < B1200)
31513795Ssam 				putchr('\n');
31613795Ssam 			/* this is the way they do it down under ... */
31713795Ssam 			else if (np > name)
31813795Ssam 				puts("                                     \r");
31913795Ssam 			prompt();
32013795Ssam 			np = name;
32113795Ssam 			continue;
32242459Smarc 		} else if (isdigit(c))
32313795Ssam 			digit++;
32418543Sralph 		if (IG && (c <= ' ' || c > 0176))
32513795Ssam 			continue;
32613795Ssam 		*np++ = c;
32713795Ssam 		putchr(cs);
32813795Ssam 	}
32913828Skre 	signal(SIGINT, SIG_IGN);
33013795Ssam 	*np = 0;
33113795Ssam 	if (c == '\r')
33213795Ssam 		crmod++;
33313795Ssam 	if (upper && !lower && !LC || UC)
33413795Ssam 		for (np = name; *np; np++)
33513795Ssam 			if (isupper(*np))
33613795Ssam 				*np = tolower(*np);
33713795Ssam 	return (1);
33813795Ssam }
33913795Ssam 
34013795Ssam static
34113795Ssam short	tmspc10[] = {
34213795Ssam 	0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5, 15
34313795Ssam };
34413795Ssam 
34513795Ssam putpad(s)
34613795Ssam 	register char *s;
34713795Ssam {
34813795Ssam 	register pad = 0;
34913795Ssam 	register mspc10;
35013795Ssam 
35113795Ssam 	if (isdigit(*s)) {
35213795Ssam 		while (isdigit(*s)) {
35313795Ssam 			pad *= 10;
35413795Ssam 			pad += *s++ - '0';
35513795Ssam 		}
35613795Ssam 		pad *= 10;
35713795Ssam 		if (*s == '.' && isdigit(s[1])) {
35813795Ssam 			pad += s[1] - '0';
35913795Ssam 			s += 2;
36013795Ssam 		}
36113795Ssam 	}
36213795Ssam 
36313795Ssam 	puts(s);
36413795Ssam 	/*
36513795Ssam 	 * If no delay needed, or output speed is
36613795Ssam 	 * not comprehensible, then don't try to delay.
36713795Ssam 	 */
36813795Ssam 	if (pad == 0)
36913795Ssam 		return;
37013795Ssam 	if (tmode.sg_ospeed <= 0 ||
37113795Ssam 	    tmode.sg_ospeed >= (sizeof tmspc10 / sizeof tmspc10[0]))
37213795Ssam 		return;
37313795Ssam 
37413795Ssam 	/*
37513795Ssam 	 * Round up by a half a character frame,
37613795Ssam 	 * and then do the delay.
37713795Ssam 	 * Too bad there are no user program accessible programmed delays.
37813795Ssam 	 * Transmitting pad characters slows many
37913795Ssam 	 * terminals down and also loads the system.
38013795Ssam 	 */
38113795Ssam 	mspc10 = tmspc10[tmode.sg_ospeed];
38213795Ssam 	pad += mspc10 / 2;
38313795Ssam 	for (pad /= mspc10; pad > 0; pad--)
38413795Ssam 		putchr(*PC);
38513795Ssam }
38613795Ssam 
38713795Ssam puts(s)
38813795Ssam 	register char *s;
38913795Ssam {
39013795Ssam 
39113795Ssam 	while (*s)
39213795Ssam 		putchr(*s++);
39313795Ssam }
39413795Ssam 
39513828Skre char	outbuf[OBUFSIZ];
39613828Skre int	obufcnt = 0;
39713828Skre 
39813795Ssam putchr(cc)
39913795Ssam {
40013795Ssam 	char c;
40113795Ssam 
40213795Ssam 	c = cc;
40313795Ssam 	c |= partab[c&0177] & 0200;
40413795Ssam 	if (OP)
40513795Ssam 		c ^= 0200;
40613828Skre 	if (!UB) {
40713828Skre 		outbuf[obufcnt++] = c;
40813828Skre 		if (obufcnt >= OBUFSIZ)
40913828Skre 			oflush();
41013828Skre 	} else
41113828Skre 		write(1, &c, 1);
41213795Ssam }
41313795Ssam 
41413828Skre oflush()
41513828Skre {
41613828Skre 	if (obufcnt)
41713828Skre 		write(1, outbuf, obufcnt);
41813828Skre 	obufcnt = 0;
41913828Skre }
42013828Skre 
42113795Ssam prompt()
42213795Ssam {
42313795Ssam 
42413795Ssam 	putf(LM);
42513795Ssam 	if (CO)
42613795Ssam 		putchr('\n');
42713795Ssam }
42813795Ssam 
42913795Ssam putf(cp)
43013795Ssam 	register char *cp;
43113795Ssam {
43242460Smckusick 	char *slash;
43318543Sralph 	char datebuffer[60];
43413795Ssam 	extern char editedhost[];
43542460Smckusick 	extern char *rindex();
43613795Ssam 
43713795Ssam 	while (*cp) {
43813795Ssam 		if (*cp != '%') {
43913795Ssam 			putchr(*cp++);
44013795Ssam 			continue;
44113795Ssam 		}
44213795Ssam 		switch (*++cp) {
44313795Ssam 
44418543Sralph 		case 't':
44518543Sralph 			slash = rindex(ttyn, '/');
44618543Sralph 			if (slash == (char *) 0)
44718543Sralph 				puts(ttyn);
44818543Sralph 			else
44918543Sralph 				puts(&slash[1]);
45018543Sralph 			break;
45118543Sralph 
45213795Ssam 		case 'h':
45313795Ssam 			puts(editedhost);
45413795Ssam 			break;
45513795Ssam 
45618543Sralph 		case 'd':
45718543Sralph 			get_date(datebuffer);
45818543Sralph 			puts(datebuffer);
45915713Sralph 			break;
46015713Sralph 
46113795Ssam 		case '%':
46213795Ssam 			putchr('%');
46313795Ssam 			break;
46413795Ssam 		}
46513795Ssam 		cp++;
46613795Ssam 	}
46713795Ssam }
468