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*60499Selan static char sccsid[] = "@(#)main.c 5.20 (Berkeley) 05/27/93"; 1646043Sbostic #endif /* not lint */ 1719054Sdist 1846043Sbostic #define USE_OLD_TTY 1913795Ssam 2042459Smarc #include <sys/param.h> 2146670Sbostic #include <sys/stat.h> 2260091Sbostic 2360091Sbostic #include <ctype.h> 2460091Sbostic #include <ctype.h> 2546670Sbostic #include <fcntl.h> 2660091Sbostic #include <setjmp.h> 2713795Ssam #include <sgtty.h> 2860091Sbostic #include <signal.h> 2960091Sbostic #include <stdlib.h> 3060091Sbostic #include <string.h> 3160091Sbostic #include <syslog.h> 3246670Sbostic #include <time.h> 3346043Sbostic #include <unistd.h> 3460091Sbostic 3513795Ssam #include "gettytab.h" 3642459Smarc #include "pathnames.h" 3760091Sbostic #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 tabent[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 9346670Sbostic static void 9413795Ssam dingdong() 9513795Ssam { 9613795Ssam 9713795Ssam alarm(0); 9813795Ssam signal(SIGALRM, SIG_DFL); 9913795Ssam longjmp(timeout, 1); 10013795Ssam } 10113795Ssam 10213828Skre jmp_buf intrupt; 10313828Skre 10446670Sbostic static void 10513828Skre interrupt() 10613828Skre { 10713828Skre 10813828Skre signal(SIGINT, interrupt); 10913828Skre longjmp(intrupt, 1); 11013828Skre } 11113828Skre 11260091Sbostic static int getname __P((void)); 11360091Sbostic static void oflush __P((void)); 11460091Sbostic static void prompt __P((void)); 11560091Sbostic static void putchr __P((int)); 11660091Sbostic static void putf __P((char *)); 11760091Sbostic static void putpad __P((char *)); 11860091Sbostic static void puts __P((char *)); 11960091Sbostic 12060091Sbostic int 12113795Ssam main(argc, argv) 12246043Sbostic int argc; 12360091Sbostic char *argv[]; 12413795Ssam { 12560091Sbostic extern char **environ; 12613795Ssam char *tname; 12713795Ssam long allflags; 12818543Sralph int repcnt = 0; 12913795Ssam 13013828Skre signal(SIGINT, SIG_IGN); 13113795Ssam /* 13213795Ssam signal(SIGQUIT, SIG_DFL); 13313795Ssam */ 13424890Seric openlog("getty", LOG_ODELAY|LOG_CONS, LOG_AUTH); 13513795Ssam gethostname(hostname, sizeof(hostname)); 13613795Ssam if (hostname[0] == '\0') 13713795Ssam strcpy(hostname, "Amnesiac"); 13818543Sralph /* 13918543Sralph * The following is a work around for vhangup interactions 14018543Sralph * which cause great problems getting window systems started. 14118543Sralph * If the tty line is "-", we do the old style getty presuming 14218543Sralph * that the file descriptors are already set up for us. 14318543Sralph * J. Gettys - MIT Project Athena. 14418543Sralph */ 14518543Sralph if (argc <= 2 || strcmp(argv[2], "-") == 0) 14625954Sbloom strcpy(ttyn, ttyname(0)); 14718543Sralph else { 14844567Smarc int i; 14944567Smarc 15025954Sbloom strcpy(ttyn, dev); 15125954Sbloom strncat(ttyn, argv[2], sizeof(ttyn)-sizeof(dev)); 15225954Sbloom if (strcmp(argv[0], "+") != 0) { 15318543Sralph chown(ttyn, 0, 0); 15444567Smarc chmod(ttyn, 0600); 15544567Smarc revoke(ttyn); 15625553Smckusick /* 15725553Smckusick * Delay the open so DTR stays down long enough to be detected. 15825553Smckusick */ 15925553Smckusick sleep(2); 16044567Smarc while ((i = open(ttyn, O_RDWR)) == -1) { 16118543Sralph if (repcnt % 10 == 0) { 16224895Seric syslog(LOG_ERR, "%s: %m", ttyn); 16318543Sralph closelog(); 16418543Sralph } 16518543Sralph repcnt++; 16618543Sralph sleep(60); 16718543Sralph } 16844567Smarc login_tty(i); 16925954Sbloom } 17018543Sralph } 17118543Sralph 172*60499Selan gettable("default", defent); 17313795Ssam gendefaults(); 17413795Ssam tname = "default"; 17513795Ssam if (argc > 1) 17613795Ssam tname = argv[1]; 17713795Ssam for (;;) { 17853076Sbostic int off; 17913795Ssam 180*60499Selan gettable(tname, tabent); 18113828Skre if (OPset || EPset || APset) 18213828Skre APset++, OPset++, EPset++; 18313795Ssam setdefaults(); 18453076Sbostic off = 0; 18553076Sbostic ioctl(0, TIOCFLUSH, &off); /* clear out the crap */ 18632209Sbostic ioctl(0, FIONBIO, &off); /* turn off non-blocking mode */ 18746043Sbostic ioctl(0, FIOASYNC, &off); /* ditto for async mode */ 18813795Ssam if (IS) 18913795Ssam tmode.sg_ispeed = speed(IS); 19013795Ssam else if (SP) 19113795Ssam tmode.sg_ispeed = speed(SP); 19213795Ssam if (OS) 19313795Ssam tmode.sg_ospeed = speed(OS); 19413795Ssam else if (SP) 19513795Ssam tmode.sg_ospeed = speed(SP); 19613795Ssam tmode.sg_flags = setflags(0); 19713795Ssam ioctl(0, TIOCSETP, &tmode); 19813795Ssam setchars(); 19913795Ssam ioctl(0, TIOCSETC, &tc); 20013795Ssam if (HC) 20113795Ssam ioctl(0, TIOCHPCL, 0); 20218543Sralph if (AB) { 20318543Sralph extern char *autobaud(); 20418543Sralph 20518543Sralph tname = autobaud(); 20618543Sralph continue; 20718543Sralph } 20813795Ssam if (PS) { 20913795Ssam tname = portselector(); 21013795Ssam continue; 21113795Ssam } 21213795Ssam if (CL && *CL) 21313795Ssam putpad(CL); 21413795Ssam edithost(HE); 21513795Ssam if (IM && *IM) 21613795Ssam putf(IM); 21713795Ssam if (setjmp(timeout)) { 21813795Ssam tmode.sg_ispeed = tmode.sg_ospeed = 0; 21913795Ssam ioctl(0, TIOCSETP, &tmode); 22013795Ssam exit(1); 22113795Ssam } 22213795Ssam if (TO) { 22313795Ssam signal(SIGALRM, dingdong); 22413795Ssam alarm(TO); 22513795Ssam } 22613795Ssam if (getname()) { 22718543Sralph register int i; 22818543Sralph 22918543Sralph oflush(); 23013795Ssam alarm(0); 23113795Ssam signal(SIGALRM, SIG_DFL); 23232308Sbostic if (name[0] == '-') { 23342459Smarc puts("user names may not start with '-'."); 23432308Sbostic continue; 23532308Sbostic } 23613831Ssam if (!(upper || lower || digit)) 23713795Ssam continue; 23813795Ssam allflags = setflags(2); 23913795Ssam tmode.sg_flags = allflags & 0xffff; 24013795Ssam allflags >>= 16; 24113795Ssam if (crmod || NL) 24213795Ssam tmode.sg_flags |= CRMOD; 24313795Ssam if (upper || UC) 24413795Ssam tmode.sg_flags |= LCASE; 24513795Ssam if (lower || LC) 24613795Ssam tmode.sg_flags &= ~LCASE; 24713795Ssam ioctl(0, TIOCSETP, &tmode); 24813795Ssam ioctl(0, TIOCSLTC, <c); 24913795Ssam ioctl(0, TIOCLSET, &allflags); 25013828Skre signal(SIGINT, SIG_DFL); 25118543Sralph for (i = 0; environ[i] != (char *)0; i++) 25218543Sralph env[i] = environ[i]; 25318543Sralph makeenv(&env[i]); 25444640Smarc 25544640Smarc /* 25644640Smarc * this is what login was doing anyway. 25744640Smarc * soon we rewrite getty completely. 25844640Smarc */ 25944640Smarc set_ttydefaults(0); 26018543Sralph execle(LO, "login", "-p", name, (char *) 0, env); 26132209Sbostic syslog(LOG_ERR, "%s: %m", LO); 26213795Ssam exit(1); 26313795Ssam } 26413795Ssam alarm(0); 26513795Ssam signal(SIGALRM, SIG_DFL); 26613828Skre signal(SIGINT, SIG_IGN); 26713795Ssam if (NX && *NX) 26813795Ssam tname = NX; 26913795Ssam } 27013795Ssam } 27113795Ssam 27260091Sbostic static int 27313795Ssam getname() 27413795Ssam { 27546043Sbostic register int c; 27613795Ssam register char *np; 27713795Ssam char cs; 27813795Ssam 27913828Skre /* 28013831Ssam * Interrupt may happen if we use CBREAK mode 28113828Skre */ 28213828Skre if (setjmp(intrupt)) { 28313828Skre signal(SIGINT, SIG_IGN); 28413828Skre return (0); 28513828Skre } 28613828Skre signal(SIGINT, interrupt); 28713795Ssam tmode.sg_flags = setflags(0); 28813795Ssam ioctl(0, TIOCSETP, &tmode); 28913795Ssam tmode.sg_flags = setflags(1); 29013795Ssam prompt(); 29113885Ssam if (PF > 0) { 29214322Ssam oflush(); 29313885Ssam sleep(PF); 29413885Ssam PF = 0; 29513885Ssam } 29613795Ssam ioctl(0, TIOCSETP, &tmode); 29746043Sbostic crmod = digit = lower = upper = 0; 29813795Ssam np = name; 29913795Ssam for (;;) { 30013828Skre oflush(); 30146043Sbostic if (read(STDIN_FILENO, &cs, 1) <= 0) 30213795Ssam exit(0); 30313795Ssam if ((c = cs&0177) == 0) 30413795Ssam return (0); 30513831Ssam if (c == EOT) 30613795Ssam exit(1); 30718543Sralph if (c == '\r' || c == '\n' || np >= &name[sizeof name]) { 30818543Sralph putf("\r\n"); 30913795Ssam break; 31018543Sralph } 31142459Smarc if (islower(c)) 31246043Sbostic lower = 1; 31342459Smarc else if (isupper(c)) 31446043Sbostic upper = 1; 31518543Sralph else if (c == ERASE || c == '#' || c == '\b') { 31613795Ssam if (np > name) { 31713795Ssam np--; 31813795Ssam if (tmode.sg_ospeed >= B1200) 31913795Ssam puts("\b \b"); 32013795Ssam else 32113795Ssam putchr(cs); 32213795Ssam } 32313795Ssam continue; 32413831Ssam } else if (c == KILL || c == '@') { 32513795Ssam putchr(cs); 32613795Ssam putchr('\r'); 32713795Ssam if (tmode.sg_ospeed < B1200) 32813795Ssam putchr('\n'); 32913795Ssam /* this is the way they do it down under ... */ 33013795Ssam else if (np > name) 33113795Ssam puts(" \r"); 33213795Ssam prompt(); 33313795Ssam np = name; 33413795Ssam continue; 33542459Smarc } else if (isdigit(c)) 33613795Ssam digit++; 33718543Sralph if (IG && (c <= ' ' || c > 0176)) 33813795Ssam continue; 33913795Ssam *np++ = c; 34013795Ssam putchr(cs); 34113795Ssam } 34213828Skre signal(SIGINT, SIG_IGN); 34313795Ssam *np = 0; 34413795Ssam if (c == '\r') 34546043Sbostic crmod = 1; 34613795Ssam if (upper && !lower && !LC || UC) 34713795Ssam for (np = name; *np; np++) 34813795Ssam if (isupper(*np)) 34913795Ssam *np = tolower(*np); 35013795Ssam return (1); 35113795Ssam } 35213795Ssam 35313795Ssam static 35413795Ssam short tmspc10[] = { 35513795Ssam 0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5, 15 35613795Ssam }; 35713795Ssam 35860091Sbostic static void 35913795Ssam putpad(s) 36013795Ssam register char *s; 36113795Ssam { 36213795Ssam register pad = 0; 36313795Ssam register mspc10; 36413795Ssam 36513795Ssam if (isdigit(*s)) { 36613795Ssam while (isdigit(*s)) { 36713795Ssam pad *= 10; 36813795Ssam pad += *s++ - '0'; 36913795Ssam } 37013795Ssam pad *= 10; 37113795Ssam if (*s == '.' && isdigit(s[1])) { 37213795Ssam pad += s[1] - '0'; 37313795Ssam s += 2; 37413795Ssam } 37513795Ssam } 37613795Ssam 37713795Ssam puts(s); 37813795Ssam /* 37913795Ssam * If no delay needed, or output speed is 38013795Ssam * not comprehensible, then don't try to delay. 38113795Ssam */ 38213795Ssam if (pad == 0) 38313795Ssam return; 38413795Ssam if (tmode.sg_ospeed <= 0 || 38513795Ssam tmode.sg_ospeed >= (sizeof tmspc10 / sizeof tmspc10[0])) 38613795Ssam return; 38713795Ssam 38813795Ssam /* 38946043Sbostic * Round up by a half a character frame, and then do the delay. 39013795Ssam * Too bad there are no user program accessible programmed delays. 39146043Sbostic * Transmitting pad characters slows many terminals down and also 39246043Sbostic * loads the system. 39313795Ssam */ 39413795Ssam mspc10 = tmspc10[tmode.sg_ospeed]; 39513795Ssam pad += mspc10 / 2; 39613795Ssam for (pad /= mspc10; pad > 0; pad--) 39713795Ssam putchr(*PC); 39813795Ssam } 39913795Ssam 40060091Sbostic static void 40113795Ssam puts(s) 40213795Ssam register char *s; 40313795Ssam { 40413795Ssam while (*s) 40513795Ssam putchr(*s++); 40613795Ssam } 40713795Ssam 40813828Skre char outbuf[OBUFSIZ]; 40913828Skre int obufcnt = 0; 41013828Skre 41160091Sbostic static void 41213795Ssam putchr(cc) 41360091Sbostic int cc; 41413795Ssam { 41513795Ssam char c; 41613795Ssam 41713795Ssam c = cc; 41847664Swilliam if (!NP) { 41947664Swilliam c |= partab[c&0177] & 0200; 42047664Swilliam if (OP) 42147664Swilliam c ^= 0200; 42247664Swilliam } 42313828Skre if (!UB) { 42413828Skre outbuf[obufcnt++] = c; 42513828Skre if (obufcnt >= OBUFSIZ) 42613828Skre oflush(); 42713828Skre } else 42846043Sbostic write(STDOUT_FILENO, &c, 1); 42913795Ssam } 43013795Ssam 43160091Sbostic static void 43213828Skre oflush() 43313828Skre { 43413828Skre if (obufcnt) 43546043Sbostic write(STDOUT_FILENO, outbuf, obufcnt); 43613828Skre obufcnt = 0; 43713828Skre } 43813828Skre 43960091Sbostic static void 44013795Ssam prompt() 44113795Ssam { 44213795Ssam 44313795Ssam putf(LM); 44413795Ssam if (CO) 44513795Ssam putchr('\n'); 44613795Ssam } 44713795Ssam 44860091Sbostic static void 44913795Ssam putf(cp) 45013795Ssam register char *cp; 45113795Ssam { 45213795Ssam extern char editedhost[]; 45346043Sbostic time_t t; 45446670Sbostic char *slash, db[100]; 45513795Ssam 45613795Ssam while (*cp) { 45713795Ssam if (*cp != '%') { 45813795Ssam putchr(*cp++); 45913795Ssam continue; 46013795Ssam } 46113795Ssam switch (*++cp) { 46213795Ssam 46318543Sralph case 't': 46460091Sbostic slash = strrchr(ttyn, '/'); 46518543Sralph if (slash == (char *) 0) 46618543Sralph puts(ttyn); 46718543Sralph else 46818543Sralph puts(&slash[1]); 46918543Sralph break; 47018543Sralph 47113795Ssam case 'h': 47213795Ssam puts(editedhost); 47313795Ssam break; 47413795Ssam 47546670Sbostic case 'd': { 47646967Sbostic static char fmt[] = "%l:% %P on %A, %d %B %Y"; 47746670Sbostic 47846670Sbostic fmt[4] = 'M'; /* I *hate* SCCS... */ 47946043Sbostic (void)time(&t); 48046670Sbostic (void)strftime(db, sizeof(db), fmt, localtime(&t)); 48146043Sbostic puts(db); 48215713Sralph break; 48346670Sbostic } 48415713Sralph 48513795Ssam case '%': 48613795Ssam putchr('%'); 48713795Ssam break; 48813795Ssam } 48913795Ssam cp++; 49013795Ssam } 49113795Ssam } 492