main.c revision 22491
11592Srgrimes/*- 215645Sjoerg * Copyright (c) 1980, 1993 315645Sjoerg * The Regents of the University of California. All rights reserved. 41592Srgrimes * 51592Srgrimes * Redistribution and use in source and binary forms, with or without 61592Srgrimes * modification, are permitted provided that the following conditions 71592Srgrimes * are met: 81592Srgrimes * 1. Redistributions of source code must retain the above copyright 91592Srgrimes * notice, this list of conditions and the following disclaimer. 101592Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111592Srgrimes * notice, this list of conditions and the following disclaimer in the 121592Srgrimes * documentation and/or other materials provided with the distribution. 131592Srgrimes * 3. All advertising materials mentioning features or use of this software 141592Srgrimes * must display the following acknowledgement: 151592Srgrimes * This product includes software developed by the University of 161592Srgrimes * California, Berkeley and its contributors. 171592Srgrimes * 4. Neither the name of the University nor the names of its contributors 181592Srgrimes * may be used to endorse or promote products derived from this software 191592Srgrimes * without specific prior written permission. 201592Srgrimes * 211592Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221592Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231592Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241592Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251592Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261592Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271592Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281592Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291592Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301592Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311592Srgrimes * SUCH DAMAGE. 321592Srgrimes */ 331592Srgrimes 341592Srgrimes#ifndef lint 3515645Sjoergstatic char copyright[] = 3615645Sjoerg"@(#) Copyright (c) 1980, 1993\n\ 3715645Sjoerg The Regents of the University of California. All rights reserved.\n"; 381592Srgrimes#endif /* not lint */ 391592Srgrimes 401592Srgrimes#ifndef lint 4115645Sjoerg/*static char sccsid[] = "from: @(#)main.c 8.1 (Berkeley) 6/20/93";*/ 4221673Sjkhstatic char rcsid[] = "$FreeBSD: head/libexec/getty/main.c 22491 1997-02-09 16:12:08Z davidn $"; 431592Srgrimes#endif /* not lint */ 441592Srgrimes 451592Srgrimes#include <sys/param.h> 461592Srgrimes#include <sys/stat.h> 4715645Sjoerg#include <sys/ioctl.h> 4815645Sjoerg#include <sys/resource.h> 4915645Sjoerg#include <sys/ttydefaults.h> 5015645Sjoerg#include <sys/utsname.h> 5115645Sjoerg#include <errno.h> 522286Sjkh#include <signal.h> 532286Sjkh#include <fcntl.h> 542286Sjkh#include <time.h> 551592Srgrimes#include <ctype.h> 5615645Sjoerg#include <fcntl.h> 5715645Sjoerg#include <libutil.h> 5815645Sjoerg#include <locale.h> 592286Sjkh#include <setjmp.h> 6015645Sjoerg#include <signal.h> 6115645Sjoerg#include <stdlib.h> 6215645Sjoerg#include <string.h> 632286Sjkh#include <syslog.h> 6415645Sjoerg#include <termios.h> 6515645Sjoerg#include <time.h> 662286Sjkh#include <unistd.h> 6715645Sjoerg 681592Srgrimes#include "gettytab.h" 691592Srgrimes#include "pathnames.h" 7015645Sjoerg#include "extern.h" 711592Srgrimes 7215645Sjoerg/* 7315645Sjoerg * Set the amount of running time that getty should accumulate 7415645Sjoerg * before deciding that something is wrong and exit. 7515645Sjoerg */ 7615645Sjoerg#define GETTY_TIMEOUT 60 /* seconds */ 771592Srgrimes 7815645Sjoerg#undef CTRL 7915645Sjoerg#define CTRL(x) (x&037) 8015645Sjoerg 8119697Spst/* defines for auto detection of incoming PPP calls (->PAP/CHAP) */ 8219697Spst 8319697Spst#define PPP_FRAME 0x7e /* PPP Framing character */ 8419697Spst#define PPP_STATION 0xff /* "All Station" character */ 8519697Spst#define PPP_ESCAPE 0x7d /* Escape Character */ 8619697Spst#define PPP_CONTROL 0x03 /* PPP Control Field */ 8719697Spst#define PPP_CONTROL_ESCAPED 0x23 /* PPP Control Field, escaped */ 8819697Spst#define PPP_LCP_HI 0xc0 /* LCP protocol - high byte */ 8919697Spst#define PPP_LCP_LOW 0x21 /* LCP protocol - low byte */ 9019697Spst 9115645Sjoergstruct termios tmode, omode; 9215645Sjoerg 931592Srgrimesint crmod, digit, lower, upper; 941592Srgrimes 951592Srgrimeschar hostname[MAXHOSTNAMELEN]; 9622400Sdavidnchar name[MAXLOGNAME*3]; 971592Srgrimeschar dev[] = _PATH_DEV; 981592Srgrimeschar ttyn[32]; 991592Srgrimes 1001592Srgrimes#define OBUFSIZ 128 1011592Srgrimes#define TABBUFSIZ 512 1021592Srgrimes 1031592Srgrimeschar defent[TABBUFSIZ]; 1041592Srgrimeschar tabent[TABBUFSIZ]; 1051592Srgrimes 1061592Srgrimeschar *env[128]; 1071592Srgrimes 1081592Srgrimeschar partab[] = { 1091592Srgrimes 0001,0201,0201,0001,0201,0001,0001,0201, 1101592Srgrimes 0202,0004,0003,0205,0005,0206,0201,0001, 1111592Srgrimes 0201,0001,0001,0201,0001,0201,0201,0001, 1121592Srgrimes 0001,0201,0201,0001,0201,0001,0001,0201, 1131592Srgrimes 0200,0000,0000,0200,0000,0200,0200,0000, 1141592Srgrimes 0000,0200,0200,0000,0200,0000,0000,0200, 1151592Srgrimes 0000,0200,0200,0000,0200,0000,0000,0200, 1161592Srgrimes 0200,0000,0000,0200,0000,0200,0200,0000, 1171592Srgrimes 0200,0000,0000,0200,0000,0200,0200,0000, 1181592Srgrimes 0000,0200,0200,0000,0200,0000,0000,0200, 1191592Srgrimes 0000,0200,0200,0000,0200,0000,0000,0200, 1201592Srgrimes 0200,0000,0000,0200,0000,0200,0200,0000, 1211592Srgrimes 0000,0200,0200,0000,0200,0000,0000,0200, 1221592Srgrimes 0200,0000,0000,0200,0000,0200,0200,0000, 1231592Srgrimes 0200,0000,0000,0200,0000,0200,0200,0000, 1241592Srgrimes 0000,0200,0200,0000,0200,0000,0000,0201 1251592Srgrimes}; 1261592Srgrimes 12715645Sjoerg#define ERASE tmode.c_cc[VERASE] 12815645Sjoerg#define KILL tmode.c_cc[VKILL] 12915645Sjoerg#define EOT tmode.c_cc[VEOF] 1301592Srgrimes 13115645Sjoergstatic void dingdong __P((int)); 13215645Sjoergstatic int getname __P((void)); 13315645Sjoergstatic void interrupt __P((int)); 13415645Sjoergstatic void oflush __P((void)); 13515645Sjoergstatic void prompt __P((void)); 13615645Sjoergstatic void putchr __P((int)); 13715645Sjoergstatic void putf __P((const char *)); 13815645Sjoergstatic void putpad __P((const char *)); 13915645Sjoergstatic void puts __P((const char *)); 14015645Sjoergstatic void timeoverrun __P((int)); 14122208Sdavidnstatic char *getline __P((int)); 14222208Sdavidnstatic void setttymode __P((const char *, int)); 14322208Sdavidnstatic void setdefttymode __P((const char *)); 14422208Sdavidnstatic int opentty __P((const char *, int)); 14515645Sjoerg 14615645Sjoergint main __P((int, char **)); 14715645Sjoerg 14822208Sdavidnjmp_buf timeout; 14922208Sdavidn 1501592Srgrimesstatic void 15115645Sjoergdingdong(signo) 15215645Sjoerg int signo; 1531592Srgrimes{ 1541592Srgrimes alarm(0); 1551592Srgrimes longjmp(timeout, 1); 1561592Srgrimes} 1571592Srgrimes 1581592Srgrimesjmp_buf intrupt; 1591592Srgrimes 1601592Srgrimesstatic void 16115645Sjoerginterrupt(signo) 16215645Sjoerg int signo; 1631592Srgrimes{ 1641592Srgrimes longjmp(intrupt, 1); 1651592Srgrimes} 1661592Srgrimes 16715645Sjoerg/* 16815645Sjoerg * Action to take when getty is running too long. 16915645Sjoerg */ 17015645Sjoergstatic void 17115645Sjoergtimeoverrun(signo) 17215645Sjoerg int signo; 17315645Sjoerg{ 17415645Sjoerg 17515645Sjoerg syslog(LOG_ERR, "getty exiting due to excessive running time\n"); 17615645Sjoerg exit(1); 17715645Sjoerg} 17815645Sjoerg 17915645Sjoergint 1801592Srgrimesmain(argc, argv) 1811592Srgrimes int argc; 1822286Sjkh char **argv; 1831592Srgrimes{ 1842286Sjkh extern char **environ; 18515645Sjoerg const char *tname; 18622491Sdavidn int repcnt = 0, failopenlogged = 0; 18722491Sdavidn int first_sleep = 1, first_time = 1; 18815645Sjoerg struct rlimit limit; 18919697Spst int rval; 1901592Srgrimes 1911592Srgrimes signal(SIGINT, SIG_IGN); 1922391Sache signal(SIGQUIT, SIG_IGN); 1932286Sjkh 19415645Sjoerg openlog("getty", LOG_ODELAY|LOG_CONS|LOG_PID, LOG_AUTH); 1951592Srgrimes gethostname(hostname, sizeof(hostname)); 1961592Srgrimes if (hostname[0] == '\0') 1971592Srgrimes strcpy(hostname, "Amnesiac"); 19815645Sjoerg 1991592Srgrimes /* 20015645Sjoerg * Limit running time to deal with broken or dead lines. 20115645Sjoerg */ 20215645Sjoerg (void)signal(SIGXCPU, timeoverrun); 20315645Sjoerg limit.rlim_max = RLIM_INFINITY; 20415645Sjoerg limit.rlim_cur = GETTY_TIMEOUT; 20515645Sjoerg (void)setrlimit(RLIMIT_CPU, &limit); 20615645Sjoerg 20722208Sdavidn gettable("default", defent); 20822208Sdavidn gendefaults(); 20922208Sdavidn tname = "default"; 21022208Sdavidn if (argc > 1) 21122208Sdavidn tname = argv[1]; 21222208Sdavidn 21315645Sjoerg /* 2141592Srgrimes * The following is a work around for vhangup interactions 2151592Srgrimes * which cause great problems getting window systems started. 2161592Srgrimes * If the tty line is "-", we do the old style getty presuming 2178870Srgrimes * that the file descriptors are already set up for us. 2181592Srgrimes * J. Gettys - MIT Project Athena. 2191592Srgrimes */ 2201592Srgrimes if (argc <= 2 || strcmp(argv[2], "-") == 0) 22122208Sdavidn strcpy(ttyn, ttyname(STDIN_FILENO)); 2221592Srgrimes else { 2231592Srgrimes int i; 2241592Srgrimes 2251592Srgrimes strcpy(ttyn, dev); 2261592Srgrimes strncat(ttyn, argv[2], sizeof(ttyn)-sizeof(dev)); 2271592Srgrimes if (strcmp(argv[0], "+") != 0) { 2281592Srgrimes chown(ttyn, 0, 0); 2291592Srgrimes chmod(ttyn, 0600); 2301592Srgrimes revoke(ttyn); 23122208Sdavidn 23222208Sdavidn gettable(tname, tabent); 23322208Sdavidn 23422208Sdavidn /* Init modem sequence has been specified 23522208Sdavidn */ 23622208Sdavidn if (IC) { 23722208Sdavidn if (!opentty(ttyn, O_RDWR|O_NONBLOCK)) 23822208Sdavidn exit(1); 23922208Sdavidn setdefttymode(tname); 24022208Sdavidn if (getty_chat(IC, CT, DC) > 0) { 24122208Sdavidn syslog(LOG_ERR, "modem init problem on %s", ttyn); 24222491Sdavidn (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode); 24322208Sdavidn exit(1); 2441592Srgrimes } 2451592Srgrimes } 24622208Sdavidn 24722208Sdavidn if (AC) { 24822208Sdavidn int i, rfds; 24922208Sdavidn struct timeval timeout; 25022208Sdavidn 25122208Sdavidn if (!opentty(ttyn, O_RDWR|O_NONBLOCK)) 25222208Sdavidn exit(1); 25322208Sdavidn setdefttymode(tname); 25422208Sdavidn rfds = 1 << 0; /* FD_SET */ 25522208Sdavidn timeout.tv_sec = RT; 25622208Sdavidn timeout.tv_usec = 0; 25722208Sdavidn i = select(32, (fd_set*)&rfds, (fd_set*)NULL, 25822208Sdavidn (fd_set*)NULL, RT ? &timeout : NULL); 25922208Sdavidn if (i < 0) { 26022208Sdavidn syslog(LOG_ERR, "select %s: %m", ttyn); 26122208Sdavidn } else if (i == 0) { 26222208Sdavidn syslog(LOG_NOTICE, "recycle tty %s", ttyn); 26322491Sdavidn (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode); 26422208Sdavidn exit(0); /* recycle for init */ 26522208Sdavidn } 26622208Sdavidn i = getty_chat(AC, CT, DC); 26722208Sdavidn if (i > 0) { 26822208Sdavidn syslog(LOG_ERR, "modem answer problem on %s", ttyn); 26922491Sdavidn (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode); 27022208Sdavidn exit(1); 27122208Sdavidn } 27222208Sdavidn } else { /* blocking open */ 27322208Sdavidn if (!opentty(ttyn, O_RDWR)) 27422208Sdavidn exit(1); 27522208Sdavidn } 2761592Srgrimes } 2771592Srgrimes } 2781592Srgrimes 27915645Sjoerg /* Start with default tty settings */ 28022208Sdavidn if (tcgetattr(STDIN_FILENO, &tmode) < 0) { 28122208Sdavidn syslog(LOG_ERR, "tcgetattr %s: %m", ttyn); 28215645Sjoerg exit(1); 28315645Sjoerg } 28415645Sjoerg /* 28515645Sjoerg * Don't rely on the driver too much, and initialize crucial 28615645Sjoerg * things according to <sys/ttydefaults.h>. Avoid clobbering 28715645Sjoerg * the c_cc[] settings however, the console drivers might wish 28815645Sjoerg * to leave their idea of the preferred VERASE key value 28915645Sjoerg * there. 29015645Sjoerg */ 29115645Sjoerg tmode.c_iflag = TTYDEF_IFLAG; 29215645Sjoerg tmode.c_oflag = TTYDEF_OFLAG; 29315645Sjoerg tmode.c_lflag = TTYDEF_LFLAG; 29415645Sjoerg tmode.c_cflag = TTYDEF_CFLAG; 29515645Sjoerg omode = tmode; 29615645Sjoerg 2971592Srgrimes for (;;) { 2981592Srgrimes 29922491Sdavidn /* 30022491Sdavidn * if a delay was specified then sleep for that 30122491Sdavidn * number of seconds before writing the initial prompt 30222491Sdavidn */ 30322491Sdavidn if (first_sleep && DE) { 30422491Sdavidn sleep(DE); 30522491Sdavidn /* remove any noise */ 30622491Sdavidn (void)tcflush(STDIN_FILENO, TCIOFLUSH); 30722491Sdavidn } 30822491Sdavidn first_sleep = 0; 30922491Sdavidn 31022208Sdavidn setttymode(tname, 0); 3111592Srgrimes if (AB) { 3121592Srgrimes tname = autobaud(); 3131592Srgrimes continue; 3141592Srgrimes } 3151592Srgrimes if (PS) { 3161592Srgrimes tname = portselector(); 3171592Srgrimes continue; 3181592Srgrimes } 3191592Srgrimes if (CL && *CL) 3201592Srgrimes putpad(CL); 3211592Srgrimes edithost(HE); 32221120Smsmith 32322208Sdavidn /* if this is the first time through this, and an 32422208Sdavidn issue file has been given, then send it */ 32522208Sdavidn if (first_time && IF) { 32622208Sdavidn int fd; 32722208Sdavidn 32822208Sdavidn if ((fd = open(IF, O_RDONLY)) != -1) { 32922208Sdavidn char * cp; 33022208Sdavidn 33122208Sdavidn while ((cp = getline(fd)) != NULL) { 33222208Sdavidn putf(cp); 33322208Sdavidn } 33422208Sdavidn close(fd); 33522208Sdavidn } 33622208Sdavidn } 33722491Sdavidn first_time = 0; 33822208Sdavidn 3391592Srgrimes if (IM && *IM) 3401592Srgrimes putf(IM); 3411592Srgrimes if (setjmp(timeout)) { 34215659Sache cfsetispeed(&tmode, B0); 34315659Sache cfsetospeed(&tmode, B0); 34422208Sdavidn (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode); 3451592Srgrimes exit(1); 3461592Srgrimes } 3471592Srgrimes if (TO) { 3481592Srgrimes signal(SIGALRM, dingdong); 3491592Srgrimes alarm(TO); 3501592Srgrimes } 35119697Spst if ((rval = getname()) == 2) { 35219697Spst execle(PP, "ppplogin", ttyn, (char *) 0, env); 35319697Spst syslog(LOG_ERR, "%s: %m", PP); 35419697Spst exit(1); 35519697Spst } else if (rval) { 3561592Srgrimes register int i; 3571592Srgrimes 35815645Sjoerg oflush(); 3591592Srgrimes alarm(0); 3601592Srgrimes signal(SIGALRM, SIG_DFL); 3611592Srgrimes if (name[0] == '-') { 3621592Srgrimes puts("user names may not start with '-'."); 3631592Srgrimes continue; 3641592Srgrimes } 3651592Srgrimes if (!(upper || lower || digit)) 3661592Srgrimes continue; 36715645Sjoerg setflags(2); 36815645Sjoerg if (crmod) { 36915645Sjoerg tmode.c_iflag |= ICRNL; 37015645Sjoerg tmode.c_oflag |= ONLCR; 37115645Sjoerg } 37215645Sjoerg#if REALLY_OLD_TTYS 37315645Sjoerg if (upper || UC) 37415645Sjoerg tmode.sg_flags |= LCASE; 37515645Sjoerg if (lower || LC) 37615645Sjoerg tmode.sg_flags &= ~LCASE; 37715645Sjoerg#endif 37822208Sdavidn if (tcsetattr(STDIN_FILENO, TCSANOW, &tmode) < 0) { 37922208Sdavidn syslog(LOG_ERR, "tcsetattr %s: %m", ttyn); 38015645Sjoerg exit(1); 38115645Sjoerg } 38215645Sjoerg signal(SIGINT, SIG_DFL); 3831592Srgrimes for (i = 0; environ[i] != (char *)0; i++) 3841592Srgrimes env[i] = environ[i]; 3851592Srgrimes makeenv(&env[i]); 3861592Srgrimes 38715645Sjoerg limit.rlim_max = RLIM_INFINITY; 38815645Sjoerg limit.rlim_cur = RLIM_INFINITY; 38915645Sjoerg (void)setrlimit(RLIMIT_CPU, &limit); 3901592Srgrimes execle(LO, "login", "-p", name, (char *) 0, env); 3911592Srgrimes syslog(LOG_ERR, "%s: %m", LO); 3921592Srgrimes exit(1); 3931592Srgrimes } 3941592Srgrimes alarm(0); 3951592Srgrimes signal(SIGALRM, SIG_DFL); 39615645Sjoerg signal(SIGINT, SIG_IGN); 3971592Srgrimes if (NX && *NX) 3981592Srgrimes tname = NX; 3991592Srgrimes } 4001592Srgrimes} 4011592Srgrimes 40215645Sjoergstatic int 40322208Sdavidnopentty(const char *ttyn, int flags) 40422208Sdavidn{ 40522208Sdavidn int i, j = 0; 40622208Sdavidn int failopenlogged = 0; 40722208Sdavidn 40822208Sdavidn while (j < 10 && (i = open(ttyn, flags)) == -1) 40922208Sdavidn { 41022208Sdavidn if (((j % 10) == 0) && (errno != ENXIO || !failopenlogged)) { 41122208Sdavidn syslog(LOG_ERR, "open %s: %m", ttyn); 41222208Sdavidn failopenlogged = 1; 41322208Sdavidn } 41422208Sdavidn j++; 41522208Sdavidn sleep(60); 41622208Sdavidn } 41722208Sdavidn if (i == -1) { 41822208Sdavidn syslog(LOG_ERR, "open %s: %m", ttyn); 41922208Sdavidn return 0; 42022208Sdavidn } 42122208Sdavidn else { 42222208Sdavidn login_tty(i); 42322208Sdavidn return 1; 42422208Sdavidn } 42522208Sdavidn} 42622208Sdavidn 42722208Sdavidnstatic void 42822208Sdavidnsetdefttymode(tname) 42922208Sdavidn const char * tname; 43022208Sdavidn{ 43122208Sdavidn if (tcgetattr(STDIN_FILENO, &tmode) < 0) { 43222208Sdavidn syslog(LOG_ERR, "tcgetattr %s: %m", ttyn); 43322208Sdavidn exit(1); 43422208Sdavidn } 43522208Sdavidn tmode.c_iflag = TTYDEF_IFLAG; 43622208Sdavidn tmode.c_oflag = TTYDEF_OFLAG; 43722208Sdavidn tmode.c_lflag = TTYDEF_LFLAG; 43822208Sdavidn tmode.c_cflag = TTYDEF_CFLAG; 43922208Sdavidn omode = tmode; 44022208Sdavidn setttymode(tname, 1); 44122208Sdavidn} 44222208Sdavidn 44322208Sdavidnstatic void 44422208Sdavidnsetttymode(tname, raw) 44522208Sdavidn const char * tname; 44622208Sdavidn int raw; 44722208Sdavidn{ 44822208Sdavidn int off = 0; 44922208Sdavidn 45022208Sdavidn gettable(tname, tabent); 45122208Sdavidn if (OPset || EPset || APset) 45222208Sdavidn APset++, OPset++, EPset++; 45322208Sdavidn setdefaults(); 45422208Sdavidn (void)tcflush(STDIN_FILENO, TCIOFLUSH); /* clear out the crap */ 45522208Sdavidn ioctl(STDIN_FILENO, FIONBIO, &off); /* turn off non-blocking mode */ 45622208Sdavidn ioctl(STDIN_FILENO, FIOASYNC, &off); /* ditto for async mode */ 45722208Sdavidn 45822208Sdavidn if (IS) 45922208Sdavidn cfsetispeed(&tmode, speed(IS)); 46022208Sdavidn else if (SP) 46122208Sdavidn cfsetispeed(&tmode, speed(SP)); 46222208Sdavidn if (OS) 46322208Sdavidn cfsetospeed(&tmode, speed(OS)); 46422208Sdavidn else if (SP) 46522208Sdavidn cfsetospeed(&tmode, speed(SP)); 46622208Sdavidn setflags(0); 46722208Sdavidn setchars(); 46822208Sdavidn if (raw) 46922208Sdavidn cfmakeraw(&tmode); 47022208Sdavidn if (tcsetattr(STDIN_FILENO, TCSANOW, &tmode) < 0) { 47122208Sdavidn syslog(LOG_ERR, "tcsetattr %s: %m", ttyn); 47222208Sdavidn exit(1); 47322208Sdavidn } 47422208Sdavidn} 47522208Sdavidn 47622208Sdavidn 47722208Sdavidnstatic int 4781592Srgrimesgetname() 4791592Srgrimes{ 4801592Srgrimes register int c; 4811592Srgrimes register char *np; 48219697Spst unsigned char cs; 48322208Sdavidn int ppp_state = 0; 48419697Spst int ppp_connection = 0; 4851592Srgrimes 4861592Srgrimes /* 4871592Srgrimes * Interrupt may happen if we use CBREAK mode 4881592Srgrimes */ 4891592Srgrimes if (setjmp(intrupt)) { 4901592Srgrimes signal(SIGINT, SIG_IGN); 4911592Srgrimes return (0); 4921592Srgrimes } 4931592Srgrimes signal(SIGINT, interrupt); 49415645Sjoerg setflags(1); 4951592Srgrimes prompt(); 4962286Sjkh oflush(); 4971592Srgrimes if (PF > 0) { 4981592Srgrimes sleep(PF); 4991592Srgrimes PF = 0; 5001592Srgrimes } 50122208Sdavidn if (tcsetattr(STDIN_FILENO, TCSANOW, &tmode) < 0) { 50215645Sjoerg syslog(LOG_ERR, "%s: %m", ttyn); 50315645Sjoerg exit(1); 50415645Sjoerg } 5051592Srgrimes crmod = digit = lower = upper = 0; 5061592Srgrimes np = name; 5071592Srgrimes for (;;) { 5081592Srgrimes oflush(); 5091592Srgrimes if (read(STDIN_FILENO, &cs, 1) <= 0) 5101592Srgrimes exit(0); 5111592Srgrimes if ((c = cs&0177) == 0) 5121592Srgrimes return (0); 51319697Spst 51419697Spst /* PPP detection state machine.. 51519697Spst Look for sequences: 51619697Spst PPP_FRAME, PPP_STATION, PPP_ESCAPE, PPP_CONTROL_ESCAPED or 51719697Spst PPP_FRAME, PPP_STATION, PPP_CONTROL (deviant from RFC) 51819697Spst See RFC1662. 51919697Spst Derived from code from Michael Hancock, <michaelh@cet.co.jp> 52019697Spst and Erik 'PPP' Olson, <eriko@wrq.com> 52119697Spst */ 52219697Spst 52319697Spst if (PP && (cs == PPP_FRAME)) { 52419697Spst ppp_state = 1; 52519697Spst } else if (ppp_state == 1 && cs == PPP_STATION) { 52619697Spst ppp_state = 2; 52719697Spst } else if (ppp_state == 2 && cs == PPP_ESCAPE) { 52819697Spst ppp_state = 3; 52919697Spst } else if ((ppp_state == 2 && cs == PPP_CONTROL) 53019697Spst || (ppp_state == 3 && cs == PPP_CONTROL_ESCAPED)) { 53119697Spst ppp_state = 4; 53219697Spst } else if (ppp_state == 4 && cs == PPP_LCP_HI) { 53319697Spst ppp_state = 5; 53419697Spst } else if (ppp_state == 5 && cs == PPP_LCP_LOW) { 53519697Spst ppp_connection = 1; 53619697Spst break; 53719697Spst } else { 53819697Spst ppp_state = 0; 53919697Spst } 54019697Spst 54115645Sjoerg if (c == EOT || c == CTRL('d')) 5421592Srgrimes exit(1); 54322211Sdavidn if (c == '\r' || c == '\n' || np >= &name[sizeof name-1]) { 5441592Srgrimes putf("\r\n"); 5451592Srgrimes break; 5461592Srgrimes } 5471592Srgrimes if (islower(c)) 5481592Srgrimes lower = 1; 5491592Srgrimes else if (isupper(c)) 5501592Srgrimes upper = 1; 5512286Sjkh else if (c == ERASE || c == '\b' || c == 0177) { 5521592Srgrimes if (np > name) { 5531592Srgrimes np--; 55415645Sjoerg if (cfgetospeed(&tmode) >= 1200) 5551592Srgrimes puts("\b \b"); 5561592Srgrimes else 5571592Srgrimes putchr(cs); 5581592Srgrimes } 5591592Srgrimes continue; 56015645Sjoerg } else if (c == KILL || c == CTRL('u')) { 5611592Srgrimes putchr('\r'); 56215645Sjoerg if (cfgetospeed(&tmode) < 1200) 5631592Srgrimes putchr('\n'); 5641592Srgrimes /* this is the way they do it down under ... */ 5651592Srgrimes else if (np > name) 5661592Srgrimes puts(" \r"); 5671592Srgrimes prompt(); 5681592Srgrimes np = name; 5691592Srgrimes continue; 5701592Srgrimes } else if (isdigit(c)) 5711592Srgrimes digit++; 5721592Srgrimes if (IG && (c <= ' ' || c > 0176)) 5731592Srgrimes continue; 5741592Srgrimes *np++ = c; 5751592Srgrimes putchr(cs); 5761592Srgrimes } 5771592Srgrimes signal(SIGINT, SIG_IGN); 5781592Srgrimes *np = 0; 5791592Srgrimes if (c == '\r') 5801592Srgrimes crmod = 1; 58115645Sjoerg if ((upper && !lower && !LC) || UC) 5821592Srgrimes for (np = name; *np; np++) 5831592Srgrimes if (isupper(*np)) 5841592Srgrimes *np = tolower(*np); 58519697Spst return (1 + ppp_connection); 5861592Srgrimes} 5871592Srgrimes 58815645Sjoergstatic void 5891592Srgrimesputpad(s) 59015645Sjoerg register const char *s; 5911592Srgrimes{ 5921592Srgrimes register pad = 0; 59315645Sjoerg speed_t ospeed = cfgetospeed(&tmode); 5941592Srgrimes 5951592Srgrimes if (isdigit(*s)) { 5961592Srgrimes while (isdigit(*s)) { 5971592Srgrimes pad *= 10; 5981592Srgrimes pad += *s++ - '0'; 5991592Srgrimes } 6001592Srgrimes pad *= 10; 6011592Srgrimes if (*s == '.' && isdigit(s[1])) { 6021592Srgrimes pad += s[1] - '0'; 6031592Srgrimes s += 2; 6041592Srgrimes } 6051592Srgrimes } 6061592Srgrimes 6071592Srgrimes puts(s); 6081592Srgrimes /* 6091592Srgrimes * If no delay needed, or output speed is 6101592Srgrimes * not comprehensible, then don't try to delay. 6111592Srgrimes */ 61215645Sjoerg if (pad == 0 || ospeed <= 0) 6131592Srgrimes return; 6141592Srgrimes 6151592Srgrimes /* 6161592Srgrimes * Round up by a half a character frame, and then do the delay. 6171592Srgrimes * Too bad there are no user program accessible programmed delays. 6181592Srgrimes * Transmitting pad characters slows many terminals down and also 6191592Srgrimes * loads the system. 6201592Srgrimes */ 62115645Sjoerg pad = (pad * ospeed + 50000) / 100000; 62215645Sjoerg while (pad--) 6231592Srgrimes putchr(*PC); 6241592Srgrimes} 6251592Srgrimes 62615645Sjoergstatic void 6271592Srgrimesputs(s) 62815645Sjoerg register const char *s; 6291592Srgrimes{ 6301592Srgrimes while (*s) 6311592Srgrimes putchr(*s++); 6321592Srgrimes} 6331592Srgrimes 6341592Srgrimeschar outbuf[OBUFSIZ]; 6351592Srgrimesint obufcnt = 0; 6361592Srgrimes 63715645Sjoergstatic void 6381592Srgrimesputchr(cc) 63915645Sjoerg int cc; 6401592Srgrimes{ 6411592Srgrimes char c; 6421592Srgrimes 6431592Srgrimes c = cc; 6441592Srgrimes if (!NP) { 6451592Srgrimes c |= partab[c&0177] & 0200; 6461592Srgrimes if (OP) 6471592Srgrimes c ^= 0200; 6481592Srgrimes } 6491592Srgrimes if (!UB) { 6501592Srgrimes outbuf[obufcnt++] = c; 6511592Srgrimes if (obufcnt >= OBUFSIZ) 6521592Srgrimes oflush(); 6531592Srgrimes } else 6541592Srgrimes write(STDOUT_FILENO, &c, 1); 6551592Srgrimes} 6561592Srgrimes 65715645Sjoergstatic void 6581592Srgrimesoflush() 6591592Srgrimes{ 6601592Srgrimes if (obufcnt) 6611592Srgrimes write(STDOUT_FILENO, outbuf, obufcnt); 6621592Srgrimes obufcnt = 0; 6631592Srgrimes} 6641592Srgrimes 66515645Sjoergstatic void 6661592Srgrimesprompt() 6671592Srgrimes{ 6681592Srgrimes 6691592Srgrimes putf(LM); 6701592Srgrimes if (CO) 6711592Srgrimes putchr('\n'); 6721592Srgrimes} 6731592Srgrimes 67422208Sdavidn 67522208Sdavidnstatic char * 67622208Sdavidngetline(fd) 67722208Sdavidn int fd; 67822208Sdavidn{ 67922208Sdavidn int i = 0; 68022208Sdavidn static char linebuf[512]; 68122208Sdavidn 68222208Sdavidn /* 68322208Sdavidn * This is certainly slow, but it avoids having to include 68422208Sdavidn * stdio.h unnecessarily. Issue files should be small anyway. 68522208Sdavidn */ 68622208Sdavidn while (i < (sizeof linebuf - 3) && read(fd, linebuf+i, 1)==1) { 68722208Sdavidn if (linebuf[i] == '\n') { 68822208Sdavidn /* Don't rely on newline mode, assume raw */ 68922208Sdavidn linebuf[i++] = '\r'; 69022208Sdavidn linebuf[i++] = '\n'; 69122208Sdavidn linebuf[i] = '\0'; 69222208Sdavidn return linebuf; 69322208Sdavidn } 69422208Sdavidn ++i; 69522208Sdavidn } 69622208Sdavidn linebuf[i] = '\0'; 69722208Sdavidn return i ? linebuf : 0; 69822208Sdavidn} 69922208Sdavidn 70015645Sjoergstatic void 7011592Srgrimesputf(cp) 70215645Sjoerg register const char *cp; 7031592Srgrimes{ 7041592Srgrimes extern char editedhost[]; 7051592Srgrimes time_t t; 7061592Srgrimes char *slash, db[100]; 7071592Srgrimes 70822199Sdavidn static struct utsname kerninfo; 70922199Sdavidn 71022199Sdavidn if (!*kerninfo.sysname) 71122199Sdavidn uname(&kerninfo); 71222199Sdavidn 7131592Srgrimes while (*cp) { 7141592Srgrimes if (*cp != '%') { 7151592Srgrimes putchr(*cp++); 7161592Srgrimes continue; 7171592Srgrimes } 7181592Srgrimes switch (*++cp) { 7191592Srgrimes 7201592Srgrimes case 't': 72115645Sjoerg slash = strrchr(ttyn, '/'); 7221592Srgrimes if (slash == (char *) 0) 7231592Srgrimes puts(ttyn); 7241592Srgrimes else 7251592Srgrimes puts(&slash[1]); 7261592Srgrimes break; 7271592Srgrimes 7281592Srgrimes case 'h': 7291592Srgrimes puts(editedhost); 7301592Srgrimes break; 7311592Srgrimes 7321592Srgrimes case 'd': { 73315645Sjoerg t = (time_t)0; 7341592Srgrimes (void)time(&t); 73515645Sjoerg if (Lo) 73615645Sjoerg (void)setlocale(LC_TIME, Lo); 73715645Sjoerg (void)strftime(db, sizeof(db), "%+", localtime(&t)); 7381592Srgrimes puts(db); 7399875Sjkh break; 74015645Sjoerg 74115645Sjoerg case 's': 74215645Sjoerg puts(kerninfo.sysname); 74315645Sjoerg break; 74415645Sjoerg 74515645Sjoerg case 'm': 74615645Sjoerg puts(kerninfo.machine); 74715645Sjoerg break; 74815645Sjoerg 74915645Sjoerg case 'r': 75015645Sjoerg puts(kerninfo.release); 75115645Sjoerg break; 75215645Sjoerg 75315645Sjoerg case 'v': 75415645Sjoerg puts(kerninfo.version); 75515645Sjoerg break; 7561592Srgrimes } 7571592Srgrimes 7581592Srgrimes case '%': 7591592Srgrimes putchr('%'); 7601592Srgrimes break; 7611592Srgrimes } 7621592Srgrimes cp++; 7631592Srgrimes } 7641592Srgrimes} 765