146043Sbostic /*- 246043Sbostic * Copyright (c) 1980 The Regents of the University of California. 346043Sbostic * All rights reserved. 446043Sbostic * 546043Sbostic * %sccs.include.redist.c% 619054Sdist */ 719054Sdist 813795Ssam #ifndef lint 919054Sdist char copyright[] = 1046043Sbostic "@(#) Copyright (c) 1980 The Regents of the University of California.\n\ 1119054Sdist All rights reserved.\n"; 1246043Sbostic #endif /* not lint */ 1313795Ssam 1419054Sdist #ifndef lint 15*60091Sbostic static char sccsid[] = "@(#)main.c 5.19 (Berkeley) 05/17/93"; 1646043Sbostic #endif /* not lint */ 1719054Sdist 1846043Sbostic #define USE_OLD_TTY 1913795Ssam 2042459Smarc #include <sys/param.h> 2146670Sbostic #include <sys/stat.h> 22*60091Sbostic 23*60091Sbostic #include <ctype.h> 24*60091Sbostic #include <ctype.h> 2546670Sbostic #include <fcntl.h> 26*60091Sbostic #include <setjmp.h> 2713795Ssam #include <sgtty.h> 28*60091Sbostic #include <signal.h> 29*60091Sbostic #include <stdlib.h> 30*60091Sbostic #include <string.h> 31*60091Sbostic #include <syslog.h> 3246670Sbostic #include <time.h> 3346043Sbostic #include <unistd.h> 34*60091Sbostic 3513795Ssam #include "gettytab.h" 3642459Smarc #include "pathnames.h" 37*60091Sbostic #include "extern.h" 3813795Ssam 3913795Ssam struct sgttyb tmode = { 4013795Ssam 0, 0, CERASE, CKILL, 0 4113795Ssam }; 4213795Ssam struct tchars tc = { 4313795Ssam CINTR, CQUIT, CSTART, 4413795Ssam CSTOP, CEOF, CBRK, 4513795Ssam }; 4613795Ssam struct ltchars ltc = { 4713795Ssam CSUSP, CDSUSP, CRPRNT, 4813795Ssam CFLUSH, CWERASE, CLNEXT 4913795Ssam }; 5013795Ssam 5146043Sbostic int crmod, digit, lower, upper; 5213795Ssam 5342459Smarc char hostname[MAXHOSTNAMELEN]; 5413795Ssam char name[16]; 5542459Smarc char dev[] = _PATH_DEV; 5618543Sralph char ttyn[32]; 5713795Ssam char *portselector(); 5818543Sralph char *ttyname(); 5913795Ssam 6013828Skre #define OBUFSIZ 128 6113795Ssam #define TABBUFSIZ 512 6213795Ssam 6313795Ssam char defent[TABBUFSIZ]; 6413795Ssam char defstrs[TABBUFSIZ]; 6513795Ssam char tabent[TABBUFSIZ]; 6613795Ssam char tabstrs[TABBUFSIZ]; 6713795Ssam 6813795Ssam char *env[128]; 6913795Ssam 7013795Ssam char partab[] = { 7113795Ssam 0001,0201,0201,0001,0201,0001,0001,0201, 7213795Ssam 0202,0004,0003,0205,0005,0206,0201,0001, 7313795Ssam 0201,0001,0001,0201,0001,0201,0201,0001, 7413795Ssam 0001,0201,0201,0001,0201,0001,0001,0201, 7513795Ssam 0200,0000,0000,0200,0000,0200,0200,0000, 7613795Ssam 0000,0200,0200,0000,0200,0000,0000,0200, 7713795Ssam 0000,0200,0200,0000,0200,0000,0000,0200, 7813795Ssam 0200,0000,0000,0200,0000,0200,0200,0000, 7913795Ssam 0200,0000,0000,0200,0000,0200,0200,0000, 8013795Ssam 0000,0200,0200,0000,0200,0000,0000,0200, 8113795Ssam 0000,0200,0200,0000,0200,0000,0000,0200, 8213795Ssam 0200,0000,0000,0200,0000,0200,0200,0000, 8313795Ssam 0000,0200,0200,0000,0200,0000,0000,0200, 8413795Ssam 0200,0000,0000,0200,0000,0200,0200,0000, 8513795Ssam 0200,0000,0000,0200,0000,0200,0200,0000, 8613795Ssam 0000,0200,0200,0000,0200,0000,0000,0201 8713795Ssam }; 8813795Ssam 8913795Ssam #define ERASE tmode.sg_erase 9013795Ssam #define KILL tmode.sg_kill 9113795Ssam #define EOT tc.t_eofc 9213795Ssam 9313795Ssam jmp_buf timeout; 9413795Ssam 9546670Sbostic static void 9613795Ssam dingdong() 9713795Ssam { 9813795Ssam 9913795Ssam alarm(0); 10013795Ssam signal(SIGALRM, SIG_DFL); 10113795Ssam longjmp(timeout, 1); 10213795Ssam } 10313795Ssam 10413828Skre jmp_buf intrupt; 10513828Skre 10646670Sbostic static void 10713828Skre interrupt() 10813828Skre { 10913828Skre 11013828Skre signal(SIGINT, interrupt); 11113828Skre longjmp(intrupt, 1); 11213828Skre } 11313828Skre 114*60091Sbostic static int getname __P((void)); 115*60091Sbostic static void oflush __P((void)); 116*60091Sbostic static void prompt __P((void)); 117*60091Sbostic static void putchr __P((int)); 118*60091Sbostic static void putf __P((char *)); 119*60091Sbostic static void putpad __P((char *)); 120*60091Sbostic static void puts __P((char *)); 121*60091Sbostic 122*60091Sbostic int 12313795Ssam main(argc, argv) 12446043Sbostic int argc; 125*60091Sbostic char *argv[]; 12613795Ssam { 127*60091Sbostic extern char **environ; 12813795Ssam char *tname; 12913795Ssam long allflags; 13018543Sralph int repcnt = 0; 13113795Ssam 13213828Skre signal(SIGINT, SIG_IGN); 13313795Ssam /* 13413795Ssam signal(SIGQUIT, SIG_DFL); 13513795Ssam */ 13624890Seric openlog("getty", LOG_ODELAY|LOG_CONS, LOG_AUTH); 13713795Ssam gethostname(hostname, sizeof(hostname)); 13813795Ssam if (hostname[0] == '\0') 13913795Ssam strcpy(hostname, "Amnesiac"); 14018543Sralph /* 14118543Sralph * The following is a work around for vhangup interactions 14218543Sralph * which cause great problems getting window systems started. 14318543Sralph * If the tty line is "-", we do the old style getty presuming 14418543Sralph * that the file descriptors are already set up for us. 14518543Sralph * J. Gettys - MIT Project Athena. 14618543Sralph */ 14718543Sralph if (argc <= 2 || strcmp(argv[2], "-") == 0) 14825954Sbloom strcpy(ttyn, ttyname(0)); 14918543Sralph else { 15044567Smarc int i; 15144567Smarc 15225954Sbloom strcpy(ttyn, dev); 15325954Sbloom strncat(ttyn, argv[2], sizeof(ttyn)-sizeof(dev)); 15425954Sbloom if (strcmp(argv[0], "+") != 0) { 15518543Sralph chown(ttyn, 0, 0); 15644567Smarc chmod(ttyn, 0600); 15744567Smarc revoke(ttyn); 15825553Smckusick /* 15925553Smckusick * Delay the open so DTR stays down long enough to be detected. 16025553Smckusick */ 16125553Smckusick sleep(2); 16244567Smarc while ((i = open(ttyn, O_RDWR)) == -1) { 16318543Sralph if (repcnt % 10 == 0) { 16424895Seric syslog(LOG_ERR, "%s: %m", ttyn); 16518543Sralph closelog(); 16618543Sralph } 16718543Sralph repcnt++; 16818543Sralph sleep(60); 16918543Sralph } 17044567Smarc login_tty(i); 17125954Sbloom } 17218543Sralph } 17318543Sralph 17413795Ssam gettable("default", defent, defstrs); 17513795Ssam gendefaults(); 17613795Ssam tname = "default"; 17713795Ssam if (argc > 1) 17813795Ssam tname = argv[1]; 17913795Ssam for (;;) { 18053076Sbostic int off; 18113795Ssam 18213795Ssam gettable(tname, tabent, tabstrs); 18313828Skre if (OPset || EPset || APset) 18413828Skre APset++, OPset++, EPset++; 18513795Ssam setdefaults(); 18653076Sbostic off = 0; 18753076Sbostic ioctl(0, TIOCFLUSH, &off); /* clear out the crap */ 18832209Sbostic ioctl(0, FIONBIO, &off); /* turn off non-blocking mode */ 18946043Sbostic ioctl(0, FIOASYNC, &off); /* ditto for async mode */ 19013795Ssam if (IS) 19113795Ssam tmode.sg_ispeed = speed(IS); 19213795Ssam else if (SP) 19313795Ssam tmode.sg_ispeed = speed(SP); 19413795Ssam if (OS) 19513795Ssam tmode.sg_ospeed = speed(OS); 19613795Ssam else if (SP) 19713795Ssam tmode.sg_ospeed = speed(SP); 19813795Ssam tmode.sg_flags = setflags(0); 19913795Ssam ioctl(0, TIOCSETP, &tmode); 20013795Ssam setchars(); 20113795Ssam ioctl(0, TIOCSETC, &tc); 20213795Ssam if (HC) 20313795Ssam ioctl(0, TIOCHPCL, 0); 20418543Sralph if (AB) { 20518543Sralph extern char *autobaud(); 20618543Sralph 20718543Sralph tname = autobaud(); 20818543Sralph continue; 20918543Sralph } 21013795Ssam if (PS) { 21113795Ssam tname = portselector(); 21213795Ssam continue; 21313795Ssam } 21413795Ssam if (CL && *CL) 21513795Ssam putpad(CL); 21613795Ssam edithost(HE); 21713795Ssam if (IM && *IM) 21813795Ssam putf(IM); 21913795Ssam if (setjmp(timeout)) { 22013795Ssam tmode.sg_ispeed = tmode.sg_ospeed = 0; 22113795Ssam ioctl(0, TIOCSETP, &tmode); 22213795Ssam exit(1); 22313795Ssam } 22413795Ssam if (TO) { 22513795Ssam signal(SIGALRM, dingdong); 22613795Ssam alarm(TO); 22713795Ssam } 22813795Ssam if (getname()) { 22918543Sralph register int i; 23018543Sralph 23118543Sralph oflush(); 23213795Ssam alarm(0); 23313795Ssam signal(SIGALRM, SIG_DFL); 23432308Sbostic if (name[0] == '-') { 23542459Smarc puts("user names may not start with '-'."); 23632308Sbostic continue; 23732308Sbostic } 23813831Ssam if (!(upper || lower || digit)) 23913795Ssam continue; 24013795Ssam allflags = setflags(2); 24113795Ssam tmode.sg_flags = allflags & 0xffff; 24213795Ssam allflags >>= 16; 24313795Ssam if (crmod || NL) 24413795Ssam tmode.sg_flags |= CRMOD; 24513795Ssam if (upper || UC) 24613795Ssam tmode.sg_flags |= LCASE; 24713795Ssam if (lower || LC) 24813795Ssam tmode.sg_flags &= ~LCASE; 24913795Ssam ioctl(0, TIOCSETP, &tmode); 25013795Ssam ioctl(0, TIOCSLTC, <c); 25113795Ssam ioctl(0, TIOCLSET, &allflags); 25213828Skre signal(SIGINT, SIG_DFL); 25318543Sralph for (i = 0; environ[i] != (char *)0; i++) 25418543Sralph env[i] = environ[i]; 25518543Sralph makeenv(&env[i]); 25644640Smarc 25744640Smarc /* 25844640Smarc * this is what login was doing anyway. 25944640Smarc * soon we rewrite getty completely. 26044640Smarc */ 26144640Smarc set_ttydefaults(0); 26218543Sralph execle(LO, "login", "-p", name, (char *) 0, env); 26332209Sbostic syslog(LOG_ERR, "%s: %m", LO); 26413795Ssam exit(1); 26513795Ssam } 26613795Ssam alarm(0); 26713795Ssam signal(SIGALRM, SIG_DFL); 26813828Skre signal(SIGINT, SIG_IGN); 26913795Ssam if (NX && *NX) 27013795Ssam tname = NX; 27113795Ssam } 27213795Ssam } 27313795Ssam 274*60091Sbostic static int 27513795Ssam getname() 27613795Ssam { 27746043Sbostic register int c; 27813795Ssam register char *np; 27913795Ssam char cs; 28013795Ssam 28113828Skre /* 28213831Ssam * Interrupt may happen if we use CBREAK mode 28313828Skre */ 28413828Skre if (setjmp(intrupt)) { 28513828Skre signal(SIGINT, SIG_IGN); 28613828Skre return (0); 28713828Skre } 28813828Skre signal(SIGINT, interrupt); 28913795Ssam tmode.sg_flags = setflags(0); 29013795Ssam ioctl(0, TIOCSETP, &tmode); 29113795Ssam tmode.sg_flags = setflags(1); 29213795Ssam prompt(); 29313885Ssam if (PF > 0) { 29414322Ssam oflush(); 29513885Ssam sleep(PF); 29613885Ssam PF = 0; 29713885Ssam } 29813795Ssam ioctl(0, TIOCSETP, &tmode); 29946043Sbostic crmod = digit = lower = upper = 0; 30013795Ssam np = name; 30113795Ssam for (;;) { 30213828Skre oflush(); 30346043Sbostic if (read(STDIN_FILENO, &cs, 1) <= 0) 30413795Ssam exit(0); 30513795Ssam if ((c = cs&0177) == 0) 30613795Ssam return (0); 30713831Ssam if (c == EOT) 30813795Ssam exit(1); 30918543Sralph if (c == '\r' || c == '\n' || np >= &name[sizeof name]) { 31018543Sralph putf("\r\n"); 31113795Ssam break; 31218543Sralph } 31342459Smarc if (islower(c)) 31446043Sbostic lower = 1; 31542459Smarc else if (isupper(c)) 31646043Sbostic upper = 1; 31718543Sralph else if (c == ERASE || c == '#' || c == '\b') { 31813795Ssam if (np > name) { 31913795Ssam np--; 32013795Ssam if (tmode.sg_ospeed >= B1200) 32113795Ssam puts("\b \b"); 32213795Ssam else 32313795Ssam putchr(cs); 32413795Ssam } 32513795Ssam continue; 32613831Ssam } else if (c == KILL || c == '@') { 32713795Ssam putchr(cs); 32813795Ssam putchr('\r'); 32913795Ssam if (tmode.sg_ospeed < B1200) 33013795Ssam putchr('\n'); 33113795Ssam /* this is the way they do it down under ... */ 33213795Ssam else if (np > name) 33313795Ssam puts(" \r"); 33413795Ssam prompt(); 33513795Ssam np = name; 33613795Ssam continue; 33742459Smarc } else if (isdigit(c)) 33813795Ssam digit++; 33918543Sralph if (IG && (c <= ' ' || c > 0176)) 34013795Ssam continue; 34113795Ssam *np++ = c; 34213795Ssam putchr(cs); 34313795Ssam } 34413828Skre signal(SIGINT, SIG_IGN); 34513795Ssam *np = 0; 34613795Ssam if (c == '\r') 34746043Sbostic crmod = 1; 34813795Ssam if (upper && !lower && !LC || UC) 34913795Ssam for (np = name; *np; np++) 35013795Ssam if (isupper(*np)) 35113795Ssam *np = tolower(*np); 35213795Ssam return (1); 35313795Ssam } 35413795Ssam 35513795Ssam static 35613795Ssam short tmspc10[] = { 35713795Ssam 0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5, 15 35813795Ssam }; 35913795Ssam 360*60091Sbostic static void 36113795Ssam putpad(s) 36213795Ssam register char *s; 36313795Ssam { 36413795Ssam register pad = 0; 36513795Ssam register mspc10; 36613795Ssam 36713795Ssam if (isdigit(*s)) { 36813795Ssam while (isdigit(*s)) { 36913795Ssam pad *= 10; 37013795Ssam pad += *s++ - '0'; 37113795Ssam } 37213795Ssam pad *= 10; 37313795Ssam if (*s == '.' && isdigit(s[1])) { 37413795Ssam pad += s[1] - '0'; 37513795Ssam s += 2; 37613795Ssam } 37713795Ssam } 37813795Ssam 37913795Ssam puts(s); 38013795Ssam /* 38113795Ssam * If no delay needed, or output speed is 38213795Ssam * not comprehensible, then don't try to delay. 38313795Ssam */ 38413795Ssam if (pad == 0) 38513795Ssam return; 38613795Ssam if (tmode.sg_ospeed <= 0 || 38713795Ssam tmode.sg_ospeed >= (sizeof tmspc10 / sizeof tmspc10[0])) 38813795Ssam return; 38913795Ssam 39013795Ssam /* 39146043Sbostic * Round up by a half a character frame, and then do the delay. 39213795Ssam * Too bad there are no user program accessible programmed delays. 39346043Sbostic * Transmitting pad characters slows many terminals down and also 39446043Sbostic * loads the system. 39513795Ssam */ 39613795Ssam mspc10 = tmspc10[tmode.sg_ospeed]; 39713795Ssam pad += mspc10 / 2; 39813795Ssam for (pad /= mspc10; pad > 0; pad--) 39913795Ssam putchr(*PC); 40013795Ssam } 40113795Ssam 402*60091Sbostic static void 40313795Ssam puts(s) 40413795Ssam register char *s; 40513795Ssam { 40613795Ssam while (*s) 40713795Ssam putchr(*s++); 40813795Ssam } 40913795Ssam 41013828Skre char outbuf[OBUFSIZ]; 41113828Skre int obufcnt = 0; 41213828Skre 413*60091Sbostic static void 41413795Ssam putchr(cc) 415*60091Sbostic int cc; 41613795Ssam { 41713795Ssam char c; 41813795Ssam 41913795Ssam c = cc; 42047664Swilliam if (!NP) { 42147664Swilliam c |= partab[c&0177] & 0200; 42247664Swilliam if (OP) 42347664Swilliam c ^= 0200; 42447664Swilliam } 42513828Skre if (!UB) { 42613828Skre outbuf[obufcnt++] = c; 42713828Skre if (obufcnt >= OBUFSIZ) 42813828Skre oflush(); 42913828Skre } else 43046043Sbostic write(STDOUT_FILENO, &c, 1); 43113795Ssam } 43213795Ssam 433*60091Sbostic static void 43413828Skre oflush() 43513828Skre { 43613828Skre if (obufcnt) 43746043Sbostic write(STDOUT_FILENO, outbuf, obufcnt); 43813828Skre obufcnt = 0; 43913828Skre } 44013828Skre 441*60091Sbostic static void 44213795Ssam prompt() 44313795Ssam { 44413795Ssam 44513795Ssam putf(LM); 44613795Ssam if (CO) 44713795Ssam putchr('\n'); 44813795Ssam } 44913795Ssam 450*60091Sbostic static void 45113795Ssam putf(cp) 45213795Ssam register char *cp; 45313795Ssam { 45413795Ssam extern char editedhost[]; 45546043Sbostic time_t t; 45646670Sbostic char *slash, db[100]; 45713795Ssam 45813795Ssam while (*cp) { 45913795Ssam if (*cp != '%') { 46013795Ssam putchr(*cp++); 46113795Ssam continue; 46213795Ssam } 46313795Ssam switch (*++cp) { 46413795Ssam 46518543Sralph case 't': 466*60091Sbostic slash = strrchr(ttyn, '/'); 46718543Sralph if (slash == (char *) 0) 46818543Sralph puts(ttyn); 46918543Sralph else 47018543Sralph puts(&slash[1]); 47118543Sralph break; 47218543Sralph 47313795Ssam case 'h': 47413795Ssam puts(editedhost); 47513795Ssam break; 47613795Ssam 47746670Sbostic case 'd': { 47846967Sbostic static char fmt[] = "%l:% %P on %A, %d %B %Y"; 47946670Sbostic 48046670Sbostic fmt[4] = 'M'; /* I *hate* SCCS... */ 48146043Sbostic (void)time(&t); 48246670Sbostic (void)strftime(db, sizeof(db), fmt, localtime(&t)); 48346043Sbostic puts(db); 48415713Sralph break; 48546670Sbostic } 48615713Sralph 48713795Ssam case '%': 48813795Ssam putchr('%'); 48913795Ssam break; 49013795Ssam } 49113795Ssam cp++; 49213795Ssam } 49313795Ssam } 494