main.c revision 8870
1139823Simp/*- 21541Srgrimes * Copyright (c) 1980 The Regents of the University of California. 31541Srgrimes * All rights reserved. 4137668Smlaier * 51541Srgrimes * Redistribution and use in source and binary forms, with or without 61541Srgrimes * modification, are permitted provided that the following conditions 71541Srgrimes * are met: 81541Srgrimes * 1. Redistributions of source code must retain the above copyright 91541Srgrimes * notice, this list of conditions and the following disclaimer. 101541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111541Srgrimes * notice, this list of conditions and the following disclaimer in the 121541Srgrimes * documentation and/or other materials provided with the distribution. 131541Srgrimes * 3. All advertising materials mentioning features or use of this software 141541Srgrimes * must display the following acknowledgement: 151541Srgrimes * This product includes software developed by the University of 161541Srgrimes * California, Berkeley and its contributors. 171541Srgrimes * 4. Neither the name of the University nor the names of its contributors 181541Srgrimes * may be used to endorse or promote products derived from this software 191541Srgrimes * without specific prior written permission. 201541Srgrimes * 211541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241541Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3010939Swollman * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311541Srgrimes * SUCH DAMAGE. 321541Srgrimes */ 33172467Ssilby 34172467Ssilby#ifndef lint 35172467Ssilbychar copyright[] = 36204902Sqingli"@(#) Copyright (c) 1980 The Regents of the University of California.\n\ 37143868Sglebius All rights reserved.\n"; 381541Srgrimes#endif /* not lint */ 391549Srgrimes 4024204Sbde#ifndef lint 411541Srgrimesstatic char sccsid[] = "@(#)main.c 5.16 (Berkeley) 3/27/91"; 42164033Srwatson#endif /* not lint */ 431541Srgrimes 44186948Sbz#define USE_OLD_TTY 4512704Sphk 46186948Sbz#include <sys/param.h> 4712704Sphk#include <sys/stat.h> 48192011Sqingli#include <signal.h> 491541Srgrimes#include <fcntl.h> 501541Srgrimes#include <sgtty.h> 51195914Sqingli#include <time.h> 52215207Sgnn#include <ctype.h> 53192011Sqingli#include <setjmp.h> 54186119Sqingli#include <syslog.h> 5555009Sshin#include <unistd.h> 561541Srgrimes#include <ctype.h> 57192011Sqingli#include <stdlib.h> 581541Srgrimes#include <string.h> 59228571Sglebius#include "gettytab.h" 601541Srgrimes#include "pathnames.h" 611541Srgrimes 6281127Sumestruct sgttyb tmode = { 63170613Sbms 0, 0, CERASE, CKILL, 0 64228571Sglebius}; 65189592Sbmsstruct tchars tc = { 66195699Srwatson CINTR, CQUIT, CSTART, 67195699Srwatson CSTOP, CEOF, CBRK, 681541Srgrimes}; 6992723Salfredstruct ltchars ltc = { 7092723Salfred CSUSP, CDSUSP, CRPRNT, 7192723Salfred CFLUSH, CWERASE, CLNEXT 7292723Salfred}; 7355009Sshin 7492723Salfredint crmod, digit, lower, upper; 75228571Sglebius 76228571Sglebiuschar hostname[MAXHOSTNAMELEN]; 77167729Sbmschar name[16]; 781541Srgrimeschar dev[] = _PATH_DEV; 79228571Sglebiuschar ttyn[32]; 80228571Sglebiuschar *portselector(); 81228571Sglebiuschar *ttyname(); 82228571Sglebius 83149221Sglebius#define OBUFSIZ 128 8421666Swollman#define TABBUFSIZ 512 85207369Sbz 86207369Sbzchar defent[TABBUFSIZ]; 87207369Sbzchar defstrs[TABBUFSIZ]; 88215207Sgnnchar tabent[TABBUFSIZ]; 89215207Sgnnchar tabstrs[TABBUFSIZ]; 90215207Sgnn 911541Srgrimeschar *env[128]; 921541Srgrimes 93226401Sglebiuschar partab[] = { 941541Srgrimes 0001,0201,0201,0001,0201,0001,0001,0201, 951549Srgrimes 0202,0004,0003,0205,0005,0206,0201,0001, 96169454Srwatson 0201,0001,0001,0201,0001,0201,0201,0001, 971541Srgrimes 0001,0201,0201,0001,0201,0001,0001,0201, 981541Srgrimes 0200,0000,0000,0200,0000,0200,0200,0000, 991541Srgrimes 0000,0200,0200,0000,0200,0000,0000,0200, 1001541Srgrimes 0000,0200,0200,0000,0200,0000,0000,0200, 101194951Srwatson 0200,0000,0000,0200,0000,0200,0200,0000, 102226401Sglebius 0200,0000,0000,0200,0000,0200,0200,0000, 103226401Sglebius 0000,0200,0200,0000,0200,0000,0000,0200, 104226401Sglebius 0000,0200,0200,0000,0200,0000,0000,0200, 105226401Sglebius 0200,0000,0000,0200,0000,0200,0200,0000, 106194951Srwatson 0000,0200,0200,0000,0200,0000,0000,0200, 1071541Srgrimes 0200,0000,0000,0200,0000,0200,0200,0000, 108194951Srwatson 0200,0000,0000,0200,0000,0200,0200,0000, 1091541Srgrimes 0000,0200,0200,0000,0200,0000,0000,0201 1101541Srgrimes}; 1111541Srgrimes 1121541Srgrimes#define ERASE tmode.sg_erase 113133486Sandre#define KILL tmode.sg_kill 114133486Sandre#define EOT tc.t_eofc 115133486Sandre 116133486Sandrejmp_buf timeout; 117169454Srwatson 118133486Sandrestatic void 119133486Sandredingdong() 120133486Sandre{ 121194951Srwatson 122133486Sandre alarm(0); 123194951Srwatson signal(SIGALRM, SIG_DFL); 124194951Srwatson longjmp(timeout, 1); 125184295Sbz} 126194951Srwatson 127133486Sandrejmp_buf intrupt; 128194951Srwatson 129184295Sbzstatic void 130133486Sandreinterrupt() 131133486Sandre{ 132133486Sandre 1331541Srgrimes signal(SIGINT, interrupt); 1341541Srgrimes longjmp(intrupt, 1); 1351541Srgrimes} 1361541Srgrimes 1371549Srgrimesmain(argc, argv) 138169454Srwatson int argc; 1391541Srgrimes char **argv; 1401541Srgrimes{ 1411541Srgrimes extern char **environ; 1421541Srgrimes char *tname; 143166450Sbms int repcnt = 0; 1441541Srgrimes 1451541Srgrimes signal(SIGINT, SIG_IGN); 1461541Srgrimes signal(SIGQUIT, SIG_IGN); 1471541Srgrimes 1481541Srgrimes openlog("getty", LOG_ODELAY|LOG_CONS, LOG_AUTH); 1491541Srgrimes gethostname(hostname, sizeof(hostname)); 1501541Srgrimes if (hostname[0] == '\0') 1511541Srgrimes strcpy(hostname, "Amnesiac"); 1521541Srgrimes /* 1531541Srgrimes * The following is a work around for vhangup interactions 1541541Srgrimes * which cause great problems getting window systems started. 1551541Srgrimes * If the tty line is "-", we do the old style getty presuming 15612296Sphk * that the file descriptors are already set up for us. 157169454Srwatson * J. Gettys - MIT Project Athena. 1581541Srgrimes */ 1591541Srgrimes if (argc <= 2 || strcmp(argv[2], "-") == 0) 1601541Srgrimes strcpy(ttyn, ttyname(0)); 1611541Srgrimes else { 1621541Srgrimes int i; 1634127Swollman 164133874Srwatson strcpy(ttyn, dev); 1651541Srgrimes strncat(ttyn, argv[2], sizeof(ttyn)-sizeof(dev)); 1661541Srgrimes if (strcmp(argv[0], "+") != 0) { 1671541Srgrimes chown(ttyn, 0, 0); 1681541Srgrimes chmod(ttyn, 0600); 1691541Srgrimes revoke(ttyn); 17055009Sshin while ((i = open(ttyn, O_RDWR)) == -1) { 17155009Sshin if (repcnt % 10 == 0) { 17255009Sshin syslog(LOG_ERR, "%s: %m", ttyn); 17355009Sshin closelog(); 17455009Sshin } 17555009Sshin repcnt++; 17655009Sshin sleep(60); 17755009Sshin } 17855009Sshin login_tty(i); 17955009Sshin } 18055009Sshin } 18155009Sshin 18255009Sshin gettable("default", defent, defstrs); 18355009Sshin gendefaults(); 18455009Sshin tname = "default"; 18555009Sshin if (argc > 1) 18655009Sshin tname = argv[1]; 18755009Sshin for (;;) { 18855009Sshin int off = 0; 189184295Sbz int flushboth = 0; 19055009Sshin struct sgttyb fake; 19155009Sshin 19255009Sshin gettable(tname, tabent, tabstrs); 193169454Srwatson if (OPset || EPset || APset) 19455009Sshin APset++, OPset++, EPset++; 19555009Sshin setdefaults(); 19655009Sshin ioctl(0, TIOCFLUSH, &flushboth); /* clear out the crap */ 19755009Sshin ioctl(0, FIONBIO, &off); /* turn off non-blocking mode */ 19855009Sshin ioctl(0, FIOASYNC, &off); /* ditto for async mode */ 19955009Sshin ioctl(0, TIOCGETP, &fake); /* initialize kernel termios */ 20055009Sshin if (IS) 20155009Sshin tmode.sg_ispeed = speed(IS); 20255009Sshin else if (SP) 20355009Sshin tmode.sg_ispeed = speed(SP); 20455009Sshin if (OS) 20555009Sshin tmode.sg_ospeed = speed(OS); 2061541Srgrimes else if (SP) 2071541Srgrimes tmode.sg_ospeed = speed(SP); 208191443Srwatson set_tmode(0); 209191443Srwatson setchars(); 2101541Srgrimes ioctl(0, TIOCSETC, &tc); 2111541Srgrimes if (HC) 2121549Srgrimes ioctl(0, TIOCHPCL, 0); 213169454Srwatson if (AB) { 214169454Srwatson extern char *autobaud(); 2151541Srgrimes 2161541Srgrimes tname = autobaud(); 217184295Sbz continue; 2181541Srgrimes } 219168032Sbms if (PS) { 22084102Sjlemon tname = portselector(); 221189592Sbms continue; 2221541Srgrimes } 2231541Srgrimes if (CL && *CL) 224194951Srwatson putpad(CL); 225168032Sbms edithost(HE); 226228768Sglebius if (IM && *IM) 2271541Srgrimes putf(IM); 228228768Sglebius if (setjmp(timeout)) { 229228768Sglebius tmode.sg_ispeed = tmode.sg_ospeed = 0; 230228768Sglebius ioctl(0, TIOCSETP, &tmode); 231228768Sglebius exit(1); 232228768Sglebius } 233228768Sglebius if (TO) { 234228768Sglebius signal(SIGALRM, dingdong); 235184295Sbz alarm(TO); 236168032Sbms } 23787124Sbrian if (getname()) { 238168032Sbms register int i; 23987124Sbrian 240191443Srwatson alarm(0); 241191443Srwatson signal(SIGALRM, SIG_DFL); 242191443Srwatson oflush(); 243191443Srwatson if (name[0] == '-') { 24455009Sshin puts("user names may not start with '-'."); 245191443Srwatson continue; 246191443Srwatson } 247191443Srwatson if (!(upper || lower || digit)) 248191443Srwatson continue; 249227791Sglebius set_tmode(2); 250227791Sglebius ioctl(0, TIOCSLTC, <c); 251227791Sglebius for (i = 0; environ[i] != (char *)0; i++) 252227791Sglebius env[i] = environ[i]; 253227791Sglebius makeenv(&env[i]); 254227791Sglebius 255227791Sglebius execle(LO, "login", "-p", name, (char *) 0, env); 256227791Sglebius syslog(LOG_ERR, "%s: %m", LO); 257227791Sglebius exit(1); 258227791Sglebius } 259227791Sglebius signal(SIGINT, SIG_IGN); 260227831Sglebius alarm(0); 261227831Sglebius signal(SIGALRM, SIG_DFL); 262227791Sglebius if (NX && *NX) 263227791Sglebius tname = NX; 264228768Sglebius } 265228768Sglebius} 266228768Sglebius 267228768Sglebiusgetname() 268228768Sglebius{ 269228768Sglebius register int c; 270228768Sglebius register char *np; 271227791Sglebius char cs; 272227791Sglebius int flushin = 1 /*FREAD*/; 273227791Sglebius 274227791Sglebius /* 275228768Sglebius * Interrupt may happen if we use CBREAK mode 276227791Sglebius */ 277191443Srwatson if (setjmp(intrupt)) { 278191443Srwatson signal(SIGINT, SIG_IGN); 279191443Srwatson return (0); 280191443Srwatson } 281227791Sglebius signal(SIGINT, interrupt); 282227791Sglebius ioctl(0, TIOCFLUSH, &flushin); /* purge any input */ 283227791Sglebius prompt(); 284191443Srwatson oflush(); 285191443Srwatson if (PF > 0) { 28655009Sshin sleep(PF); 287164033Srwatson PF = 0; 288164033Srwatson } 289164033Srwatson set_tmode(1); 290164033Srwatson crmod = digit = lower = upper = 0; 291164033Srwatson np = name; 292184295Sbz for (;;) { 293184295Sbz oflush(); 294164033Srwatson if (read(STDIN_FILENO, &cs, 1) <= 0) 295164033Srwatson exit(0); 29655009Sshin if ((c = cs&0177) == 0) 297164033Srwatson return (0); 298164033Srwatson if (c == EOT || c == 4 /*^D*/) 299164033Srwatson exit(1); 300164033Srwatson if (c == '\r' || c == '\n' || np >= &name[sizeof name]) { 301164033Srwatson putf("\r\n"); 302184295Sbz break; 303184295Sbz } 304164033Srwatson if (islower(c)) 305164033Srwatson lower = 1; 30655009Sshin else if (isupper(c)) 307184295Sbz upper = 1; 308184295Sbz else if (c == ERASE || c == '\b' || c == 0177) { 30983366Sjulian if (np > name) { 310191443Srwatson np--; 311191443Srwatson if (tmode.sg_ospeed >= B1200) 312191443Srwatson puts("\b \b"); 313191443Srwatson else 314191443Srwatson putchr(cs); 31555009Sshin } 31655009Sshin continue; 317191443Srwatson } else if (c == KILL || c == 025 /*^U*/) { 318191443Srwatson putchr('\r'); 319191443Srwatson if (tmode.sg_ospeed < B1200) 3201541Srgrimes putchr('\n'); 321191456Srwatson /* this is the way they do it down under ... */ 322191456Srwatson else if (np > name) 323191456Srwatson puts(" \r"); 324191456Srwatson prompt(); 325191456Srwatson np = name; 326191456Srwatson continue; 327191456Srwatson } else if (isdigit(c)) 328191456Srwatson digit++; 329191456Srwatson if (IG && (c <= ' ' || c > 0176)) 330191456Srwatson continue; 331191456Srwatson *np++ = c; 332191456Srwatson putchr(cs); 333191456Srwatson } 334191456Srwatson signal(SIGINT, SIG_IGN); 335191456Srwatson *np = 0; 336191456Srwatson if (c == '\r') 337191456Srwatson crmod = 1; 338191456Srwatson if (upper && !lower && !LC || UC) 339191456Srwatson for (np = name; *np; np++) 340191456Srwatson if (isupper(*np)) 341191456Srwatson *np = tolower(*np); 342191456Srwatson return (1); 343191456Srwatson} 344191456Srwatson 345191456Srwatsonstatic 3461541Srgrimesshort tmspc10[] = { 34714632Sfenner 0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5, 15 348191443Srwatson}; 349191443Srwatson 3501541Srgrimesputpad(s) 351191443Srwatson register char *s; 352194951Srwatson{ 353191443Srwatson register pad = 0; 354191443Srwatson register mspc10; 355191443Srwatson 356191443Srwatson if (isdigit(*s)) { 357191443Srwatson while (isdigit(*s)) { 358191443Srwatson pad *= 10; 359191443Srwatson pad += *s++ - '0'; 360191443Srwatson } 361191443Srwatson pad *= 10; 362194760Srwatson if (*s == '.' && isdigit(s[1])) { 363194760Srwatson pad += s[1] - '0'; 364194951Srwatson s += 2; 365191443Srwatson } 366194760Srwatson } 367191443Srwatson 368191443Srwatson puts(s); 369191443Srwatson /* 370191443Srwatson * If no delay needed, or output speed is 371191443Srwatson * not comprehensible, then don't try to delay. 372191443Srwatson */ 373191443Srwatson if (pad == 0) 374191443Srwatson return; 37584102Sjlemon if (tmode.sg_ospeed <= 0 || 37684102Sjlemon tmode.sg_ospeed >= (sizeof tmspc10 / sizeof tmspc10[0])) 377191443Srwatson return; 378194760Srwatson 379194760Srwatson /* 380194760Srwatson * Round up by a half a character frame, and then do the delay. 38184102Sjlemon * Too bad there are no user program accessible programmed delays. 382191443Srwatson * Transmitting pad characters slows many terminals down and also 383191443Srwatson * loads the system. 3841541Srgrimes */ 385191500Srwatson mspc10 = tmspc10[tmode.sg_ospeed]; 3861541Srgrimes pad += mspc10 / 2; 3871541Srgrimes for (pad /= mspc10; pad > 0; pad--) 3881541Srgrimes putchr(*PC); 389227958Sglebius} 390194760Srwatson 391194760Srwatsonputs(s) 392194951Srwatson register char *s; 39371999Sphk{ 3948071Swollman while (*s) 3958071Swollman putchr(*s++); 3968071Swollman} 3978071Swollman 3988071Swollmanchar outbuf[OBUFSIZ]; 399194760Srwatsonint obufcnt = 0; 400194760Srwatson 401194760Srwatsonputchr(cc) 402194760Srwatson{ 403194951Srwatson char c; 4048876Srgrimes 4058071Swollman c = cc; 4068071Swollman if (!NP) { 4078071Swollman c |= partab[c&0177] & 0200; 408191500Srwatson if (OP) 409194760Srwatson c ^= 0200; 4108071Swollman } 4111541Srgrimes if (!UB) { 412191500Srwatson outbuf[obufcnt++] = c; 413191500Srwatson if (obufcnt >= OBUFSIZ) 414194760Srwatson oflush(); 415191500Srwatson } else 4161541Srgrimes write(STDOUT_FILENO, &c, 1); 4171541Srgrimes} 4181541Srgrimes 4191541Srgrimesoflush() 420184295Sbz{ 42120407Swollman if (obufcnt) 422191500Srwatson write(STDOUT_FILENO, outbuf, obufcnt); 423191500Srwatson obufcnt = 0; 424191500Srwatson} 425191500Srwatson 426194760Srwatsonprompt() 427191500Srwatson{ 428191500Srwatson 42920407Swollman putf(LM); 430194602Srwatson if (CO) 43120407Swollman putchr('\n'); 43220407Swollman} 43320407Swollman 434108033Shsuputf(cp) 4351541Srgrimes register char *cp; 43685740Sdes{ 4371541Srgrimes extern char editedhost[]; 4381541Srgrimes time_t t; 4391541Srgrimes char *slash, db[100]; 4401541Srgrimes 4411541Srgrimes while (*cp) { 442151824Sglebius if (*cp != '%') { 443194760Srwatson putchr(*cp++); 444194760Srwatson continue; 445191285Srwatson } 446194760Srwatson switch (*++cp) { 447194760Srwatson 448194951Srwatson case 't': 449181803Sbz slash = rindex(ttyn, '/'); 450194951Srwatson if (slash == (char *) 0) 45187124Sbrian puts(ttyn); 4521541Srgrimes else 4531541Srgrimes puts(&slash[1]); 4541541Srgrimes break; 4551541Srgrimes 4561541Srgrimes case 'h': 4571541Srgrimes puts(editedhost); 4581541Srgrimes break; 4591541Srgrimes 460191500Srwatson case 'd': { 461191500Srwatson static char fmt[] = "%l:% %p on %A, %d %B %Y"; 462194760Srwatson 463191500Srwatson fmt[4] = 'M'; /* I *hate* SCCS... */ 4641541Srgrimes (void)time(&t); 4651541Srgrimes (void)strftime(db, sizeof(db), fmt, localtime(&t)); 466191500Srwatson puts(db); 467191500Srwatson break; 468194760Srwatson } 469194760Srwatson 470191500Srwatson case '%': 4711541Srgrimes putchr('%'); 4721541Srgrimes break; 4731541Srgrimes } 474194760Srwatson cp++; 4751541Srgrimes } 4761541Srgrimes} 477191500Srwatson 478191500Srwatson/* 479194760Srwatson * The conversions from sgttyb to termios make LITOUT and PASS8 affect 480191500Srwatson * the parity. So every TIOCSETP ioctl has to be paired with a TIOCLSET 4811541Srgrimes * ioctl (at least if LITOUT or PASS8 has changed, and PASS8 may vary 482194760Srwatson * with 'n'). 4831541Srgrimes */ 4841541Srgrimesset_tmode(n) 485191500Srwatson int n; 486191500Srwatson{ 487194760Srwatson long allflags; 488191500Srwatson 4891541Srgrimes allflags = setflags(n); 490194760Srwatson tmode.sg_flags = allflags & 0xffff; 4911541Srgrimes allflags >>= 16; 4921541Srgrimes if (n == 2) { 4931541Srgrimes if (crmod || NL) 494194760Srwatson tmode.sg_flags |= CRMOD; 4951541Srgrimes if (upper || UC) 4961541Srgrimes tmode.sg_flags |= LCASE; 497191500Srwatson if (lower || LC) 498191500Srwatson tmode.sg_flags &= ~LCASE; 499194760Srwatson } 500191500Srwatson ioctl(0, TIOCSETP, &tmode); 5011541Srgrimes ioctl(0, TIOCLSET, &allflags); 5021541Srgrimes} 503184295Sbz