1*4538572bSbluhm /* $OpenBSD: main.c,v 1.56 2024/07/19 15:28:51 bluhm Exp $ */ 25d36dfa4Sniklas 3df930be7Sderaadt /*- 4df930be7Sderaadt * Copyright (c) 1980, 1993 5df930be7Sderaadt * The Regents of the University of California. All rights reserved. 6df930be7Sderaadt * 7df930be7Sderaadt * Redistribution and use in source and binary forms, with or without 8df930be7Sderaadt * modification, are permitted provided that the following conditions 9df930be7Sderaadt * are met: 10df930be7Sderaadt * 1. Redistributions of source code must retain the above copyright 11df930be7Sderaadt * notice, this list of conditions and the following disclaimer. 12df930be7Sderaadt * 2. Redistributions in binary form must reproduce the above copyright 13df930be7Sderaadt * notice, this list of conditions and the following disclaimer in the 14df930be7Sderaadt * documentation and/or other materials provided with the distribution. 15e33d3bd3Smillert * 3. Neither the name of the University nor the names of its contributors 16df930be7Sderaadt * may be used to endorse or promote products derived from this software 17df930be7Sderaadt * without specific prior written permission. 18df930be7Sderaadt * 19df930be7Sderaadt * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20df930be7Sderaadt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21df930be7Sderaadt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22df930be7Sderaadt * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23df930be7Sderaadt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24df930be7Sderaadt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25df930be7Sderaadt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26df930be7Sderaadt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27df930be7Sderaadt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28df930be7Sderaadt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29df930be7Sderaadt * SUCH DAMAGE. 30df930be7Sderaadt */ 31df930be7Sderaadt 32df930be7Sderaadt #include <sys/stat.h> 33df930be7Sderaadt #include <termios.h> 34df930be7Sderaadt #include <sys/ioctl.h> 35df930be7Sderaadt #include <sys/resource.h> 36df930be7Sderaadt #include <sys/utsname.h> 37df930be7Sderaadt #include <errno.h> 38df930be7Sderaadt #include <signal.h> 39df930be7Sderaadt #include <fcntl.h> 40df930be7Sderaadt #include <time.h> 41df930be7Sderaadt #include <ctype.h> 42df930be7Sderaadt #include <stdlib.h> 43df930be7Sderaadt #include <string.h> 44df930be7Sderaadt #include <syslog.h> 45ae56b8b7Sderaadt #include <stdio.h> 46df930be7Sderaadt #include <unistd.h> 4752dc30e1Sderaadt #include <limits.h> 480abcd724Sderaadt #include <util.h> 49df930be7Sderaadt 50df930be7Sderaadt #include "gettytab.h" 51df930be7Sderaadt #include "pathnames.h" 52df930be7Sderaadt #include "extern.h" 53df930be7Sderaadt 54df930be7Sderaadt /* 55df930be7Sderaadt * Set the amount of running time that getty should accumulate 56df930be7Sderaadt * before deciding that something is wrong and exit. 57df930be7Sderaadt */ 58df930be7Sderaadt #define GETTY_TIMEOUT 60 /* seconds */ 59df930be7Sderaadt 60df930be7Sderaadt struct termios tmode, omode; 61df930be7Sderaadt 62df930be7Sderaadt int crmod, digit, lower, upper; 63df930be7Sderaadt 6452dc30e1Sderaadt char hostname[HOST_NAME_MAX+1]; 6530d77a25Stedu char globalhostname[HOST_NAME_MAX+1]; 66df930be7Sderaadt struct utsname kerninfo; 6752dc30e1Sderaadt char name[LOGIN_NAME_MAX]; 68df930be7Sderaadt char ttyn[32]; 6974637cb2Sderaadt char *portselector(void); 70df930be7Sderaadt 71df930be7Sderaadt #define OBUFSIZ 128 72df930be7Sderaadt #define TABBUFSIZ 512 73df930be7Sderaadt 74df930be7Sderaadt char defent[TABBUFSIZ]; 75df930be7Sderaadt char tabent[TABBUFSIZ]; 76bf6d4de2Sderaadt char saveLO[FILENAME_MAX]; 77df930be7Sderaadt 78df930be7Sderaadt char *env[128]; 79df930be7Sderaadt 80df930be7Sderaadt char partab[] = { 81df930be7Sderaadt 0001,0201,0201,0001,0201,0001,0001,0201, 82df930be7Sderaadt 0202,0004,0003,0205,0005,0206,0201,0001, 83df930be7Sderaadt 0201,0001,0001,0201,0001,0201,0201,0001, 84df930be7Sderaadt 0001,0201,0201,0001,0201,0001,0001,0201, 85df930be7Sderaadt 0200,0000,0000,0200,0000,0200,0200,0000, 86df930be7Sderaadt 0000,0200,0200,0000,0200,0000,0000,0200, 87df930be7Sderaadt 0000,0200,0200,0000,0200,0000,0000,0200, 88df930be7Sderaadt 0200,0000,0000,0200,0000,0200,0200,0000, 89df930be7Sderaadt 0200,0000,0000,0200,0000,0200,0200,0000, 90df930be7Sderaadt 0000,0200,0200,0000,0200,0000,0000,0200, 91df930be7Sderaadt 0000,0200,0200,0000,0200,0000,0000,0200, 92df930be7Sderaadt 0200,0000,0000,0200,0000,0200,0200,0000, 93df930be7Sderaadt 0000,0200,0200,0000,0200,0000,0000,0200, 94df930be7Sderaadt 0200,0000,0000,0200,0000,0200,0200,0000, 95df930be7Sderaadt 0200,0000,0000,0200,0000,0200,0200,0000, 96df930be7Sderaadt 0000,0200,0200,0000,0200,0000,0000,0201 97df930be7Sderaadt }; 98df930be7Sderaadt 99df930be7Sderaadt #define ERASE tmode.c_cc[VERASE] 100df930be7Sderaadt #define KILL tmode.c_cc[VKILL] 101df930be7Sderaadt #define EOT tmode.c_cc[VEOF] 102df930be7Sderaadt 103df930be7Sderaadt static void 1045b48e80aSderaadt dingdong(int signo) 105df930be7Sderaadt { 10652113b74Sderaadt tmode.c_ispeed = tmode.c_ospeed = 0; 10752113b74Sderaadt (void)tcsetattr(0, TCSANOW, &tmode); 10852113b74Sderaadt _exit(1); 109df930be7Sderaadt } 110df930be7Sderaadt 11152113b74Sderaadt volatile sig_atomic_t interrupt_flag; 112df930be7Sderaadt 113df930be7Sderaadt static void 1145b48e80aSderaadt interrupt(int signo) 115df930be7Sderaadt { 11652113b74Sderaadt int save_errno = errno; 117df930be7Sderaadt 11852113b74Sderaadt interrupt_flag = 1; 119df930be7Sderaadt signal(SIGINT, interrupt); 12052113b74Sderaadt errno = save_errno; 121df930be7Sderaadt } 122df930be7Sderaadt 123df930be7Sderaadt /* 124df930be7Sderaadt * Action to take when getty is running too long. 125df930be7Sderaadt */ 126aa31cba2Sderaadt static void 1275b48e80aSderaadt timeoverrun(int signo) 128df930be7Sderaadt { 12952113b74Sderaadt struct syslog_data sdata = SYSLOG_DATA_INIT; 13052113b74Sderaadt 13152113b74Sderaadt syslog_r(LOG_ERR, &sdata, 13252113b74Sderaadt "getty exiting due to excessive running time"); 133af4f388aSderaadt _exit(1); 134df930be7Sderaadt } 135df930be7Sderaadt 136c72b5b24Smillert static int getname(void); 137c72b5b24Smillert static void oflush(void); 138c72b5b24Smillert static void prompt(void); 139c72b5b24Smillert static void putchr(int); 140c72b5b24Smillert static void putf(char *); 141c72b5b24Smillert static void putpad(char *); 142c72b5b24Smillert static void xputs(char *); 143df930be7Sderaadt 144df930be7Sderaadt int 1455b48e80aSderaadt main(int argc, char *argv[]) 146df930be7Sderaadt { 147df930be7Sderaadt extern char **environ; 148df930be7Sderaadt char *tname; 149df930be7Sderaadt int repcnt = 0, failopenlogged = 0; 150df930be7Sderaadt struct rlimit limit; 15154eda240Stedu int off = 0; 152df930be7Sderaadt 153df930be7Sderaadt signal(SIGINT, SIG_IGN); 154df930be7Sderaadt /* 155df930be7Sderaadt signal(SIGQUIT, SIG_DFL); 156df930be7Sderaadt */ 157df930be7Sderaadt openlog("getty", LOG_ODELAY|LOG_CONS|LOG_PID, LOG_AUTH); 158df930be7Sderaadt gethostname(hostname, sizeof(hostname)); 159df930be7Sderaadt if (hostname[0] == '\0') 16048f8891fSderaadt strlcpy(hostname, "Amnesiac", sizeof hostname); 161df930be7Sderaadt uname(&kerninfo); 162df930be7Sderaadt 163df930be7Sderaadt /* 164df930be7Sderaadt * Limit running time to deal with broken or dead lines. 165df930be7Sderaadt */ 166df930be7Sderaadt (void)signal(SIGXCPU, timeoverrun); 167df930be7Sderaadt limit.rlim_max = RLIM_INFINITY; 168df930be7Sderaadt limit.rlim_cur = GETTY_TIMEOUT; 169df930be7Sderaadt (void)setrlimit(RLIMIT_CPU, &limit); 170df930be7Sderaadt 171ae7aa16aSderaadt ioctl(0, FIOASYNC, &off); /* turn off async mode */ 172ae7aa16aSderaadt 1739542d0dfSflorian tname = "default"; 1749542d0dfSflorian 175*4538572bSbluhm if (unveil(_PATH_GETTYTAB, "r") == -1 || 176*4538572bSbluhm unveil(_PATH_GETTYTAB ".db", "r") == -1) { 177239b4933Sderaadt syslog(LOG_ERR, "%s: %m", tname); 178239b4933Sderaadt exit(1); 179239b4933Sderaadt } 180239b4933Sderaadt if (unveil("/dev", "rw") == -1) { 181239b4933Sderaadt syslog(LOG_ERR, "%s: %m", tname); 182239b4933Sderaadt exit(1); 183239b4933Sderaadt } 184bf6d4de2Sderaadt if (unveil(_PATH_GETTY, "x") == -1) { 185bf6d4de2Sderaadt syslog(LOG_ERR, "%s: %m", tname); 186bf6d4de2Sderaadt exit(1); 187bf6d4de2Sderaadt } 188bf6d4de2Sderaadt 189bf6d4de2Sderaadt gettable("default", defent); 190bf6d4de2Sderaadt gendefaults(); 191bf6d4de2Sderaadt if (argc > 1) 192bf6d4de2Sderaadt tname = argv[1]; 193bf6d4de2Sderaadt gettable(tname, tabent); 194bf6d4de2Sderaadt if (LO == NULL) 195bf6d4de2Sderaadt LO = _PATH_LOGIN; 196bf6d4de2Sderaadt if (unveil(LO, "x") == -1) { 197bf6d4de2Sderaadt syslog(LOG_ERR, "%s: %m", tname); 198bf6d4de2Sderaadt exit(1); 199bf6d4de2Sderaadt } 2009e74ecfaSrob if (unveil(NULL, NULL) == -1) { 2019e74ecfaSrob syslog(LOG_ERR, "%s: %m", tname); 2029e74ecfaSrob exit(1); 2039e74ecfaSrob } 204bf6d4de2Sderaadt strlcpy(saveLO, LO, sizeof saveLO); 205239b4933Sderaadt 206df930be7Sderaadt /* 207df930be7Sderaadt * The following is a work around for vhangup interactions 208df930be7Sderaadt * which cause great problems getting window systems started. 209df930be7Sderaadt * If the tty line is "-", we do the old style getty presuming 210df930be7Sderaadt * that the file descriptors are already set up for us. 211df930be7Sderaadt * J. Gettys - MIT Project Athena. 212df930be7Sderaadt */ 213d0329355Sderaadt if (argc <= 2 || strcmp(argv[2], "-") == 0) { 2142acff669Sderaadt if (pledge("stdio rpath proc exec tty", NULL) == -1) { 2152acff669Sderaadt syslog(LOG_ERR, "pledge: %m"); 2162acff669Sderaadt exit(1); 2172acff669Sderaadt } 2182acff669Sderaadt 21965746b0cSmillert if ((tname = ttyname(0)) == NULL) { 22065746b0cSmillert syslog(LOG_ERR, "stdin: %m"); 22165746b0cSmillert exit(1); 22265746b0cSmillert } 22365746b0cSmillert if (strlcpy(ttyn, tname, sizeof(ttyn)) >= sizeof(ttyn)) { 22465746b0cSmillert errno = ENAMETOOLONG; 22565746b0cSmillert syslog(LOG_ERR, "%s: %m", tname); 22665746b0cSmillert exit(1); 22765746b0cSmillert } 228d0329355Sderaadt } else { 229df930be7Sderaadt int i; 230df930be7Sderaadt 2312d313e67Sderaadt snprintf(ttyn, sizeof ttyn, "%s%s", _PATH_DEV, argv[2]); 232df930be7Sderaadt if (strcmp(argv[0], "+") != 0) { 233df930be7Sderaadt chown(ttyn, 0, 0); 234df930be7Sderaadt chmod(ttyn, 0600); 235df930be7Sderaadt revoke(ttyn); 236df930be7Sderaadt /* 237df930be7Sderaadt * Delay the open so DTR stays down long enough to be detected. 238df930be7Sderaadt */ 239df930be7Sderaadt sleep(2); 240df930be7Sderaadt while ((i = open(ttyn, O_RDWR)) == -1) { 241df930be7Sderaadt if ((repcnt % 10 == 0) && 242df930be7Sderaadt (errno != ENXIO || !failopenlogged)) { 243df930be7Sderaadt syslog(LOG_ERR, "%s: %m", ttyn); 244df930be7Sderaadt closelog(); 245df930be7Sderaadt failopenlogged = 1; 246df930be7Sderaadt } 247df930be7Sderaadt repcnt++; 248df930be7Sderaadt sleep(60); 249df930be7Sderaadt } 250df930be7Sderaadt login_tty(i); 251df930be7Sderaadt } 252df930be7Sderaadt } 253cfbffc8cSderaadt 254ae7aa16aSderaadt if (pledge("stdio rpath proc exec tty", NULL) == -1) { 255cfbffc8cSderaadt syslog(LOG_ERR, "pledge: %m"); 256cfbffc8cSderaadt exit(1); 257cfbffc8cSderaadt } 258df930be7Sderaadt 259df930be7Sderaadt /* Start with default tty settings */ 260df69c215Sderaadt if (tcgetattr(0, &tmode) == -1) { 261df930be7Sderaadt syslog(LOG_ERR, "%s: %m", ttyn); 262df930be7Sderaadt exit(1); 263df930be7Sderaadt } 264df930be7Sderaadt omode = tmode; 265df930be7Sderaadt 266df930be7Sderaadt for (;;) { 267df930be7Sderaadt gettable(tname, tabent); 268bf6d4de2Sderaadt if (strcmp(LO, saveLO) != 0) { 269bf6d4de2Sderaadt /* re-exec to apply new unveil */ 2703e05b07bSderaadt closefrom(0); 271bf6d4de2Sderaadt execv(_PATH_GETTY, argv); 272bf6d4de2Sderaadt exit(0); 273bf6d4de2Sderaadt } 274df930be7Sderaadt if (OPset || EPset || APset) 275df930be7Sderaadt APset++, OPset++, EPset++; 276df930be7Sderaadt setdefaults(); 277df930be7Sderaadt (void)tcflush(0, TCIOFLUSH); /* clear out the crap */ 278df930be7Sderaadt ioctl(0, FIONBIO, &off); /* turn off non-blocking mode */ 279df930be7Sderaadt 280df930be7Sderaadt if (IS) 281df930be7Sderaadt cfsetispeed(&tmode, IS); 282df930be7Sderaadt else if (SP) 283df930be7Sderaadt cfsetispeed(&tmode, SP); 284df930be7Sderaadt if (OS) 285df930be7Sderaadt cfsetospeed(&tmode, OS); 286df930be7Sderaadt else if (SP) 287df930be7Sderaadt cfsetospeed(&tmode, SP); 288df930be7Sderaadt setflags(0); 289df930be7Sderaadt setchars(); 290df69c215Sderaadt if (tcsetattr(0, TCSANOW, &tmode) == -1) { 291df930be7Sderaadt syslog(LOG_ERR, "%s: %m", ttyn); 292df930be7Sderaadt exit(1); 293df930be7Sderaadt } 294df930be7Sderaadt if (AB) { 295df930be7Sderaadt tname = autobaud(); 296df930be7Sderaadt continue; 297df930be7Sderaadt } 298df930be7Sderaadt if (PS) { 299df930be7Sderaadt tname = portselector(); 300df930be7Sderaadt continue; 301df930be7Sderaadt } 302df930be7Sderaadt if (CL && *CL) 303df930be7Sderaadt putpad(CL); 30430d77a25Stedu strlcpy(globalhostname, HN, sizeof(globalhostname)); 305df930be7Sderaadt if (IM && *IM) 306df930be7Sderaadt putf(IM); 307df930be7Sderaadt if (TO) { 308df930be7Sderaadt signal(SIGALRM, dingdong); 309df930be7Sderaadt alarm(TO); 310df930be7Sderaadt } 31154eda240Stedu if (getname()) { 31252113b74Sderaadt int i; 313df930be7Sderaadt 314df930be7Sderaadt oflush(); 315df930be7Sderaadt alarm(0); 316df930be7Sderaadt signal(SIGALRM, SIG_DFL); 317df930be7Sderaadt if (name[0] == '-') { 31839235a5fSderaadt xputs("user names may not start with '-'."); 319df930be7Sderaadt continue; 320df930be7Sderaadt } 321df930be7Sderaadt if (!(upper || lower || digit)) 322df930be7Sderaadt continue; 323df930be7Sderaadt setflags(2); 324df930be7Sderaadt if (crmod) { 325df930be7Sderaadt tmode.c_iflag |= ICRNL; 326df930be7Sderaadt tmode.c_oflag |= ONLCR; 327df930be7Sderaadt } 328e095ce90Sbenno if (UC) { 3298f901b87Stholo tmode.c_iflag |= IUCLC; 3308f901b87Stholo tmode.c_oflag |= OLCUC; 3318f901b87Stholo tmode.c_lflag |= XCASE; 3328f901b87Stholo } 3338f901b87Stholo if (lower || LC) { 3348f901b87Stholo tmode.c_iflag &= ~IUCLC; 3358f901b87Stholo tmode.c_oflag &= ~OLCUC; 3368f901b87Stholo tmode.c_lflag &= ~XCASE; 3378f901b87Stholo } 338df69c215Sderaadt if (tcsetattr(0, TCSANOW, &tmode) == -1) { 339df930be7Sderaadt syslog(LOG_ERR, "%s: %m", ttyn); 340df930be7Sderaadt exit(1); 341df930be7Sderaadt } 342df930be7Sderaadt signal(SIGINT, SIG_DFL); 343c9899b11Skrw for (i = 0; environ[i] != NULL; i++) 344df930be7Sderaadt env[i] = environ[i]; 345df930be7Sderaadt makeenv(&env[i]); 346df930be7Sderaadt 347df930be7Sderaadt limit.rlim_max = RLIM_INFINITY; 348df930be7Sderaadt limit.rlim_cur = RLIM_INFINITY; 349df930be7Sderaadt (void)setrlimit(RLIMIT_CPU, &limit); 350c9899b11Skrw execle(LO, "login", "-p", "--", name, NULL, env); 351df930be7Sderaadt syslog(LOG_ERR, "%s: %m", LO); 352df930be7Sderaadt exit(1); 353df930be7Sderaadt } 354df930be7Sderaadt alarm(0); 355df930be7Sderaadt signal(SIGALRM, SIG_DFL); 356df930be7Sderaadt signal(SIGINT, SIG_IGN); 357df930be7Sderaadt if (NX && *NX) 358df930be7Sderaadt tname = NX; 359df930be7Sderaadt } 360df930be7Sderaadt } 361df930be7Sderaadt 362df930be7Sderaadt static int 3635b48e80aSderaadt getname(void) 364df930be7Sderaadt { 365cf0bd593Sderaadt unsigned char cs; 36652113b74Sderaadt int c, r; 36752113b74Sderaadt char *np; 368df930be7Sderaadt 369df930be7Sderaadt /* 370df930be7Sderaadt * Interrupt may happen if we use CBREAK mode 371df930be7Sderaadt */ 372df930be7Sderaadt signal(SIGINT, interrupt); 373df930be7Sderaadt setflags(1); 374df930be7Sderaadt prompt(); 375df930be7Sderaadt if (PF > 0) { 376df930be7Sderaadt oflush(); 377df930be7Sderaadt sleep(PF); 378df930be7Sderaadt PF = 0; 379df930be7Sderaadt } 380df69c215Sderaadt if (tcsetattr(0, TCSANOW, &tmode) == -1) { 381df930be7Sderaadt syslog(LOG_ERR, "%s: %m", ttyn); 382df930be7Sderaadt exit(1); 383df930be7Sderaadt } 384df930be7Sderaadt crmod = digit = lower = upper = 0; 385df930be7Sderaadt np = name; 386df930be7Sderaadt for (;;) { 387df930be7Sderaadt oflush(); 38852113b74Sderaadt r = read(STDIN_FILENO, &cs, 1); 38952113b74Sderaadt if (r <= 0) { 39052113b74Sderaadt if (r == -1 && errno == EINTR && interrupt_flag) { 39152113b74Sderaadt interrupt_flag = 0; 39252113b74Sderaadt return (0); 39352113b74Sderaadt } 394df930be7Sderaadt exit(0); 39552113b74Sderaadt } 396ba2216bdSderaadt /* Handle 'printables' we cannot erase */ 397ba2216bdSderaadt if (cs == CTRL('L') || cs == CTRL('K')) 398ba2216bdSderaadt continue; 399ba2216bdSderaadt if (cs == '\t') 400ba2216bdSderaadt cs = ' '; 401df930be7Sderaadt if ((c = cs&0177) == 0) 402df930be7Sderaadt return (0); 403cf0bd593Sderaadt 404df930be7Sderaadt if (c == EOT) 405df930be7Sderaadt exit(1); 4062b7dee8fSderaadt if (c == '\r' || c == '\n' || np >= name + sizeof name -1) { 407df930be7Sderaadt putf("\r\n"); 408df930be7Sderaadt break; 409df930be7Sderaadt } 410df930be7Sderaadt if (islower(c)) 411df930be7Sderaadt lower = 1; 412df930be7Sderaadt else if (isupper(c)) 413df930be7Sderaadt upper = 1; 41447625c84Sderaadt else if (c == ERASE || c == '\b') { 415df930be7Sderaadt if (np > name) { 416ba2216bdSderaadt if (*--np == '\033') 417ba2216bdSderaadt xputs("\b\b \b\b"); 418ba2216bdSderaadt else if (isprint(*np)) 41939235a5fSderaadt xputs("\b \b"); 420df930be7Sderaadt } 421df930be7Sderaadt continue; 42247625c84Sderaadt } else if (c == KILL) { 423df930be7Sderaadt putchr('\r'); 424ba2216bdSderaadt putf(LM); 425ba2216bdSderaadt while (np > name) { 426ba2216bdSderaadt if (*--np == '\033') 427ba2216bdSderaadt xputs(" "); 428ba2216bdSderaadt else if (isprint(*np)) 429ba2216bdSderaadt putchr(' '); 430ba2216bdSderaadt } 431ba2216bdSderaadt putchr('\r'); 432df930be7Sderaadt prompt(); 433df930be7Sderaadt np = name; 434df930be7Sderaadt continue; 435df930be7Sderaadt } else if (isdigit(c)) 436df930be7Sderaadt digit++; 437df930be7Sderaadt if (IG && (c <= ' ' || c > 0176)) 438df930be7Sderaadt continue; 439df930be7Sderaadt *np++ = c; 440979c5072Sderaadt if (c == '\033') { 441979c5072Sderaadt putchr('^'); 442979c5072Sderaadt putchr('['); 443979c5072Sderaadt } else 444df930be7Sderaadt putchr(cs); 445df930be7Sderaadt } 446df930be7Sderaadt signal(SIGINT, SIG_IGN); 44752113b74Sderaadt if (interrupt_flag) { 44852113b74Sderaadt interrupt_flag = 0; 44952113b74Sderaadt return (0); 45052113b74Sderaadt } 451df930be7Sderaadt *np = 0; 452df930be7Sderaadt if (c == '\r') 453df930be7Sderaadt crmod = 1; 45454eda240Stedu return (1); 455df930be7Sderaadt } 456df930be7Sderaadt 457df930be7Sderaadt static void 4585b48e80aSderaadt putpad(char *s) 459df930be7Sderaadt { 460a5553e71Sderaadt int pad = 0; 461df930be7Sderaadt speed_t ospeed = cfgetospeed(&tmode); 462df930be7Sderaadt 4634207a9b6Sderaadt if (isdigit((unsigned char)*s)) { 4644207a9b6Sderaadt while (isdigit((unsigned char)*s)) { 465df930be7Sderaadt pad *= 10; 466df930be7Sderaadt pad += *s++ - '0'; 467df930be7Sderaadt } 468df930be7Sderaadt pad *= 10; 4694207a9b6Sderaadt if (*s == '.' && isdigit((unsigned char)s[1])) { 470df930be7Sderaadt pad += s[1] - '0'; 471df930be7Sderaadt s += 2; 472df930be7Sderaadt } 473df930be7Sderaadt } 474df930be7Sderaadt 47539235a5fSderaadt xputs(s); 476df930be7Sderaadt /* 477df930be7Sderaadt * If no delay needed, or output speed is 478df930be7Sderaadt * not comprehensible, then don't try to delay. 479df930be7Sderaadt */ 480df930be7Sderaadt if (pad == 0 || ospeed <= 0) 481df930be7Sderaadt return; 482df930be7Sderaadt 483df930be7Sderaadt /* 484df930be7Sderaadt * Round up by a half a character frame, and then do the delay. 485df930be7Sderaadt * Too bad there are no user program accessible programmed delays. 486df930be7Sderaadt * Transmitting pad characters slows many terminals down and also 487df930be7Sderaadt * loads the system. 488df930be7Sderaadt */ 489df930be7Sderaadt pad = (pad * ospeed + 50000) / 100000; 490df930be7Sderaadt while (pad--) 491df930be7Sderaadt putchr(*PC); 492df930be7Sderaadt } 493df930be7Sderaadt 494df930be7Sderaadt static void 4955b48e80aSderaadt xputs(char *s) 496df930be7Sderaadt { 497df930be7Sderaadt while (*s) 498df930be7Sderaadt putchr(*s++); 499df930be7Sderaadt } 500df930be7Sderaadt 501df930be7Sderaadt char outbuf[OBUFSIZ]; 502df930be7Sderaadt int obufcnt = 0; 503df930be7Sderaadt 504df930be7Sderaadt static void 5055b48e80aSderaadt putchr(int cc) 506df930be7Sderaadt { 507df930be7Sderaadt char c; 508df930be7Sderaadt 509df930be7Sderaadt c = cc; 510df930be7Sderaadt if (!NP) { 511df930be7Sderaadt c |= partab[c&0177] & 0200; 512df930be7Sderaadt if (OP) 513df930be7Sderaadt c ^= 0200; 514df930be7Sderaadt } 515df930be7Sderaadt if (!UB) { 516df930be7Sderaadt outbuf[obufcnt++] = c; 517df930be7Sderaadt if (obufcnt >= OBUFSIZ) 518df930be7Sderaadt oflush(); 519df930be7Sderaadt } else 520df930be7Sderaadt write(STDOUT_FILENO, &c, 1); 521df930be7Sderaadt } 522df930be7Sderaadt 523df930be7Sderaadt static void 5245b48e80aSderaadt oflush(void) 525df930be7Sderaadt { 526df930be7Sderaadt if (obufcnt) 527df930be7Sderaadt write(STDOUT_FILENO, outbuf, obufcnt); 528df930be7Sderaadt obufcnt = 0; 529df930be7Sderaadt } 530df930be7Sderaadt 531df930be7Sderaadt static void 5325b48e80aSderaadt prompt(void) 533df930be7Sderaadt { 534df930be7Sderaadt 535df930be7Sderaadt putf(LM); 536df930be7Sderaadt if (CO) 537df930be7Sderaadt putchr('\n'); 538df930be7Sderaadt } 539df930be7Sderaadt 540df930be7Sderaadt static void 5415b48e80aSderaadt putf(char *cp) 542df930be7Sderaadt { 543df930be7Sderaadt char *slash, db[100]; 54452113b74Sderaadt time_t t; 545df930be7Sderaadt 546df930be7Sderaadt while (*cp) { 547df930be7Sderaadt if (*cp != '%') { 548df930be7Sderaadt putchr(*cp++); 549df930be7Sderaadt continue; 550df930be7Sderaadt } 551df930be7Sderaadt switch (*++cp) { 552df930be7Sderaadt 553df930be7Sderaadt case 't': 554df930be7Sderaadt slash = strrchr(ttyn, '/'); 555df930be7Sderaadt if (slash == (char *) 0) 55639235a5fSderaadt xputs(ttyn); 557df930be7Sderaadt else 55839235a5fSderaadt xputs(&slash[1]); 559df930be7Sderaadt break; 560df930be7Sderaadt 561df930be7Sderaadt case 'h': 56230d77a25Stedu xputs(globalhostname); 563df930be7Sderaadt break; 564df930be7Sderaadt 565df930be7Sderaadt case 'd': { 56673fe6daaSflorian struct tm *tm; 56773fe6daaSflorian time(&t); 56873fe6daaSflorian if ((tm = localtime(&t)) != NULL) 56973fe6daaSflorian if (strftime(db, sizeof(db), 57073fe6daaSflorian "%l:%M%p on %A, %d %B %Y", tm) != 0) 57139235a5fSderaadt xputs(db); 572df930be7Sderaadt break; 57352113b74Sderaadt } 574df930be7Sderaadt 575df930be7Sderaadt case 's': 57639235a5fSderaadt xputs(kerninfo.sysname); 577df930be7Sderaadt break; 578df930be7Sderaadt 579df930be7Sderaadt case 'm': 58039235a5fSderaadt xputs(kerninfo.machine); 581df930be7Sderaadt break; 582df930be7Sderaadt 583df930be7Sderaadt case 'r': 58439235a5fSderaadt xputs(kerninfo.release); 585df930be7Sderaadt break; 586df930be7Sderaadt 587df930be7Sderaadt case 'v': 58839235a5fSderaadt xputs(kerninfo.version); 589df930be7Sderaadt break; 590df930be7Sderaadt 591df930be7Sderaadt case '%': 592df930be7Sderaadt putchr('%'); 593df930be7Sderaadt break; 594df930be7Sderaadt } 595df930be7Sderaadt cp++; 596df930be7Sderaadt } 597df930be7Sderaadt } 598