1: /* 2: * Copyright (c) 1980 Regents of the University of California. 3: * All rights reserved. The Berkeley software License Agreement 4: * specifies the terms and conditions for redistribution. 5: */ 6: 7: #ifndef lint 8: char copyright[] = 9: "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 10: All rights reserved.\n"; 11: #endif not lint 12: 13: #ifndef lint 14: static char sccsid[] = "@(#)main.c 5.5 (Berkeley) 1/23/86"; 15: #endif not lint 16: 17: /* 18: * getty -- adapt to terminal speed on dialup, and call login 19: * 20: * Melbourne getty, June 83, kre. 21: */ 22: 23: #include <sgtty.h> 24: #include <signal.h> 25: #include <ctype.h> 26: #include <setjmp.h> 27: #include <syslog.h> 28: #include <sys/file.h> 29: #include "gettytab.h" 30: 31: extern char **environ; 32: 33: struct sgttyb tmode = { 34: 0, 0, CERASE, CKILL, 0 35: }; 36: struct tchars tc = { 37: CINTR, CQUIT, CSTART, 38: CSTOP, CEOF, CBRK, 39: }; 40: struct ltchars ltc = { 41: CSUSP, CDSUSP, CRPRNT, 42: CFLUSH, CWERASE, CLNEXT 43: }; 44: 45: int crmod; 46: int upper; 47: int lower; 48: int digit; 49: 50: char hostname[32]; 51: char name[16]; 52: char dev[] = "/dev/"; 53: char ctty[] = "/dev/console"; 54: char ttyn[32]; 55: char *portselector(); 56: char *ttyname(); 57: 58: #define OBUFSIZ 128 59: #define TABBUFSIZ 512 60: 61: char defent[TABBUFSIZ]; 62: char defstrs[TABBUFSIZ]; 63: char tabent[TABBUFSIZ]; 64: char tabstrs[TABBUFSIZ]; 65: 66: char *env[128]; 67: 68: char partab[] = { 69: 0001,0201,0201,0001,0201,0001,0001,0201, 70: 0202,0004,0003,0205,0005,0206,0201,0001, 71: 0201,0001,0001,0201,0001,0201,0201,0001, 72: 0001,0201,0201,0001,0201,0001,0001,0201, 73: 0200,0000,0000,0200,0000,0200,0200,0000, 74: 0000,0200,0200,0000,0200,0000,0000,0200, 75: 0000,0200,0200,0000,0200,0000,0000,0200, 76: 0200,0000,0000,0200,0000,0200,0200,0000, 77: 0200,0000,0000,0200,0000,0200,0200,0000, 78: 0000,0200,0200,0000,0200,0000,0000,0200, 79: 0000,0200,0200,0000,0200,0000,0000,0200, 80: 0200,0000,0000,0200,0000,0200,0200,0000, 81: 0000,0200,0200,0000,0200,0000,0000,0200, 82: 0200,0000,0000,0200,0000,0200,0200,0000, 83: 0200,0000,0000,0200,0000,0200,0200,0000, 84: 0000,0200,0200,0000,0200,0000,0000,0201 85: }; 86: 87: #define ERASE tmode.sg_erase 88: #define KILL tmode.sg_kill 89: #define EOT tc.t_eofc 90: 91: jmp_buf timeout; 92: 93: dingdong() 94: { 95: 96: alarm(0); 97: signal(SIGALRM, SIG_DFL); 98: longjmp(timeout, 1); 99: } 100: 101: jmp_buf intrupt; 102: 103: interrupt() 104: { 105: 106: signal(SIGINT, interrupt); 107: longjmp(intrupt, 1); 108: } 109: 110: main(argc, argv) 111: char *argv[]; 112: { 113: char *tname; 114: long allflags; 115: int repcnt = 0; 116: 117: signal(SIGINT, SIG_IGN); 118: /* 119: signal(SIGQUIT, SIG_DFL); 120: */ 121: openlog("getty", LOG_ODELAY|LOG_CONS, LOG_AUTH); 122: gethostname(hostname, sizeof(hostname)); 123: if (hostname[0] == '\0') 124: strcpy(hostname, "Amnesiac"); 125: /* 126: * The following is a work around for vhangup interactions 127: * which cause great problems getting window systems started. 128: * If the tty line is "-", we do the old style getty presuming 129: * that the file descriptors are already set up for us. 130: * J. Gettys - MIT Project Athena. 131: */ 132: if (argc <= 2 || strcmp(argv[2], "-") == 0) 133: strcpy(ttyn, ttyname(0)); 134: else { 135: strcpy(ttyn, dev); 136: strncat(ttyn, argv[2], sizeof(ttyn)-sizeof(dev)); 137: if (strcmp(argv[0], "+") != 0) { 138: chown(ttyn, 0, 0); 139: chmod(ttyn, 0622); 140: /* 141: * Delay the open so DTR stays down long enough to be detected. 142: */ 143: sleep(2); 144: while (open(ttyn, O_RDWR) != 0) { 145: if (repcnt % 10 == 0) { 146: syslog(LOG_ERR, "%s: %m", ttyn); 147: closelog(); 148: } 149: repcnt++; 150: sleep(60); 151: } 152: signal(SIGHUP, SIG_IGN); 153: vhangup(); 154: (void) open(ttyn, O_RDWR); 155: close(0); 156: dup(1); 157: dup(0); 158: signal(SIGHUP, SIG_DFL); 159: } 160: } 161: 162: gettable("default", defent, defstrs); 163: gendefaults(); 164: tname = "default"; 165: if (argc > 1) 166: tname = argv[1]; 167: for (;;) { 168: int ldisp = OTTYDISC; 169: 170: gettable(tname, tabent, tabstrs); 171: if (OPset || EPset || APset) 172: APset++, OPset++, EPset++; 173: setdefaults(); 174: ioctl(0, TIOCFLUSH, 0); /* clear out the crap */ 175: if (IS) 176: tmode.sg_ispeed = speed(IS); 177: else if (SP) 178: tmode.sg_ispeed = speed(SP); 179: if (OS) 180: tmode.sg_ospeed = speed(OS); 181: else if (SP) 182: tmode.sg_ospeed = speed(SP); 183: tmode.sg_flags = setflags(0); 184: ioctl(0, TIOCSETP, &tmode); 185: setchars(); 186: ioctl(0, TIOCSETC, &tc); 187: ioctl(0, TIOCSETD, &ldisp); 188: if (HC) 189: ioctl(0, TIOCHPCL, 0); 190: if (AB) { 191: extern char *autobaud(); 192: 193: tname = autobaud(); 194: continue; 195: } 196: if (PS) { 197: tname = portselector(); 198: continue; 199: } 200: if (CL && *CL) 201: putpad(CL); 202: edithost(HE); 203: if (IM && *IM) 204: putf(IM); 205: if (setjmp(timeout)) { 206: tmode.sg_ispeed = tmode.sg_ospeed = 0; 207: ioctl(0, TIOCSETP, &tmode); 208: exit(1); 209: } 210: if (TO) { 211: signal(SIGALRM, dingdong); 212: alarm(TO); 213: } 214: if (getname()) { 215: register int i; 216: 217: oflush(); 218: alarm(0); 219: signal(SIGALRM, SIG_DFL); 220: if (!(upper || lower || digit)) 221: continue; 222: allflags = setflags(2); 223: tmode.sg_flags = allflags & 0xffff; 224: allflags >>= 16; 225: if (crmod || NL) 226: tmode.sg_flags |= CRMOD; 227: if (upper || UC) 228: tmode.sg_flags |= LCASE; 229: if (lower || LC) 230: tmode.sg_flags &= ~LCASE; 231: ioctl(0, TIOCSETP, &tmode); 232: ioctl(0, TIOCSLTC, <c); 233: ioctl(0, TIOCLSET, &allflags); 234: signal(SIGINT, SIG_DFL); 235: for (i = 0; environ[i] != (char *)0; i++) 236: env[i] = environ[i]; 237: makeenv(&env[i]); 238: execle(LO, "login", "-p", name, (char *) 0, env); 239: exit(1); 240: } 241: alarm(0); 242: signal(SIGALRM, SIG_DFL); 243: signal(SIGINT, SIG_IGN); 244: if (NX && *NX) 245: tname = NX; 246: } 247: } 248: 249: getname() 250: { 251: register char *np; 252: register c; 253: char cs; 254: 255: /* 256: * Interrupt may happen if we use CBREAK mode 257: */ 258: if (setjmp(intrupt)) { 259: signal(SIGINT, SIG_IGN); 260: return (0); 261: } 262: signal(SIGINT, interrupt); 263: tmode.sg_flags = setflags(0); 264: ioctl(0, TIOCSETP, &tmode); 265: tmode.sg_flags = setflags(1); 266: prompt(); 267: if (PF > 0) { 268: oflush(); 269: sleep(PF); 270: PF = 0; 271: } 272: ioctl(0, TIOCSETP, &tmode); 273: crmod = 0; 274: upper = 0; 275: lower = 0; 276: digit = 0; 277: np = name; 278: for (;;) { 279: oflush(); 280: if (read(0, &cs, 1) <= 0) 281: exit(0); 282: if ((c = cs&0177) == 0) 283: return (0); 284: if (c == EOT) 285: exit(1); 286: if (c == '\r' || c == '\n' || np >= &name[sizeof name]) { 287: putf("\r\n"); 288: break; 289: } 290: if (c >= 'a' && c <= 'z') 291: lower++; 292: else if (c >= 'A' && c <= 'Z') 293: upper++; 294: else if (c == ERASE || c == '#' || c == '\b') { 295: if (np > name) { 296: np--; 297: if (tmode.sg_ospeed >= B1200) 298: puts("\b \b"); 299: else 300: putchr(cs); 301: } 302: continue; 303: } else if (c == KILL || c == '@') { 304: putchr(cs); 305: putchr('\r'); 306: if (tmode.sg_ospeed < B1200) 307: putchr('\n'); 308: /* this is the way they do it down under ... */ 309: else if (np > name) 310: puts(" \r"); 311: prompt(); 312: np = name; 313: continue; 314: } else if (c >= '0' && c <= '9') 315: digit++; 316: if (IG && (c <= ' ' || c > 0176)) 317: continue; 318: *np++ = c; 319: putchr(cs); 320: } 321: signal(SIGINT, SIG_IGN); 322: *np = 0; 323: if (c == '\r') 324: crmod++; 325: if (upper && !lower && !LC || UC) 326: for (np = name; *np; np++) 327: if (isupper(*np)) 328: *np = tolower(*np); 329: return (1); 330: } 331: 332: static 333: short tmspc10[] = { 334: 0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5, 15 335: }; 336: 337: putpad(s) 338: register char *s; 339: { 340: register pad = 0; 341: register mspc10; 342: 343: if (isdigit(*s)) { 344: while (isdigit(*s)) { 345: pad *= 10; 346: pad += *s++ - '0'; 347: } 348: pad *= 10; 349: if (*s == '.' && isdigit(s[1])) { 350: pad += s[1] - '0'; 351: s += 2; 352: } 353: } 354: 355: puts(s); 356: /* 357: * If no delay needed, or output speed is 358: * not comprehensible, then don't try to delay. 359: */ 360: if (pad == 0) 361: return; 362: if (tmode.sg_ospeed <= 0 || 363: tmode.sg_ospeed >= (sizeof tmspc10 / sizeof tmspc10[0])) 364: return; 365: 366: /* 367: * Round up by a half a character frame, 368: * and then do the delay. 369: * Too bad there are no user program accessible programmed delays. 370: * Transmitting pad characters slows many 371: * terminals down and also loads the system. 372: */ 373: mspc10 = tmspc10[tmode.sg_ospeed]; 374: pad += mspc10 / 2; 375: for (pad /= mspc10; pad > 0; pad--) 376: putchr(*PC); 377: } 378: 379: puts(s) 380: register char *s; 381: { 382: 383: while (*s) 384: putchr(*s++); 385: } 386: 387: char outbuf[OBUFSIZ]; 388: int obufcnt = 0; 389: 390: putchr(cc) 391: { 392: char c; 393: 394: c = cc; 395: c |= partab[c&0177] & 0200; 396: if (OP) 397: c ^= 0200; 398: if (!UB) { 399: outbuf[obufcnt++] = c; 400: if (obufcnt >= OBUFSIZ) 401: oflush(); 402: } else 403: write(1, &c, 1); 404: } 405: 406: oflush() 407: { 408: if (obufcnt) 409: write(1, outbuf, obufcnt); 410: obufcnt = 0; 411: } 412: 413: prompt() 414: { 415: 416: putf(LM); 417: if (CO) 418: putchr('\n'); 419: } 420: 421: putf(cp) 422: register char *cp; 423: { 424: char *ttyn, *slash; 425: char datebuffer[60]; 426: extern char editedhost[]; 427: extern char *ttyname(), *rindex(); 428: 429: while (*cp) { 430: if (*cp != '%') { 431: putchr(*cp++); 432: continue; 433: } 434: switch (*++cp) { 435: 436: case 't': 437: ttyn = ttyname(0); 438: slash = rindex(ttyn, '/'); 439: if (slash == (char *) 0) 440: puts(ttyn); 441: else 442: puts(&slash[1]); 443: break; 444: 445: case 'h': 446: puts(editedhost); 447: break; 448: 449: case 'd': 450: get_date(datebuffer); 451: puts(datebuffer); 452: break; 453: 454: case '%': 455: putchr('%'); 456: break; 457: } 458: cp++; 459: } 460: }