1*19054Sdist /* 2*19054Sdist * Copyright (c) 1980 Regents of the University of California. 3*19054Sdist * All rights reserved. The Berkeley software License Agreement 4*19054Sdist * specifies the terms and conditions for redistribution. 5*19054Sdist */ 6*19054Sdist 713795Ssam #ifndef lint 8*19054Sdist char copyright[] = 9*19054Sdist "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 10*19054Sdist All rights reserved.\n"; 11*19054Sdist #endif not lint 1213795Ssam 13*19054Sdist #ifndef lint 14*19054Sdist static char sccsid[] = "@(#)main.c 5.1 (Berkeley) 04/29/85"; 15*19054Sdist #endif not lint 16*19054Sdist 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 */ 12118543Sralph openlog("getty", LOG_ODELAY|LOG_CONS, 0); 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); 13918543Sralph while (open(ttyn, O_RDWR) != 0) { 14018543Sralph if (repcnt % 10 == 0) { 14118543Sralph syslog(LOG_FAIL, "%s: %m", ttyn); 14218543Sralph closelog(); 14318543Sralph } 14418543Sralph repcnt++; 14518543Sralph sleep(60); 14618543Sralph } 14718543Sralph signal(SIGHUP, SIG_IGN); 14818543Sralph vhangup(); 14918543Sralph (void) open(ttyn, O_RDWR); 15018543Sralph close(0); 15118543Sralph dup(1); 15218543Sralph dup(0); 15318543Sralph signal(SIGHUP, SIG_DFL); 15418543Sralph } 15518543Sralph 15613795Ssam gettable("default", defent, defstrs); 15713795Ssam gendefaults(); 15813795Ssam tname = "default"; 15913795Ssam if (argc > 1) 16013795Ssam tname = argv[1]; 16113795Ssam for (;;) { 16213795Ssam int ldisp = OTTYDISC; 16313795Ssam 16413795Ssam gettable(tname, tabent, tabstrs); 16513828Skre if (OPset || EPset || APset) 16613828Skre APset++, OPset++, EPset++; 16713795Ssam setdefaults(); 16813795Ssam ioctl(0, TIOCFLUSH, 0); /* clear out the crap */ 16913795Ssam if (IS) 17013795Ssam tmode.sg_ispeed = speed(IS); 17113795Ssam else if (SP) 17213795Ssam tmode.sg_ispeed = speed(SP); 17313795Ssam if (OS) 17413795Ssam tmode.sg_ospeed = speed(OS); 17513795Ssam else if (SP) 17613795Ssam tmode.sg_ospeed = speed(SP); 17713795Ssam tmode.sg_flags = setflags(0); 17813795Ssam ioctl(0, TIOCSETP, &tmode); 17913795Ssam setchars(); 18013795Ssam ioctl(0, TIOCSETC, &tc); 18113795Ssam ioctl(0, TIOCSETD, &ldisp); 18213795Ssam if (HC) 18313795Ssam ioctl(0, TIOCHPCL, 0); 18418543Sralph if (AB) { 18518543Sralph extern char *autobaud(); 18618543Sralph 18718543Sralph tname = autobaud(); 18818543Sralph continue; 18918543Sralph } 19013795Ssam if (PS) { 19113795Ssam tname = portselector(); 19213795Ssam continue; 19313795Ssam } 19413795Ssam if (CL && *CL) 19513795Ssam putpad(CL); 19613795Ssam edithost(HE); 19713795Ssam if (IM && *IM) 19813795Ssam putf(IM); 19913795Ssam if (setjmp(timeout)) { 20013795Ssam tmode.sg_ispeed = tmode.sg_ospeed = 0; 20113795Ssam ioctl(0, TIOCSETP, &tmode); 20213795Ssam exit(1); 20313795Ssam } 20413795Ssam if (TO) { 20513795Ssam signal(SIGALRM, dingdong); 20613795Ssam alarm(TO); 20713795Ssam } 20813795Ssam if (getname()) { 20918543Sralph register int i; 21018543Sralph 21118543Sralph oflush(); 21213795Ssam alarm(0); 21313795Ssam signal(SIGALRM, SIG_DFL); 21413831Ssam if (!(upper || lower || digit)) 21513795Ssam continue; 21613795Ssam allflags = setflags(2); 21713795Ssam tmode.sg_flags = allflags & 0xffff; 21813795Ssam allflags >>= 16; 21913795Ssam if (crmod || NL) 22013795Ssam tmode.sg_flags |= CRMOD; 22113795Ssam if (upper || UC) 22213795Ssam tmode.sg_flags |= LCASE; 22313795Ssam if (lower || LC) 22413795Ssam tmode.sg_flags &= ~LCASE; 22513795Ssam ioctl(0, TIOCSETP, &tmode); 22613795Ssam ioctl(0, TIOCSLTC, <c); 22713795Ssam ioctl(0, TIOCLSET, &allflags); 22813828Skre signal(SIGINT, SIG_DFL); 22918543Sralph for (i = 0; environ[i] != (char *)0; i++) 23018543Sralph env[i] = environ[i]; 23118543Sralph makeenv(&env[i]); 23218543Sralph execle(LO, "login", "-p", name, (char *) 0, env); 23313795Ssam exit(1); 23413795Ssam } 23513795Ssam alarm(0); 23613795Ssam signal(SIGALRM, SIG_DFL); 23713828Skre signal(SIGINT, SIG_IGN); 23813795Ssam if (NX && *NX) 23913795Ssam tname = NX; 24013795Ssam } 24113795Ssam } 24213795Ssam 24313795Ssam getname() 24413795Ssam { 24513795Ssam register char *np; 24613795Ssam register c; 24713795Ssam char cs; 24813795Ssam 24913828Skre /* 25013831Ssam * Interrupt may happen if we use CBREAK mode 25113828Skre */ 25213828Skre if (setjmp(intrupt)) { 25313828Skre signal(SIGINT, SIG_IGN); 25413828Skre return (0); 25513828Skre } 25613828Skre signal(SIGINT, interrupt); 25713795Ssam tmode.sg_flags = setflags(0); 25813795Ssam ioctl(0, TIOCSETP, &tmode); 25913795Ssam tmode.sg_flags = setflags(1); 26013795Ssam prompt(); 26113885Ssam if (PF > 0) { 26214322Ssam oflush(); 26313885Ssam sleep(PF); 26413885Ssam PF = 0; 26513885Ssam } 26613795Ssam ioctl(0, TIOCSETP, &tmode); 26713795Ssam crmod = 0; 26813795Ssam upper = 0; 26913795Ssam lower = 0; 27013795Ssam digit = 0; 27113795Ssam np = name; 27213795Ssam for (;;) { 27313828Skre oflush(); 27413795Ssam if (read(0, &cs, 1) <= 0) 27513795Ssam exit(0); 27613795Ssam if ((c = cs&0177) == 0) 27713795Ssam return (0); 27813831Ssam if (c == EOT) 27913795Ssam exit(1); 28018543Sralph if (c == '\r' || c == '\n' || np >= &name[sizeof name]) { 28118543Sralph putf("\r\n"); 28213795Ssam break; 28318543Sralph } 28413831Ssam if (c >= 'a' && c <= 'z') 28513795Ssam lower++; 28618543Sralph else if (c >= 'A' && c <= 'Z') 28713795Ssam upper++; 28818543Sralph else if (c == ERASE || c == '#' || c == '\b') { 28913795Ssam if (np > name) { 29013795Ssam np--; 29113795Ssam if (tmode.sg_ospeed >= B1200) 29213795Ssam puts("\b \b"); 29313795Ssam else 29413795Ssam putchr(cs); 29513795Ssam } 29613795Ssam continue; 29713831Ssam } else if (c == KILL || c == '@') { 29813795Ssam putchr(cs); 29913795Ssam putchr('\r'); 30013795Ssam if (tmode.sg_ospeed < B1200) 30113795Ssam putchr('\n'); 30213795Ssam /* this is the way they do it down under ... */ 30313795Ssam else if (np > name) 30413795Ssam puts(" \r"); 30513795Ssam prompt(); 30613795Ssam np = name; 30713795Ssam continue; 30818543Sralph } else if (c >= '0' && c <= '9') 30913795Ssam digit++; 31018543Sralph if (IG && (c <= ' ' || c > 0176)) 31113795Ssam continue; 31213795Ssam *np++ = c; 31313795Ssam putchr(cs); 31413795Ssam } 31513828Skre signal(SIGINT, SIG_IGN); 31613795Ssam *np = 0; 31713795Ssam if (c == '\r') 31813795Ssam crmod++; 31913795Ssam if (upper && !lower && !LC || UC) 32013795Ssam for (np = name; *np; np++) 32113795Ssam if (isupper(*np)) 32213795Ssam *np = tolower(*np); 32313795Ssam return (1); 32413795Ssam } 32513795Ssam 32613795Ssam static 32713795Ssam short tmspc10[] = { 32813795Ssam 0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5, 15 32913795Ssam }; 33013795Ssam 33113795Ssam putpad(s) 33213795Ssam register char *s; 33313795Ssam { 33413795Ssam register pad = 0; 33513795Ssam register mspc10; 33613795Ssam 33713795Ssam if (isdigit(*s)) { 33813795Ssam while (isdigit(*s)) { 33913795Ssam pad *= 10; 34013795Ssam pad += *s++ - '0'; 34113795Ssam } 34213795Ssam pad *= 10; 34313795Ssam if (*s == '.' && isdigit(s[1])) { 34413795Ssam pad += s[1] - '0'; 34513795Ssam s += 2; 34613795Ssam } 34713795Ssam } 34813795Ssam 34913795Ssam puts(s); 35013795Ssam /* 35113795Ssam * If no delay needed, or output speed is 35213795Ssam * not comprehensible, then don't try to delay. 35313795Ssam */ 35413795Ssam if (pad == 0) 35513795Ssam return; 35613795Ssam if (tmode.sg_ospeed <= 0 || 35713795Ssam tmode.sg_ospeed >= (sizeof tmspc10 / sizeof tmspc10[0])) 35813795Ssam return; 35913795Ssam 36013795Ssam /* 36113795Ssam * Round up by a half a character frame, 36213795Ssam * and then do the delay. 36313795Ssam * Too bad there are no user program accessible programmed delays. 36413795Ssam * Transmitting pad characters slows many 36513795Ssam * terminals down and also loads the system. 36613795Ssam */ 36713795Ssam mspc10 = tmspc10[tmode.sg_ospeed]; 36813795Ssam pad += mspc10 / 2; 36913795Ssam for (pad /= mspc10; pad > 0; pad--) 37013795Ssam putchr(*PC); 37113795Ssam } 37213795Ssam 37313795Ssam puts(s) 37413795Ssam register char *s; 37513795Ssam { 37613795Ssam 37713795Ssam while (*s) 37813795Ssam putchr(*s++); 37913795Ssam } 38013795Ssam 38113828Skre char outbuf[OBUFSIZ]; 38213828Skre int obufcnt = 0; 38313828Skre 38413795Ssam putchr(cc) 38513795Ssam { 38613795Ssam char c; 38713795Ssam 38813795Ssam c = cc; 38913795Ssam c |= partab[c&0177] & 0200; 39013795Ssam if (OP) 39113795Ssam c ^= 0200; 39213828Skre if (!UB) { 39313828Skre outbuf[obufcnt++] = c; 39413828Skre if (obufcnt >= OBUFSIZ) 39513828Skre oflush(); 39613828Skre } else 39713828Skre write(1, &c, 1); 39813795Ssam } 39913795Ssam 40013828Skre oflush() 40113828Skre { 40213828Skre if (obufcnt) 40313828Skre write(1, outbuf, obufcnt); 40413828Skre obufcnt = 0; 40513828Skre } 40613828Skre 40713795Ssam prompt() 40813795Ssam { 40913795Ssam 41013795Ssam putf(LM); 41113795Ssam if (CO) 41213795Ssam putchr('\n'); 41313795Ssam } 41413795Ssam 41513795Ssam putf(cp) 41613795Ssam register char *cp; 41713795Ssam { 41818543Sralph char *ttyn, *slash; 41918543Sralph char datebuffer[60]; 42013795Ssam extern char editedhost[]; 42118543Sralph extern char *ttyname(), *rindex(); 42213795Ssam 42313795Ssam while (*cp) { 42413795Ssam if (*cp != '%') { 42513795Ssam putchr(*cp++); 42613795Ssam continue; 42713795Ssam } 42813795Ssam switch (*++cp) { 42913795Ssam 43018543Sralph case 't': 43118543Sralph ttyn = ttyname(0); 43218543Sralph slash = rindex(ttyn, '/'); 43318543Sralph if (slash == (char *) 0) 43418543Sralph puts(ttyn); 43518543Sralph else 43618543Sralph puts(&slash[1]); 43718543Sralph break; 43818543Sralph 43913795Ssam case 'h': 44013795Ssam puts(editedhost); 44113795Ssam break; 44213795Ssam 44318543Sralph case 'd': 44418543Sralph get_date(datebuffer); 44518543Sralph puts(datebuffer); 44615713Sralph break; 44715713Sralph 44813795Ssam case '%': 44913795Ssam putchr('%'); 45013795Ssam break; 45113795Ssam } 45213795Ssam cp++; 45313795Ssam } 45413795Ssam } 455