main.c revision 117738
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 117738 2003-07-18 16:25:55Z yar $"; 461592Srgrimes#endif /* not lint */ 471592Srgrimes 481592Srgrimes#include <sys/param.h> 4915645Sjoerg#include <sys/ioctl.h> 5091216Sbde#include <sys/time.h> 5115645Sjoerg#include <sys/resource.h> 5291216Sbde#include <sys/stat.h> 5315645Sjoerg#include <sys/ttydefaults.h> 5415645Sjoerg#include <sys/utsname.h> 5566907Swollman 5631331Scharnier#include <ctype.h> 5715645Sjoerg#include <errno.h> 582286Sjkh#include <fcntl.h> 5931331Scharnier#include <locale.h> 6015645Sjoerg#include <libutil.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 7091216Sbde#include "extern.h" 711592Srgrimes#include "gettytab.h" 721592Srgrimes#include "pathnames.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 93116533Syar/* original mode; flags've been reset using values from <sys/ttydefaults.h> */ 94116533Syarstruct termios omode; 95116533Syar/* current mode */ 96116533Syarstruct termios tmode; 9715645Sjoerg 981592Srgrimesint crmod, digit, lower, upper; 991592Srgrimes 1001592Srgrimeschar hostname[MAXHOSTNAMELEN]; 10122400Sdavidnchar name[MAXLOGNAME*3]; 1021592Srgrimeschar dev[] = _PATH_DEV; 1031592Srgrimeschar ttyn[32]; 1041592Srgrimes 1051592Srgrimes#define OBUFSIZ 128 1061592Srgrimes#define TABBUFSIZ 512 1071592Srgrimes 1081592Srgrimeschar defent[TABBUFSIZ]; 1091592Srgrimeschar tabent[TABBUFSIZ]; 110116533Syarconst char *tname; 1111592Srgrimes 1121592Srgrimeschar *env[128]; 1131592Srgrimes 1141592Srgrimeschar partab[] = { 1151592Srgrimes 0001,0201,0201,0001,0201,0001,0001,0201, 1161592Srgrimes 0202,0004,0003,0205,0005,0206,0201,0001, 1171592Srgrimes 0201,0001,0001,0201,0001,0201,0201,0001, 1181592Srgrimes 0001,0201,0201,0001,0201,0001,0001,0201, 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 0200,0000,0000,0200,0000,0200,0200,0000, 1241592Srgrimes 0000,0200,0200,0000,0200,0000,0000,0200, 1251592Srgrimes 0000,0200,0200,0000,0200,0000,0000,0200, 1261592Srgrimes 0200,0000,0000,0200,0000,0200,0200,0000, 1271592Srgrimes 0000,0200,0200,0000,0200,0000,0000,0200, 1281592Srgrimes 0200,0000,0000,0200,0000,0200,0200,0000, 1291592Srgrimes 0200,0000,0000,0200,0000,0200,0200,0000, 1301592Srgrimes 0000,0200,0200,0000,0200,0000,0000,0201 1311592Srgrimes}; 1321592Srgrimes 13315645Sjoerg#define ERASE tmode.c_cc[VERASE] 13415645Sjoerg#define KILL tmode.c_cc[VKILL] 13515645Sjoerg#define EOT tmode.c_cc[VEOF] 1361592Srgrimes 13740083Sjkh#define puts Gputs 13840083Sjkh 139117738Syarstatic void defttymode(void); 14090301Simpstatic void dingdong(int); 141116533Syarstatic void dogettytab(void); 14290301Simpstatic int getname(void); 14390301Simpstatic void interrupt(int); 14490301Simpstatic void oflush(void); 14590301Simpstatic void prompt(void); 14690301Simpstatic void putchr(int); 14790301Simpstatic void putf(const char *); 14890301Simpstatic void putpad(const char *); 14990301Simpstatic void puts(const char *); 15090301Simpstatic void timeoverrun(int); 15190301Simpstatic char *getline(int); 152116164Syarstatic void setttymode(int); 15390301Simpstatic int opentty(const char *, int); 15415645Sjoerg 15522208Sdavidnjmp_buf timeout; 15622208Sdavidn 1571592Srgrimesstatic void 15890302Simpdingdong(int signo __unused) 1591592Srgrimes{ 1601592Srgrimes alarm(0); 1611592Srgrimes longjmp(timeout, 1); 1621592Srgrimes} 1631592Srgrimes 1641592Srgrimesjmp_buf intrupt; 1651592Srgrimes 1661592Srgrimesstatic void 16790302Simpinterrupt(int signo __unused) 1681592Srgrimes{ 1691592Srgrimes longjmp(intrupt, 1); 1701592Srgrimes} 1711592Srgrimes 17215645Sjoerg/* 17315645Sjoerg * Action to take when getty is running too long. 17415645Sjoerg */ 17515645Sjoergstatic void 17690302Simptimeoverrun(int signo __unused) 17715645Sjoerg{ 17815645Sjoerg 17931331Scharnier syslog(LOG_ERR, "getty exiting due to excessive running time"); 18015645Sjoerg exit(1); 18115645Sjoerg} 18215645Sjoerg 18315645Sjoergint 18490301Simpmain(int argc, char *argv[]) 1851592Srgrimes{ 1862286Sjkh extern char **environ; 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); 19545422Sbrian gethostname(hostname, sizeof(hostname) - 1); 19645422Sbrian hostname[sizeof(hostname) - 1] = '\0'; 1971592Srgrimes if (hostname[0] == '\0') 1981592Srgrimes strcpy(hostname, "Amnesiac"); 19915645Sjoerg 2001592Srgrimes /* 20115645Sjoerg * Limit running time to deal with broken or dead lines. 20215645Sjoerg */ 20315645Sjoerg (void)signal(SIGXCPU, timeoverrun); 20415645Sjoerg limit.rlim_max = RLIM_INFINITY; 20515645Sjoerg limit.rlim_cur = GETTY_TIMEOUT; 20615645Sjoerg (void)setrlimit(RLIMIT_CPU, &limit); 20715645Sjoerg 20822208Sdavidn gettable("default", defent); 20922208Sdavidn gendefaults(); 21022208Sdavidn tname = "default"; 211116329Sgreen if (argc > 1) 21222208Sdavidn tname = argv[1]; 21322208Sdavidn 21415645Sjoerg /* 2151592Srgrimes * The following is a work around for vhangup interactions 2161592Srgrimes * which cause great problems getting window systems started. 2171592Srgrimes * If the tty line is "-", we do the old style getty presuming 2188870Srgrimes * that the file descriptors are already set up for us. 2191592Srgrimes * J. Gettys - MIT Project Athena. 2201592Srgrimes */ 221116533Syar if (argc <= 2 || strcmp(argv[2], "-") == 0) 22222208Sdavidn strcpy(ttyn, ttyname(STDIN_FILENO)); 223116533Syar else { 2241592Srgrimes strcpy(ttyn, dev); 2251592Srgrimes strncat(ttyn, argv[2], sizeof(ttyn)-sizeof(dev)); 2261592Srgrimes if (strcmp(argv[0], "+") != 0) { 2271592Srgrimes chown(ttyn, 0, 0); 2281592Srgrimes chmod(ttyn, 0600); 2291592Srgrimes revoke(ttyn); 23022208Sdavidn 231116533Syar /* 232116533Syar * Do the first scan through gettytab. 233116533Syar * Terminal mode parameters will be wrong until 234116533Syar * defttymode() called, but they're irrelevant for 235116533Syar * the initial setup of the terminal device. 23622208Sdavidn */ 237116533Syar dogettytab(); 238116533Syar 239116533Syar /* 240116533Syar * Init or answer modem sequence has been specified. 241116533Syar */ 242116533Syar if (IC || AC) { 24322208Sdavidn if (!opentty(ttyn, O_RDWR|O_NONBLOCK)) 24422208Sdavidn exit(1); 245116533Syar defttymode(); 246116533Syar setttymode(1); 247116533Syar } 248116533Syar 249116533Syar if (IC) { 25022208Sdavidn if (getty_chat(IC, CT, DC) > 0) { 25122208Sdavidn syslog(LOG_ERR, "modem init problem on %s", ttyn); 25222491Sdavidn (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode); 25322208Sdavidn exit(1); 2541592Srgrimes } 2551592Srgrimes } 25622208Sdavidn 25722208Sdavidn if (AC) { 25822208Sdavidn int i, rfds; 25990302Simp struct timeval to; 26022208Sdavidn 26122208Sdavidn rfds = 1 << 0; /* FD_SET */ 26290302Simp to.tv_sec = RT; 26390302Simp to.tv_usec = 0; 26422208Sdavidn i = select(32, (fd_set*)&rfds, (fd_set*)NULL, 26590302Simp (fd_set*)NULL, RT ? &to : NULL); 26622208Sdavidn if (i < 0) { 26722208Sdavidn syslog(LOG_ERR, "select %s: %m", ttyn); 26822208Sdavidn } else if (i == 0) { 26922208Sdavidn syslog(LOG_NOTICE, "recycle tty %s", ttyn); 27022491Sdavidn (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode); 27122208Sdavidn exit(0); /* recycle for init */ 27222208Sdavidn } 27322208Sdavidn i = getty_chat(AC, CT, DC); 27422208Sdavidn if (i > 0) { 27522208Sdavidn syslog(LOG_ERR, "modem answer problem on %s", ttyn); 27622491Sdavidn (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode); 27722208Sdavidn exit(1); 27822208Sdavidn } 27964076Snsayer } else { /* maybe blocking open */ 28064076Snsayer if (!opentty(ttyn, O_RDWR | (NC ? O_NONBLOCK : 0 ))) 28122208Sdavidn exit(1); 28222208Sdavidn } 2831592Srgrimes } 2841592Srgrimes } 2851592Srgrimes 286116533Syar defttymode(); 2871592Srgrimes for (;;) { 2881592Srgrimes 28922491Sdavidn /* 29022491Sdavidn * if a delay was specified then sleep for that 29122491Sdavidn * number of seconds before writing the initial prompt 29222491Sdavidn */ 29322491Sdavidn if (first_sleep && DE) { 29422491Sdavidn sleep(DE); 29522491Sdavidn /* remove any noise */ 29622491Sdavidn (void)tcflush(STDIN_FILENO, TCIOFLUSH); 29722491Sdavidn } 29822491Sdavidn first_sleep = 0; 29922491Sdavidn 300116164Syar setttymode(0); 3011592Srgrimes if (AB) { 3021592Srgrimes tname = autobaud(); 303116533Syar dogettytab(); 3041592Srgrimes continue; 3051592Srgrimes } 3061592Srgrimes if (PS) { 3071592Srgrimes tname = portselector(); 308116533Syar dogettytab(); 3091592Srgrimes continue; 3101592Srgrimes } 3111592Srgrimes if (CL && *CL) 3121592Srgrimes putpad(CL); 3131592Srgrimes edithost(HE); 31421120Smsmith 31522208Sdavidn /* if this is the first time through this, and an 31622208Sdavidn issue file has been given, then send it */ 31722208Sdavidn if (first_time && IF) { 31822208Sdavidn int fd; 31922208Sdavidn 32022208Sdavidn if ((fd = open(IF, O_RDONLY)) != -1) { 32122208Sdavidn char * cp; 32222208Sdavidn 32322208Sdavidn while ((cp = getline(fd)) != NULL) { 32422208Sdavidn putf(cp); 32522208Sdavidn } 32622208Sdavidn close(fd); 32722208Sdavidn } 32822208Sdavidn } 32922491Sdavidn first_time = 0; 33022208Sdavidn 331109555Ssobomax if (IM && *IM && !(PL && PP)) 3321592Srgrimes putf(IM); 3331592Srgrimes if (setjmp(timeout)) { 33415659Sache cfsetispeed(&tmode, B0); 33515659Sache cfsetospeed(&tmode, B0); 33622208Sdavidn (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode); 3371592Srgrimes exit(1); 3381592Srgrimes } 3391592Srgrimes if (TO) { 3401592Srgrimes signal(SIGALRM, dingdong); 3411592Srgrimes alarm(TO); 3421592Srgrimes } 343115900Syar 344115900Syar rval = 0; 34545291Speter if (AL) { 34645291Speter const char *p = AL; 34745291Speter char *q = name; 34845291Speter 34945291Speter while (*p && q < &name[sizeof name - 1]) { 35045291Speter if (isupper(*p)) 35145291Speter upper = 1; 35245291Speter else if (islower(*p)) 35345291Speter lower = 1; 35445291Speter else if (isdigit(*p)) 355116154Syar digit = 1; 35645291Speter *q++ = *p++; 35745291Speter } 358109540Ssobomax } else if (!(PL && PP)) 35945291Speter rval = getname(); 360109540Ssobomax if (rval == 2 || (PL && PP)) { 36126415Sdavidn oflush(); 36226415Sdavidn alarm(0); 36344615Sbrian limit.rlim_max = RLIM_INFINITY; 36444615Sbrian limit.rlim_cur = RLIM_INFINITY; 36544615Sbrian (void)setrlimit(RLIMIT_CPU, &limit); 36619697Spst execle(PP, "ppplogin", ttyn, (char *) 0, env); 36719697Spst syslog(LOG_ERR, "%s: %m", PP); 36819697Spst exit(1); 36945291Speter } else if (rval || AL) { 37090301Simp int i; 3711592Srgrimes 37215645Sjoerg oflush(); 3731592Srgrimes alarm(0); 3741592Srgrimes signal(SIGALRM, SIG_DFL); 375115900Syar if (name[0] == '\0') 376115900Syar continue; 3771592Srgrimes if (name[0] == '-') { 3781592Srgrimes puts("user names may not start with '-'."); 3791592Srgrimes continue; 3801592Srgrimes } 381115900Syar if (!(upper || lower || digit)) { 382115900Syar if (AL) { 383115900Syar syslog(LOG_ERR, 384115900Syar "invalid auto-login name: %s", AL); 385115900Syar exit(1); 386115900Syar } else 387115900Syar continue; 388115900Syar } 38956725Sbde set_flags(2); 39015645Sjoerg if (crmod) { 39115645Sjoerg tmode.c_iflag |= ICRNL; 39215645Sjoerg tmode.c_oflag |= ONLCR; 39315645Sjoerg } 39415645Sjoerg#if REALLY_OLD_TTYS 39515645Sjoerg if (upper || UC) 39615645Sjoerg tmode.sg_flags |= LCASE; 39715645Sjoerg if (lower || LC) 39815645Sjoerg tmode.sg_flags &= ~LCASE; 39915645Sjoerg#endif 40022208Sdavidn if (tcsetattr(STDIN_FILENO, TCSANOW, &tmode) < 0) { 40122208Sdavidn syslog(LOG_ERR, "tcsetattr %s: %m", ttyn); 40215645Sjoerg exit(1); 40315645Sjoerg } 40415645Sjoerg signal(SIGINT, SIG_DFL); 4051592Srgrimes for (i = 0; environ[i] != (char *)0; i++) 4061592Srgrimes env[i] = environ[i]; 4071592Srgrimes makeenv(&env[i]); 4081592Srgrimes 40915645Sjoerg limit.rlim_max = RLIM_INFINITY; 41015645Sjoerg limit.rlim_cur = RLIM_INFINITY; 41115645Sjoerg (void)setrlimit(RLIMIT_CPU, &limit); 41245291Speter execle(LO, "login", AL ? "-fp" : "-p", name, 41345291Speter (char *) 0, env); 4141592Srgrimes syslog(LOG_ERR, "%s: %m", LO); 4151592Srgrimes exit(1); 4161592Srgrimes } 4171592Srgrimes alarm(0); 4181592Srgrimes signal(SIGALRM, SIG_DFL); 41915645Sjoerg signal(SIGINT, SIG_IGN); 420116164Syar if (NX && *NX) { 4211592Srgrimes tname = NX; 422116533Syar dogettytab(); 423116164Syar } 4241592Srgrimes } 4251592Srgrimes} 4261592Srgrimes 42715645Sjoergstatic int 42890302Simpopentty(const char *tty, int flags) 42922208Sdavidn{ 43022208Sdavidn int i, j = 0; 43122208Sdavidn int failopenlogged = 0; 43222208Sdavidn 43390302Simp while (j < 10 && (i = open(tty, flags)) == -1) 43422208Sdavidn { 43522208Sdavidn if (((j % 10) == 0) && (errno != ENXIO || !failopenlogged)) { 43690302Simp syslog(LOG_ERR, "open %s: %m", tty); 43722208Sdavidn failopenlogged = 1; 43822208Sdavidn } 43922208Sdavidn j++; 44022208Sdavidn sleep(60); 44122208Sdavidn } 44222208Sdavidn if (i == -1) { 44390302Simp syslog(LOG_ERR, "open %s: %m", tty); 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) { 45490302Simp syslog(LOG_ERR, "login_tty %s: %m", tty); 45568888Sjwd close(i); 45668888Sjwd return 0; 45768888Sjwd } 45868888Sjwd } 45922208Sdavidn return 1; 46022208Sdavidn } 46122208Sdavidn} 46222208Sdavidn 46322208Sdavidnstatic void 464116533Syardefttymode() 46522208Sdavidn{ 466116533Syar 467116533Syar /* Start with default tty settings. */ 46822208Sdavidn if (tcgetattr(STDIN_FILENO, &tmode) < 0) { 46922208Sdavidn syslog(LOG_ERR, "tcgetattr %s: %m", ttyn); 47022208Sdavidn exit(1); 47122208Sdavidn } 472116533Syar omode = tmode; /* fill c_cc for dogettytab() */ 473116533Syar dogettytab(); 474116533Syar /* 475116533Syar * Don't rely on the driver too much, and initialize crucial 476116533Syar * things according to <sys/ttydefaults.h>. Avoid clobbering 477116533Syar * the c_cc[] settings however, the console drivers might wish 478116533Syar * to leave their idea of the preferred VERASE key value 479116533Syar * there. 480116533Syar */ 48122208Sdavidn tmode.c_iflag = TTYDEF_IFLAG; 482116533Syar tmode.c_oflag = TTYDEF_OFLAG; 483116533Syar tmode.c_lflag = TTYDEF_LFLAG; 484116533Syar tmode.c_cflag = TTYDEF_CFLAG; 485116533Syar if (NC) 486116533Syar tmode.c_cflag |= CLOCAL; 487116533Syar omode = tmode; 48822208Sdavidn} 48922208Sdavidn 49022208Sdavidnstatic void 491116164Syarsetttymode(int raw) 49222208Sdavidn{ 49322208Sdavidn int off = 0; 49422208Sdavidn 49522208Sdavidn (void)tcflush(STDIN_FILENO, TCIOFLUSH); /* clear out the crap */ 49622208Sdavidn ioctl(STDIN_FILENO, FIONBIO, &off); /* turn off non-blocking mode */ 49722208Sdavidn ioctl(STDIN_FILENO, FIOASYNC, &off); /* ditto for async mode */ 49822208Sdavidn 49922208Sdavidn if (IS) 50022208Sdavidn cfsetispeed(&tmode, speed(IS)); 50122208Sdavidn else if (SP) 50222208Sdavidn cfsetispeed(&tmode, speed(SP)); 50322208Sdavidn if (OS) 50422208Sdavidn cfsetospeed(&tmode, speed(OS)); 50522208Sdavidn else if (SP) 50622208Sdavidn cfsetospeed(&tmode, speed(SP)); 50756725Sbde set_flags(0); 50822208Sdavidn setchars(); 50922208Sdavidn if (raw) 51022208Sdavidn cfmakeraw(&tmode); 51122208Sdavidn if (tcsetattr(STDIN_FILENO, TCSANOW, &tmode) < 0) { 51222208Sdavidn syslog(LOG_ERR, "tcsetattr %s: %m", ttyn); 51322208Sdavidn exit(1); 51422208Sdavidn } 51522208Sdavidn} 51622208Sdavidn 51722208Sdavidn 51822208Sdavidnstatic int 51990301Simpgetname(void) 5201592Srgrimes{ 52190301Simp int c; 52290301Simp char *np; 52319697Spst unsigned char cs; 52422208Sdavidn int ppp_state = 0; 52519697Spst int ppp_connection = 0; 5261592Srgrimes 5271592Srgrimes /* 5281592Srgrimes * Interrupt may happen if we use CBREAK mode 5291592Srgrimes */ 5301592Srgrimes if (setjmp(intrupt)) { 5311592Srgrimes signal(SIGINT, SIG_IGN); 5321592Srgrimes return (0); 5331592Srgrimes } 5341592Srgrimes signal(SIGINT, interrupt); 53556725Sbde set_flags(1); 5361592Srgrimes prompt(); 5372286Sjkh oflush(); 5381592Srgrimes if (PF > 0) { 5391592Srgrimes sleep(PF); 5401592Srgrimes PF = 0; 5411592Srgrimes } 54222208Sdavidn if (tcsetattr(STDIN_FILENO, TCSANOW, &tmode) < 0) { 54315645Sjoerg syslog(LOG_ERR, "%s: %m", ttyn); 54415645Sjoerg exit(1); 54515645Sjoerg } 5461592Srgrimes crmod = digit = lower = upper = 0; 5471592Srgrimes np = name; 5481592Srgrimes for (;;) { 5491592Srgrimes oflush(); 5501592Srgrimes if (read(STDIN_FILENO, &cs, 1) <= 0) 5511592Srgrimes exit(0); 5521592Srgrimes if ((c = cs&0177) == 0) 5531592Srgrimes return (0); 55419697Spst 55519697Spst /* PPP detection state machine.. 55619697Spst Look for sequences: 55719697Spst PPP_FRAME, PPP_STATION, PPP_ESCAPE, PPP_CONTROL_ESCAPED or 55819697Spst PPP_FRAME, PPP_STATION, PPP_CONTROL (deviant from RFC) 55919697Spst See RFC1662. 56019697Spst Derived from code from Michael Hancock, <michaelh@cet.co.jp> 56119697Spst and Erik 'PPP' Olson, <eriko@wrq.com> 56219697Spst */ 56319697Spst 56419697Spst if (PP && (cs == PPP_FRAME)) { 56519697Spst ppp_state = 1; 56619697Spst } else if (ppp_state == 1 && cs == PPP_STATION) { 56719697Spst ppp_state = 2; 56819697Spst } else if (ppp_state == 2 && cs == PPP_ESCAPE) { 56919697Spst ppp_state = 3; 57019697Spst } else if ((ppp_state == 2 && cs == PPP_CONTROL) 57119697Spst || (ppp_state == 3 && cs == PPP_CONTROL_ESCAPED)) { 57219697Spst ppp_state = 4; 57319697Spst } else if (ppp_state == 4 && cs == PPP_LCP_HI) { 57419697Spst ppp_state = 5; 57519697Spst } else if (ppp_state == 5 && cs == PPP_LCP_LOW) { 57619697Spst ppp_connection = 1; 57719697Spst break; 57819697Spst } else { 57919697Spst ppp_state = 0; 58019697Spst } 58119697Spst 58215645Sjoerg if (c == EOT || c == CTRL('d')) 583115900Syar exit(0); 58422211Sdavidn if (c == '\r' || c == '\n' || np >= &name[sizeof name-1]) { 5851592Srgrimes putf("\r\n"); 5861592Srgrimes break; 5871592Srgrimes } 5881592Srgrimes if (islower(c)) 5891592Srgrimes lower = 1; 5901592Srgrimes else if (isupper(c)) 5911592Srgrimes upper = 1; 5922286Sjkh else if (c == ERASE || c == '\b' || c == 0177) { 5931592Srgrimes if (np > name) { 5941592Srgrimes np--; 59515645Sjoerg if (cfgetospeed(&tmode) >= 1200) 5961592Srgrimes puts("\b \b"); 5971592Srgrimes else 5981592Srgrimes putchr(cs); 5991592Srgrimes } 6001592Srgrimes continue; 60115645Sjoerg } else if (c == KILL || c == CTRL('u')) { 6021592Srgrimes putchr('\r'); 60315645Sjoerg if (cfgetospeed(&tmode) < 1200) 6041592Srgrimes putchr('\n'); 6051592Srgrimes /* this is the way they do it down under ... */ 6061592Srgrimes else if (np > name) 6071592Srgrimes puts(" \r"); 6081592Srgrimes prompt(); 609115900Syar digit = lower = upper = 0; 6101592Srgrimes np = name; 6111592Srgrimes continue; 6121592Srgrimes } else if (isdigit(c)) 613116154Syar digit = 1; 6141592Srgrimes if (IG && (c <= ' ' || c > 0176)) 6151592Srgrimes continue; 6161592Srgrimes *np++ = c; 6171592Srgrimes putchr(cs); 6181592Srgrimes } 6191592Srgrimes signal(SIGINT, SIG_IGN); 6201592Srgrimes *np = 0; 6211592Srgrimes if (c == '\r') 6221592Srgrimes crmod = 1; 62315645Sjoerg if ((upper && !lower && !LC) || UC) 6241592Srgrimes for (np = name; *np; np++) 6251592Srgrimes if (isupper(*np)) 6261592Srgrimes *np = tolower(*np); 62719697Spst return (1 + ppp_connection); 6281592Srgrimes} 6291592Srgrimes 63015645Sjoergstatic void 63190301Simpputpad(const char *s) 6321592Srgrimes{ 63390301Simp int pad = 0; 63415645Sjoerg speed_t ospeed = cfgetospeed(&tmode); 6351592Srgrimes 6361592Srgrimes if (isdigit(*s)) { 6371592Srgrimes while (isdigit(*s)) { 6381592Srgrimes pad *= 10; 6391592Srgrimes pad += *s++ - '0'; 6401592Srgrimes } 6411592Srgrimes pad *= 10; 6421592Srgrimes if (*s == '.' && isdigit(s[1])) { 6431592Srgrimes pad += s[1] - '0'; 6441592Srgrimes s += 2; 6451592Srgrimes } 6461592Srgrimes } 6471592Srgrimes 6481592Srgrimes puts(s); 6491592Srgrimes /* 6501592Srgrimes * If no delay needed, or output speed is 6511592Srgrimes * not comprehensible, then don't try to delay. 6521592Srgrimes */ 65315645Sjoerg if (pad == 0 || ospeed <= 0) 6541592Srgrimes return; 6551592Srgrimes 6561592Srgrimes /* 6571592Srgrimes * Round up by a half a character frame, and then do the delay. 6581592Srgrimes * Too bad there are no user program accessible programmed delays. 6591592Srgrimes * Transmitting pad characters slows many terminals down and also 6601592Srgrimes * loads the system. 6611592Srgrimes */ 66215645Sjoerg pad = (pad * ospeed + 50000) / 100000; 66315645Sjoerg while (pad--) 6641592Srgrimes putchr(*PC); 6651592Srgrimes} 6661592Srgrimes 66715645Sjoergstatic void 66890301Simpputs(const char *s) 6691592Srgrimes{ 6701592Srgrimes while (*s) 6711592Srgrimes putchr(*s++); 6721592Srgrimes} 6731592Srgrimes 6741592Srgrimeschar outbuf[OBUFSIZ]; 6751592Srgrimesint obufcnt = 0; 6761592Srgrimes 67715645Sjoergstatic void 67890301Simpputchr(int cc) 6791592Srgrimes{ 6801592Srgrimes char c; 6811592Srgrimes 6821592Srgrimes c = cc; 6831592Srgrimes if (!NP) { 6841592Srgrimes c |= partab[c&0177] & 0200; 6851592Srgrimes if (OP) 6861592Srgrimes c ^= 0200; 6871592Srgrimes } 6881592Srgrimes if (!UB) { 6891592Srgrimes outbuf[obufcnt++] = c; 6901592Srgrimes if (obufcnt >= OBUFSIZ) 6911592Srgrimes oflush(); 6921592Srgrimes } else 6931592Srgrimes write(STDOUT_FILENO, &c, 1); 6941592Srgrimes} 6951592Srgrimes 69615645Sjoergstatic void 69790301Simpoflush(void) 6981592Srgrimes{ 6991592Srgrimes if (obufcnt) 7001592Srgrimes write(STDOUT_FILENO, outbuf, obufcnt); 7011592Srgrimes obufcnt = 0; 7021592Srgrimes} 7031592Srgrimes 70415645Sjoergstatic void 70590301Simpprompt(void) 7061592Srgrimes{ 7071592Srgrimes 7081592Srgrimes putf(LM); 7091592Srgrimes if (CO) 7101592Srgrimes putchr('\n'); 7111592Srgrimes} 7121592Srgrimes 71322208Sdavidn 71422208Sdavidnstatic char * 71590301Simpgetline(int fd) 71622208Sdavidn{ 71722208Sdavidn int i = 0; 71822208Sdavidn static char linebuf[512]; 71922208Sdavidn 72022208Sdavidn /* 72122208Sdavidn * This is certainly slow, but it avoids having to include 72222208Sdavidn * stdio.h unnecessarily. Issue files should be small anyway. 72322208Sdavidn */ 72422208Sdavidn while (i < (sizeof linebuf - 3) && read(fd, linebuf+i, 1)==1) { 72522208Sdavidn if (linebuf[i] == '\n') { 72622208Sdavidn /* Don't rely on newline mode, assume raw */ 72722208Sdavidn linebuf[i++] = '\r'; 72822208Sdavidn linebuf[i++] = '\n'; 72922208Sdavidn linebuf[i] = '\0'; 73022208Sdavidn return linebuf; 73122208Sdavidn } 73222208Sdavidn ++i; 73322208Sdavidn } 73422208Sdavidn linebuf[i] = '\0'; 73522208Sdavidn return i ? linebuf : 0; 73622208Sdavidn} 73722208Sdavidn 73815645Sjoergstatic void 73990301Simpputf(const char *cp) 7401592Srgrimes{ 7411592Srgrimes extern char editedhost[]; 7421592Srgrimes time_t t; 7431592Srgrimes char *slash, db[100]; 7441592Srgrimes 74522199Sdavidn static struct utsname kerninfo; 74622199Sdavidn 74722199Sdavidn if (!*kerninfo.sysname) 74822199Sdavidn uname(&kerninfo); 74922199Sdavidn 7501592Srgrimes while (*cp) { 7511592Srgrimes if (*cp != '%') { 7521592Srgrimes putchr(*cp++); 7531592Srgrimes continue; 7541592Srgrimes } 7551592Srgrimes switch (*++cp) { 7561592Srgrimes 7571592Srgrimes case 't': 75815645Sjoerg slash = strrchr(ttyn, '/'); 7591592Srgrimes if (slash == (char *) 0) 7601592Srgrimes puts(ttyn); 7611592Srgrimes else 7621592Srgrimes puts(&slash[1]); 7631592Srgrimes break; 7641592Srgrimes 7651592Srgrimes case 'h': 7661592Srgrimes puts(editedhost); 7671592Srgrimes break; 7681592Srgrimes 7691592Srgrimes case 'd': { 77015645Sjoerg t = (time_t)0; 7711592Srgrimes (void)time(&t); 77215645Sjoerg if (Lo) 77315645Sjoerg (void)setlocale(LC_TIME, Lo); 77477874Syar (void)strftime(db, sizeof(db), DF, localtime(&t)); 7751592Srgrimes puts(db); 7769875Sjkh break; 77715645Sjoerg 77815645Sjoerg case 's': 77915645Sjoerg puts(kerninfo.sysname); 78015645Sjoerg break; 78115645Sjoerg 78215645Sjoerg case 'm': 78315645Sjoerg puts(kerninfo.machine); 78415645Sjoerg break; 78515645Sjoerg 78615645Sjoerg case 'r': 78715645Sjoerg puts(kerninfo.release); 78815645Sjoerg break; 78915645Sjoerg 79015645Sjoerg case 'v': 79115645Sjoerg puts(kerninfo.version); 79215645Sjoerg break; 7931592Srgrimes } 7941592Srgrimes 7951592Srgrimes case '%': 7961592Srgrimes putchr('%'); 7971592Srgrimes break; 7981592Srgrimes } 7991592Srgrimes cp++; 8001592Srgrimes } 8011592Srgrimes} 802116164Syar 803116164Syar/* 804116164Syar * Read a gettytab database entry and perform necessary quirks. 805116164Syar */ 806116164Syarstatic void 807116533Syardogettytab() 808116164Syar{ 809116164Syar 810116533Syar /* Read the database entry. */ 811116164Syar gettable(tname, tabent); 812116164Syar 813116164Syar /* 814116164Syar * Avoid inheriting the parity values from the default entry 815116164Syar * if any of them is set in the current entry. 816116164Syar * Mixing different parity settings is unreasonable. 817116164Syar */ 818116164Syar if (OPset || EPset || APset || NPset) 819116164Syar OPset = EPset = APset = NPset = 1; 820116164Syar 821116533Syar /* Fill in default values for unset capabilities. */ 822116164Syar setdefaults(); 823116164Syar} 824