146043Sbostic /*-
2*63577Sbostic * Copyright (c) 1980, 1993
3*63577Sbostic * The Regents of the University of California. All rights reserved.
446043Sbostic *
546043Sbostic * %sccs.include.redist.c%
619054Sdist */
719054Sdist
813795Ssam #ifndef lint
9*63577Sbostic static char copyright[] =
10*63577Sbostic "@(#) Copyright (c) 1980, 1993\n\
11*63577Sbostic The Regents of the University of California. All rights reserved.\n";
1246043Sbostic #endif /* not lint */
1313795Ssam
1419054Sdist #ifndef lint
15*63577Sbostic static char sccsid[] = "@(#)main.c 8.1 (Berkeley) 06/20/93";
1646043Sbostic #endif /* not lint */
1719054Sdist
1846043Sbostic #define USE_OLD_TTY
1913795Ssam
2042459Smarc #include <sys/param.h>
2146670Sbostic #include <sys/stat.h>
2261459Smckusick #include <sys/resource.h>
2360091Sbostic
2460091Sbostic #include <ctype.h>
2560091Sbostic #include <ctype.h>
2646670Sbostic #include <fcntl.h>
2760091Sbostic #include <setjmp.h>
2813795Ssam #include <sgtty.h>
2960091Sbostic #include <signal.h>
3060091Sbostic #include <stdlib.h>
3160091Sbostic #include <string.h>
3260091Sbostic #include <syslog.h>
3346670Sbostic #include <time.h>
3446043Sbostic #include <unistd.h>
3560091Sbostic
3613795Ssam #include "gettytab.h"
3742459Smarc #include "pathnames.h"
3860091Sbostic #include "extern.h"
3913795Ssam
4061459Smckusick /*
4161459Smckusick * Set the amount of running time that getty should accumulate
4261459Smckusick * before deciding that something is wrong and exit.
4361459Smckusick */
4461459Smckusick #define GETTY_TIMEOUT 60 /* seconds */
4561459Smckusick
4613795Ssam struct sgttyb tmode = {
4713795Ssam 0, 0, CERASE, CKILL, 0
4813795Ssam };
4913795Ssam struct tchars tc = {
5013795Ssam CINTR, CQUIT, CSTART,
5113795Ssam CSTOP, CEOF, CBRK,
5213795Ssam };
5313795Ssam struct ltchars ltc = {
5413795Ssam CSUSP, CDSUSP, CRPRNT,
5513795Ssam CFLUSH, CWERASE, CLNEXT
5613795Ssam };
5713795Ssam
5846043Sbostic int crmod, digit, lower, upper;
5913795Ssam
6042459Smarc char hostname[MAXHOSTNAMELEN];
6113795Ssam char name[16];
6242459Smarc char dev[] = _PATH_DEV;
6318543Sralph char ttyn[32];
6413795Ssam char *portselector();
6518543Sralph char *ttyname();
6613795Ssam
6713828Skre #define OBUFSIZ 128
6813795Ssam #define TABBUFSIZ 512
6913795Ssam
7013795Ssam char defent[TABBUFSIZ];
7113795Ssam char tabent[TABBUFSIZ];
7213795Ssam
7313795Ssam char *env[128];
7413795Ssam
7513795Ssam char partab[] = {
7613795Ssam 0001,0201,0201,0001,0201,0001,0001,0201,
7713795Ssam 0202,0004,0003,0205,0005,0206,0201,0001,
7813795Ssam 0201,0001,0001,0201,0001,0201,0201,0001,
7913795Ssam 0001,0201,0201,0001,0201,0001,0001,0201,
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 0200,0000,0000,0200,0000,0200,0200,0000,
8513795Ssam 0000,0200,0200,0000,0200,0000,0000,0200,
8613795Ssam 0000,0200,0200,0000,0200,0000,0000,0200,
8713795Ssam 0200,0000,0000,0200,0000,0200,0200,0000,
8813795Ssam 0000,0200,0200,0000,0200,0000,0000,0200,
8913795Ssam 0200,0000,0000,0200,0000,0200,0200,0000,
9013795Ssam 0200,0000,0000,0200,0000,0200,0200,0000,
9113795Ssam 0000,0200,0200,0000,0200,0000,0000,0201
9213795Ssam };
9313795Ssam
9413795Ssam #define ERASE tmode.sg_erase
9513795Ssam #define KILL tmode.sg_kill
9613795Ssam #define EOT tc.t_eofc
9713795Ssam
9813795Ssam jmp_buf timeout;
9913795Ssam
10046670Sbostic static void
dingdong()10113795Ssam dingdong()
10213795Ssam {
10313795Ssam
10413795Ssam alarm(0);
10513795Ssam signal(SIGALRM, SIG_DFL);
10613795Ssam longjmp(timeout, 1);
10713795Ssam }
10813795Ssam
10913828Skre jmp_buf intrupt;
11013828Skre
11146670Sbostic static void
interrupt()11213828Skre interrupt()
11313828Skre {
11413828Skre
11513828Skre signal(SIGINT, interrupt);
11613828Skre longjmp(intrupt, 1);
11713828Skre }
11813828Skre
11961459Smckusick /*
12061459Smckusick * Action to take when getty is running too long.
12161459Smckusick */
12261459Smckusick void
timeoverrun(signo)12363576Sbostic timeoverrun(signo)
12463576Sbostic int signo;
12561459Smckusick {
12661459Smckusick
12761459Smckusick syslog(LOG_ERR, "getty exiting due to excessive running time\n");
12861459Smckusick exit(1);
12961459Smckusick }
13061459Smckusick
13160091Sbostic static int getname __P((void));
13260091Sbostic static void oflush __P((void));
13360091Sbostic static void prompt __P((void));
13460091Sbostic static void putchr __P((int));
13560091Sbostic static void putf __P((char *));
13660091Sbostic static void putpad __P((char *));
13760091Sbostic static void puts __P((char *));
13860091Sbostic
13960091Sbostic int
main(argc,argv)14013795Ssam main(argc, argv)
14146043Sbostic int argc;
14260091Sbostic char *argv[];
14313795Ssam {
14460091Sbostic extern char **environ;
14513795Ssam char *tname;
14613795Ssam long allflags;
14718543Sralph int repcnt = 0;
14861459Smckusick struct rlimit limit;
14913795Ssam
15013828Skre signal(SIGINT, SIG_IGN);
15113795Ssam /*
15213795Ssam signal(SIGQUIT, SIG_DFL);
15313795Ssam */
15424890Seric openlog("getty", LOG_ODELAY|LOG_CONS, LOG_AUTH);
15513795Ssam gethostname(hostname, sizeof(hostname));
15613795Ssam if (hostname[0] == '\0')
15713795Ssam strcpy(hostname, "Amnesiac");
15861459Smckusick
15918543Sralph /*
16061459Smckusick * Limit running time to deal with broken or dead lines.
16161459Smckusick */
16263576Sbostic (void)signal(SIGXCPU, timeoverrun);
16361459Smckusick limit.rlim_max = RLIM_INFINITY;
16461459Smckusick limit.rlim_cur = GETTY_TIMEOUT;
16563576Sbostic (void)setrlimit(RLIMIT_CPU, &limit);
16661459Smckusick
16761459Smckusick /*
16818543Sralph * The following is a work around for vhangup interactions
16918543Sralph * which cause great problems getting window systems started.
17018543Sralph * If the tty line is "-", we do the old style getty presuming
17118543Sralph * that the file descriptors are already set up for us.
17218543Sralph * J. Gettys - MIT Project Athena.
17318543Sralph */
17418543Sralph if (argc <= 2 || strcmp(argv[2], "-") == 0)
17525954Sbloom strcpy(ttyn, ttyname(0));
17618543Sralph else {
17744567Smarc int i;
17844567Smarc
17925954Sbloom strcpy(ttyn, dev);
18025954Sbloom strncat(ttyn, argv[2], sizeof(ttyn)-sizeof(dev));
18125954Sbloom if (strcmp(argv[0], "+") != 0) {
18218543Sralph chown(ttyn, 0, 0);
18344567Smarc chmod(ttyn, 0600);
18444567Smarc revoke(ttyn);
18525553Smckusick /*
18625553Smckusick * Delay the open so DTR stays down long enough to be detected.
18725553Smckusick */
18825553Smckusick sleep(2);
18944567Smarc while ((i = open(ttyn, O_RDWR)) == -1) {
19018543Sralph if (repcnt % 10 == 0) {
19124895Seric syslog(LOG_ERR, "%s: %m", ttyn);
19218543Sralph closelog();
19318543Sralph }
19418543Sralph repcnt++;
19518543Sralph sleep(60);
19618543Sralph }
19744567Smarc login_tty(i);
19825954Sbloom }
19918543Sralph }
20018543Sralph
20160499Selan gettable("default", defent);
20213795Ssam gendefaults();
20313795Ssam tname = "default";
20413795Ssam if (argc > 1)
20513795Ssam tname = argv[1];
20613795Ssam for (;;) {
20753076Sbostic int off;
20813795Ssam
20960499Selan gettable(tname, tabent);
21013828Skre if (OPset || EPset || APset)
21113828Skre APset++, OPset++, EPset++;
21213795Ssam setdefaults();
21353076Sbostic off = 0;
21453076Sbostic ioctl(0, TIOCFLUSH, &off); /* clear out the crap */
21532209Sbostic ioctl(0, FIONBIO, &off); /* turn off non-blocking mode */
21646043Sbostic ioctl(0, FIOASYNC, &off); /* ditto for async mode */
21713795Ssam if (IS)
21813795Ssam tmode.sg_ispeed = speed(IS);
21913795Ssam else if (SP)
22013795Ssam tmode.sg_ispeed = speed(SP);
22113795Ssam if (OS)
22213795Ssam tmode.sg_ospeed = speed(OS);
22313795Ssam else if (SP)
22413795Ssam tmode.sg_ospeed = speed(SP);
22513795Ssam tmode.sg_flags = setflags(0);
22613795Ssam ioctl(0, TIOCSETP, &tmode);
22713795Ssam setchars();
22813795Ssam ioctl(0, TIOCSETC, &tc);
22913795Ssam if (HC)
23013795Ssam ioctl(0, TIOCHPCL, 0);
23118543Sralph if (AB) {
23218543Sralph extern char *autobaud();
23318543Sralph
23418543Sralph tname = autobaud();
23518543Sralph continue;
23618543Sralph }
23713795Ssam if (PS) {
23813795Ssam tname = portselector();
23913795Ssam continue;
24013795Ssam }
24113795Ssam if (CL && *CL)
24213795Ssam putpad(CL);
24313795Ssam edithost(HE);
24413795Ssam if (IM && *IM)
24513795Ssam putf(IM);
24613795Ssam if (setjmp(timeout)) {
24713795Ssam tmode.sg_ispeed = tmode.sg_ospeed = 0;
24813795Ssam ioctl(0, TIOCSETP, &tmode);
24913795Ssam exit(1);
25013795Ssam }
25113795Ssam if (TO) {
25213795Ssam signal(SIGALRM, dingdong);
25313795Ssam alarm(TO);
25413795Ssam }
25513795Ssam if (getname()) {
25618543Sralph register int i;
25718543Sralph
25818543Sralph oflush();
25913795Ssam alarm(0);
26013795Ssam signal(SIGALRM, SIG_DFL);
26132308Sbostic if (name[0] == '-') {
26242459Smarc puts("user names may not start with '-'.");
26332308Sbostic continue;
26432308Sbostic }
26513831Ssam if (!(upper || lower || digit))
26613795Ssam continue;
26713795Ssam allflags = setflags(2);
26813795Ssam tmode.sg_flags = allflags & 0xffff;
26913795Ssam allflags >>= 16;
27013795Ssam if (crmod || NL)
27113795Ssam tmode.sg_flags |= CRMOD;
27213795Ssam if (upper || UC)
27313795Ssam tmode.sg_flags |= LCASE;
27413795Ssam if (lower || LC)
27513795Ssam tmode.sg_flags &= ~LCASE;
27613795Ssam ioctl(0, TIOCSETP, &tmode);
27713795Ssam ioctl(0, TIOCSLTC, <c);
27813795Ssam ioctl(0, TIOCLSET, &allflags);
27913828Skre signal(SIGINT, SIG_DFL);
28018543Sralph for (i = 0; environ[i] != (char *)0; i++)
28118543Sralph env[i] = environ[i];
28218543Sralph makeenv(&env[i]);
28344640Smarc
28444640Smarc /*
28544640Smarc * this is what login was doing anyway.
28644640Smarc * soon we rewrite getty completely.
28744640Smarc */
28844640Smarc set_ttydefaults(0);
28963576Sbostic limit.rlim_max = RLIM_INFINITY;
29063576Sbostic limit.rlim_cur = RLIM_INFINITY;
29163576Sbostic (void)setrlimit(RLIMIT_CPU, &limit);
29218543Sralph execle(LO, "login", "-p", name, (char *) 0, env);
29332209Sbostic syslog(LOG_ERR, "%s: %m", LO);
29413795Ssam exit(1);
29513795Ssam }
29613795Ssam alarm(0);
29713795Ssam signal(SIGALRM, SIG_DFL);
29813828Skre signal(SIGINT, SIG_IGN);
29913795Ssam if (NX && *NX)
30013795Ssam tname = NX;
30113795Ssam }
30213795Ssam }
30313795Ssam
30460091Sbostic static int
getname()30513795Ssam getname()
30613795Ssam {
30746043Sbostic register int c;
30813795Ssam register char *np;
30913795Ssam char cs;
31013795Ssam
31113828Skre /*
31213831Ssam * Interrupt may happen if we use CBREAK mode
31313828Skre */
31413828Skre if (setjmp(intrupt)) {
31513828Skre signal(SIGINT, SIG_IGN);
31613828Skre return (0);
31713828Skre }
31813828Skre signal(SIGINT, interrupt);
31913795Ssam tmode.sg_flags = setflags(0);
32013795Ssam ioctl(0, TIOCSETP, &tmode);
32113795Ssam tmode.sg_flags = setflags(1);
32213795Ssam prompt();
32313885Ssam if (PF > 0) {
32414322Ssam oflush();
32513885Ssam sleep(PF);
32613885Ssam PF = 0;
32713885Ssam }
32813795Ssam ioctl(0, TIOCSETP, &tmode);
32946043Sbostic crmod = digit = lower = upper = 0;
33013795Ssam np = name;
33113795Ssam for (;;) {
33213828Skre oflush();
33346043Sbostic if (read(STDIN_FILENO, &cs, 1) <= 0)
33413795Ssam exit(0);
33513795Ssam if ((c = cs&0177) == 0)
33613795Ssam return (0);
33713831Ssam if (c == EOT)
33813795Ssam exit(1);
33918543Sralph if (c == '\r' || c == '\n' || np >= &name[sizeof name]) {
34018543Sralph putf("\r\n");
34113795Ssam break;
34218543Sralph }
34342459Smarc if (islower(c))
34446043Sbostic lower = 1;
34542459Smarc else if (isupper(c))
34646043Sbostic upper = 1;
34718543Sralph else if (c == ERASE || c == '#' || c == '\b') {
34813795Ssam if (np > name) {
34913795Ssam np--;
35013795Ssam if (tmode.sg_ospeed >= B1200)
35113795Ssam puts("\b \b");
35213795Ssam else
35313795Ssam putchr(cs);
35413795Ssam }
35513795Ssam continue;
35613831Ssam } else if (c == KILL || c == '@') {
35713795Ssam putchr(cs);
35813795Ssam putchr('\r');
35913795Ssam if (tmode.sg_ospeed < B1200)
36013795Ssam putchr('\n');
36113795Ssam /* this is the way they do it down under ... */
36213795Ssam else if (np > name)
36313795Ssam puts(" \r");
36413795Ssam prompt();
36513795Ssam np = name;
36613795Ssam continue;
36742459Smarc } else if (isdigit(c))
36813795Ssam digit++;
36918543Sralph if (IG && (c <= ' ' || c > 0176))
37013795Ssam continue;
37113795Ssam *np++ = c;
37213795Ssam putchr(cs);
37313795Ssam }
37413828Skre signal(SIGINT, SIG_IGN);
37513795Ssam *np = 0;
37613795Ssam if (c == '\r')
37746043Sbostic crmod = 1;
37813795Ssam if (upper && !lower && !LC || UC)
37913795Ssam for (np = name; *np; np++)
38013795Ssam if (isupper(*np))
38113795Ssam *np = tolower(*np);
38213795Ssam return (1);
38313795Ssam }
38413795Ssam
38513795Ssam static
38613795Ssam short tmspc10[] = {
38713795Ssam 0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5, 15
38813795Ssam };
38913795Ssam
39060091Sbostic static void
putpad(s)39113795Ssam putpad(s)
39213795Ssam register char *s;
39313795Ssam {
39413795Ssam register pad = 0;
39513795Ssam register mspc10;
39613795Ssam
39713795Ssam if (isdigit(*s)) {
39813795Ssam while (isdigit(*s)) {
39913795Ssam pad *= 10;
40013795Ssam pad += *s++ - '0';
40113795Ssam }
40213795Ssam pad *= 10;
40313795Ssam if (*s == '.' && isdigit(s[1])) {
40413795Ssam pad += s[1] - '0';
40513795Ssam s += 2;
40613795Ssam }
40713795Ssam }
40813795Ssam
40913795Ssam puts(s);
41013795Ssam /*
41113795Ssam * If no delay needed, or output speed is
41213795Ssam * not comprehensible, then don't try to delay.
41313795Ssam */
41413795Ssam if (pad == 0)
41513795Ssam return;
41613795Ssam if (tmode.sg_ospeed <= 0 ||
41713795Ssam tmode.sg_ospeed >= (sizeof tmspc10 / sizeof tmspc10[0]))
41813795Ssam return;
41913795Ssam
42013795Ssam /*
42146043Sbostic * Round up by a half a character frame, and then do the delay.
42213795Ssam * Too bad there are no user program accessible programmed delays.
42346043Sbostic * Transmitting pad characters slows many terminals down and also
42446043Sbostic * loads the system.
42513795Ssam */
42613795Ssam mspc10 = tmspc10[tmode.sg_ospeed];
42713795Ssam pad += mspc10 / 2;
42813795Ssam for (pad /= mspc10; pad > 0; pad--)
42913795Ssam putchr(*PC);
43013795Ssam }
43113795Ssam
43260091Sbostic static void
puts(s)43313795Ssam puts(s)
43413795Ssam register char *s;
43513795Ssam {
43613795Ssam while (*s)
43713795Ssam putchr(*s++);
43813795Ssam }
43913795Ssam
44013828Skre char outbuf[OBUFSIZ];
44113828Skre int obufcnt = 0;
44213828Skre
44360091Sbostic static void
putchr(cc)44413795Ssam putchr(cc)
44560091Sbostic int cc;
44613795Ssam {
44713795Ssam char c;
44813795Ssam
44913795Ssam c = cc;
45047664Swilliam if (!NP) {
45147664Swilliam c |= partab[c&0177] & 0200;
45247664Swilliam if (OP)
45347664Swilliam c ^= 0200;
45447664Swilliam }
45513828Skre if (!UB) {
45613828Skre outbuf[obufcnt++] = c;
45713828Skre if (obufcnt >= OBUFSIZ)
45813828Skre oflush();
45913828Skre } else
46046043Sbostic write(STDOUT_FILENO, &c, 1);
46113795Ssam }
46213795Ssam
46360091Sbostic static void
oflush()46413828Skre oflush()
46513828Skre {
46613828Skre if (obufcnt)
46746043Sbostic write(STDOUT_FILENO, outbuf, obufcnt);
46813828Skre obufcnt = 0;
46913828Skre }
47013828Skre
47160091Sbostic static void
prompt()47213795Ssam prompt()
47313795Ssam {
47413795Ssam
47513795Ssam putf(LM);
47613795Ssam if (CO)
47713795Ssam putchr('\n');
47813795Ssam }
47913795Ssam
48060091Sbostic static void
putf(cp)48113795Ssam putf(cp)
48213795Ssam register char *cp;
48313795Ssam {
48413795Ssam extern char editedhost[];
48546043Sbostic time_t t;
48646670Sbostic char *slash, db[100];
48713795Ssam
48813795Ssam while (*cp) {
48913795Ssam if (*cp != '%') {
49013795Ssam putchr(*cp++);
49113795Ssam continue;
49213795Ssam }
49313795Ssam switch (*++cp) {
49413795Ssam
49518543Sralph case 't':
49660091Sbostic slash = strrchr(ttyn, '/');
49718543Sralph if (slash == (char *) 0)
49818543Sralph puts(ttyn);
49918543Sralph else
50018543Sralph puts(&slash[1]);
50118543Sralph break;
50218543Sralph
50313795Ssam case 'h':
50413795Ssam puts(editedhost);
50513795Ssam break;
50613795Ssam
50746670Sbostic case 'd': {
50846967Sbostic static char fmt[] = "%l:% %P on %A, %d %B %Y";
50946670Sbostic
51046670Sbostic fmt[4] = 'M'; /* I *hate* SCCS... */
51146043Sbostic (void)time(&t);
51246670Sbostic (void)strftime(db, sizeof(db), fmt, localtime(&t));
51346043Sbostic puts(db);
51415713Sralph break;
51546670Sbostic }
51615713Sralph
51713795Ssam case '%':
51813795Ssam putchr('%');
51913795Ssam break;
52013795Ssam }
52113795Ssam cp++;
52213795Ssam }
52313795Ssam }
524