119054Sdist /* 219054Sdist * Copyright (c) 1980 Regents of the University of California. 319054Sdist * All rights reserved. The Berkeley software License Agreement 419054Sdist * specifies the terms and conditions for redistribution. 519054Sdist */ 619054Sdist 713795Ssam #ifndef lint 819054Sdist char copyright[] = 919054Sdist "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 1019054Sdist All rights reserved.\n"; 1119054Sdist #endif not lint 1213795Ssam 1319054Sdist #ifndef lint 14*25553Smckusick static char sccsid[] = "@(#)main.c 5.4 (Berkeley) 11/30/85"; 1519054Sdist #endif not lint 1619054Sdist 1713795Ssam /* 1813795Ssam * getty -- adapt to terminal speed on dialup, and call login 1913795Ssam * 2013795Ssam * Melbourne getty, June 83, kre. 2113795Ssam */ 2213795Ssam 2313795Ssam #include <sgtty.h> 2413795Ssam #include <signal.h> 2513795Ssam #include <ctype.h> 2613795Ssam #include <setjmp.h> 2718543Sralph #include <syslog.h> 2818543Sralph #include <sys/file.h> 2913795Ssam #include "gettytab.h" 3013795Ssam 3118543Sralph extern char **environ; 3218543Sralph 3313795Ssam struct sgttyb tmode = { 3413795Ssam 0, 0, CERASE, CKILL, 0 3513795Ssam }; 3613795Ssam struct tchars tc = { 3713795Ssam CINTR, CQUIT, CSTART, 3813795Ssam CSTOP, CEOF, CBRK, 3913795Ssam }; 4013795Ssam struct ltchars ltc = { 4113795Ssam CSUSP, CDSUSP, CRPRNT, 4213795Ssam CFLUSH, CWERASE, CLNEXT 4313795Ssam }; 4413795Ssam 4513795Ssam int crmod; 4613795Ssam int upper; 4713795Ssam int lower; 4813795Ssam int digit; 4913795Ssam 5013795Ssam char hostname[32]; 5113795Ssam char name[16]; 5218543Sralph char dev[] = "/dev/"; 5318543Sralph char ctty[] = "/dev/console"; 5418543Sralph char ttyn[32]; 5513795Ssam char *portselector(); 5618543Sralph char *ttyname(); 5713795Ssam 5813828Skre #define OBUFSIZ 128 5913795Ssam #define TABBUFSIZ 512 6013795Ssam 6113795Ssam char defent[TABBUFSIZ]; 6213795Ssam char defstrs[TABBUFSIZ]; 6313795Ssam char tabent[TABBUFSIZ]; 6413795Ssam char tabstrs[TABBUFSIZ]; 6513795Ssam 6613795Ssam char *env[128]; 6713795Ssam 6813795Ssam char partab[] = { 6913795Ssam 0001,0201,0201,0001,0201,0001,0001,0201, 7013795Ssam 0202,0004,0003,0205,0005,0206,0201,0001, 7113795Ssam 0201,0001,0001,0201,0001,0201,0201,0001, 7213795Ssam 0001,0201,0201,0001,0201,0001,0001,0201, 7313795Ssam 0200,0000,0000,0200,0000,0200,0200,0000, 7413795Ssam 0000,0200,0200,0000,0200,0000,0000,0200, 7513795Ssam 0000,0200,0200,0000,0200,0000,0000,0200, 7613795Ssam 0200,0000,0000,0200,0000,0200,0200,0000, 7713795Ssam 0200,0000,0000,0200,0000,0200,0200,0000, 7813795Ssam 0000,0200,0200,0000,0200,0000,0000,0200, 7913795Ssam 0000,0200,0200,0000,0200,0000,0000,0200, 8013795Ssam 0200,0000,0000,0200,0000,0200,0200,0000, 8113795Ssam 0000,0200,0200,0000,0200,0000,0000,0200, 8213795Ssam 0200,0000,0000,0200,0000,0200,0200,0000, 8313795Ssam 0200,0000,0000,0200,0000,0200,0200,0000, 8413795Ssam 0000,0200,0200,0000,0200,0000,0000,0201 8513795Ssam }; 8613795Ssam 8713795Ssam #define ERASE tmode.sg_erase 8813795Ssam #define KILL tmode.sg_kill 8913795Ssam #define EOT tc.t_eofc 9013795Ssam 9113795Ssam jmp_buf timeout; 9213795Ssam 9313795Ssam dingdong() 9413795Ssam { 9513795Ssam 9613795Ssam alarm(0); 9713795Ssam signal(SIGALRM, SIG_DFL); 9813795Ssam longjmp(timeout, 1); 9913795Ssam } 10013795Ssam 10113828Skre jmp_buf intrupt; 10213828Skre 10313828Skre interrupt() 10413828Skre { 10513828Skre 10613828Skre signal(SIGINT, interrupt); 10713828Skre longjmp(intrupt, 1); 10813828Skre } 10913828Skre 11013795Ssam main(argc, argv) 11113795Ssam char *argv[]; 11213795Ssam { 11313795Ssam char *tname; 11413795Ssam long allflags; 11518543Sralph int repcnt = 0; 11613795Ssam 11713828Skre signal(SIGINT, SIG_IGN); 11813795Ssam /* 11913795Ssam signal(SIGQUIT, SIG_DFL); 12013795Ssam */ 12124890Seric openlog("getty", LOG_ODELAY|LOG_CONS, LOG_AUTH); 12213795Ssam gethostname(hostname, sizeof(hostname)); 12313795Ssam if (hostname[0] == '\0') 12413795Ssam strcpy(hostname, "Amnesiac"); 12518543Sralph /* 12618543Sralph * The following is a work around for vhangup interactions 12718543Sralph * which cause great problems getting window systems started. 12818543Sralph * If the tty line is "-", we do the old style getty presuming 12918543Sralph * that the file descriptors are already set up for us. 13018543Sralph * J. Gettys - MIT Project Athena. 13118543Sralph */ 13218543Sralph if (argc <= 2 || strcmp(argv[2], "-") == 0) 13318543Sralph strcpy(ttyn, ttyname(0)); 13418543Sralph else { 13518543Sralph strcpy(ttyn, dev); 13618543Sralph strncat(ttyn, argv[2], sizeof(ttyn)-sizeof(dev)); 13718543Sralph chown(ttyn, 0, 0); 13818543Sralph chmod(ttyn, 0622); 139*25553Smckusick /* 140*25553Smckusick * Delay the open so DTR stays down long enough to be detected. 141*25553Smckusick */ 142*25553Smckusick sleep(2); 14318543Sralph while (open(ttyn, O_RDWR) != 0) { 14418543Sralph if (repcnt % 10 == 0) { 14524895Seric syslog(LOG_ERR, "%s: %m", ttyn); 14618543Sralph closelog(); 14718543Sralph } 14818543Sralph repcnt++; 14918543Sralph sleep(60); 15018543Sralph } 15118543Sralph signal(SIGHUP, SIG_IGN); 15218543Sralph vhangup(); 15318543Sralph (void) open(ttyn, O_RDWR); 15418543Sralph close(0); 15518543Sralph dup(1); 15618543Sralph dup(0); 15718543Sralph signal(SIGHUP, SIG_DFL); 15818543Sralph } 15918543Sralph 16013795Ssam gettable("default", defent, defstrs); 16113795Ssam gendefaults(); 16213795Ssam tname = "default"; 16313795Ssam if (argc > 1) 16413795Ssam tname = argv[1]; 16513795Ssam for (;;) { 16613795Ssam int ldisp = OTTYDISC; 16713795Ssam 16813795Ssam gettable(tname, tabent, tabstrs); 16913828Skre if (OPset || EPset || APset) 17013828Skre APset++, OPset++, EPset++; 17113795Ssam setdefaults(); 17213795Ssam ioctl(0, TIOCFLUSH, 0); /* clear out the crap */ 17313795Ssam if (IS) 17413795Ssam tmode.sg_ispeed = speed(IS); 17513795Ssam else if (SP) 17613795Ssam tmode.sg_ispeed = speed(SP); 17713795Ssam if (OS) 17813795Ssam tmode.sg_ospeed = speed(OS); 17913795Ssam else if (SP) 18013795Ssam tmode.sg_ospeed = speed(SP); 18113795Ssam tmode.sg_flags = setflags(0); 18213795Ssam ioctl(0, TIOCSETP, &tmode); 18313795Ssam setchars(); 18413795Ssam ioctl(0, TIOCSETC, &tc); 18513795Ssam ioctl(0, TIOCSETD, &ldisp); 18613795Ssam if (HC) 18713795Ssam ioctl(0, TIOCHPCL, 0); 18818543Sralph if (AB) { 18918543Sralph extern char *autobaud(); 19018543Sralph 19118543Sralph tname = autobaud(); 19218543Sralph continue; 19318543Sralph } 19413795Ssam if (PS) { 19513795Ssam tname = portselector(); 19613795Ssam continue; 19713795Ssam } 19813795Ssam if (CL && *CL) 19913795Ssam putpad(CL); 20013795Ssam edithost(HE); 20113795Ssam if (IM && *IM) 20213795Ssam putf(IM); 20313795Ssam if (setjmp(timeout)) { 20413795Ssam tmode.sg_ispeed = tmode.sg_ospeed = 0; 20513795Ssam ioctl(0, TIOCSETP, &tmode); 20613795Ssam exit(1); 20713795Ssam } 20813795Ssam if (TO) { 20913795Ssam signal(SIGALRM, dingdong); 21013795Ssam alarm(TO); 21113795Ssam } 21213795Ssam if (getname()) { 21318543Sralph register int i; 21418543Sralph 21518543Sralph oflush(); 21613795Ssam alarm(0); 21713795Ssam signal(SIGALRM, SIG_DFL); 21813831Ssam if (!(upper || lower || digit)) 21913795Ssam continue; 22013795Ssam allflags = setflags(2); 22113795Ssam tmode.sg_flags = allflags & 0xffff; 22213795Ssam allflags >>= 16; 22313795Ssam if (crmod || NL) 22413795Ssam tmode.sg_flags |= CRMOD; 22513795Ssam if (upper || UC) 22613795Ssam tmode.sg_flags |= LCASE; 22713795Ssam if (lower || LC) 22813795Ssam tmode.sg_flags &= ~LCASE; 22913795Ssam ioctl(0, TIOCSETP, &tmode); 23013795Ssam ioctl(0, TIOCSLTC, <c); 23113795Ssam ioctl(0, TIOCLSET, &allflags); 23213828Skre signal(SIGINT, SIG_DFL); 23318543Sralph for (i = 0; environ[i] != (char *)0; i++) 23418543Sralph env[i] = environ[i]; 23518543Sralph makeenv(&env[i]); 23618543Sralph execle(LO, "login", "-p", name, (char *) 0, env); 23713795Ssam exit(1); 23813795Ssam } 23913795Ssam alarm(0); 24013795Ssam signal(SIGALRM, SIG_DFL); 24113828Skre signal(SIGINT, SIG_IGN); 24213795Ssam if (NX && *NX) 24313795Ssam tname = NX; 24413795Ssam } 24513795Ssam } 24613795Ssam 24713795Ssam getname() 24813795Ssam { 24913795Ssam register char *np; 25013795Ssam register c; 25113795Ssam char cs; 25213795Ssam 25313828Skre /* 25413831Ssam * Interrupt may happen if we use CBREAK mode 25513828Skre */ 25613828Skre if (setjmp(intrupt)) { 25713828Skre signal(SIGINT, SIG_IGN); 25813828Skre return (0); 25913828Skre } 26013828Skre signal(SIGINT, interrupt); 26113795Ssam tmode.sg_flags = setflags(0); 26213795Ssam ioctl(0, TIOCSETP, &tmode); 26313795Ssam tmode.sg_flags = setflags(1); 26413795Ssam prompt(); 26513885Ssam if (PF > 0) { 26614322Ssam oflush(); 26713885Ssam sleep(PF); 26813885Ssam PF = 0; 26913885Ssam } 27013795Ssam ioctl(0, TIOCSETP, &tmode); 27113795Ssam crmod = 0; 27213795Ssam upper = 0; 27313795Ssam lower = 0; 27413795Ssam digit = 0; 27513795Ssam np = name; 27613795Ssam for (;;) { 27713828Skre oflush(); 27813795Ssam if (read(0, &cs, 1) <= 0) 27913795Ssam exit(0); 28013795Ssam if ((c = cs&0177) == 0) 28113795Ssam return (0); 28213831Ssam if (c == EOT) 28313795Ssam exit(1); 28418543Sralph if (c == '\r' || c == '\n' || np >= &name[sizeof name]) { 28518543Sralph putf("\r\n"); 28613795Ssam break; 28718543Sralph } 28813831Ssam if (c >= 'a' && c <= 'z') 28913795Ssam lower++; 29018543Sralph else if (c >= 'A' && c <= 'Z') 29113795Ssam upper++; 29218543Sralph else if (c == ERASE || c == '#' || c == '\b') { 29313795Ssam if (np > name) { 29413795Ssam np--; 29513795Ssam if (tmode.sg_ospeed >= B1200) 29613795Ssam puts("\b \b"); 29713795Ssam else 29813795Ssam putchr(cs); 29913795Ssam } 30013795Ssam continue; 30113831Ssam } else if (c == KILL || c == '@') { 30213795Ssam putchr(cs); 30313795Ssam putchr('\r'); 30413795Ssam if (tmode.sg_ospeed < B1200) 30513795Ssam putchr('\n'); 30613795Ssam /* this is the way they do it down under ... */ 30713795Ssam else if (np > name) 30813795Ssam puts(" \r"); 30913795Ssam prompt(); 31013795Ssam np = name; 31113795Ssam continue; 31218543Sralph } else if (c >= '0' && c <= '9') 31313795Ssam digit++; 31418543Sralph if (IG && (c <= ' ' || c > 0176)) 31513795Ssam continue; 31613795Ssam *np++ = c; 31713795Ssam putchr(cs); 31813795Ssam } 31913828Skre signal(SIGINT, SIG_IGN); 32013795Ssam *np = 0; 32113795Ssam if (c == '\r') 32213795Ssam crmod++; 32313795Ssam if (upper && !lower && !LC || UC) 32413795Ssam for (np = name; *np; np++) 32513795Ssam if (isupper(*np)) 32613795Ssam *np = tolower(*np); 32713795Ssam return (1); 32813795Ssam } 32913795Ssam 33013795Ssam static 33113795Ssam short tmspc10[] = { 33213795Ssam 0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5, 15 33313795Ssam }; 33413795Ssam 33513795Ssam putpad(s) 33613795Ssam register char *s; 33713795Ssam { 33813795Ssam register pad = 0; 33913795Ssam register mspc10; 34013795Ssam 34113795Ssam if (isdigit(*s)) { 34213795Ssam while (isdigit(*s)) { 34313795Ssam pad *= 10; 34413795Ssam pad += *s++ - '0'; 34513795Ssam } 34613795Ssam pad *= 10; 34713795Ssam if (*s == '.' && isdigit(s[1])) { 34813795Ssam pad += s[1] - '0'; 34913795Ssam s += 2; 35013795Ssam } 35113795Ssam } 35213795Ssam 35313795Ssam puts(s); 35413795Ssam /* 35513795Ssam * If no delay needed, or output speed is 35613795Ssam * not comprehensible, then don't try to delay. 35713795Ssam */ 35813795Ssam if (pad == 0) 35913795Ssam return; 36013795Ssam if (tmode.sg_ospeed <= 0 || 36113795Ssam tmode.sg_ospeed >= (sizeof tmspc10 / sizeof tmspc10[0])) 36213795Ssam return; 36313795Ssam 36413795Ssam /* 36513795Ssam * Round up by a half a character frame, 36613795Ssam * and then do the delay. 36713795Ssam * Too bad there are no user program accessible programmed delays. 36813795Ssam * Transmitting pad characters slows many 36913795Ssam * terminals down and also loads the system. 37013795Ssam */ 37113795Ssam mspc10 = tmspc10[tmode.sg_ospeed]; 37213795Ssam pad += mspc10 / 2; 37313795Ssam for (pad /= mspc10; pad > 0; pad--) 37413795Ssam putchr(*PC); 37513795Ssam } 37613795Ssam 37713795Ssam puts(s) 37813795Ssam register char *s; 37913795Ssam { 38013795Ssam 38113795Ssam while (*s) 38213795Ssam putchr(*s++); 38313795Ssam } 38413795Ssam 38513828Skre char outbuf[OBUFSIZ]; 38613828Skre int obufcnt = 0; 38713828Skre 38813795Ssam putchr(cc) 38913795Ssam { 39013795Ssam char c; 39113795Ssam 39213795Ssam c = cc; 39313795Ssam c |= partab[c&0177] & 0200; 39413795Ssam if (OP) 39513795Ssam c ^= 0200; 39613828Skre if (!UB) { 39713828Skre outbuf[obufcnt++] = c; 39813828Skre if (obufcnt >= OBUFSIZ) 39913828Skre oflush(); 40013828Skre } else 40113828Skre write(1, &c, 1); 40213795Ssam } 40313795Ssam 40413828Skre oflush() 40513828Skre { 40613828Skre if (obufcnt) 40713828Skre write(1, outbuf, obufcnt); 40813828Skre obufcnt = 0; 40913828Skre } 41013828Skre 41113795Ssam prompt() 41213795Ssam { 41313795Ssam 41413795Ssam putf(LM); 41513795Ssam if (CO) 41613795Ssam putchr('\n'); 41713795Ssam } 41813795Ssam 41913795Ssam putf(cp) 42013795Ssam register char *cp; 42113795Ssam { 42218543Sralph char *ttyn, *slash; 42318543Sralph char datebuffer[60]; 42413795Ssam extern char editedhost[]; 42518543Sralph extern char *ttyname(), *rindex(); 42613795Ssam 42713795Ssam while (*cp) { 42813795Ssam if (*cp != '%') { 42913795Ssam putchr(*cp++); 43013795Ssam continue; 43113795Ssam } 43213795Ssam switch (*++cp) { 43313795Ssam 43418543Sralph case 't': 43518543Sralph ttyn = ttyname(0); 43618543Sralph slash = rindex(ttyn, '/'); 43718543Sralph if (slash == (char *) 0) 43818543Sralph puts(ttyn); 43918543Sralph else 44018543Sralph puts(&slash[1]); 44118543Sralph break; 44218543Sralph 44313795Ssam case 'h': 44413795Ssam puts(editedhost); 44513795Ssam break; 44613795Ssam 44718543Sralph case 'd': 44818543Sralph get_date(datebuffer); 44918543Sralph puts(datebuffer); 45015713Sralph break; 45115713Sralph 45213795Ssam case '%': 45313795Ssam putchr('%'); 45413795Ssam break; 45513795Ssam } 45613795Ssam cp++; 45713795Ssam } 45813795Ssam } 459