xref: /csrg-svn/libexec/getty/main.c (revision 19054)
1*19054Sdist /*
2*19054Sdist  * Copyright (c) 1980 Regents of the University of California.
3*19054Sdist  * All rights reserved.  The Berkeley software License Agreement
4*19054Sdist  * specifies the terms and conditions for redistribution.
5*19054Sdist  */
6*19054Sdist 
713795Ssam #ifndef lint
8*19054Sdist char copyright[] =
9*19054Sdist "@(#) Copyright (c) 1980 Regents of the University of California.\n\
10*19054Sdist  All rights reserved.\n";
11*19054Sdist #endif not lint
1213795Ssam 
13*19054Sdist #ifndef lint
14*19054Sdist static char sccsid[] = "@(#)main.c	5.1 (Berkeley) 04/29/85";
15*19054Sdist #endif not lint
16*19054Sdist 
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 */
12118543Sralph 	openlog("getty", LOG_ODELAY|LOG_CONS, 0);
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);
13918543Sralph 		while (open(ttyn, O_RDWR) != 0) {
14018543Sralph 			if (repcnt % 10 == 0) {
14118543Sralph 				syslog(LOG_FAIL, "%s: %m", ttyn);
14218543Sralph 				closelog();
14318543Sralph 			}
14418543Sralph 			repcnt++;
14518543Sralph 			sleep(60);
14618543Sralph 		}
14718543Sralph 		signal(SIGHUP, SIG_IGN);
14818543Sralph 		vhangup();
14918543Sralph 		(void) open(ttyn, O_RDWR);
15018543Sralph 		close(0);
15118543Sralph 		dup(1);
15218543Sralph 		dup(0);
15318543Sralph 		signal(SIGHUP, SIG_DFL);
15418543Sralph 	}
15518543Sralph 
15613795Ssam 	gettable("default", defent, defstrs);
15713795Ssam 	gendefaults();
15813795Ssam 	tname = "default";
15913795Ssam 	if (argc > 1)
16013795Ssam 		tname = argv[1];
16113795Ssam 	for (;;) {
16213795Ssam 		int ldisp = OTTYDISC;
16313795Ssam 
16413795Ssam 		gettable(tname, tabent, tabstrs);
16513828Skre 		if (OPset || EPset || APset)
16613828Skre 			APset++, OPset++, EPset++;
16713795Ssam 		setdefaults();
16813795Ssam 		ioctl(0, TIOCFLUSH, 0);		/* clear out the crap */
16913795Ssam 		if (IS)
17013795Ssam 			tmode.sg_ispeed = speed(IS);
17113795Ssam 		else if (SP)
17213795Ssam 			tmode.sg_ispeed = speed(SP);
17313795Ssam 		if (OS)
17413795Ssam 			tmode.sg_ospeed = speed(OS);
17513795Ssam 		else if (SP)
17613795Ssam 			tmode.sg_ospeed = speed(SP);
17713795Ssam 		tmode.sg_flags = setflags(0);
17813795Ssam 		ioctl(0, TIOCSETP, &tmode);
17913795Ssam 		setchars();
18013795Ssam 		ioctl(0, TIOCSETC, &tc);
18113795Ssam 		ioctl(0, TIOCSETD, &ldisp);
18213795Ssam 		if (HC)
18313795Ssam 			ioctl(0, TIOCHPCL, 0);
18418543Sralph 		if (AB) {
18518543Sralph 			extern char *autobaud();
18618543Sralph 
18718543Sralph 			tname = autobaud();
18818543Sralph 			continue;
18918543Sralph 		}
19013795Ssam 		if (PS) {
19113795Ssam 			tname = portselector();
19213795Ssam 			continue;
19313795Ssam 		}
19413795Ssam 		if (CL && *CL)
19513795Ssam 			putpad(CL);
19613795Ssam 		edithost(HE);
19713795Ssam 		if (IM && *IM)
19813795Ssam 			putf(IM);
19913795Ssam 		if (setjmp(timeout)) {
20013795Ssam 			tmode.sg_ispeed = tmode.sg_ospeed = 0;
20113795Ssam 			ioctl(0, TIOCSETP, &tmode);
20213795Ssam 			exit(1);
20313795Ssam 		}
20413795Ssam 		if (TO) {
20513795Ssam 			signal(SIGALRM, dingdong);
20613795Ssam 			alarm(TO);
20713795Ssam 		}
20813795Ssam 		if (getname()) {
20918543Sralph 			register int i;
21018543Sralph 
21118543Sralph 			oflush();
21213795Ssam 			alarm(0);
21313795Ssam 			signal(SIGALRM, SIG_DFL);
21413831Ssam 			if (!(upper || lower || digit))
21513795Ssam 				continue;
21613795Ssam 			allflags = setflags(2);
21713795Ssam 			tmode.sg_flags = allflags & 0xffff;
21813795Ssam 			allflags >>= 16;
21913795Ssam 			if (crmod || NL)
22013795Ssam 				tmode.sg_flags |= CRMOD;
22113795Ssam 			if (upper || UC)
22213795Ssam 				tmode.sg_flags |= LCASE;
22313795Ssam 			if (lower || LC)
22413795Ssam 				tmode.sg_flags &= ~LCASE;
22513795Ssam 			ioctl(0, TIOCSETP, &tmode);
22613795Ssam 			ioctl(0, TIOCSLTC, &ltc);
22713795Ssam 			ioctl(0, TIOCLSET, &allflags);
22813828Skre 			signal(SIGINT, SIG_DFL);
22918543Sralph 			for (i = 0; environ[i] != (char *)0; i++)
23018543Sralph 				env[i] = environ[i];
23118543Sralph 			makeenv(&env[i]);
23218543Sralph 			execle(LO, "login", "-p", name, (char *) 0, env);
23313795Ssam 			exit(1);
23413795Ssam 		}
23513795Ssam 		alarm(0);
23613795Ssam 		signal(SIGALRM, SIG_DFL);
23713828Skre 		signal(SIGINT, SIG_IGN);
23813795Ssam 		if (NX && *NX)
23913795Ssam 			tname = NX;
24013795Ssam 	}
24113795Ssam }
24213795Ssam 
24313795Ssam getname()
24413795Ssam {
24513795Ssam 	register char *np;
24613795Ssam 	register c;
24713795Ssam 	char cs;
24813795Ssam 
24913828Skre 	/*
25013831Ssam 	 * Interrupt may happen if we use CBREAK mode
25113828Skre 	 */
25213828Skre 	if (setjmp(intrupt)) {
25313828Skre 		signal(SIGINT, SIG_IGN);
25413828Skre 		return (0);
25513828Skre 	}
25613828Skre 	signal(SIGINT, interrupt);
25713795Ssam 	tmode.sg_flags = setflags(0);
25813795Ssam 	ioctl(0, TIOCSETP, &tmode);
25913795Ssam 	tmode.sg_flags = setflags(1);
26013795Ssam 	prompt();
26113885Ssam 	if (PF > 0) {
26214322Ssam 		oflush();
26313885Ssam 		sleep(PF);
26413885Ssam 		PF = 0;
26513885Ssam 	}
26613795Ssam 	ioctl(0, TIOCSETP, &tmode);
26713795Ssam 	crmod = 0;
26813795Ssam 	upper = 0;
26913795Ssam 	lower = 0;
27013795Ssam 	digit = 0;
27113795Ssam 	np = name;
27213795Ssam 	for (;;) {
27313828Skre 		oflush();
27413795Ssam 		if (read(0, &cs, 1) <= 0)
27513795Ssam 			exit(0);
27613795Ssam 		if ((c = cs&0177) == 0)
27713795Ssam 			return (0);
27813831Ssam 		if (c == EOT)
27913795Ssam 			exit(1);
28018543Sralph 		if (c == '\r' || c == '\n' || np >= &name[sizeof name]) {
28118543Sralph 			putf("\r\n");
28213795Ssam 			break;
28318543Sralph 		}
28413831Ssam 		if (c >= 'a' && c <= 'z')
28513795Ssam 			lower++;
28618543Sralph 		else if (c >= 'A' && c <= 'Z')
28713795Ssam 			upper++;
28818543Sralph 		else if (c == ERASE || c == '#' || c == '\b') {
28913795Ssam 			if (np > name) {
29013795Ssam 				np--;
29113795Ssam 				if (tmode.sg_ospeed >= B1200)
29213795Ssam 					puts("\b \b");
29313795Ssam 				else
29413795Ssam 					putchr(cs);
29513795Ssam 			}
29613795Ssam 			continue;
29713831Ssam 		} else if (c == KILL || c == '@') {
29813795Ssam 			putchr(cs);
29913795Ssam 			putchr('\r');
30013795Ssam 			if (tmode.sg_ospeed < B1200)
30113795Ssam 				putchr('\n');
30213795Ssam 			/* this is the way they do it down under ... */
30313795Ssam 			else if (np > name)
30413795Ssam 				puts("                                     \r");
30513795Ssam 			prompt();
30613795Ssam 			np = name;
30713795Ssam 			continue;
30818543Sralph 		} else if (c >= '0' && c <= '9')
30913795Ssam 			digit++;
31018543Sralph 		if (IG && (c <= ' ' || c > 0176))
31113795Ssam 			continue;
31213795Ssam 		*np++ = c;
31313795Ssam 		putchr(cs);
31413795Ssam 	}
31513828Skre 	signal(SIGINT, SIG_IGN);
31613795Ssam 	*np = 0;
31713795Ssam 	if (c == '\r')
31813795Ssam 		crmod++;
31913795Ssam 	if (upper && !lower && !LC || UC)
32013795Ssam 		for (np = name; *np; np++)
32113795Ssam 			if (isupper(*np))
32213795Ssam 				*np = tolower(*np);
32313795Ssam 	return (1);
32413795Ssam }
32513795Ssam 
32613795Ssam static
32713795Ssam short	tmspc10[] = {
32813795Ssam 	0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5, 15
32913795Ssam };
33013795Ssam 
33113795Ssam putpad(s)
33213795Ssam 	register char *s;
33313795Ssam {
33413795Ssam 	register pad = 0;
33513795Ssam 	register mspc10;
33613795Ssam 
33713795Ssam 	if (isdigit(*s)) {
33813795Ssam 		while (isdigit(*s)) {
33913795Ssam 			pad *= 10;
34013795Ssam 			pad += *s++ - '0';
34113795Ssam 		}
34213795Ssam 		pad *= 10;
34313795Ssam 		if (*s == '.' && isdigit(s[1])) {
34413795Ssam 			pad += s[1] - '0';
34513795Ssam 			s += 2;
34613795Ssam 		}
34713795Ssam 	}
34813795Ssam 
34913795Ssam 	puts(s);
35013795Ssam 	/*
35113795Ssam 	 * If no delay needed, or output speed is
35213795Ssam 	 * not comprehensible, then don't try to delay.
35313795Ssam 	 */
35413795Ssam 	if (pad == 0)
35513795Ssam 		return;
35613795Ssam 	if (tmode.sg_ospeed <= 0 ||
35713795Ssam 	    tmode.sg_ospeed >= (sizeof tmspc10 / sizeof tmspc10[0]))
35813795Ssam 		return;
35913795Ssam 
36013795Ssam 	/*
36113795Ssam 	 * Round up by a half a character frame,
36213795Ssam 	 * and then do the delay.
36313795Ssam 	 * Too bad there are no user program accessible programmed delays.
36413795Ssam 	 * Transmitting pad characters slows many
36513795Ssam 	 * terminals down and also loads the system.
36613795Ssam 	 */
36713795Ssam 	mspc10 = tmspc10[tmode.sg_ospeed];
36813795Ssam 	pad += mspc10 / 2;
36913795Ssam 	for (pad /= mspc10; pad > 0; pad--)
37013795Ssam 		putchr(*PC);
37113795Ssam }
37213795Ssam 
37313795Ssam puts(s)
37413795Ssam 	register char *s;
37513795Ssam {
37613795Ssam 
37713795Ssam 	while (*s)
37813795Ssam 		putchr(*s++);
37913795Ssam }
38013795Ssam 
38113828Skre char	outbuf[OBUFSIZ];
38213828Skre int	obufcnt = 0;
38313828Skre 
38413795Ssam putchr(cc)
38513795Ssam {
38613795Ssam 	char c;
38713795Ssam 
38813795Ssam 	c = cc;
38913795Ssam 	c |= partab[c&0177] & 0200;
39013795Ssam 	if (OP)
39113795Ssam 		c ^= 0200;
39213828Skre 	if (!UB) {
39313828Skre 		outbuf[obufcnt++] = c;
39413828Skre 		if (obufcnt >= OBUFSIZ)
39513828Skre 			oflush();
39613828Skre 	} else
39713828Skre 		write(1, &c, 1);
39813795Ssam }
39913795Ssam 
40013828Skre oflush()
40113828Skre {
40213828Skre 	if (obufcnt)
40313828Skre 		write(1, outbuf, obufcnt);
40413828Skre 	obufcnt = 0;
40513828Skre }
40613828Skre 
40713795Ssam prompt()
40813795Ssam {
40913795Ssam 
41013795Ssam 	putf(LM);
41113795Ssam 	if (CO)
41213795Ssam 		putchr('\n');
41313795Ssam }
41413795Ssam 
41513795Ssam putf(cp)
41613795Ssam 	register char *cp;
41713795Ssam {
41818543Sralph 	char *ttyn, *slash;
41918543Sralph 	char datebuffer[60];
42013795Ssam 	extern char editedhost[];
42118543Sralph 	extern char *ttyname(), *rindex();
42213795Ssam 
42313795Ssam 	while (*cp) {
42413795Ssam 		if (*cp != '%') {
42513795Ssam 			putchr(*cp++);
42613795Ssam 			continue;
42713795Ssam 		}
42813795Ssam 		switch (*++cp) {
42913795Ssam 
43018543Sralph 		case 't':
43118543Sralph 			ttyn = ttyname(0);
43218543Sralph 			slash = rindex(ttyn, '/');
43318543Sralph 			if (slash == (char *) 0)
43418543Sralph 				puts(ttyn);
43518543Sralph 			else
43618543Sralph 				puts(&slash[1]);
43718543Sralph 			break;
43818543Sralph 
43913795Ssam 		case 'h':
44013795Ssam 			puts(editedhost);
44113795Ssam 			break;
44213795Ssam 
44318543Sralph 		case 'd':
44418543Sralph 			get_date(datebuffer);
44518543Sralph 			puts(datebuffer);
44615713Sralph 			break;
44715713Sralph 
44813795Ssam 		case '%':
44913795Ssam 			putchr('%');
45013795Ssam 			break;
45113795Ssam 		}
45213795Ssam 		cp++;
45313795Ssam 	}
45413795Ssam }
455