main.c revision 77874
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 3531331Scharnierstatic const 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 4131331Scharnier#if 0 4231331Scharnierstatic char sccsid[] = "@(#)from: main.c 8.1 (Berkeley) 6/20/93"; 4331331Scharnier#endif 4431331Scharnierstatic const char rcsid[] = 4550476Speter "$FreeBSD: head/libexec/getty/main.c 77874 2001-06-07 13:53:23Z yar $"; 461592Srgrimes#endif /* not lint */ 471592Srgrimes 481592Srgrimes#include <sys/param.h> 491592Srgrimes#include <sys/stat.h> 5015645Sjoerg#include <sys/ioctl.h> 5115645Sjoerg#include <sys/resource.h> 5215645Sjoerg#include <sys/ttydefaults.h> 5315645Sjoerg#include <sys/utsname.h> 5466907Swollman 5531331Scharnier#include <ctype.h> 5615645Sjoerg#include <errno.h> 572286Sjkh#include <fcntl.h> 5831331Scharnier#include <locale.h> 5915645Sjoerg#include <libutil.h> 6031331Scharnier#include <signal.h> 612286Sjkh#include <setjmp.h> 6215645Sjoerg#include <signal.h> 6315645Sjoerg#include <stdlib.h> 6415645Sjoerg#include <string.h> 652286Sjkh#include <syslog.h> 6615645Sjoerg#include <termios.h> 6715645Sjoerg#include <time.h> 682286Sjkh#include <unistd.h> 6915645Sjoerg 701592Srgrimes#include "gettytab.h" 711592Srgrimes#include "pathnames.h" 7215645Sjoerg#include "extern.h" 731592Srgrimes 7415645Sjoerg/* 7515645Sjoerg * Set the amount of running time that getty should accumulate 7615645Sjoerg * before deciding that something is wrong and exit. 7715645Sjoerg */ 7815645Sjoerg#define GETTY_TIMEOUT 60 /* seconds */ 791592Srgrimes 8015645Sjoerg#undef CTRL 8115645Sjoerg#define CTRL(x) (x&037) 8215645Sjoerg 8319697Spst/* defines for auto detection of incoming PPP calls (->PAP/CHAP) */ 8419697Spst 8519697Spst#define PPP_FRAME 0x7e /* PPP Framing character */ 8619697Spst#define PPP_STATION 0xff /* "All Station" character */ 8719697Spst#define PPP_ESCAPE 0x7d /* Escape Character */ 8819697Spst#define PPP_CONTROL 0x03 /* PPP Control Field */ 8919697Spst#define PPP_CONTROL_ESCAPED 0x23 /* PPP Control Field, escaped */ 9019697Spst#define PPP_LCP_HI 0xc0 /* LCP protocol - high byte */ 9119697Spst#define PPP_LCP_LOW 0x21 /* LCP protocol - low byte */ 9219697Spst 9315645Sjoergstruct termios tmode, omode; 9415645Sjoerg 951592Srgrimesint crmod, digit, lower, upper; 961592Srgrimes 971592Srgrimeschar hostname[MAXHOSTNAMELEN]; 9822400Sdavidnchar name[MAXLOGNAME*3]; 991592Srgrimeschar dev[] = _PATH_DEV; 1001592Srgrimeschar ttyn[32]; 1011592Srgrimes 1021592Srgrimes#define OBUFSIZ 128 1031592Srgrimes#define TABBUFSIZ 512 1041592Srgrimes 1051592Srgrimeschar defent[TABBUFSIZ]; 1061592Srgrimeschar tabent[TABBUFSIZ]; 1071592Srgrimes 1081592Srgrimeschar *env[128]; 1091592Srgrimes 1101592Srgrimeschar partab[] = { 1111592Srgrimes 0001,0201,0201,0001,0201,0001,0001,0201, 1121592Srgrimes 0202,0004,0003,0205,0005,0206,0201,0001, 1131592Srgrimes 0201,0001,0001,0201,0001,0201,0201,0001, 1141592Srgrimes 0001,0201,0201,0001,0201,0001,0001,0201, 1151592Srgrimes 0200,0000,0000,0200,0000,0200,0200,0000, 1161592Srgrimes 0000,0200,0200,0000,0200,0000,0000,0200, 1171592Srgrimes 0000,0200,0200,0000,0200,0000,0000,0200, 1181592Srgrimes 0200,0000,0000,0200,0000,0200,0200,0000, 1191592Srgrimes 0200,0000,0000,0200,0000,0200,0200,0000, 1201592Srgrimes 0000,0200,0200,0000,0200,0000,0000,0200, 1211592Srgrimes 0000,0200,0200,0000,0200,0000,0000,0200, 1221592Srgrimes 0200,0000,0000,0200,0000,0200,0200,0000, 1231592Srgrimes 0000,0200,0200,0000,0200,0000,0000,0200, 1241592Srgrimes 0200,0000,0000,0200,0000,0200,0200,0000, 1251592Srgrimes 0200,0000,0000,0200,0000,0200,0200,0000, 1261592Srgrimes 0000,0200,0200,0000,0200,0000,0000,0201 1271592Srgrimes}; 1281592Srgrimes 12915645Sjoerg#define ERASE tmode.c_cc[VERASE] 13015645Sjoerg#define KILL tmode.c_cc[VKILL] 13115645Sjoerg#define EOT tmode.c_cc[VEOF] 1321592Srgrimes 13340083Sjkh#define puts Gputs 13440083Sjkh 13515645Sjoergstatic void dingdong __P((int)); 13615645Sjoergstatic int getname __P((void)); 13715645Sjoergstatic void interrupt __P((int)); 13815645Sjoergstatic void oflush __P((void)); 13915645Sjoergstatic void prompt __P((void)); 14015645Sjoergstatic void putchr __P((int)); 14115645Sjoergstatic void putf __P((const char *)); 14215645Sjoergstatic void putpad __P((const char *)); 14315645Sjoergstatic void puts __P((const char *)); 14415645Sjoergstatic void timeoverrun __P((int)); 14522208Sdavidnstatic char *getline __P((int)); 14622208Sdavidnstatic void setttymode __P((const char *, int)); 14722208Sdavidnstatic void setdefttymode __P((const char *)); 14822208Sdavidnstatic int opentty __P((const char *, int)); 14915645Sjoerg 15015645Sjoergint main __P((int, char **)); 15115645Sjoerg 15222208Sdavidnjmp_buf timeout; 15322208Sdavidn 1541592Srgrimesstatic void 15515645Sjoergdingdong(signo) 15615645Sjoerg int signo; 1571592Srgrimes{ 1581592Srgrimes alarm(0); 1591592Srgrimes longjmp(timeout, 1); 1601592Srgrimes} 1611592Srgrimes 1621592Srgrimesjmp_buf intrupt; 1631592Srgrimes 1641592Srgrimesstatic void 16515645Sjoerginterrupt(signo) 16615645Sjoerg int signo; 1671592Srgrimes{ 1681592Srgrimes longjmp(intrupt, 1); 1691592Srgrimes} 1701592Srgrimes 17115645Sjoerg/* 17215645Sjoerg * Action to take when getty is running too long. 17315645Sjoerg */ 17415645Sjoergstatic void 17515645Sjoergtimeoverrun(signo) 17615645Sjoerg int signo; 17715645Sjoerg{ 17815645Sjoerg 17931331Scharnier syslog(LOG_ERR, "getty exiting due to excessive running time"); 18015645Sjoerg exit(1); 18115645Sjoerg} 18215645Sjoerg 18315645Sjoergint 1841592Srgrimesmain(argc, argv) 1851592Srgrimes int argc; 1862286Sjkh char **argv; 1871592Srgrimes{ 1882286Sjkh extern char **environ; 18915645Sjoerg const char *tname; 19022491Sdavidn int first_sleep = 1, first_time = 1; 19115645Sjoerg struct rlimit limit; 19219697Spst int rval; 1931592Srgrimes 1941592Srgrimes signal(SIGINT, SIG_IGN); 1952391Sache signal(SIGQUIT, SIG_IGN); 1962286Sjkh 19715645Sjoerg openlog("getty", LOG_ODELAY|LOG_CONS|LOG_PID, LOG_AUTH); 19845422Sbrian gethostname(hostname, sizeof(hostname) - 1); 19945422Sbrian hostname[sizeof(hostname) - 1] = '\0'; 2001592Srgrimes if (hostname[0] == '\0') 2011592Srgrimes strcpy(hostname, "Amnesiac"); 20215645Sjoerg 2031592Srgrimes /* 20415645Sjoerg * Limit running time to deal with broken or dead lines. 20515645Sjoerg */ 20615645Sjoerg (void)signal(SIGXCPU, timeoverrun); 20715645Sjoerg limit.rlim_max = RLIM_INFINITY; 20815645Sjoerg limit.rlim_cur = GETTY_TIMEOUT; 20915645Sjoerg (void)setrlimit(RLIMIT_CPU, &limit); 21015645Sjoerg 21122208Sdavidn gettable("default", defent); 21222208Sdavidn gendefaults(); 21322208Sdavidn tname = "default"; 21422208Sdavidn if (argc > 1) 21522208Sdavidn tname = argv[1]; 21622208Sdavidn 21715645Sjoerg /* 2181592Srgrimes * The following is a work around for vhangup interactions 2191592Srgrimes * which cause great problems getting window systems started. 2201592Srgrimes * If the tty line is "-", we do the old style getty presuming 2218870Srgrimes * that the file descriptors are already set up for us. 2221592Srgrimes * J. Gettys - MIT Project Athena. 2231592Srgrimes */ 2241592Srgrimes if (argc <= 2 || strcmp(argv[2], "-") == 0) 22522208Sdavidn strcpy(ttyn, ttyname(STDIN_FILENO)); 2261592Srgrimes else { 2271592Srgrimes strcpy(ttyn, dev); 2281592Srgrimes strncat(ttyn, argv[2], sizeof(ttyn)-sizeof(dev)); 2291592Srgrimes if (strcmp(argv[0], "+") != 0) { 2301592Srgrimes chown(ttyn, 0, 0); 2311592Srgrimes chmod(ttyn, 0600); 2321592Srgrimes revoke(ttyn); 23322208Sdavidn 23422208Sdavidn gettable(tname, tabent); 23522208Sdavidn 23622208Sdavidn /* Init modem sequence has been specified 23722208Sdavidn */ 23822208Sdavidn if (IC) { 23922208Sdavidn if (!opentty(ttyn, O_RDWR|O_NONBLOCK)) 24022208Sdavidn exit(1); 24122208Sdavidn setdefttymode(tname); 24222208Sdavidn if (getty_chat(IC, CT, DC) > 0) { 24322208Sdavidn syslog(LOG_ERR, "modem init problem on %s", ttyn); 24422491Sdavidn (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode); 24522208Sdavidn exit(1); 2461592Srgrimes } 2471592Srgrimes } 24822208Sdavidn 24922208Sdavidn if (AC) { 25022208Sdavidn int i, rfds; 25122208Sdavidn struct timeval timeout; 25222208Sdavidn 25322208Sdavidn if (!opentty(ttyn, O_RDWR|O_NONBLOCK)) 25422208Sdavidn exit(1); 25522208Sdavidn setdefttymode(tname); 25622208Sdavidn rfds = 1 << 0; /* FD_SET */ 25722208Sdavidn timeout.tv_sec = RT; 25822208Sdavidn timeout.tv_usec = 0; 25922208Sdavidn i = select(32, (fd_set*)&rfds, (fd_set*)NULL, 26022208Sdavidn (fd_set*)NULL, RT ? &timeout : NULL); 26122208Sdavidn if (i < 0) { 26222208Sdavidn syslog(LOG_ERR, "select %s: %m", ttyn); 26322208Sdavidn } else if (i == 0) { 26422208Sdavidn syslog(LOG_NOTICE, "recycle tty %s", ttyn); 26522491Sdavidn (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode); 26622208Sdavidn exit(0); /* recycle for init */ 26722208Sdavidn } 26822208Sdavidn i = getty_chat(AC, CT, DC); 26922208Sdavidn if (i > 0) { 27022208Sdavidn syslog(LOG_ERR, "modem answer problem on %s", ttyn); 27122491Sdavidn (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode); 27222208Sdavidn exit(1); 27322208Sdavidn } 27464076Snsayer } else { /* maybe blocking open */ 27564076Snsayer if (!opentty(ttyn, O_RDWR | (NC ? O_NONBLOCK : 0 ))) 27622208Sdavidn exit(1); 27722208Sdavidn } 2781592Srgrimes } 2791592Srgrimes } 2801592Srgrimes 28115645Sjoerg /* Start with default tty settings */ 28222208Sdavidn if (tcgetattr(STDIN_FILENO, &tmode) < 0) { 28322208Sdavidn syslog(LOG_ERR, "tcgetattr %s: %m", ttyn); 28415645Sjoerg exit(1); 28515645Sjoerg } 28615645Sjoerg /* 28715645Sjoerg * Don't rely on the driver too much, and initialize crucial 28815645Sjoerg * things according to <sys/ttydefaults.h>. Avoid clobbering 28915645Sjoerg * the c_cc[] settings however, the console drivers might wish 29015645Sjoerg * to leave their idea of the preferred VERASE key value 29115645Sjoerg * there. 29215645Sjoerg */ 29315645Sjoerg tmode.c_iflag = TTYDEF_IFLAG; 29415645Sjoerg tmode.c_oflag = TTYDEF_OFLAG; 29515645Sjoerg tmode.c_lflag = TTYDEF_LFLAG; 29615645Sjoerg tmode.c_cflag = TTYDEF_CFLAG; 29764076Snsayer tmode.c_cflag |= (NC ? CLOCAL : 0); 29815645Sjoerg omode = tmode; 29915645Sjoerg 3001592Srgrimes for (;;) { 3011592Srgrimes 30222491Sdavidn /* 30322491Sdavidn * if a delay was specified then sleep for that 30422491Sdavidn * number of seconds before writing the initial prompt 30522491Sdavidn */ 30622491Sdavidn if (first_sleep && DE) { 30722491Sdavidn sleep(DE); 30822491Sdavidn /* remove any noise */ 30922491Sdavidn (void)tcflush(STDIN_FILENO, TCIOFLUSH); 31022491Sdavidn } 31122491Sdavidn first_sleep = 0; 31222491Sdavidn 31322208Sdavidn setttymode(tname, 0); 3141592Srgrimes if (AB) { 3151592Srgrimes tname = autobaud(); 3161592Srgrimes continue; 3171592Srgrimes } 3181592Srgrimes if (PS) { 3191592Srgrimes tname = portselector(); 3201592Srgrimes continue; 3211592Srgrimes } 3221592Srgrimes if (CL && *CL) 3231592Srgrimes putpad(CL); 3241592Srgrimes edithost(HE); 32521120Smsmith 32622208Sdavidn /* if this is the first time through this, and an 32722208Sdavidn issue file has been given, then send it */ 32822208Sdavidn if (first_time && IF) { 32922208Sdavidn int fd; 33022208Sdavidn 33122208Sdavidn if ((fd = open(IF, O_RDONLY)) != -1) { 33222208Sdavidn char * cp; 33322208Sdavidn 33422208Sdavidn while ((cp = getline(fd)) != NULL) { 33522208Sdavidn putf(cp); 33622208Sdavidn } 33722208Sdavidn close(fd); 33822208Sdavidn } 33922208Sdavidn } 34022491Sdavidn first_time = 0; 34122208Sdavidn 3421592Srgrimes if (IM && *IM) 3431592Srgrimes putf(IM); 3441592Srgrimes if (setjmp(timeout)) { 34515659Sache cfsetispeed(&tmode, B0); 34615659Sache cfsetospeed(&tmode, B0); 34722208Sdavidn (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode); 3481592Srgrimes exit(1); 3491592Srgrimes } 3501592Srgrimes if (TO) { 3511592Srgrimes signal(SIGALRM, dingdong); 3521592Srgrimes alarm(TO); 3531592Srgrimes } 35445291Speter if (AL) { 35545291Speter const char *p = AL; 35645291Speter char *q = name; 35745291Speter int n = sizeof name; 35845291Speter 35945291Speter while (*p && q < &name[sizeof name - 1]) { 36045291Speter if (isupper(*p)) 36145291Speter upper = 1; 36245291Speter else if (islower(*p)) 36345291Speter lower = 1; 36445291Speter else if (isdigit(*p)) 36545291Speter digit++; 36645291Speter *q++ = *p++; 36745291Speter } 36845291Speter } else 36945291Speter rval = getname(); 37045291Speter if (rval == 2) { 37126415Sdavidn oflush(); 37226415Sdavidn alarm(0); 37344615Sbrian limit.rlim_max = RLIM_INFINITY; 37444615Sbrian limit.rlim_cur = RLIM_INFINITY; 37544615Sbrian (void)setrlimit(RLIMIT_CPU, &limit); 37619697Spst execle(PP, "ppplogin", ttyn, (char *) 0, env); 37719697Spst syslog(LOG_ERR, "%s: %m", PP); 37819697Spst exit(1); 37945291Speter } else if (rval || AL) { 3801592Srgrimes register int i; 3811592Srgrimes 38215645Sjoerg oflush(); 3831592Srgrimes alarm(0); 3841592Srgrimes signal(SIGALRM, SIG_DFL); 3851592Srgrimes if (name[0] == '-') { 3861592Srgrimes puts("user names may not start with '-'."); 3871592Srgrimes continue; 3881592Srgrimes } 3891592Srgrimes if (!(upper || lower || digit)) 3901592Srgrimes continue; 39156725Sbde set_flags(2); 39215645Sjoerg if (crmod) { 39315645Sjoerg tmode.c_iflag |= ICRNL; 39415645Sjoerg tmode.c_oflag |= ONLCR; 39515645Sjoerg } 39615645Sjoerg#if REALLY_OLD_TTYS 39715645Sjoerg if (upper || UC) 39815645Sjoerg tmode.sg_flags |= LCASE; 39915645Sjoerg if (lower || LC) 40015645Sjoerg tmode.sg_flags &= ~LCASE; 40115645Sjoerg#endif 40222208Sdavidn if (tcsetattr(STDIN_FILENO, TCSANOW, &tmode) < 0) { 40322208Sdavidn syslog(LOG_ERR, "tcsetattr %s: %m", ttyn); 40415645Sjoerg exit(1); 40515645Sjoerg } 40615645Sjoerg signal(SIGINT, SIG_DFL); 4071592Srgrimes for (i = 0; environ[i] != (char *)0; i++) 4081592Srgrimes env[i] = environ[i]; 4091592Srgrimes makeenv(&env[i]); 4101592Srgrimes 41115645Sjoerg limit.rlim_max = RLIM_INFINITY; 41215645Sjoerg limit.rlim_cur = RLIM_INFINITY; 41315645Sjoerg (void)setrlimit(RLIMIT_CPU, &limit); 41445291Speter execle(LO, "login", AL ? "-fp" : "-p", name, 41545291Speter (char *) 0, env); 4161592Srgrimes syslog(LOG_ERR, "%s: %m", LO); 4171592Srgrimes exit(1); 4181592Srgrimes } 4191592Srgrimes alarm(0); 4201592Srgrimes signal(SIGALRM, SIG_DFL); 42115645Sjoerg signal(SIGINT, SIG_IGN); 4221592Srgrimes if (NX && *NX) 4231592Srgrimes tname = NX; 4241592Srgrimes } 4251592Srgrimes} 4261592Srgrimes 42715645Sjoergstatic int 42822208Sdavidnopentty(const char *ttyn, int flags) 42922208Sdavidn{ 43022208Sdavidn int i, j = 0; 43122208Sdavidn int failopenlogged = 0; 43222208Sdavidn 43322208Sdavidn while (j < 10 && (i = open(ttyn, flags)) == -1) 43422208Sdavidn { 43522208Sdavidn if (((j % 10) == 0) && (errno != ENXIO || !failopenlogged)) { 43622208Sdavidn syslog(LOG_ERR, "open %s: %m", ttyn); 43722208Sdavidn failopenlogged = 1; 43822208Sdavidn } 43922208Sdavidn j++; 44022208Sdavidn sleep(60); 44122208Sdavidn } 44222208Sdavidn if (i == -1) { 44322208Sdavidn syslog(LOG_ERR, "open %s: %m", ttyn); 44422208Sdavidn return 0; 44522208Sdavidn } 44622208Sdavidn else { 44768888Sjwd if (login_tty(i) < 0) { 44868888Sjwd if (daemon(0,0) < 0) { 44968888Sjwd syslog(LOG_ERR,"daemon: %m"); 45068888Sjwd close(i); 45168888Sjwd return 0; 45268888Sjwd } 45368888Sjwd if (login_tty(i) < 0) { 45468888Sjwd syslog(LOG_ERR, "login_tty %s: %m", ttyn); 45568888Sjwd close(i); 45668888Sjwd return 0; 45768888Sjwd } 45868888Sjwd } 45922208Sdavidn return 1; 46022208Sdavidn } 46122208Sdavidn} 46222208Sdavidn 46322208Sdavidnstatic void 46422208Sdavidnsetdefttymode(tname) 46522208Sdavidn const char * tname; 46622208Sdavidn{ 46722208Sdavidn if (tcgetattr(STDIN_FILENO, &tmode) < 0) { 46822208Sdavidn syslog(LOG_ERR, "tcgetattr %s: %m", ttyn); 46922208Sdavidn exit(1); 47022208Sdavidn } 47122208Sdavidn tmode.c_iflag = TTYDEF_IFLAG; 47222208Sdavidn tmode.c_oflag = TTYDEF_OFLAG; 47322208Sdavidn tmode.c_lflag = TTYDEF_LFLAG; 47422208Sdavidn tmode.c_cflag = TTYDEF_CFLAG; 47522208Sdavidn omode = tmode; 47622208Sdavidn setttymode(tname, 1); 47722208Sdavidn} 47822208Sdavidn 47922208Sdavidnstatic void 48022208Sdavidnsetttymode(tname, raw) 48122208Sdavidn const char * tname; 48222208Sdavidn int raw; 48322208Sdavidn{ 48422208Sdavidn int off = 0; 48522208Sdavidn 48622208Sdavidn gettable(tname, tabent); 48722208Sdavidn if (OPset || EPset || APset) 48822208Sdavidn APset++, OPset++, EPset++; 48922208Sdavidn setdefaults(); 49022208Sdavidn (void)tcflush(STDIN_FILENO, TCIOFLUSH); /* clear out the crap */ 49122208Sdavidn ioctl(STDIN_FILENO, FIONBIO, &off); /* turn off non-blocking mode */ 49222208Sdavidn ioctl(STDIN_FILENO, FIOASYNC, &off); /* ditto for async mode */ 49322208Sdavidn 49422208Sdavidn if (IS) 49522208Sdavidn cfsetispeed(&tmode, speed(IS)); 49622208Sdavidn else if (SP) 49722208Sdavidn cfsetispeed(&tmode, speed(SP)); 49822208Sdavidn if (OS) 49922208Sdavidn cfsetospeed(&tmode, speed(OS)); 50022208Sdavidn else if (SP) 50122208Sdavidn cfsetospeed(&tmode, speed(SP)); 50256725Sbde set_flags(0); 50322208Sdavidn setchars(); 50422208Sdavidn if (raw) 50522208Sdavidn cfmakeraw(&tmode); 50622208Sdavidn if (tcsetattr(STDIN_FILENO, TCSANOW, &tmode) < 0) { 50722208Sdavidn syslog(LOG_ERR, "tcsetattr %s: %m", ttyn); 50822208Sdavidn exit(1); 50922208Sdavidn } 51022208Sdavidn} 51122208Sdavidn 51222208Sdavidn 51322208Sdavidnstatic int 5141592Srgrimesgetname() 5151592Srgrimes{ 5161592Srgrimes register int c; 5171592Srgrimes register char *np; 51819697Spst unsigned char cs; 51922208Sdavidn int ppp_state = 0; 52019697Spst int ppp_connection = 0; 5211592Srgrimes 5221592Srgrimes /* 5231592Srgrimes * Interrupt may happen if we use CBREAK mode 5241592Srgrimes */ 5251592Srgrimes if (setjmp(intrupt)) { 5261592Srgrimes signal(SIGINT, SIG_IGN); 5271592Srgrimes return (0); 5281592Srgrimes } 5291592Srgrimes signal(SIGINT, interrupt); 53056725Sbde set_flags(1); 5311592Srgrimes prompt(); 5322286Sjkh oflush(); 5331592Srgrimes if (PF > 0) { 5341592Srgrimes sleep(PF); 5351592Srgrimes PF = 0; 5361592Srgrimes } 53722208Sdavidn if (tcsetattr(STDIN_FILENO, TCSANOW, &tmode) < 0) { 53815645Sjoerg syslog(LOG_ERR, "%s: %m", ttyn); 53915645Sjoerg exit(1); 54015645Sjoerg } 5411592Srgrimes crmod = digit = lower = upper = 0; 5421592Srgrimes np = name; 5431592Srgrimes for (;;) { 5441592Srgrimes oflush(); 5451592Srgrimes if (read(STDIN_FILENO, &cs, 1) <= 0) 5461592Srgrimes exit(0); 5471592Srgrimes if ((c = cs&0177) == 0) 5481592Srgrimes return (0); 54919697Spst 55019697Spst /* PPP detection state machine.. 55119697Spst Look for sequences: 55219697Spst PPP_FRAME, PPP_STATION, PPP_ESCAPE, PPP_CONTROL_ESCAPED or 55319697Spst PPP_FRAME, PPP_STATION, PPP_CONTROL (deviant from RFC) 55419697Spst See RFC1662. 55519697Spst Derived from code from Michael Hancock, <michaelh@cet.co.jp> 55619697Spst and Erik 'PPP' Olson, <eriko@wrq.com> 55719697Spst */ 55819697Spst 55919697Spst if (PP && (cs == PPP_FRAME)) { 56019697Spst ppp_state = 1; 56119697Spst } else if (ppp_state == 1 && cs == PPP_STATION) { 56219697Spst ppp_state = 2; 56319697Spst } else if (ppp_state == 2 && cs == PPP_ESCAPE) { 56419697Spst ppp_state = 3; 56519697Spst } else if ((ppp_state == 2 && cs == PPP_CONTROL) 56619697Spst || (ppp_state == 3 && cs == PPP_CONTROL_ESCAPED)) { 56719697Spst ppp_state = 4; 56819697Spst } else if (ppp_state == 4 && cs == PPP_LCP_HI) { 56919697Spst ppp_state = 5; 57019697Spst } else if (ppp_state == 5 && cs == PPP_LCP_LOW) { 57119697Spst ppp_connection = 1; 57219697Spst break; 57319697Spst } else { 57419697Spst ppp_state = 0; 57519697Spst } 57619697Spst 57715645Sjoerg if (c == EOT || c == CTRL('d')) 5781592Srgrimes exit(1); 57922211Sdavidn if (c == '\r' || c == '\n' || np >= &name[sizeof name-1]) { 5801592Srgrimes putf("\r\n"); 5811592Srgrimes break; 5821592Srgrimes } 5831592Srgrimes if (islower(c)) 5841592Srgrimes lower = 1; 5851592Srgrimes else if (isupper(c)) 5861592Srgrimes upper = 1; 5872286Sjkh else if (c == ERASE || c == '\b' || c == 0177) { 5881592Srgrimes if (np > name) { 5891592Srgrimes np--; 59015645Sjoerg if (cfgetospeed(&tmode) >= 1200) 5911592Srgrimes puts("\b \b"); 5921592Srgrimes else 5931592Srgrimes putchr(cs); 5941592Srgrimes } 5951592Srgrimes continue; 59615645Sjoerg } else if (c == KILL || c == CTRL('u')) { 5971592Srgrimes putchr('\r'); 59815645Sjoerg if (cfgetospeed(&tmode) < 1200) 5991592Srgrimes putchr('\n'); 6001592Srgrimes /* this is the way they do it down under ... */ 6011592Srgrimes else if (np > name) 6021592Srgrimes puts(" \r"); 6031592Srgrimes prompt(); 6041592Srgrimes np = name; 6051592Srgrimes continue; 6061592Srgrimes } else if (isdigit(c)) 6071592Srgrimes digit++; 6081592Srgrimes if (IG && (c <= ' ' || c > 0176)) 6091592Srgrimes continue; 6101592Srgrimes *np++ = c; 6111592Srgrimes putchr(cs); 6121592Srgrimes } 6131592Srgrimes signal(SIGINT, SIG_IGN); 6141592Srgrimes *np = 0; 6151592Srgrimes if (c == '\r') 6161592Srgrimes crmod = 1; 61715645Sjoerg if ((upper && !lower && !LC) || UC) 6181592Srgrimes for (np = name; *np; np++) 6191592Srgrimes if (isupper(*np)) 6201592Srgrimes *np = tolower(*np); 62119697Spst return (1 + ppp_connection); 6221592Srgrimes} 6231592Srgrimes 62415645Sjoergstatic void 6251592Srgrimesputpad(s) 62615645Sjoerg register const char *s; 6271592Srgrimes{ 6281592Srgrimes register pad = 0; 62915645Sjoerg speed_t ospeed = cfgetospeed(&tmode); 6301592Srgrimes 6311592Srgrimes if (isdigit(*s)) { 6321592Srgrimes while (isdigit(*s)) { 6331592Srgrimes pad *= 10; 6341592Srgrimes pad += *s++ - '0'; 6351592Srgrimes } 6361592Srgrimes pad *= 10; 6371592Srgrimes if (*s == '.' && isdigit(s[1])) { 6381592Srgrimes pad += s[1] - '0'; 6391592Srgrimes s += 2; 6401592Srgrimes } 6411592Srgrimes } 6421592Srgrimes 6431592Srgrimes puts(s); 6441592Srgrimes /* 6451592Srgrimes * If no delay needed, or output speed is 6461592Srgrimes * not comprehensible, then don't try to delay. 6471592Srgrimes */ 64815645Sjoerg if (pad == 0 || ospeed <= 0) 6491592Srgrimes return; 6501592Srgrimes 6511592Srgrimes /* 6521592Srgrimes * Round up by a half a character frame, and then do the delay. 6531592Srgrimes * Too bad there are no user program accessible programmed delays. 6541592Srgrimes * Transmitting pad characters slows many terminals down and also 6551592Srgrimes * loads the system. 6561592Srgrimes */ 65715645Sjoerg pad = (pad * ospeed + 50000) / 100000; 65815645Sjoerg while (pad--) 6591592Srgrimes putchr(*PC); 6601592Srgrimes} 6611592Srgrimes 66215645Sjoergstatic void 6631592Srgrimesputs(s) 66415645Sjoerg register const char *s; 6651592Srgrimes{ 6661592Srgrimes while (*s) 6671592Srgrimes putchr(*s++); 6681592Srgrimes} 6691592Srgrimes 6701592Srgrimeschar outbuf[OBUFSIZ]; 6711592Srgrimesint obufcnt = 0; 6721592Srgrimes 67315645Sjoergstatic void 6741592Srgrimesputchr(cc) 67515645Sjoerg int cc; 6761592Srgrimes{ 6771592Srgrimes char c; 6781592Srgrimes 6791592Srgrimes c = cc; 6801592Srgrimes if (!NP) { 6811592Srgrimes c |= partab[c&0177] & 0200; 6821592Srgrimes if (OP) 6831592Srgrimes c ^= 0200; 6841592Srgrimes } 6851592Srgrimes if (!UB) { 6861592Srgrimes outbuf[obufcnt++] = c; 6871592Srgrimes if (obufcnt >= OBUFSIZ) 6881592Srgrimes oflush(); 6891592Srgrimes } else 6901592Srgrimes write(STDOUT_FILENO, &c, 1); 6911592Srgrimes} 6921592Srgrimes 69315645Sjoergstatic void 6941592Srgrimesoflush() 6951592Srgrimes{ 6961592Srgrimes if (obufcnt) 6971592Srgrimes write(STDOUT_FILENO, outbuf, obufcnt); 6981592Srgrimes obufcnt = 0; 6991592Srgrimes} 7001592Srgrimes 70115645Sjoergstatic void 7021592Srgrimesprompt() 7031592Srgrimes{ 7041592Srgrimes 7051592Srgrimes putf(LM); 7061592Srgrimes if (CO) 7071592Srgrimes putchr('\n'); 7081592Srgrimes} 7091592Srgrimes 71022208Sdavidn 71122208Sdavidnstatic char * 71222208Sdavidngetline(fd) 71322208Sdavidn int fd; 71422208Sdavidn{ 71522208Sdavidn int i = 0; 71622208Sdavidn static char linebuf[512]; 71722208Sdavidn 71822208Sdavidn /* 71922208Sdavidn * This is certainly slow, but it avoids having to include 72022208Sdavidn * stdio.h unnecessarily. Issue files should be small anyway. 72122208Sdavidn */ 72222208Sdavidn while (i < (sizeof linebuf - 3) && read(fd, linebuf+i, 1)==1) { 72322208Sdavidn if (linebuf[i] == '\n') { 72422208Sdavidn /* Don't rely on newline mode, assume raw */ 72522208Sdavidn linebuf[i++] = '\r'; 72622208Sdavidn linebuf[i++] = '\n'; 72722208Sdavidn linebuf[i] = '\0'; 72822208Sdavidn return linebuf; 72922208Sdavidn } 73022208Sdavidn ++i; 73122208Sdavidn } 73222208Sdavidn linebuf[i] = '\0'; 73322208Sdavidn return i ? linebuf : 0; 73422208Sdavidn} 73522208Sdavidn 73615645Sjoergstatic void 7371592Srgrimesputf(cp) 73815645Sjoerg register const char *cp; 7391592Srgrimes{ 7401592Srgrimes extern char editedhost[]; 7411592Srgrimes time_t t; 7421592Srgrimes char *slash, db[100]; 7431592Srgrimes 74422199Sdavidn static struct utsname kerninfo; 74522199Sdavidn 74622199Sdavidn if (!*kerninfo.sysname) 74722199Sdavidn uname(&kerninfo); 74822199Sdavidn 7491592Srgrimes while (*cp) { 7501592Srgrimes if (*cp != '%') { 7511592Srgrimes putchr(*cp++); 7521592Srgrimes continue; 7531592Srgrimes } 7541592Srgrimes switch (*++cp) { 7551592Srgrimes 7561592Srgrimes case 't': 75715645Sjoerg slash = strrchr(ttyn, '/'); 7581592Srgrimes if (slash == (char *) 0) 7591592Srgrimes puts(ttyn); 7601592Srgrimes else 7611592Srgrimes puts(&slash[1]); 7621592Srgrimes break; 7631592Srgrimes 7641592Srgrimes case 'h': 7651592Srgrimes puts(editedhost); 7661592Srgrimes break; 7671592Srgrimes 7681592Srgrimes case 'd': { 76915645Sjoerg t = (time_t)0; 7701592Srgrimes (void)time(&t); 77115645Sjoerg if (Lo) 77215645Sjoerg (void)setlocale(LC_TIME, Lo); 77377874Syar (void)strftime(db, sizeof(db), DF, localtime(&t)); 7741592Srgrimes puts(db); 7759875Sjkh break; 77615645Sjoerg 77715645Sjoerg case 's': 77815645Sjoerg puts(kerninfo.sysname); 77915645Sjoerg break; 78015645Sjoerg 78115645Sjoerg case 'm': 78215645Sjoerg puts(kerninfo.machine); 78315645Sjoerg break; 78415645Sjoerg 78515645Sjoerg case 'r': 78615645Sjoerg puts(kerninfo.release); 78715645Sjoerg break; 78815645Sjoerg 78915645Sjoerg case 'v': 79015645Sjoerg puts(kerninfo.version); 79115645Sjoerg break; 7921592Srgrimes } 7931592Srgrimes 7941592Srgrimes case '%': 7951592Srgrimes putchr('%'); 7961592Srgrimes break; 7971592Srgrimes } 7981592Srgrimes cp++; 7991592Srgrimes } 8001592Srgrimes} 801