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. 13262136Sbrueffer * 3. Neither the name of the University nor the names of its contributors 141592Srgrimes * may be used to endorse or promote products derived from this software 151592Srgrimes * without specific prior written permission. 161592Srgrimes * 171592Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 181592Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191592Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201592Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 211592Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221592Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231592Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241592Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251592Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261592Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271592Srgrimes * SUCH DAMAGE. 281592Srgrimes */ 291592Srgrimes 301592Srgrimes#ifndef lint 3131331Scharnierstatic const char copyright[] = 3215645Sjoerg"@(#) Copyright (c) 1980, 1993\n\ 3315645Sjoerg The Regents of the University of California. All rights reserved.\n"; 341592Srgrimes#endif /* not lint */ 351592Srgrimes 361592Srgrimes#ifndef lint 3731331Scharnier#if 0 3831331Scharnierstatic char sccsid[] = "@(#)from: main.c 8.1 (Berkeley) 6/20/93"; 3931331Scharnier#endif 401592Srgrimes#endif /* not lint */ 41216582Scharnier#include <sys/cdefs.h> 42216582Scharnier__FBSDID("$FreeBSD: stable/11/libexec/getty/main.c 323992 2017-09-25 20:04:14Z dab $"); 431592Srgrimes 441592Srgrimes#include <sys/param.h> 4515645Sjoerg#include <sys/ioctl.h> 4691216Sbde#include <sys/time.h> 4715645Sjoerg#include <sys/resource.h> 4891216Sbde#include <sys/stat.h> 4915645Sjoerg#include <sys/ttydefaults.h> 5015645Sjoerg#include <sys/utsname.h> 5166907Swollman 5231331Scharnier#include <ctype.h> 5315645Sjoerg#include <errno.h> 542286Sjkh#include <fcntl.h> 5531331Scharnier#include <locale.h> 5615645Sjoerg#include <libutil.h> 572286Sjkh#include <setjmp.h> 5815645Sjoerg#include <signal.h> 5915645Sjoerg#include <stdlib.h> 6015645Sjoerg#include <string.h> 612286Sjkh#include <syslog.h> 6215645Sjoerg#include <termios.h> 6315645Sjoerg#include <time.h> 642286Sjkh#include <unistd.h> 6515645Sjoerg 66144716Sstefanf#include "gettytab.h" 6791216Sbde#include "extern.h" 681592Srgrimes#include "pathnames.h" 691592Srgrimes 7015645Sjoerg/* 7115645Sjoerg * Set the amount of running time that getty should accumulate 7215645Sjoerg * before deciding that something is wrong and exit. 7315645Sjoerg */ 7415645Sjoerg#define GETTY_TIMEOUT 60 /* seconds */ 751592Srgrimes 7615645Sjoerg#undef CTRL 7715645Sjoerg#define CTRL(x) (x&037) 7815645Sjoerg 7919697Spst/* defines for auto detection of incoming PPP calls (->PAP/CHAP) */ 8019697Spst 8119697Spst#define PPP_FRAME 0x7e /* PPP Framing character */ 8219697Spst#define PPP_STATION 0xff /* "All Station" character */ 8319697Spst#define PPP_ESCAPE 0x7d /* Escape Character */ 8419697Spst#define PPP_CONTROL 0x03 /* PPP Control Field */ 8519697Spst#define PPP_CONTROL_ESCAPED 0x23 /* PPP Control Field, escaped */ 8619697Spst#define PPP_LCP_HI 0xc0 /* LCP protocol - high byte */ 8719697Spst#define PPP_LCP_LOW 0x21 /* LCP protocol - low byte */ 8819697Spst 89116533Syar/* original mode; flags've been reset using values from <sys/ttydefaults.h> */ 90116533Syarstruct termios omode; 91116533Syar/* current mode */ 92116533Syarstruct termios tmode; 9315645Sjoerg 941592Srgrimesint crmod, digit, lower, upper; 951592Srgrimes 961592Srgrimeschar hostname[MAXHOSTNAMELEN]; 9722400Sdavidnchar name[MAXLOGNAME*3]; 981592Srgrimeschar dev[] = _PATH_DEV; 991592Srgrimeschar ttyn[32]; 1001592Srgrimes 1011592Srgrimes#define OBUFSIZ 128 1021592Srgrimes#define TABBUFSIZ 512 1031592Srgrimes 1041592Srgrimeschar defent[TABBUFSIZ]; 1051592Srgrimeschar tabent[TABBUFSIZ]; 106116533Syarconst char *tname; 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 135117738Syarstatic void defttymode(void); 13690301Simpstatic void dingdong(int); 137116533Syarstatic void dogettytab(void); 13890301Simpstatic int getname(void); 13990301Simpstatic void interrupt(int); 14090301Simpstatic void oflush(void); 14190301Simpstatic void prompt(void); 14290301Simpstatic void putchr(int); 14390301Simpstatic void putf(const char *); 14490301Simpstatic void putpad(const char *); 14590301Simpstatic void puts(const char *); 14690301Simpstatic void timeoverrun(int); 14790301Simpstatic char *getline(int); 148116164Syarstatic void setttymode(int); 14990301Simpstatic int opentty(const char *, int); 15015645Sjoerg 15122208Sdavidnjmp_buf timeout; 15222208Sdavidn 1531592Srgrimesstatic void 15490302Simpdingdong(int signo __unused) 1551592Srgrimes{ 1561592Srgrimes alarm(0); 1571592Srgrimes longjmp(timeout, 1); 1581592Srgrimes} 1591592Srgrimes 1601592Srgrimesjmp_buf intrupt; 1611592Srgrimes 1621592Srgrimesstatic void 16390302Simpinterrupt(int signo __unused) 1641592Srgrimes{ 1651592Srgrimes longjmp(intrupt, 1); 1661592Srgrimes} 1671592Srgrimes 16815645Sjoerg/* 16915645Sjoerg * Action to take when getty is running too long. 17015645Sjoerg */ 17115645Sjoergstatic void 17290302Simptimeoverrun(int signo __unused) 17315645Sjoerg{ 17415645Sjoerg 17531331Scharnier syslog(LOG_ERR, "getty exiting due to excessive running time"); 17615645Sjoerg exit(1); 17715645Sjoerg} 17815645Sjoerg 17915645Sjoergint 18090301Simpmain(int argc, char *argv[]) 1811592Srgrimes{ 1822286Sjkh extern char **environ; 18322491Sdavidn int first_sleep = 1, first_time = 1; 18415645Sjoerg struct rlimit limit; 18519697Spst int rval; 1861592Srgrimes 1871592Srgrimes signal(SIGINT, SIG_IGN); 1882391Sache signal(SIGQUIT, SIG_IGN); 1892286Sjkh 190270111Sneel openlog("getty", LOG_CONS|LOG_PID, LOG_AUTH); 19145422Sbrian gethostname(hostname, sizeof(hostname) - 1); 19245422Sbrian hostname[sizeof(hostname) - 1] = '\0'; 1931592Srgrimes if (hostname[0] == '\0') 1941592Srgrimes strcpy(hostname, "Amnesiac"); 19515645Sjoerg 1961592Srgrimes /* 19715645Sjoerg * Limit running time to deal with broken or dead lines. 19815645Sjoerg */ 19915645Sjoerg (void)signal(SIGXCPU, timeoverrun); 20015645Sjoerg limit.rlim_max = RLIM_INFINITY; 20115645Sjoerg limit.rlim_cur = GETTY_TIMEOUT; 20215645Sjoerg (void)setrlimit(RLIMIT_CPU, &limit); 20315645Sjoerg 20422208Sdavidn gettable("default", defent); 20522208Sdavidn gendefaults(); 20622208Sdavidn tname = "default"; 207116329Sgreen if (argc > 1) 20822208Sdavidn tname = argv[1]; 20922208Sdavidn 21015645Sjoerg /* 2111592Srgrimes * The following is a work around for vhangup interactions 2121592Srgrimes * which cause great problems getting window systems started. 2131592Srgrimes * If the tty line is "-", we do the old style getty presuming 2148870Srgrimes * that the file descriptors are already set up for us. 2151592Srgrimes * J. Gettys - MIT Project Athena. 2161592Srgrimes */ 217116533Syar if (argc <= 2 || strcmp(argv[2], "-") == 0) 21822208Sdavidn strcpy(ttyn, ttyname(STDIN_FILENO)); 219116533Syar else { 2201592Srgrimes strcpy(ttyn, dev); 2211592Srgrimes strncat(ttyn, argv[2], sizeof(ttyn)-sizeof(dev)); 2221592Srgrimes if (strcmp(argv[0], "+") != 0) { 2231592Srgrimes chown(ttyn, 0, 0); 2241592Srgrimes chmod(ttyn, 0600); 2251592Srgrimes revoke(ttyn); 22622208Sdavidn 227116533Syar /* 228116533Syar * Do the first scan through gettytab. 229116533Syar * Terminal mode parameters will be wrong until 230116533Syar * defttymode() called, but they're irrelevant for 231116533Syar * the initial setup of the terminal device. 23222208Sdavidn */ 233116533Syar dogettytab(); 234116533Syar 235116533Syar /* 236116533Syar * Init or answer modem sequence has been specified. 237116533Syar */ 238116533Syar if (IC || AC) { 23922208Sdavidn if (!opentty(ttyn, O_RDWR|O_NONBLOCK)) 24022208Sdavidn exit(1); 241116533Syar defttymode(); 242116533Syar setttymode(1); 243116533Syar } 244116533Syar 245116533Syar if (IC) { 24622208Sdavidn if (getty_chat(IC, CT, DC) > 0) { 24722208Sdavidn syslog(LOG_ERR, "modem init problem on %s", ttyn); 24822491Sdavidn (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode); 24922208Sdavidn exit(1); 2501592Srgrimes } 2511592Srgrimes } 25222208Sdavidn 25322208Sdavidn if (AC) { 25422208Sdavidn int i, rfds; 25590302Simp struct timeval to; 25622208Sdavidn 25722208Sdavidn rfds = 1 << 0; /* FD_SET */ 25890302Simp to.tv_sec = RT; 25990302Simp to.tv_usec = 0; 26022208Sdavidn i = select(32, (fd_set*)&rfds, (fd_set*)NULL, 26190302Simp (fd_set*)NULL, RT ? &to : NULL); 26222208Sdavidn if (i < 0) { 26322208Sdavidn syslog(LOG_ERR, "select %s: %m", ttyn); 26422208Sdavidn } else if (i == 0) { 26522208Sdavidn syslog(LOG_NOTICE, "recycle tty %s", ttyn); 26622491Sdavidn (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode); 26722208Sdavidn exit(0); /* recycle for init */ 26822208Sdavidn } 26922208Sdavidn i = getty_chat(AC, CT, DC); 27022208Sdavidn if (i > 0) { 27122208Sdavidn syslog(LOG_ERR, "modem answer problem on %s", ttyn); 27222491Sdavidn (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode); 27322208Sdavidn exit(1); 27422208Sdavidn } 27564076Snsayer } else { /* maybe blocking open */ 27664076Snsayer if (!opentty(ttyn, O_RDWR | (NC ? O_NONBLOCK : 0 ))) 27722208Sdavidn exit(1); 27822208Sdavidn } 2791592Srgrimes } 2801592Srgrimes } 2811592Srgrimes 282116533Syar defttymode(); 2831592Srgrimes for (;;) { 2841592Srgrimes 28522491Sdavidn /* 28622491Sdavidn * if a delay was specified then sleep for that 28722491Sdavidn * number of seconds before writing the initial prompt 28822491Sdavidn */ 28922491Sdavidn if (first_sleep && DE) { 29022491Sdavidn sleep(DE); 29122491Sdavidn /* remove any noise */ 29222491Sdavidn (void)tcflush(STDIN_FILENO, TCIOFLUSH); 29322491Sdavidn } 29422491Sdavidn first_sleep = 0; 29522491Sdavidn 296116164Syar setttymode(0); 2971592Srgrimes if (AB) { 2981592Srgrimes tname = autobaud(); 299116533Syar dogettytab(); 3001592Srgrimes continue; 3011592Srgrimes } 3021592Srgrimes if (PS) { 3031592Srgrimes tname = portselector(); 304116533Syar dogettytab(); 3051592Srgrimes continue; 3061592Srgrimes } 3071592Srgrimes if (CL && *CL) 3081592Srgrimes putpad(CL); 3091592Srgrimes edithost(HE); 31021120Smsmith 31122208Sdavidn /* if this is the first time through this, and an 31222208Sdavidn issue file has been given, then send it */ 31322208Sdavidn if (first_time && IF) { 31422208Sdavidn int fd; 31522208Sdavidn 31622208Sdavidn if ((fd = open(IF, O_RDONLY)) != -1) { 31722208Sdavidn char * cp; 31822208Sdavidn 31922208Sdavidn while ((cp = getline(fd)) != NULL) { 32022208Sdavidn putf(cp); 32122208Sdavidn } 32222208Sdavidn close(fd); 32322208Sdavidn } 32422208Sdavidn } 32522491Sdavidn first_time = 0; 32622208Sdavidn 327323992Sdab if (IMP && *IMP && !(PL && PP)) 328323992Sdab system(IMP); 329109555Ssobomax if (IM && *IM && !(PL && PP)) 3301592Srgrimes putf(IM); 3311592Srgrimes if (setjmp(timeout)) { 33215659Sache cfsetispeed(&tmode, B0); 33315659Sache cfsetospeed(&tmode, B0); 33422208Sdavidn (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode); 3351592Srgrimes exit(1); 3361592Srgrimes } 3371592Srgrimes if (TO) { 3381592Srgrimes signal(SIGALRM, dingdong); 3391592Srgrimes alarm(TO); 3401592Srgrimes } 341115900Syar 342115900Syar rval = 0; 34345291Speter if (AL) { 34445291Speter const char *p = AL; 34545291Speter char *q = name; 34645291Speter 34745291Speter while (*p && q < &name[sizeof name - 1]) { 34845291Speter if (isupper(*p)) 34945291Speter upper = 1; 35045291Speter else if (islower(*p)) 35145291Speter lower = 1; 35245291Speter else if (isdigit(*p)) 353116154Syar digit = 1; 35445291Speter *q++ = *p++; 35545291Speter } 356109540Ssobomax } else if (!(PL && PP)) 35745291Speter rval = getname(); 358109540Ssobomax if (rval == 2 || (PL && PP)) { 35926415Sdavidn oflush(); 36026415Sdavidn alarm(0); 36144615Sbrian limit.rlim_max = RLIM_INFINITY; 36244615Sbrian limit.rlim_cur = RLIM_INFINITY; 36344615Sbrian (void)setrlimit(RLIMIT_CPU, &limit); 36419697Spst execle(PP, "ppplogin", ttyn, (char *) 0, env); 36519697Spst syslog(LOG_ERR, "%s: %m", PP); 36619697Spst exit(1); 36745291Speter } else if (rval || AL) { 36890301Simp int i; 3691592Srgrimes 37015645Sjoerg oflush(); 3711592Srgrimes alarm(0); 3721592Srgrimes signal(SIGALRM, SIG_DFL); 373115900Syar if (name[0] == '\0') 374115900Syar continue; 3751592Srgrimes if (name[0] == '-') { 3761592Srgrimes puts("user names may not start with '-'."); 3771592Srgrimes continue; 3781592Srgrimes } 379115900Syar if (!(upper || lower || digit)) { 380115900Syar if (AL) { 381115900Syar syslog(LOG_ERR, 382115900Syar "invalid auto-login name: %s", AL); 383115900Syar exit(1); 384115900Syar } else 385115900Syar continue; 386115900Syar } 38756725Sbde set_flags(2); 38815645Sjoerg if (crmod) { 38915645Sjoerg tmode.c_iflag |= ICRNL; 39015645Sjoerg tmode.c_oflag |= ONLCR; 39115645Sjoerg } 39215645Sjoerg#if REALLY_OLD_TTYS 39315645Sjoerg if (upper || UC) 39415645Sjoerg tmode.sg_flags |= LCASE; 39515645Sjoerg if (lower || LC) 39615645Sjoerg tmode.sg_flags &= ~LCASE; 39715645Sjoerg#endif 39822208Sdavidn if (tcsetattr(STDIN_FILENO, TCSANOW, &tmode) < 0) { 39922208Sdavidn syslog(LOG_ERR, "tcsetattr %s: %m", ttyn); 40015645Sjoerg exit(1); 40115645Sjoerg } 40215645Sjoerg signal(SIGINT, SIG_DFL); 4031592Srgrimes for (i = 0; environ[i] != (char *)0; i++) 4041592Srgrimes env[i] = environ[i]; 4051592Srgrimes makeenv(&env[i]); 4061592Srgrimes 40715645Sjoerg limit.rlim_max = RLIM_INFINITY; 40815645Sjoerg limit.rlim_cur = RLIM_INFINITY; 40915645Sjoerg (void)setrlimit(RLIMIT_CPU, &limit); 41045291Speter execle(LO, "login", AL ? "-fp" : "-p", name, 41145291Speter (char *) 0, env); 4121592Srgrimes syslog(LOG_ERR, "%s: %m", LO); 4131592Srgrimes exit(1); 4141592Srgrimes } 4151592Srgrimes alarm(0); 4161592Srgrimes signal(SIGALRM, SIG_DFL); 41715645Sjoerg signal(SIGINT, SIG_IGN); 418116164Syar if (NX && *NX) { 4191592Srgrimes tname = NX; 420116533Syar dogettytab(); 421116164Syar } 4221592Srgrimes } 4231592Srgrimes} 4241592Srgrimes 42515645Sjoergstatic int 42690302Simpopentty(const char *tty, int flags) 42722208Sdavidn{ 428135941Simp int i; 42922208Sdavidn int failopenlogged = 0; 43022208Sdavidn 431135941Simp while ((i = open(tty, flags)) == -1) 43222208Sdavidn { 433135941Simp if (!failopenlogged) { 43490302Simp syslog(LOG_ERR, "open %s: %m", tty); 43522208Sdavidn failopenlogged = 1; 43622208Sdavidn } 43722208Sdavidn sleep(60); 43822208Sdavidn } 439135941Simp if (login_tty(i) < 0) { 440135941Simp if (daemon(0,0) < 0) { 441135941Simp syslog(LOG_ERR,"daemon: %m"); 442135941Simp close(i); 443135941Simp return 0; 44468888Sjwd } 445135941Simp if (login_tty(i) < 0) { 446135941Simp syslog(LOG_ERR, "login_tty %s: %m", tty); 447135941Simp close(i); 448135941Simp return 0; 449135941Simp } 45022208Sdavidn } 451135941Simp return 1; 45222208Sdavidn} 45322208Sdavidn 45422208Sdavidnstatic void 455214680Seddefttymode(void) 45622208Sdavidn{ 457214680Sed struct termios def; 458116533Syar 459116533Syar /* Start with default tty settings. */ 46022208Sdavidn if (tcgetattr(STDIN_FILENO, &tmode) < 0) { 46122208Sdavidn syslog(LOG_ERR, "tcgetattr %s: %m", ttyn); 46222208Sdavidn exit(1); 46322208Sdavidn } 464116533Syar omode = tmode; /* fill c_cc for dogettytab() */ 465116533Syar dogettytab(); 466116533Syar /* 467116533Syar * Don't rely on the driver too much, and initialize crucial 468116533Syar * things according to <sys/ttydefaults.h>. Avoid clobbering 469116533Syar * the c_cc[] settings however, the console drivers might wish 470116533Syar * to leave their idea of the preferred VERASE key value 471116533Syar * there. 472116533Syar */ 473214680Sed cfmakesane(&def); 474214680Sed tmode.c_iflag = def.c_iflag; 475214680Sed tmode.c_oflag = def.c_oflag; 476214680Sed tmode.c_lflag = def.c_lflag; 477214680Sed tmode.c_cflag = def.c_cflag; 478116533Syar if (NC) 479116533Syar tmode.c_cflag |= CLOCAL; 480116533Syar omode = tmode; 48122208Sdavidn} 48222208Sdavidn 48322208Sdavidnstatic void 484116164Syarsetttymode(int raw) 48522208Sdavidn{ 48622208Sdavidn int off = 0; 48722208Sdavidn 48822208Sdavidn (void)tcflush(STDIN_FILENO, TCIOFLUSH); /* clear out the crap */ 48922208Sdavidn ioctl(STDIN_FILENO, FIONBIO, &off); /* turn off non-blocking mode */ 49022208Sdavidn ioctl(STDIN_FILENO, FIOASYNC, &off); /* ditto for async mode */ 49122208Sdavidn 49222208Sdavidn if (IS) 49322208Sdavidn cfsetispeed(&tmode, speed(IS)); 49422208Sdavidn else if (SP) 49522208Sdavidn cfsetispeed(&tmode, speed(SP)); 49622208Sdavidn if (OS) 49722208Sdavidn cfsetospeed(&tmode, speed(OS)); 49822208Sdavidn else if (SP) 49922208Sdavidn cfsetospeed(&tmode, speed(SP)); 50056725Sbde set_flags(0); 50122208Sdavidn setchars(); 50222208Sdavidn if (raw) 50322208Sdavidn cfmakeraw(&tmode); 50422208Sdavidn if (tcsetattr(STDIN_FILENO, TCSANOW, &tmode) < 0) { 50522208Sdavidn syslog(LOG_ERR, "tcsetattr %s: %m", ttyn); 50622208Sdavidn exit(1); 50722208Sdavidn } 50822208Sdavidn} 50922208Sdavidn 51022208Sdavidn 51122208Sdavidnstatic int 51290301Simpgetname(void) 5131592Srgrimes{ 51490301Simp int c; 51590301Simp char *np; 51619697Spst unsigned char cs; 51722208Sdavidn int ppp_state = 0; 51819697Spst int ppp_connection = 0; 5191592Srgrimes 5201592Srgrimes /* 5211592Srgrimes * Interrupt may happen if we use CBREAK mode 5221592Srgrimes */ 5231592Srgrimes if (setjmp(intrupt)) { 5241592Srgrimes signal(SIGINT, SIG_IGN); 5251592Srgrimes return (0); 5261592Srgrimes } 5271592Srgrimes signal(SIGINT, interrupt); 52856725Sbde set_flags(1); 5291592Srgrimes prompt(); 5302286Sjkh oflush(); 5311592Srgrimes if (PF > 0) { 5321592Srgrimes sleep(PF); 5331592Srgrimes PF = 0; 5341592Srgrimes } 53522208Sdavidn if (tcsetattr(STDIN_FILENO, TCSANOW, &tmode) < 0) { 53615645Sjoerg syslog(LOG_ERR, "%s: %m", ttyn); 53715645Sjoerg exit(1); 53815645Sjoerg } 5391592Srgrimes crmod = digit = lower = upper = 0; 5401592Srgrimes np = name; 5411592Srgrimes for (;;) { 5421592Srgrimes oflush(); 5431592Srgrimes if (read(STDIN_FILENO, &cs, 1) <= 0) 5441592Srgrimes exit(0); 5451592Srgrimes if ((c = cs&0177) == 0) 5461592Srgrimes return (0); 54719697Spst 54819697Spst /* PPP detection state machine.. 54919697Spst Look for sequences: 55019697Spst PPP_FRAME, PPP_STATION, PPP_ESCAPE, PPP_CONTROL_ESCAPED or 55119697Spst PPP_FRAME, PPP_STATION, PPP_CONTROL (deviant from RFC) 55219697Spst See RFC1662. 55319697Spst Derived from code from Michael Hancock, <michaelh@cet.co.jp> 55419697Spst and Erik 'PPP' Olson, <eriko@wrq.com> 55519697Spst */ 55619697Spst 55719697Spst if (PP && (cs == PPP_FRAME)) { 55819697Spst ppp_state = 1; 55919697Spst } else if (ppp_state == 1 && cs == PPP_STATION) { 56019697Spst ppp_state = 2; 56119697Spst } else if (ppp_state == 2 && cs == PPP_ESCAPE) { 56219697Spst ppp_state = 3; 56319697Spst } else if ((ppp_state == 2 && cs == PPP_CONTROL) 56419697Spst || (ppp_state == 3 && cs == PPP_CONTROL_ESCAPED)) { 56519697Spst ppp_state = 4; 56619697Spst } else if (ppp_state == 4 && cs == PPP_LCP_HI) { 56719697Spst ppp_state = 5; 56819697Spst } else if (ppp_state == 5 && cs == PPP_LCP_LOW) { 56919697Spst ppp_connection = 1; 57019697Spst break; 57119697Spst } else { 57219697Spst ppp_state = 0; 57319697Spst } 57419697Spst 57515645Sjoerg if (c == EOT || c == CTRL('d')) 576115900Syar exit(0); 57722211Sdavidn if (c == '\r' || c == '\n' || np >= &name[sizeof name-1]) { 5781592Srgrimes putf("\r\n"); 5791592Srgrimes break; 5801592Srgrimes } 5811592Srgrimes if (islower(c)) 5821592Srgrimes lower = 1; 5831592Srgrimes else if (isupper(c)) 5841592Srgrimes upper = 1; 5852286Sjkh else if (c == ERASE || c == '\b' || c == 0177) { 5861592Srgrimes if (np > name) { 5871592Srgrimes np--; 58815645Sjoerg if (cfgetospeed(&tmode) >= 1200) 5891592Srgrimes puts("\b \b"); 5901592Srgrimes else 5911592Srgrimes putchr(cs); 5921592Srgrimes } 5931592Srgrimes continue; 59415645Sjoerg } else if (c == KILL || c == CTRL('u')) { 5951592Srgrimes putchr('\r'); 59615645Sjoerg if (cfgetospeed(&tmode) < 1200) 5971592Srgrimes putchr('\n'); 5981592Srgrimes /* this is the way they do it down under ... */ 5991592Srgrimes else if (np > name) 6001592Srgrimes puts(" \r"); 6011592Srgrimes prompt(); 602115900Syar digit = lower = upper = 0; 6031592Srgrimes np = name; 6041592Srgrimes continue; 6051592Srgrimes } else if (isdigit(c)) 606116154Syar digit = 1; 6071592Srgrimes if (IG && (c <= ' ' || c > 0176)) 6081592Srgrimes continue; 6091592Srgrimes *np++ = c; 6101592Srgrimes putchr(cs); 6111592Srgrimes } 6121592Srgrimes signal(SIGINT, SIG_IGN); 6131592Srgrimes *np = 0; 6141592Srgrimes if (c == '\r') 6151592Srgrimes crmod = 1; 61615645Sjoerg if ((upper && !lower && !LC) || UC) 6171592Srgrimes for (np = name; *np; np++) 6181592Srgrimes if (isupper(*np)) 6191592Srgrimes *np = tolower(*np); 62019697Spst return (1 + ppp_connection); 6211592Srgrimes} 6221592Srgrimes 62315645Sjoergstatic void 62490301Simpputpad(const char *s) 6251592Srgrimes{ 62690301Simp int pad = 0; 62715645Sjoerg speed_t ospeed = cfgetospeed(&tmode); 6281592Srgrimes 6291592Srgrimes if (isdigit(*s)) { 6301592Srgrimes while (isdigit(*s)) { 6311592Srgrimes pad *= 10; 6321592Srgrimes pad += *s++ - '0'; 6331592Srgrimes } 6341592Srgrimes pad *= 10; 6351592Srgrimes if (*s == '.' && isdigit(s[1])) { 6361592Srgrimes pad += s[1] - '0'; 6371592Srgrimes s += 2; 6381592Srgrimes } 6391592Srgrimes } 6401592Srgrimes 6411592Srgrimes puts(s); 6421592Srgrimes /* 6431592Srgrimes * If no delay needed, or output speed is 6441592Srgrimes * not comprehensible, then don't try to delay. 6451592Srgrimes */ 64615645Sjoerg if (pad == 0 || ospeed <= 0) 6471592Srgrimes return; 6481592Srgrimes 6491592Srgrimes /* 6501592Srgrimes * Round up by a half a character frame, and then do the delay. 6511592Srgrimes * Too bad there are no user program accessible programmed delays. 6521592Srgrimes * Transmitting pad characters slows many terminals down and also 6531592Srgrimes * loads the system. 6541592Srgrimes */ 65515645Sjoerg pad = (pad * ospeed + 50000) / 100000; 65615645Sjoerg while (pad--) 6571592Srgrimes putchr(*PC); 6581592Srgrimes} 6591592Srgrimes 66015645Sjoergstatic void 66190301Simpputs(const char *s) 6621592Srgrimes{ 6631592Srgrimes while (*s) 6641592Srgrimes putchr(*s++); 6651592Srgrimes} 6661592Srgrimes 6671592Srgrimeschar outbuf[OBUFSIZ]; 6681592Srgrimesint obufcnt = 0; 6691592Srgrimes 67015645Sjoergstatic void 67190301Simpputchr(int cc) 6721592Srgrimes{ 6731592Srgrimes char c; 6741592Srgrimes 6751592Srgrimes c = cc; 6761592Srgrimes if (!NP) { 6771592Srgrimes c |= partab[c&0177] & 0200; 6781592Srgrimes if (OP) 6791592Srgrimes c ^= 0200; 6801592Srgrimes } 6811592Srgrimes if (!UB) { 6821592Srgrimes outbuf[obufcnt++] = c; 6831592Srgrimes if (obufcnt >= OBUFSIZ) 6841592Srgrimes oflush(); 6851592Srgrimes } else 6861592Srgrimes write(STDOUT_FILENO, &c, 1); 6871592Srgrimes} 6881592Srgrimes 68915645Sjoergstatic void 69090301Simpoflush(void) 6911592Srgrimes{ 6921592Srgrimes if (obufcnt) 6931592Srgrimes write(STDOUT_FILENO, outbuf, obufcnt); 6941592Srgrimes obufcnt = 0; 6951592Srgrimes} 6961592Srgrimes 69715645Sjoergstatic void 69890301Simpprompt(void) 6991592Srgrimes{ 7001592Srgrimes 7011592Srgrimes putf(LM); 7021592Srgrimes if (CO) 7031592Srgrimes putchr('\n'); 7041592Srgrimes} 7051592Srgrimes 70622208Sdavidn 70722208Sdavidnstatic char * 70890301Simpgetline(int fd) 70922208Sdavidn{ 71022208Sdavidn int i = 0; 71122208Sdavidn static char linebuf[512]; 71222208Sdavidn 71322208Sdavidn /* 71422208Sdavidn * This is certainly slow, but it avoids having to include 71522208Sdavidn * stdio.h unnecessarily. Issue files should be small anyway. 71622208Sdavidn */ 71722208Sdavidn while (i < (sizeof linebuf - 3) && read(fd, linebuf+i, 1)==1) { 71822208Sdavidn if (linebuf[i] == '\n') { 71922208Sdavidn /* Don't rely on newline mode, assume raw */ 72022208Sdavidn linebuf[i++] = '\r'; 72122208Sdavidn linebuf[i++] = '\n'; 72222208Sdavidn linebuf[i] = '\0'; 72322208Sdavidn return linebuf; 72422208Sdavidn } 72522208Sdavidn ++i; 72622208Sdavidn } 72722208Sdavidn linebuf[i] = '\0'; 72822208Sdavidn return i ? linebuf : 0; 72922208Sdavidn} 73022208Sdavidn 73115645Sjoergstatic void 73290301Simpputf(const char *cp) 7331592Srgrimes{ 7341592Srgrimes extern char editedhost[]; 7351592Srgrimes time_t t; 7361592Srgrimes char *slash, db[100]; 7371592Srgrimes 73822199Sdavidn static struct utsname kerninfo; 73922199Sdavidn 74022199Sdavidn if (!*kerninfo.sysname) 74122199Sdavidn uname(&kerninfo); 74222199Sdavidn 7431592Srgrimes while (*cp) { 7441592Srgrimes if (*cp != '%') { 7451592Srgrimes putchr(*cp++); 7461592Srgrimes continue; 7471592Srgrimes } 7481592Srgrimes switch (*++cp) { 7491592Srgrimes 7501592Srgrimes case 't': 75115645Sjoerg slash = strrchr(ttyn, '/'); 7521592Srgrimes if (slash == (char *) 0) 7531592Srgrimes puts(ttyn); 7541592Srgrimes else 7551592Srgrimes puts(&slash[1]); 7561592Srgrimes break; 7571592Srgrimes 7581592Srgrimes case 'h': 7591592Srgrimes puts(editedhost); 7601592Srgrimes break; 7611592Srgrimes 7621592Srgrimes case 'd': { 76315645Sjoerg t = (time_t)0; 7641592Srgrimes (void)time(&t); 76515645Sjoerg if (Lo) 76615645Sjoerg (void)setlocale(LC_TIME, Lo); 76777874Syar (void)strftime(db, sizeof(db), DF, localtime(&t)); 7681592Srgrimes puts(db); 7699875Sjkh break; 77015645Sjoerg 77115645Sjoerg case 's': 77215645Sjoerg puts(kerninfo.sysname); 77315645Sjoerg break; 77415645Sjoerg 77515645Sjoerg case 'm': 77615645Sjoerg puts(kerninfo.machine); 77715645Sjoerg break; 77815645Sjoerg 77915645Sjoerg case 'r': 78015645Sjoerg puts(kerninfo.release); 78115645Sjoerg break; 78215645Sjoerg 78315645Sjoerg case 'v': 78415645Sjoerg puts(kerninfo.version); 78515645Sjoerg break; 7861592Srgrimes } 7871592Srgrimes 7881592Srgrimes case '%': 7891592Srgrimes putchr('%'); 7901592Srgrimes break; 7911592Srgrimes } 7921592Srgrimes cp++; 7931592Srgrimes } 7941592Srgrimes} 795116164Syar 796116164Syar/* 797116164Syar * Read a gettytab database entry and perform necessary quirks. 798116164Syar */ 799116164Syarstatic void 800216582Scharnierdogettytab(void) 801116164Syar{ 802116164Syar 803116533Syar /* Read the database entry. */ 804116164Syar gettable(tname, tabent); 805116164Syar 806116164Syar /* 807116164Syar * Avoid inheriting the parity values from the default entry 808116164Syar * if any of them is set in the current entry. 809116164Syar * Mixing different parity settings is unreasonable. 810116164Syar */ 811116164Syar if (OPset || EPset || APset || NPset) 812116164Syar OPset = EPset = APset = NPset = 1; 813116164Syar 814116533Syar /* Fill in default values for unset capabilities. */ 815116164Syar setdefaults(); 816116164Syar} 817