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*47664Swilliam static char sccsid[] = "@(#)main.c 5.16 (Berkeley) 03/27/91"; 1646043Sbostic #endif /* not lint */ 1719054Sdist 1846043Sbostic #define USE_OLD_TTY 1913795Ssam 2042459Smarc #include <sys/param.h> 2146670Sbostic #include <sys/stat.h> 2246670Sbostic #include <signal.h> 2346670Sbostic #include <fcntl.h> 2413795Ssam #include <sgtty.h> 2546670Sbostic #include <time.h> 2613795Ssam #include <ctype.h> 2713795Ssam #include <setjmp.h> 2818543Sralph #include <syslog.h> 2946043Sbostic #include <unistd.h> 3042459Smarc #include <ctype.h> 3146670Sbostic #include <stdlib.h> 3246043Sbostic #include <string.h> 3313795Ssam #include "gettytab.h" 3442459Smarc #include "pathnames.h" 3513795Ssam 3613795Ssam struct sgttyb tmode = { 3713795Ssam 0, 0, CERASE, CKILL, 0 3813795Ssam }; 3913795Ssam struct tchars tc = { 4013795Ssam CINTR, CQUIT, CSTART, 4113795Ssam CSTOP, CEOF, CBRK, 4213795Ssam }; 4313795Ssam struct ltchars ltc = { 4413795Ssam CSUSP, CDSUSP, CRPRNT, 4513795Ssam CFLUSH, CWERASE, CLNEXT 4613795Ssam }; 4713795Ssam 4846043Sbostic int crmod, digit, lower, upper; 4913795Ssam 5042459Smarc char hostname[MAXHOSTNAMELEN]; 5113795Ssam char name[16]; 5242459Smarc char dev[] = _PATH_DEV; 5318543Sralph char ttyn[32]; 5413795Ssam char *portselector(); 5518543Sralph char *ttyname(); 5613795Ssam 5713828Skre #define OBUFSIZ 128 5813795Ssam #define TABBUFSIZ 512 5913795Ssam 6013795Ssam char defent[TABBUFSIZ]; 6113795Ssam char defstrs[TABBUFSIZ]; 6213795Ssam char tabent[TABBUFSIZ]; 6313795Ssam char tabstrs[TABBUFSIZ]; 6413795Ssam 6513795Ssam char *env[128]; 6613795Ssam 6713795Ssam char partab[] = { 6813795Ssam 0001,0201,0201,0001,0201,0001,0001,0201, 6913795Ssam 0202,0004,0003,0205,0005,0206,0201,0001, 7013795Ssam 0201,0001,0001,0201,0001,0201,0201,0001, 7113795Ssam 0001,0201,0201,0001,0201,0001,0001,0201, 7213795Ssam 0200,0000,0000,0200,0000,0200,0200,0000, 7313795Ssam 0000,0200,0200,0000,0200,0000,0000,0200, 7413795Ssam 0000,0200,0200,0000,0200,0000,0000,0200, 7513795Ssam 0200,0000,0000,0200,0000,0200,0200,0000, 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 0000,0200,0200,0000,0200,0000,0000,0200, 8113795Ssam 0200,0000,0000,0200,0000,0200,0200,0000, 8213795Ssam 0200,0000,0000,0200,0000,0200,0200,0000, 8313795Ssam 0000,0200,0200,0000,0200,0000,0000,0201 8413795Ssam }; 8513795Ssam 8613795Ssam #define ERASE tmode.sg_erase 8713795Ssam #define KILL tmode.sg_kill 8813795Ssam #define EOT tc.t_eofc 8913795Ssam 9013795Ssam jmp_buf timeout; 9113795Ssam 9246670Sbostic static void 9313795Ssam dingdong() 9413795Ssam { 9513795Ssam 9613795Ssam alarm(0); 9713795Ssam signal(SIGALRM, SIG_DFL); 9813795Ssam longjmp(timeout, 1); 9913795Ssam } 10013795Ssam 10113828Skre jmp_buf intrupt; 10213828Skre 10346670Sbostic static void 10413828Skre interrupt() 10513828Skre { 10613828Skre 10713828Skre signal(SIGINT, interrupt); 10813828Skre longjmp(intrupt, 1); 10913828Skre } 11013828Skre 11113795Ssam main(argc, argv) 11246043Sbostic int argc; 11346043Sbostic char **argv; 11413795Ssam { 11546043Sbostic extern char **environ; 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 { 13844567Smarc int i; 13944567Smarc 14025954Sbloom strcpy(ttyn, dev); 14125954Sbloom strncat(ttyn, argv[2], sizeof(ttyn)-sizeof(dev)); 14225954Sbloom if (strcmp(argv[0], "+") != 0) { 14318543Sralph chown(ttyn, 0, 0); 14444567Smarc chmod(ttyn, 0600); 14544567Smarc revoke(ttyn); 14625553Smckusick /* 14725553Smckusick * Delay the open so DTR stays down long enough to be detected. 14825553Smckusick */ 14925553Smckusick sleep(2); 15044567Smarc 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 } 15844567Smarc 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 */ 17746043Sbostic ioctl(0, FIOASYNC, &off); /* ditto for async 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 if (HC) 19113795Ssam ioctl(0, TIOCHPCL, 0); 19218543Sralph if (AB) { 19318543Sralph extern char *autobaud(); 19418543Sralph 19518543Sralph tname = autobaud(); 19618543Sralph continue; 19718543Sralph } 19813795Ssam if (PS) { 19913795Ssam tname = portselector(); 20013795Ssam continue; 20113795Ssam } 20213795Ssam if (CL && *CL) 20313795Ssam putpad(CL); 20413795Ssam edithost(HE); 20513795Ssam if (IM && *IM) 20613795Ssam putf(IM); 20713795Ssam if (setjmp(timeout)) { 20813795Ssam tmode.sg_ispeed = tmode.sg_ospeed = 0; 20913795Ssam ioctl(0, TIOCSETP, &tmode); 21013795Ssam exit(1); 21113795Ssam } 21213795Ssam if (TO) { 21313795Ssam signal(SIGALRM, dingdong); 21413795Ssam alarm(TO); 21513795Ssam } 21613795Ssam if (getname()) { 21718543Sralph register int i; 21818543Sralph 21918543Sralph oflush(); 22013795Ssam alarm(0); 22113795Ssam signal(SIGALRM, SIG_DFL); 22232308Sbostic if (name[0] == '-') { 22342459Smarc puts("user names may not start with '-'."); 22432308Sbostic continue; 22532308Sbostic } 22613831Ssam if (!(upper || lower || digit)) 22713795Ssam continue; 22813795Ssam allflags = setflags(2); 22913795Ssam tmode.sg_flags = allflags & 0xffff; 23013795Ssam allflags >>= 16; 23113795Ssam if (crmod || NL) 23213795Ssam tmode.sg_flags |= CRMOD; 23313795Ssam if (upper || UC) 23413795Ssam tmode.sg_flags |= LCASE; 23513795Ssam if (lower || LC) 23613795Ssam tmode.sg_flags &= ~LCASE; 23713795Ssam ioctl(0, TIOCSETP, &tmode); 23813795Ssam ioctl(0, TIOCSLTC, <c); 23913795Ssam ioctl(0, TIOCLSET, &allflags); 24013828Skre signal(SIGINT, SIG_DFL); 24118543Sralph for (i = 0; environ[i] != (char *)0; i++) 24218543Sralph env[i] = environ[i]; 24318543Sralph makeenv(&env[i]); 24444640Smarc 24544640Smarc /* 24644640Smarc * this is what login was doing anyway. 24744640Smarc * soon we rewrite getty completely. 24844640Smarc */ 24944640Smarc set_ttydefaults(0); 25018543Sralph execle(LO, "login", "-p", name, (char *) 0, env); 25132209Sbostic syslog(LOG_ERR, "%s: %m", LO); 25213795Ssam exit(1); 25313795Ssam } 25413795Ssam alarm(0); 25513795Ssam signal(SIGALRM, SIG_DFL); 25613828Skre signal(SIGINT, SIG_IGN); 25713795Ssam if (NX && *NX) 25813795Ssam tname = NX; 25913795Ssam } 26013795Ssam } 26113795Ssam 26213795Ssam getname() 26313795Ssam { 26446043Sbostic register int c; 26513795Ssam register char *np; 26613795Ssam char cs; 26713795Ssam 26813828Skre /* 26913831Ssam * Interrupt may happen if we use CBREAK mode 27013828Skre */ 27113828Skre if (setjmp(intrupt)) { 27213828Skre signal(SIGINT, SIG_IGN); 27313828Skre return (0); 27413828Skre } 27513828Skre signal(SIGINT, interrupt); 27613795Ssam tmode.sg_flags = setflags(0); 27713795Ssam ioctl(0, TIOCSETP, &tmode); 27813795Ssam tmode.sg_flags = setflags(1); 27913795Ssam prompt(); 28013885Ssam if (PF > 0) { 28114322Ssam oflush(); 28213885Ssam sleep(PF); 28313885Ssam PF = 0; 28413885Ssam } 28513795Ssam ioctl(0, TIOCSETP, &tmode); 28646043Sbostic crmod = digit = lower = upper = 0; 28713795Ssam np = name; 28813795Ssam for (;;) { 28913828Skre oflush(); 29046043Sbostic if (read(STDIN_FILENO, &cs, 1) <= 0) 29113795Ssam exit(0); 29213795Ssam if ((c = cs&0177) == 0) 29313795Ssam return (0); 29413831Ssam if (c == EOT) 29513795Ssam exit(1); 29618543Sralph if (c == '\r' || c == '\n' || np >= &name[sizeof name]) { 29718543Sralph putf("\r\n"); 29813795Ssam break; 29918543Sralph } 30042459Smarc if (islower(c)) 30146043Sbostic lower = 1; 30242459Smarc else if (isupper(c)) 30346043Sbostic upper = 1; 30418543Sralph else if (c == ERASE || c == '#' || c == '\b') { 30513795Ssam if (np > name) { 30613795Ssam np--; 30713795Ssam if (tmode.sg_ospeed >= B1200) 30813795Ssam puts("\b \b"); 30913795Ssam else 31013795Ssam putchr(cs); 31113795Ssam } 31213795Ssam continue; 31313831Ssam } else if (c == KILL || c == '@') { 31413795Ssam putchr(cs); 31513795Ssam putchr('\r'); 31613795Ssam if (tmode.sg_ospeed < B1200) 31713795Ssam putchr('\n'); 31813795Ssam /* this is the way they do it down under ... */ 31913795Ssam else if (np > name) 32013795Ssam puts(" \r"); 32113795Ssam prompt(); 32213795Ssam np = name; 32313795Ssam continue; 32442459Smarc } else if (isdigit(c)) 32513795Ssam digit++; 32618543Sralph if (IG && (c <= ' ' || c > 0176)) 32713795Ssam continue; 32813795Ssam *np++ = c; 32913795Ssam putchr(cs); 33013795Ssam } 33113828Skre signal(SIGINT, SIG_IGN); 33213795Ssam *np = 0; 33313795Ssam if (c == '\r') 33446043Sbostic crmod = 1; 33513795Ssam if (upper && !lower && !LC || UC) 33613795Ssam for (np = name; *np; np++) 33713795Ssam if (isupper(*np)) 33813795Ssam *np = tolower(*np); 33913795Ssam return (1); 34013795Ssam } 34113795Ssam 34213795Ssam static 34313795Ssam short tmspc10[] = { 34413795Ssam 0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5, 15 34513795Ssam }; 34613795Ssam 34713795Ssam putpad(s) 34813795Ssam register char *s; 34913795Ssam { 35013795Ssam register pad = 0; 35113795Ssam register mspc10; 35213795Ssam 35313795Ssam if (isdigit(*s)) { 35413795Ssam while (isdigit(*s)) { 35513795Ssam pad *= 10; 35613795Ssam pad += *s++ - '0'; 35713795Ssam } 35813795Ssam pad *= 10; 35913795Ssam if (*s == '.' && isdigit(s[1])) { 36013795Ssam pad += s[1] - '0'; 36113795Ssam s += 2; 36213795Ssam } 36313795Ssam } 36413795Ssam 36513795Ssam puts(s); 36613795Ssam /* 36713795Ssam * If no delay needed, or output speed is 36813795Ssam * not comprehensible, then don't try to delay. 36913795Ssam */ 37013795Ssam if (pad == 0) 37113795Ssam return; 37213795Ssam if (tmode.sg_ospeed <= 0 || 37313795Ssam tmode.sg_ospeed >= (sizeof tmspc10 / sizeof tmspc10[0])) 37413795Ssam return; 37513795Ssam 37613795Ssam /* 37746043Sbostic * Round up by a half a character frame, and then do the delay. 37813795Ssam * Too bad there are no user program accessible programmed delays. 37946043Sbostic * Transmitting pad characters slows many terminals down and also 38046043Sbostic * loads the system. 38113795Ssam */ 38213795Ssam mspc10 = tmspc10[tmode.sg_ospeed]; 38313795Ssam pad += mspc10 / 2; 38413795Ssam for (pad /= mspc10; pad > 0; pad--) 38513795Ssam putchr(*PC); 38613795Ssam } 38713795Ssam 38813795Ssam puts(s) 38913795Ssam register char *s; 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; 403*47664Swilliam if (!NP) { 404*47664Swilliam c |= partab[c&0177] & 0200; 405*47664Swilliam if (OP) 406*47664Swilliam c ^= 0200; 407*47664Swilliam } 40813828Skre if (!UB) { 40913828Skre outbuf[obufcnt++] = c; 41013828Skre if (obufcnt >= OBUFSIZ) 41113828Skre oflush(); 41213828Skre } else 41346043Sbostic write(STDOUT_FILENO, &c, 1); 41413795Ssam } 41513795Ssam 41613828Skre oflush() 41713828Skre { 41813828Skre if (obufcnt) 41946043Sbostic write(STDOUT_FILENO, outbuf, obufcnt); 42013828Skre obufcnt = 0; 42113828Skre } 42213828Skre 42313795Ssam prompt() 42413795Ssam { 42513795Ssam 42613795Ssam putf(LM); 42713795Ssam if (CO) 42813795Ssam putchr('\n'); 42913795Ssam } 43013795Ssam 43113795Ssam putf(cp) 43213795Ssam register char *cp; 43313795Ssam { 43413795Ssam extern char editedhost[]; 43546043Sbostic time_t t; 43646670Sbostic char *slash, db[100]; 43713795Ssam 43813795Ssam while (*cp) { 43913795Ssam if (*cp != '%') { 44013795Ssam putchr(*cp++); 44113795Ssam continue; 44213795Ssam } 44313795Ssam switch (*++cp) { 44413795Ssam 44518543Sralph case 't': 44618543Sralph slash = rindex(ttyn, '/'); 44718543Sralph if (slash == (char *) 0) 44818543Sralph puts(ttyn); 44918543Sralph else 45018543Sralph puts(&slash[1]); 45118543Sralph break; 45218543Sralph 45313795Ssam case 'h': 45413795Ssam puts(editedhost); 45513795Ssam break; 45613795Ssam 45746670Sbostic case 'd': { 45846967Sbostic static char fmt[] = "%l:% %P on %A, %d %B %Y"; 45946670Sbostic 46046670Sbostic fmt[4] = 'M'; /* I *hate* SCCS... */ 46146043Sbostic (void)time(&t); 46246670Sbostic (void)strftime(db, sizeof(db), fmt, localtime(&t)); 46346043Sbostic puts(db); 46415713Sralph break; 46546670Sbostic } 46615713Sralph 46713795Ssam case '%': 46813795Ssam putchr('%'); 46913795Ssam break; 47013795Ssam } 47113795Ssam cp++; 47213795Ssam } 47313795Ssam } 474