main.c revision 2391
11592Srgrimes/*- 22286Sjkh * Copyright (c) 1980 The Regents of the University of California. 32286Sjkh * All rights reserved. 41592Srgrimes * 51592Srgrimes * Redistribution and use in source and binary forms, with or without 61592Srgrimes * modification, are permitted provided that the following conditions 71592Srgrimes * are met: 81592Srgrimes * 1. Redistributions of source code must retain the above copyright 91592Srgrimes * notice, this list of conditions and the following disclaimer. 101592Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111592Srgrimes * notice, this list of conditions and the following disclaimer in the 121592Srgrimes * documentation and/or other materials provided with the distribution. 131592Srgrimes * 3. All advertising materials mentioning features or use of this software 141592Srgrimes * must display the following acknowledgement: 151592Srgrimes * This product includes software developed by the University of 161592Srgrimes * California, Berkeley and its contributors. 171592Srgrimes * 4. Neither the name of the University nor the names of its contributors 181592Srgrimes * may be used to endorse or promote products derived from this software 191592Srgrimes * without specific prior written permission. 201592Srgrimes * 211592Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221592Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231592Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241592Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251592Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261592Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271592Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281592Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291592Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301592Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311592Srgrimes * SUCH DAMAGE. 321592Srgrimes */ 331592Srgrimes 341592Srgrimes#ifndef lint 352286Sjkhchar copyright[] = 362286Sjkh"@(#) Copyright (c) 1980 The Regents of the University of California.\n\ 372286Sjkh All rights reserved.\n"; 381592Srgrimes#endif /* not lint */ 391592Srgrimes 401592Srgrimes#ifndef lint 412286Sjkhstatic char sccsid[] = "@(#)main.c 5.16 (Berkeley) 3/27/91"; 421592Srgrimes#endif /* not lint */ 431592Srgrimes 441592Srgrimes#define USE_OLD_TTY 451592Srgrimes 461592Srgrimes#include <sys/param.h> 471592Srgrimes#include <sys/stat.h> 482286Sjkh#include <signal.h> 492286Sjkh#include <fcntl.h> 502286Sjkh#include <sgtty.h> 512286Sjkh#include <time.h> 521592Srgrimes#include <ctype.h> 532286Sjkh#include <setjmp.h> 542286Sjkh#include <syslog.h> 552286Sjkh#include <unistd.h> 561592Srgrimes#include <ctype.h> 571592Srgrimes#include <stdlib.h> 581592Srgrimes#include <string.h> 591592Srgrimes#include "gettytab.h" 601592Srgrimes#include "pathnames.h" 611592Srgrimes 621592Srgrimesstruct sgttyb tmode = { 631592Srgrimes 0, 0, CERASE, CKILL, 0 641592Srgrimes}; 651592Srgrimesstruct tchars tc = { 661592Srgrimes CINTR, CQUIT, CSTART, 671592Srgrimes CSTOP, CEOF, CBRK, 681592Srgrimes}; 691592Srgrimesstruct ltchars ltc = { 701592Srgrimes CSUSP, CDSUSP, CRPRNT, 711592Srgrimes CFLUSH, CWERASE, CLNEXT 721592Srgrimes}; 731592Srgrimes 741592Srgrimesint crmod, digit, lower, upper; 751592Srgrimes 761592Srgrimeschar hostname[MAXHOSTNAMELEN]; 771592Srgrimeschar name[16]; 781592Srgrimeschar dev[] = _PATH_DEV; 791592Srgrimeschar ttyn[32]; 801592Srgrimeschar *portselector(); 811592Srgrimeschar *ttyname(); 821592Srgrimes 831592Srgrimes#define OBUFSIZ 128 841592Srgrimes#define TABBUFSIZ 512 851592Srgrimes 861592Srgrimeschar defent[TABBUFSIZ]; 872286Sjkhchar defstrs[TABBUFSIZ]; 881592Srgrimeschar tabent[TABBUFSIZ]; 892286Sjkhchar tabstrs[TABBUFSIZ]; 901592Srgrimes 911592Srgrimeschar *env[128]; 921592Srgrimes 931592Srgrimeschar partab[] = { 941592Srgrimes 0001,0201,0201,0001,0201,0001,0001,0201, 951592Srgrimes 0202,0004,0003,0205,0005,0206,0201,0001, 961592Srgrimes 0201,0001,0001,0201,0001,0201,0201,0001, 971592Srgrimes 0001,0201,0201,0001,0201,0001,0001,0201, 981592Srgrimes 0200,0000,0000,0200,0000,0200,0200,0000, 991592Srgrimes 0000,0200,0200,0000,0200,0000,0000,0200, 1001592Srgrimes 0000,0200,0200,0000,0200,0000,0000,0200, 1011592Srgrimes 0200,0000,0000,0200,0000,0200,0200,0000, 1021592Srgrimes 0200,0000,0000,0200,0000,0200,0200,0000, 1031592Srgrimes 0000,0200,0200,0000,0200,0000,0000,0200, 1041592Srgrimes 0000,0200,0200,0000,0200,0000,0000,0200, 1051592Srgrimes 0200,0000,0000,0200,0000,0200,0200,0000, 1061592Srgrimes 0000,0200,0200,0000,0200,0000,0000,0200, 1071592Srgrimes 0200,0000,0000,0200,0000,0200,0200,0000, 1081592Srgrimes 0200,0000,0000,0200,0000,0200,0200,0000, 1091592Srgrimes 0000,0200,0200,0000,0200,0000,0000,0201 1101592Srgrimes}; 1111592Srgrimes 1121592Srgrimes#define ERASE tmode.sg_erase 1131592Srgrimes#define KILL tmode.sg_kill 1141592Srgrimes#define EOT tc.t_eofc 1151592Srgrimes 1161592Srgrimesjmp_buf timeout; 1171592Srgrimes 1181592Srgrimesstatic void 1191592Srgrimesdingdong() 1201592Srgrimes{ 1211592Srgrimes 1221592Srgrimes alarm(0); 1231592Srgrimes signal(SIGALRM, SIG_DFL); 1241592Srgrimes longjmp(timeout, 1); 1251592Srgrimes} 1261592Srgrimes 1271592Srgrimesjmp_buf intrupt; 1281592Srgrimes 1291592Srgrimesstatic void 1301592Srgrimesinterrupt() 1311592Srgrimes{ 1321592Srgrimes 1331592Srgrimes signal(SIGINT, interrupt); 1341592Srgrimes longjmp(intrupt, 1); 1351592Srgrimes} 1361592Srgrimes 1371592Srgrimesmain(argc, argv) 1381592Srgrimes int argc; 1392286Sjkh char **argv; 1401592Srgrimes{ 1412286Sjkh extern char **environ; 1421592Srgrimes char *tname; 1431592Srgrimes int repcnt = 0; 1441592Srgrimes 1451592Srgrimes signal(SIGINT, SIG_IGN); 1462391Sache signal(SIGQUIT, SIG_IGN); 1472286Sjkh 1481592Srgrimes openlog("getty", LOG_ODELAY|LOG_CONS, LOG_AUTH); 1491592Srgrimes gethostname(hostname, sizeof(hostname)); 1501592Srgrimes if (hostname[0] == '\0') 1511592Srgrimes strcpy(hostname, "Amnesiac"); 1521592Srgrimes /* 1531592Srgrimes * The following is a work around for vhangup interactions 1541592Srgrimes * which cause great problems getting window systems started. 1551592Srgrimes * If the tty line is "-", we do the old style getty presuming 1561592Srgrimes * that the file descriptors are already set up for us. 1571592Srgrimes * J. Gettys - MIT Project Athena. 1581592Srgrimes */ 1591592Srgrimes if (argc <= 2 || strcmp(argv[2], "-") == 0) 1601592Srgrimes strcpy(ttyn, ttyname(0)); 1611592Srgrimes else { 1621592Srgrimes int i; 1631592Srgrimes 1641592Srgrimes strcpy(ttyn, dev); 1651592Srgrimes strncat(ttyn, argv[2], sizeof(ttyn)-sizeof(dev)); 1661592Srgrimes if (strcmp(argv[0], "+") != 0) { 1671592Srgrimes chown(ttyn, 0, 0); 1681592Srgrimes chmod(ttyn, 0600); 1691592Srgrimes revoke(ttyn); 1701592Srgrimes while ((i = open(ttyn, O_RDWR)) == -1) { 1711592Srgrimes if (repcnt % 10 == 0) { 1721592Srgrimes syslog(LOG_ERR, "%s: %m", ttyn); 1731592Srgrimes closelog(); 1741592Srgrimes } 1751592Srgrimes repcnt++; 1761592Srgrimes sleep(60); 1771592Srgrimes } 1781592Srgrimes login_tty(i); 1791592Srgrimes } 1801592Srgrimes } 1811592Srgrimes 1822286Sjkh gettable("default", defent, defstrs); 1831592Srgrimes gendefaults(); 1841592Srgrimes tname = "default"; 1851592Srgrimes if (argc > 1) 1861592Srgrimes tname = argv[1]; 1871592Srgrimes for (;;) { 1882286Sjkh int off = 0; 1892286Sjkh int flushboth = 0; 1902286Sjkh struct sgttyb fake; 1911592Srgrimes 1922286Sjkh gettable(tname, tabent, tabstrs); 1931592Srgrimes if (OPset || EPset || APset) 1941592Srgrimes APset++, OPset++, EPset++; 1951592Srgrimes setdefaults(); 1962286Sjkh ioctl(0, TIOCFLUSH, &flushboth); /* clear out the crap */ 1971592Srgrimes ioctl(0, FIONBIO, &off); /* turn off non-blocking mode */ 1981592Srgrimes ioctl(0, FIOASYNC, &off); /* ditto for async mode */ 1992286Sjkh ioctl(0, TIOCGETP, &fake); /* initialize kernel termios */ 2001592Srgrimes if (IS) 2011592Srgrimes tmode.sg_ispeed = speed(IS); 2021592Srgrimes else if (SP) 2031592Srgrimes tmode.sg_ispeed = speed(SP); 2041592Srgrimes if (OS) 2051592Srgrimes tmode.sg_ospeed = speed(OS); 2061592Srgrimes else if (SP) 2071592Srgrimes tmode.sg_ospeed = speed(SP); 2082286Sjkh set_tmode(0); 2091592Srgrimes setchars(); 2101592Srgrimes ioctl(0, TIOCSETC, &tc); 2111592Srgrimes if (HC) 2121592Srgrimes ioctl(0, TIOCHPCL, 0); 2131592Srgrimes if (AB) { 2141592Srgrimes extern char *autobaud(); 2151592Srgrimes 2161592Srgrimes tname = autobaud(); 2171592Srgrimes continue; 2181592Srgrimes } 2191592Srgrimes if (PS) { 2201592Srgrimes tname = portselector(); 2211592Srgrimes continue; 2221592Srgrimes } 2231592Srgrimes if (CL && *CL) 2241592Srgrimes putpad(CL); 2251592Srgrimes edithost(HE); 2261592Srgrimes if (IM && *IM) 2271592Srgrimes putf(IM); 2281592Srgrimes if (setjmp(timeout)) { 2291592Srgrimes tmode.sg_ispeed = tmode.sg_ospeed = 0; 2301592Srgrimes ioctl(0, TIOCSETP, &tmode); 2311592Srgrimes exit(1); 2321592Srgrimes } 2331592Srgrimes if (TO) { 2341592Srgrimes signal(SIGALRM, dingdong); 2351592Srgrimes alarm(TO); 2361592Srgrimes } 2371592Srgrimes if (getname()) { 2381592Srgrimes register int i; 2391592Srgrimes 2401592Srgrimes alarm(0); 2411592Srgrimes signal(SIGALRM, SIG_DFL); 2422286Sjkh oflush(); 2431592Srgrimes if (name[0] == '-') { 2441592Srgrimes puts("user names may not start with '-'."); 2451592Srgrimes continue; 2461592Srgrimes } 2471592Srgrimes if (!(upper || lower || digit)) 2481592Srgrimes continue; 2492286Sjkh set_tmode(2); 2501592Srgrimes ioctl(0, TIOCSLTC, <c); 2511592Srgrimes for (i = 0; environ[i] != (char *)0; i++) 2521592Srgrimes env[i] = environ[i]; 2531592Srgrimes makeenv(&env[i]); 2541592Srgrimes 2551592Srgrimes execle(LO, "login", "-p", name, (char *) 0, env); 2561592Srgrimes syslog(LOG_ERR, "%s: %m", LO); 2571592Srgrimes exit(1); 2581592Srgrimes } 2592286Sjkh signal(SIGINT, SIG_IGN); 2601592Srgrimes alarm(0); 2611592Srgrimes signal(SIGALRM, SIG_DFL); 2621592Srgrimes if (NX && *NX) 2631592Srgrimes tname = NX; 2641592Srgrimes } 2651592Srgrimes} 2661592Srgrimes 2671592Srgrimesgetname() 2681592Srgrimes{ 2691592Srgrimes register int c; 2701592Srgrimes register char *np; 2711592Srgrimes char cs; 2722286Sjkh int flushin = 1 /*FREAD*/; 2731592Srgrimes 2741592Srgrimes /* 2751592Srgrimes * Interrupt may happen if we use CBREAK mode 2761592Srgrimes */ 2771592Srgrimes if (setjmp(intrupt)) { 2781592Srgrimes signal(SIGINT, SIG_IGN); 2791592Srgrimes return (0); 2801592Srgrimes } 2811592Srgrimes signal(SIGINT, interrupt); 2822286Sjkh ioctl(0, TIOCFLUSH, &flushin); /* purge any input */ 2831592Srgrimes prompt(); 2842286Sjkh oflush(); 2851592Srgrimes if (PF > 0) { 2861592Srgrimes sleep(PF); 2871592Srgrimes PF = 0; 2881592Srgrimes } 2892286Sjkh set_tmode(1); 2901592Srgrimes crmod = digit = lower = upper = 0; 2911592Srgrimes np = name; 2921592Srgrimes for (;;) { 2931592Srgrimes oflush(); 2941592Srgrimes if (read(STDIN_FILENO, &cs, 1) <= 0) 2951592Srgrimes exit(0); 2961592Srgrimes if ((c = cs&0177) == 0) 2971592Srgrimes return (0); 2982286Sjkh if (c == EOT || c == 4 /*^D*/) 2991592Srgrimes exit(1); 3001592Srgrimes if (c == '\r' || c == '\n' || np >= &name[sizeof name]) { 3011592Srgrimes putf("\r\n"); 3021592Srgrimes break; 3031592Srgrimes } 3041592Srgrimes if (islower(c)) 3051592Srgrimes lower = 1; 3061592Srgrimes else if (isupper(c)) 3071592Srgrimes upper = 1; 3082286Sjkh else if (c == ERASE || c == '\b' || c == 0177) { 3091592Srgrimes if (np > name) { 3101592Srgrimes np--; 3111592Srgrimes if (tmode.sg_ospeed >= B1200) 3121592Srgrimes puts("\b \b"); 3131592Srgrimes else 3141592Srgrimes putchr(cs); 3151592Srgrimes } 3161592Srgrimes continue; 3172286Sjkh } else if (c == KILL || c == 025 /*^U*/) { 3181592Srgrimes putchr('\r'); 3191592Srgrimes if (tmode.sg_ospeed < B1200) 3201592Srgrimes putchr('\n'); 3211592Srgrimes /* this is the way they do it down under ... */ 3221592Srgrimes else if (np > name) 3231592Srgrimes puts(" \r"); 3241592Srgrimes prompt(); 3251592Srgrimes np = name; 3261592Srgrimes continue; 3271592Srgrimes } else if (isdigit(c)) 3281592Srgrimes digit++; 3291592Srgrimes if (IG && (c <= ' ' || c > 0176)) 3301592Srgrimes continue; 3311592Srgrimes *np++ = c; 3321592Srgrimes putchr(cs); 3331592Srgrimes } 3341592Srgrimes signal(SIGINT, SIG_IGN); 3351592Srgrimes *np = 0; 3361592Srgrimes if (c == '\r') 3371592Srgrimes crmod = 1; 3381592Srgrimes if (upper && !lower && !LC || UC) 3391592Srgrimes for (np = name; *np; np++) 3401592Srgrimes if (isupper(*np)) 3411592Srgrimes *np = tolower(*np); 3421592Srgrimes return (1); 3431592Srgrimes} 3441592Srgrimes 3451592Srgrimesstatic 3461592Srgrimesshort tmspc10[] = { 3471592Srgrimes 0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5, 15 3481592Srgrimes}; 3491592Srgrimes 3501592Srgrimesputpad(s) 3511592Srgrimes register char *s; 3521592Srgrimes{ 3531592Srgrimes register pad = 0; 3541592Srgrimes register mspc10; 3551592Srgrimes 3561592Srgrimes if (isdigit(*s)) { 3571592Srgrimes while (isdigit(*s)) { 3581592Srgrimes pad *= 10; 3591592Srgrimes pad += *s++ - '0'; 3601592Srgrimes } 3611592Srgrimes pad *= 10; 3621592Srgrimes if (*s == '.' && isdigit(s[1])) { 3631592Srgrimes pad += s[1] - '0'; 3641592Srgrimes s += 2; 3651592Srgrimes } 3661592Srgrimes } 3671592Srgrimes 3681592Srgrimes puts(s); 3691592Srgrimes /* 3701592Srgrimes * If no delay needed, or output speed is 3711592Srgrimes * not comprehensible, then don't try to delay. 3721592Srgrimes */ 3731592Srgrimes if (pad == 0) 3741592Srgrimes return; 3751592Srgrimes if (tmode.sg_ospeed <= 0 || 3761592Srgrimes tmode.sg_ospeed >= (sizeof tmspc10 / sizeof tmspc10[0])) 3771592Srgrimes return; 3781592Srgrimes 3791592Srgrimes /* 3801592Srgrimes * Round up by a half a character frame, and then do the delay. 3811592Srgrimes * Too bad there are no user program accessible programmed delays. 3821592Srgrimes * Transmitting pad characters slows many terminals down and also 3831592Srgrimes * loads the system. 3841592Srgrimes */ 3851592Srgrimes mspc10 = tmspc10[tmode.sg_ospeed]; 3861592Srgrimes pad += mspc10 / 2; 3871592Srgrimes for (pad /= mspc10; pad > 0; pad--) 3881592Srgrimes putchr(*PC); 3891592Srgrimes} 3901592Srgrimes 3911592Srgrimesputs(s) 3921592Srgrimes register char *s; 3931592Srgrimes{ 3941592Srgrimes while (*s) 3951592Srgrimes putchr(*s++); 3961592Srgrimes} 3971592Srgrimes 3981592Srgrimeschar outbuf[OBUFSIZ]; 3991592Srgrimesint obufcnt = 0; 4001592Srgrimes 4011592Srgrimesputchr(cc) 4021592Srgrimes{ 4031592Srgrimes char c; 4041592Srgrimes 4051592Srgrimes c = cc; 4061592Srgrimes if (!NP) { 4071592Srgrimes c |= partab[c&0177] & 0200; 4081592Srgrimes if (OP) 4091592Srgrimes c ^= 0200; 4101592Srgrimes } 4111592Srgrimes if (!UB) { 4121592Srgrimes outbuf[obufcnt++] = c; 4131592Srgrimes if (obufcnt >= OBUFSIZ) 4141592Srgrimes oflush(); 4151592Srgrimes } else 4161592Srgrimes write(STDOUT_FILENO, &c, 1); 4171592Srgrimes} 4181592Srgrimes 4191592Srgrimesoflush() 4201592Srgrimes{ 4211592Srgrimes if (obufcnt) 4221592Srgrimes write(STDOUT_FILENO, outbuf, obufcnt); 4231592Srgrimes obufcnt = 0; 4241592Srgrimes} 4251592Srgrimes 4261592Srgrimesprompt() 4271592Srgrimes{ 4281592Srgrimes 4291592Srgrimes putf(LM); 4301592Srgrimes if (CO) 4311592Srgrimes putchr('\n'); 4321592Srgrimes} 4331592Srgrimes 4341592Srgrimesputf(cp) 4351592Srgrimes register char *cp; 4361592Srgrimes{ 4371592Srgrimes extern char editedhost[]; 4381592Srgrimes time_t t; 4391592Srgrimes char *slash, db[100]; 4401592Srgrimes 4411592Srgrimes while (*cp) { 4421592Srgrimes if (*cp != '%') { 4431592Srgrimes putchr(*cp++); 4441592Srgrimes continue; 4451592Srgrimes } 4461592Srgrimes switch (*++cp) { 4471592Srgrimes 4481592Srgrimes case 't': 4492286Sjkh slash = rindex(ttyn, '/'); 4501592Srgrimes if (slash == (char *) 0) 4511592Srgrimes puts(ttyn); 4521592Srgrimes else 4531592Srgrimes puts(&slash[1]); 4541592Srgrimes break; 4551592Srgrimes 4561592Srgrimes case 'h': 4571592Srgrimes puts(editedhost); 4581592Srgrimes break; 4591592Srgrimes 4601592Srgrimes case 'd': { 4611592Srgrimes static char fmt[] = "%l:% %P on %A, %d %B %Y"; 4621592Srgrimes 4631592Srgrimes fmt[4] = 'M'; /* I *hate* SCCS... */ 4641592Srgrimes (void)time(&t); 4651592Srgrimes (void)strftime(db, sizeof(db), fmt, localtime(&t)); 4661592Srgrimes puts(db); 4671592Srgrimes break; 4681592Srgrimes } 4691592Srgrimes 4701592Srgrimes case '%': 4711592Srgrimes putchr('%'); 4721592Srgrimes break; 4731592Srgrimes } 4741592Srgrimes cp++; 4751592Srgrimes } 4761592Srgrimes} 4772286Sjkh 4782286Sjkh/* 4792286Sjkh * The conversions from sgttyb to termios make LITOUT and PASS8 affect 4802286Sjkh * the parity. So every TIOCSETP ioctl has to be paired with a TIOCLSET 4812286Sjkh * ioctl (at least if LITOUT or PASS8 has changed, and PASS8 may vary 4822286Sjkh * with 'n'). 4832286Sjkh */ 4842286Sjkhset_tmode(n) 4852286Sjkh int n; 4862286Sjkh{ 4872286Sjkh long allflags; 4882286Sjkh 4892286Sjkh allflags = setflags(n); 4902286Sjkh tmode.sg_flags = allflags & 0xffff; 4912286Sjkh allflags >>= 16; 4922286Sjkh if (n == 2) { 4932286Sjkh if (crmod || NL) 4942286Sjkh tmode.sg_flags |= CRMOD; 4952286Sjkh if (upper || UC) 4962286Sjkh tmode.sg_flags |= LCASE; 4972286Sjkh if (lower || LC) 4982286Sjkh tmode.sg_flags &= ~LCASE; 4992286Sjkh } 5002286Sjkh ioctl(0, TIOCSETP, &tmode); 5012286Sjkh ioctl(0, TIOCLSET, &allflags); 5022286Sjkh} 503