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*25954Sbloom static char sccsid[] = "@(#)main.c 5.5 (Berkeley) 01/23/86"; 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) 133*25954Sbloom strcpy(ttyn, ttyname(0)); 13418543Sralph else { 135*25954Sbloom strcpy(ttyn, dev); 136*25954Sbloom strncat(ttyn, argv[2], sizeof(ttyn)-sizeof(dev)); 137*25954Sbloom if (strcmp(argv[0], "+") != 0) { 13818543Sralph chown(ttyn, 0, 0); 13918543Sralph chmod(ttyn, 0622); 14025553Smckusick /* 14125553Smckusick * Delay the open so DTR stays down long enough to be detected. 14225553Smckusick */ 14325553Smckusick sleep(2); 14418543Sralph while (open(ttyn, O_RDWR) != 0) { 14518543Sralph if (repcnt % 10 == 0) { 14624895Seric syslog(LOG_ERR, "%s: %m", ttyn); 14718543Sralph closelog(); 14818543Sralph } 14918543Sralph repcnt++; 15018543Sralph sleep(60); 15118543Sralph } 15218543Sralph signal(SIGHUP, SIG_IGN); 15318543Sralph vhangup(); 15418543Sralph (void) open(ttyn, O_RDWR); 15518543Sralph close(0); 15618543Sralph dup(1); 15718543Sralph dup(0); 15818543Sralph signal(SIGHUP, SIG_DFL); 159*25954Sbloom } 16018543Sralph } 16118543Sralph 16213795Ssam gettable("default", defent, defstrs); 16313795Ssam gendefaults(); 16413795Ssam tname = "default"; 16513795Ssam if (argc > 1) 16613795Ssam tname = argv[1]; 16713795Ssam for (;;) { 16813795Ssam int ldisp = OTTYDISC; 16913795Ssam 17013795Ssam gettable(tname, tabent, tabstrs); 17113828Skre if (OPset || EPset || APset) 17213828Skre APset++, OPset++, EPset++; 17313795Ssam setdefaults(); 17413795Ssam ioctl(0, TIOCFLUSH, 0); /* clear out the crap */ 17513795Ssam if (IS) 17613795Ssam tmode.sg_ispeed = speed(IS); 17713795Ssam else if (SP) 17813795Ssam tmode.sg_ispeed = speed(SP); 17913795Ssam if (OS) 18013795Ssam tmode.sg_ospeed = speed(OS); 18113795Ssam else if (SP) 18213795Ssam tmode.sg_ospeed = speed(SP); 18313795Ssam tmode.sg_flags = setflags(0); 18413795Ssam ioctl(0, TIOCSETP, &tmode); 18513795Ssam setchars(); 18613795Ssam ioctl(0, TIOCSETC, &tc); 18713795Ssam ioctl(0, TIOCSETD, &ldisp); 18813795Ssam if (HC) 18913795Ssam ioctl(0, TIOCHPCL, 0); 19018543Sralph if (AB) { 19118543Sralph extern char *autobaud(); 19218543Sralph 19318543Sralph tname = autobaud(); 19418543Sralph continue; 19518543Sralph } 19613795Ssam if (PS) { 19713795Ssam tname = portselector(); 19813795Ssam continue; 19913795Ssam } 20013795Ssam if (CL && *CL) 20113795Ssam putpad(CL); 20213795Ssam edithost(HE); 20313795Ssam if (IM && *IM) 20413795Ssam putf(IM); 20513795Ssam if (setjmp(timeout)) { 20613795Ssam tmode.sg_ispeed = tmode.sg_ospeed = 0; 20713795Ssam ioctl(0, TIOCSETP, &tmode); 20813795Ssam exit(1); 20913795Ssam } 21013795Ssam if (TO) { 21113795Ssam signal(SIGALRM, dingdong); 21213795Ssam alarm(TO); 21313795Ssam } 21413795Ssam if (getname()) { 21518543Sralph register int i; 21618543Sralph 21718543Sralph oflush(); 21813795Ssam alarm(0); 21913795Ssam signal(SIGALRM, SIG_DFL); 22013831Ssam if (!(upper || lower || digit)) 22113795Ssam continue; 22213795Ssam allflags = setflags(2); 22313795Ssam tmode.sg_flags = allflags & 0xffff; 22413795Ssam allflags >>= 16; 22513795Ssam if (crmod || NL) 22613795Ssam tmode.sg_flags |= CRMOD; 22713795Ssam if (upper || UC) 22813795Ssam tmode.sg_flags |= LCASE; 22913795Ssam if (lower || LC) 23013795Ssam tmode.sg_flags &= ~LCASE; 23113795Ssam ioctl(0, TIOCSETP, &tmode); 23213795Ssam ioctl(0, TIOCSLTC, <c); 23313795Ssam ioctl(0, TIOCLSET, &allflags); 23413828Skre signal(SIGINT, SIG_DFL); 23518543Sralph for (i = 0; environ[i] != (char *)0; i++) 23618543Sralph env[i] = environ[i]; 23718543Sralph makeenv(&env[i]); 23818543Sralph execle(LO, "login", "-p", name, (char *) 0, env); 23913795Ssam exit(1); 24013795Ssam } 24113795Ssam alarm(0); 24213795Ssam signal(SIGALRM, SIG_DFL); 24313828Skre signal(SIGINT, SIG_IGN); 24413795Ssam if (NX && *NX) 24513795Ssam tname = NX; 24613795Ssam } 24713795Ssam } 24813795Ssam 24913795Ssam getname() 25013795Ssam { 25113795Ssam register char *np; 25213795Ssam register c; 25313795Ssam char cs; 25413795Ssam 25513828Skre /* 25613831Ssam * Interrupt may happen if we use CBREAK mode 25713828Skre */ 25813828Skre if (setjmp(intrupt)) { 25913828Skre signal(SIGINT, SIG_IGN); 26013828Skre return (0); 26113828Skre } 26213828Skre signal(SIGINT, interrupt); 26313795Ssam tmode.sg_flags = setflags(0); 26413795Ssam ioctl(0, TIOCSETP, &tmode); 26513795Ssam tmode.sg_flags = setflags(1); 26613795Ssam prompt(); 26713885Ssam if (PF > 0) { 26814322Ssam oflush(); 26913885Ssam sleep(PF); 27013885Ssam PF = 0; 27113885Ssam } 27213795Ssam ioctl(0, TIOCSETP, &tmode); 27313795Ssam crmod = 0; 27413795Ssam upper = 0; 27513795Ssam lower = 0; 27613795Ssam digit = 0; 27713795Ssam np = name; 27813795Ssam for (;;) { 27913828Skre oflush(); 28013795Ssam if (read(0, &cs, 1) <= 0) 28113795Ssam exit(0); 28213795Ssam if ((c = cs&0177) == 0) 28313795Ssam return (0); 28413831Ssam if (c == EOT) 28513795Ssam exit(1); 28618543Sralph if (c == '\r' || c == '\n' || np >= &name[sizeof name]) { 28718543Sralph putf("\r\n"); 28813795Ssam break; 28918543Sralph } 29013831Ssam if (c >= 'a' && c <= 'z') 29113795Ssam lower++; 29218543Sralph else if (c >= 'A' && c <= 'Z') 29313795Ssam upper++; 29418543Sralph else if (c == ERASE || c == '#' || c == '\b') { 29513795Ssam if (np > name) { 29613795Ssam np--; 29713795Ssam if (tmode.sg_ospeed >= B1200) 29813795Ssam puts("\b \b"); 29913795Ssam else 30013795Ssam putchr(cs); 30113795Ssam } 30213795Ssam continue; 30313831Ssam } else if (c == KILL || c == '@') { 30413795Ssam putchr(cs); 30513795Ssam putchr('\r'); 30613795Ssam if (tmode.sg_ospeed < B1200) 30713795Ssam putchr('\n'); 30813795Ssam /* this is the way they do it down under ... */ 30913795Ssam else if (np > name) 31013795Ssam puts(" \r"); 31113795Ssam prompt(); 31213795Ssam np = name; 31313795Ssam continue; 31418543Sralph } else if (c >= '0' && c <= '9') 31513795Ssam digit++; 31618543Sralph if (IG && (c <= ' ' || c > 0176)) 31713795Ssam continue; 31813795Ssam *np++ = c; 31913795Ssam putchr(cs); 32013795Ssam } 32113828Skre signal(SIGINT, SIG_IGN); 32213795Ssam *np = 0; 32313795Ssam if (c == '\r') 32413795Ssam crmod++; 32513795Ssam if (upper && !lower && !LC || UC) 32613795Ssam for (np = name; *np; np++) 32713795Ssam if (isupper(*np)) 32813795Ssam *np = tolower(*np); 32913795Ssam return (1); 33013795Ssam } 33113795Ssam 33213795Ssam static 33313795Ssam short tmspc10[] = { 33413795Ssam 0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5, 15 33513795Ssam }; 33613795Ssam 33713795Ssam putpad(s) 33813795Ssam register char *s; 33913795Ssam { 34013795Ssam register pad = 0; 34113795Ssam register mspc10; 34213795Ssam 34313795Ssam if (isdigit(*s)) { 34413795Ssam while (isdigit(*s)) { 34513795Ssam pad *= 10; 34613795Ssam pad += *s++ - '0'; 34713795Ssam } 34813795Ssam pad *= 10; 34913795Ssam if (*s == '.' && isdigit(s[1])) { 35013795Ssam pad += s[1] - '0'; 35113795Ssam s += 2; 35213795Ssam } 35313795Ssam } 35413795Ssam 35513795Ssam puts(s); 35613795Ssam /* 35713795Ssam * If no delay needed, or output speed is 35813795Ssam * not comprehensible, then don't try to delay. 35913795Ssam */ 36013795Ssam if (pad == 0) 36113795Ssam return; 36213795Ssam if (tmode.sg_ospeed <= 0 || 36313795Ssam tmode.sg_ospeed >= (sizeof tmspc10 / sizeof tmspc10[0])) 36413795Ssam return; 36513795Ssam 36613795Ssam /* 36713795Ssam * Round up by a half a character frame, 36813795Ssam * and then do the delay. 36913795Ssam * Too bad there are no user program accessible programmed delays. 37013795Ssam * Transmitting pad characters slows many 37113795Ssam * terminals down and also loads the system. 37213795Ssam */ 37313795Ssam mspc10 = tmspc10[tmode.sg_ospeed]; 37413795Ssam pad += mspc10 / 2; 37513795Ssam for (pad /= mspc10; pad > 0; pad--) 37613795Ssam putchr(*PC); 37713795Ssam } 37813795Ssam 37913795Ssam puts(s) 38013795Ssam register char *s; 38113795Ssam { 38213795Ssam 38313795Ssam while (*s) 38413795Ssam putchr(*s++); 38513795Ssam } 38613795Ssam 38713828Skre char outbuf[OBUFSIZ]; 38813828Skre int obufcnt = 0; 38913828Skre 39013795Ssam putchr(cc) 39113795Ssam { 39213795Ssam char c; 39313795Ssam 39413795Ssam c = cc; 39513795Ssam c |= partab[c&0177] & 0200; 39613795Ssam if (OP) 39713795Ssam c ^= 0200; 39813828Skre if (!UB) { 39913828Skre outbuf[obufcnt++] = c; 40013828Skre if (obufcnt >= OBUFSIZ) 40113828Skre oflush(); 40213828Skre } else 40313828Skre write(1, &c, 1); 40413795Ssam } 40513795Ssam 40613828Skre oflush() 40713828Skre { 40813828Skre if (obufcnt) 40913828Skre write(1, outbuf, obufcnt); 41013828Skre obufcnt = 0; 41113828Skre } 41213828Skre 41313795Ssam prompt() 41413795Ssam { 41513795Ssam 41613795Ssam putf(LM); 41713795Ssam if (CO) 41813795Ssam putchr('\n'); 41913795Ssam } 42013795Ssam 42113795Ssam putf(cp) 42213795Ssam register char *cp; 42313795Ssam { 42418543Sralph char *ttyn, *slash; 42518543Sralph char datebuffer[60]; 42613795Ssam extern char editedhost[]; 42718543Sralph extern char *ttyname(), *rindex(); 42813795Ssam 42913795Ssam while (*cp) { 43013795Ssam if (*cp != '%') { 43113795Ssam putchr(*cp++); 43213795Ssam continue; 43313795Ssam } 43413795Ssam switch (*++cp) { 43513795Ssam 43618543Sralph case 't': 43718543Sralph ttyn = ttyname(0); 43818543Sralph slash = rindex(ttyn, '/'); 43918543Sralph if (slash == (char *) 0) 44018543Sralph puts(ttyn); 44118543Sralph else 44218543Sralph puts(&slash[1]); 44318543Sralph break; 44418543Sralph 44513795Ssam case 'h': 44613795Ssam puts(editedhost); 44713795Ssam break; 44813795Ssam 44918543Sralph case 'd': 45018543Sralph get_date(datebuffer); 45118543Sralph puts(datebuffer); 45215713Sralph break; 45315713Sralph 45413795Ssam case '%': 45513795Ssam putchr('%'); 45613795Ssam break; 45713795Ssam } 45813795Ssam cp++; 45913795Ssam } 46013795Ssam } 461