/*- * Copyright (c) 1980 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef lint char copyright[] = "@(#) Copyright (c) 1980 The Regents of the University of California.\n\ All rights reserved.\n"; #endif /* not lint */ #ifndef lint static char sccsid[] = "@(#)main.c 5.16 (Berkeley) 3/27/91"; #endif /* not lint */ #define USE_OLD_TTY #include #include #include #include #include #include #include #include #include #include #include #include #include #include "gettytab.h" #include "pathnames.h" struct sgttyb tmode = { 0, 0, CERASE, CKILL, 0 }; struct tchars tc = { CINTR, CQUIT, CSTART, CSTOP, CEOF, CBRK, }; struct ltchars ltc = { CSUSP, CDSUSP, CRPRNT, CFLUSH, CWERASE, CLNEXT }; int crmod, digit, lower, upper; char hostname[MAXHOSTNAMELEN]; char name[16]; char dev[] = _PATH_DEV; char ttyn[32]; char *portselector(); char *ttyname(); #define OBUFSIZ 128 #define TABBUFSIZ 512 char defent[TABBUFSIZ]; char defstrs[TABBUFSIZ]; char tabent[TABBUFSIZ]; char tabstrs[TABBUFSIZ]; char *env[128]; char partab[] = { 0001,0201,0201,0001,0201,0001,0001,0201, 0202,0004,0003,0205,0005,0206,0201,0001, 0201,0001,0001,0201,0001,0201,0201,0001, 0001,0201,0201,0001,0201,0001,0001,0201, 0200,0000,0000,0200,0000,0200,0200,0000, 0000,0200,0200,0000,0200,0000,0000,0200, 0000,0200,0200,0000,0200,0000,0000,0200, 0200,0000,0000,0200,0000,0200,0200,0000, 0200,0000,0000,0200,0000,0200,0200,0000, 0000,0200,0200,0000,0200,0000,0000,0200, 0000,0200,0200,0000,0200,0000,0000,0200, 0200,0000,0000,0200,0000,0200,0200,0000, 0000,0200,0200,0000,0200,0000,0000,0200, 0200,0000,0000,0200,0000,0200,0200,0000, 0200,0000,0000,0200,0000,0200,0200,0000, 0000,0200,0200,0000,0200,0000,0000,0201 }; #define ERASE tmode.sg_erase #define KILL tmode.sg_kill #define EOT tc.t_eofc jmp_buf timeout; static void dingdong() { alarm(0); signal(SIGALRM, SIG_DFL); longjmp(timeout, 1); } jmp_buf intrupt; static void interrupt() { signal(SIGINT, interrupt); longjmp(intrupt, 1); } main(argc, argv) int argc; char **argv; { extern char **environ; char *tname; int repcnt = 0; signal(SIGINT, SIG_IGN); signal(SIGQUIT, SIG_IGN); openlog("getty", LOG_ODELAY|LOG_CONS, LOG_AUTH); gethostname(hostname, sizeof(hostname)); if (hostname[0] == '\0') strcpy(hostname, "Amnesiac"); /* * The following is a work around for vhangup interactions * which cause great problems getting window systems started. * If the tty line is "-", we do the old style getty presuming * that the file descriptors are already set up for us. * J. Gettys - MIT Project Athena. */ if (argc <= 2 || strcmp(argv[2], "-") == 0) strcpy(ttyn, ttyname(0)); else { int i; strcpy(ttyn, dev); strncat(ttyn, argv[2], sizeof(ttyn)-sizeof(dev)); if (strcmp(argv[0], "+") != 0) { chown(ttyn, 0, 0); chmod(ttyn, 0600); revoke(ttyn); while ((i = open(ttyn, O_RDWR)) == -1) { if (repcnt % 10 == 0) { syslog(LOG_ERR, "%s: %m", ttyn); closelog(); } repcnt++; sleep(60); } login_tty(i); } } gettable("default", defent, defstrs); gendefaults(); tname = "default"; if (argc > 1) tname = argv[1]; for (;;) { int off = 0; int flushboth = 0; struct sgttyb fake; gettable(tname, tabent, tabstrs); if (OPset || EPset || APset) APset++, OPset++, EPset++; setdefaults(); ioctl(0, TIOCFLUSH, &flushboth); /* clear out the crap */ ioctl(0, FIONBIO, &off); /* turn off non-blocking mode */ ioctl(0, FIOASYNC, &off); /* ditto for async mode */ ioctl(0, TIOCGETP, &fake); /* initialize kernel termios */ if (IS) tmode.sg_ispeed = speed(IS); else if (SP) tmode.sg_ispeed = speed(SP); if (OS) tmode.sg_ospeed = speed(OS); else if (SP) tmode.sg_ospeed = speed(SP); set_tmode(0); setchars(); ioctl(0, TIOCSETC, &tc); if (HC) ioctl(0, TIOCHPCL, 0); if (AB) { extern char *autobaud(); tname = autobaud(); continue; } if (PS) { tname = portselector(); continue; } if (CL && *CL) putpad(CL); edithost(HE); if (IM && *IM) putf(IM); if (setjmp(timeout)) { tmode.sg_ispeed = tmode.sg_ospeed = 0; ioctl(0, TIOCSETP, &tmode); exit(1); } if (TO) { signal(SIGALRM, dingdong); alarm(TO); } if (getname()) { register int i; alarm(0); signal(SIGALRM, SIG_DFL); oflush(); if (name[0] == '-') { puts("user names may not start with '-'."); continue; } if (!(upper || lower || digit)) continue; set_tmode(2); ioctl(0, TIOCSLTC, <c); for (i = 0; environ[i] != (char *)0; i++) env[i] = environ[i]; makeenv(&env[i]); execle(LO, "login", "-p", name, (char *) 0, env); syslog(LOG_ERR, "%s: %m", LO); exit(1); } signal(SIGINT, SIG_IGN); alarm(0); signal(SIGALRM, SIG_DFL); if (NX && *NX) tname = NX; } } getname() { register int c; register char *np; char cs; int flushin = 1 /*FREAD*/; /* * Interrupt may happen if we use CBREAK mode */ if (setjmp(intrupt)) { signal(SIGINT, SIG_IGN); return (0); } signal(SIGINT, interrupt); ioctl(0, TIOCFLUSH, &flushin); /* purge any input */ prompt(); oflush(); if (PF > 0) { sleep(PF); PF = 0; } set_tmode(1); crmod = digit = lower = upper = 0; np = name; for (;;) { oflush(); if (read(STDIN_FILENO, &cs, 1) <= 0) exit(0); if ((c = cs&0177) == 0) return (0); if (c == EOT || c == 4 /*^D*/) exit(1); if (c == '\r' || c == '\n' || np >= &name[sizeof name]) { putf("\r\n"); break; } if (islower(c)) lower = 1; else if (isupper(c)) upper = 1; else if (c == ERASE || c == '\b' || c == 0177) { if (np > name) { np--; if (tmode.sg_ospeed >= B1200) puts("\b \b"); else putchr(cs); } continue; } else if (c == KILL || c == 025 /*^U*/) { putchr('\r'); if (tmode.sg_ospeed < B1200) putchr('\n'); /* this is the way they do it down under ... */ else if (np > name) puts(" \r"); prompt(); np = name; continue; } else if (isdigit(c)) digit++; if (IG && (c <= ' ' || c > 0176)) continue; *np++ = c; putchr(cs); } signal(SIGINT, SIG_IGN); *np = 0; if (c == '\r') crmod = 1; if (upper && !lower && !LC || UC) for (np = name; *np; np++) if (isupper(*np)) *np = tolower(*np); return (1); } static short tmspc10[] = { 0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5, 15 }; putpad(s) register char *s; { register pad = 0; register mspc10; if (isdigit(*s)) { while (isdigit(*s)) { pad *= 10; pad += *s++ - '0'; } pad *= 10; if (*s == '.' && isdigit(s[1])) { pad += s[1] - '0'; s += 2; } } puts(s); /* * If no delay needed, or output speed is * not comprehensible, then don't try to delay. */ if (pad == 0) return; if (tmode.sg_ospeed <= 0 || tmode.sg_ospeed >= (sizeof tmspc10 / sizeof tmspc10[0])) return; /* * Round up by a half a character frame, and then do the delay. * Too bad there are no user program accessible programmed delays. * Transmitting pad characters slows many terminals down and also * loads the system. */ mspc10 = tmspc10[tmode.sg_ospeed]; pad += mspc10 / 2; for (pad /= mspc10; pad > 0; pad--) putchr(*PC); } puts(s) register char *s; { while (*s) putchr(*s++); } char outbuf[OBUFSIZ]; int obufcnt = 0; putchr(cc) { char c; c = cc; if (!NP) { c |= partab[c&0177] & 0200; if (OP) c ^= 0200; } if (!UB) { outbuf[obufcnt++] = c; if (obufcnt >= OBUFSIZ) oflush(); } else write(STDOUT_FILENO, &c, 1); } oflush() { if (obufcnt) write(STDOUT_FILENO, outbuf, obufcnt); obufcnt = 0; } prompt() { putf(LM); if (CO) putchr('\n'); } putf(cp) register char *cp; { extern char editedhost[]; time_t t; char *slash, db[100]; while (*cp) { if (*cp != '%') { putchr(*cp++); continue; } switch (*++cp) { case 't': slash = rindex(ttyn, '/'); if (slash == (char *) 0) puts(ttyn); else puts(&slash[1]); break; case 'h': puts(editedhost); break; case 'd': { static char fmt[] = "%l:% %p on %A, %d %B %Y"; fmt[4] = 'M'; /* I *hate* SCCS... */ (void)time(&t); (void)strftime(db, sizeof(db), fmt, localtime(&t)); puts(db); break; } case '%': putchr('%'); break; } cp++; } } /* * The conversions from sgttyb to termios make LITOUT and PASS8 affect * the parity. So every TIOCSETP ioctl has to be paired with a TIOCLSET * ioctl (at least if LITOUT or PASS8 has changed, and PASS8 may vary * with 'n'). */ set_tmode(n) int n; { long allflags; allflags = setflags(n); tmode.sg_flags = allflags & 0xffff; allflags >>= 16; if (n == 2) { if (crmod || NL) tmode.sg_flags |= CRMOD; if (upper || UC) tmode.sg_flags |= LCASE; if (lower || LC) tmode.sg_flags &= ~LCASE; } ioctl(0, TIOCSETP, &tmode); ioctl(0, TIOCLSET, &allflags); }