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