1*a06e2ab3SBen Gras /* $NetBSD: main.c,v 1.59 2012/06/28 08:55:10 roy Exp $ */ 2*a06e2ab3SBen Gras 3*a06e2ab3SBen Gras /*- 4*a06e2ab3SBen Gras * Copyright (c) 1980, 1993 5*a06e2ab3SBen Gras * The Regents of the University of California. All rights reserved. 6*a06e2ab3SBen Gras * 7*a06e2ab3SBen Gras * Redistribution and use in source and binary forms, with or without 8*a06e2ab3SBen Gras * modification, are permitted provided that the following conditions 9*a06e2ab3SBen Gras * are met: 10*a06e2ab3SBen Gras * 1. Redistributions of source code must retain the above copyright 11*a06e2ab3SBen Gras * notice, this list of conditions and the following disclaimer. 12*a06e2ab3SBen Gras * 2. Redistributions in binary form must reproduce the above copyright 13*a06e2ab3SBen Gras * notice, this list of conditions and the following disclaimer in the 14*a06e2ab3SBen Gras * documentation and/or other materials provided with the distribution. 15*a06e2ab3SBen Gras * 3. Neither the name of the University nor the names of its contributors 16*a06e2ab3SBen Gras * may be used to endorse or promote products derived from this software 17*a06e2ab3SBen Gras * without specific prior written permission. 18*a06e2ab3SBen Gras * 19*a06e2ab3SBen Gras * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20*a06e2ab3SBen Gras * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21*a06e2ab3SBen Gras * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22*a06e2ab3SBen Gras * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23*a06e2ab3SBen Gras * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24*a06e2ab3SBen Gras * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25*a06e2ab3SBen Gras * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26*a06e2ab3SBen Gras * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27*a06e2ab3SBen Gras * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28*a06e2ab3SBen Gras * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29*a06e2ab3SBen Gras * SUCH DAMAGE. 30*a06e2ab3SBen Gras */ 31*a06e2ab3SBen Gras 32*a06e2ab3SBen Gras #include <sys/cdefs.h> 33*a06e2ab3SBen Gras 34*a06e2ab3SBen Gras #ifndef lint 35*a06e2ab3SBen Gras __COPYRIGHT("@(#) Copyright (c) 1980, 1993\ 36*a06e2ab3SBen Gras The Regents of the University of California. All rights reserved."); 37*a06e2ab3SBen Gras #endif /* not lint */ 38*a06e2ab3SBen Gras 39*a06e2ab3SBen Gras #ifndef lint 40*a06e2ab3SBen Gras #if 0 41*a06e2ab3SBen Gras static char sccsid[] = "from: @(#)main.c 8.1 (Berkeley) 6/20/93"; 42*a06e2ab3SBen Gras #else 43*a06e2ab3SBen Gras __RCSID("$NetBSD: main.c,v 1.59 2012/06/28 08:55:10 roy Exp $"); 44*a06e2ab3SBen Gras #endif 45*a06e2ab3SBen Gras #endif /* not lint */ 46*a06e2ab3SBen Gras 47*a06e2ab3SBen Gras #include <sys/param.h> 48*a06e2ab3SBen Gras #include <sys/stat.h> 49*a06e2ab3SBen Gras #include <termios.h> 50*a06e2ab3SBen Gras #include <sys/ioctl.h> 51*a06e2ab3SBen Gras #include <sys/resource.h> 52*a06e2ab3SBen Gras #include <sys/utsname.h> 53*a06e2ab3SBen Gras 54*a06e2ab3SBen Gras #include <ctype.h> 55*a06e2ab3SBen Gras #include <errno.h> 56*a06e2ab3SBen Gras #include <fcntl.h> 57*a06e2ab3SBen Gras #include <limits.h> 58*a06e2ab3SBen Gras #include <pwd.h> 59*a06e2ab3SBen Gras #include <setjmp.h> 60*a06e2ab3SBen Gras #include <signal.h> 61*a06e2ab3SBen Gras #include <stdlib.h> 62*a06e2ab3SBen Gras #include <string.h> 63*a06e2ab3SBen Gras #include <syslog.h> 64*a06e2ab3SBen Gras #include <term.h> 65*a06e2ab3SBen Gras #include <time.h> 66*a06e2ab3SBen Gras #include <ttyent.h> 67*a06e2ab3SBen Gras #include <unistd.h> 68*a06e2ab3SBen Gras #include <util.h> 69*a06e2ab3SBen Gras 70*a06e2ab3SBen Gras #include "gettytab.h" 71*a06e2ab3SBen Gras #include "pathnames.h" 72*a06e2ab3SBen Gras #include "extern.h" 73*a06e2ab3SBen Gras 74*a06e2ab3SBen Gras extern char editedhost[]; 75*a06e2ab3SBen Gras 76*a06e2ab3SBen Gras /* 77*a06e2ab3SBen Gras * Set the amount of running time that getty should accumulate 78*a06e2ab3SBen Gras * before deciding that something is wrong and exit. 79*a06e2ab3SBen Gras */ 80*a06e2ab3SBen Gras #define GETTY_TIMEOUT 60 /* seconds */ 81*a06e2ab3SBen Gras 82*a06e2ab3SBen Gras /* defines for auto detection of incoming PPP calls (->PAP/CHAP) */ 83*a06e2ab3SBen Gras 84*a06e2ab3SBen Gras #define PPP_FRAME 0x7e /* PPP Framing character */ 85*a06e2ab3SBen Gras #define PPP_STATION 0xff /* "All Station" character */ 86*a06e2ab3SBen Gras #define PPP_ESCAPE 0x7d /* Escape Character */ 87*a06e2ab3SBen Gras #define PPP_CONTROL 0x03 /* PPP Control Field */ 88*a06e2ab3SBen Gras #define PPP_CONTROL_ESCAPED 0x23 /* PPP Control Field, escaped */ 89*a06e2ab3SBen Gras #define PPP_LCP_HI 0xc0 /* LCP protocol - high byte */ 90*a06e2ab3SBen Gras #define PPP_LCP_LOW 0x21 /* LCP protocol - low byte */ 91*a06e2ab3SBen Gras 92*a06e2ab3SBen Gras struct termios tmode, omode; 93*a06e2ab3SBen Gras 94*a06e2ab3SBen Gras int crmod, digit_or_punc, lower, upper; 95*a06e2ab3SBen Gras 96*a06e2ab3SBen Gras char hostname[MAXHOSTNAMELEN + 1]; 97*a06e2ab3SBen Gras struct utsname kerninfo; 98*a06e2ab3SBen Gras char name[LOGIN_NAME_MAX]; 99*a06e2ab3SBen Gras char dev[] = _PATH_DEV; 100*a06e2ab3SBen Gras char ttyn[32]; 101*a06e2ab3SBen Gras char lockfile[512]; 102*a06e2ab3SBen Gras uid_t ttyowner; 103*a06e2ab3SBen Gras char *rawttyn; 104*a06e2ab3SBen Gras 105*a06e2ab3SBen Gras #define OBUFSIZ 128 106*a06e2ab3SBen Gras #define TABBUFSIZ 512 107*a06e2ab3SBen Gras 108*a06e2ab3SBen Gras char defent[TABBUFSIZ]; 109*a06e2ab3SBen Gras char tabent[TABBUFSIZ]; 110*a06e2ab3SBen Gras 111*a06e2ab3SBen Gras char *env[128]; 112*a06e2ab3SBen Gras 113*a06e2ab3SBen Gras const unsigned char partab[] = { 114*a06e2ab3SBen Gras 0001,0201,0201,0001,0201,0001,0001,0201, 115*a06e2ab3SBen Gras 0202,0004,0003,0205,0005,0206,0201,0001, 116*a06e2ab3SBen Gras 0201,0001,0001,0201,0001,0201,0201,0001, 117*a06e2ab3SBen Gras 0001,0201,0201,0001,0201,0001,0001,0201, 118*a06e2ab3SBen Gras 0200,0000,0000,0200,0000,0200,0200,0000, 119*a06e2ab3SBen Gras 0000,0200,0200,0000,0200,0000,0000,0200, 120*a06e2ab3SBen Gras 0000,0200,0200,0000,0200,0000,0000,0200, 121*a06e2ab3SBen Gras 0200,0000,0000,0200,0000,0200,0200,0000, 122*a06e2ab3SBen Gras 0200,0000,0000,0200,0000,0200,0200,0000, 123*a06e2ab3SBen Gras 0000,0200,0200,0000,0200,0000,0000,0200, 124*a06e2ab3SBen Gras 0000,0200,0200,0000,0200,0000,0000,0200, 125*a06e2ab3SBen Gras 0200,0000,0000,0200,0000,0200,0200,0000, 126*a06e2ab3SBen Gras 0000,0200,0200,0000,0200,0000,0000,0200, 127*a06e2ab3SBen Gras 0200,0000,0000,0200,0000,0200,0200,0000, 128*a06e2ab3SBen Gras 0200,0000,0000,0200,0000,0200,0200,0000, 129*a06e2ab3SBen Gras 0000,0200,0200,0000,0200,0000,0000,0201 130*a06e2ab3SBen Gras }; 131*a06e2ab3SBen Gras 132*a06e2ab3SBen Gras #define ERASE tmode.c_cc[VERASE] 133*a06e2ab3SBen Gras #define KILL tmode.c_cc[VKILL] 134*a06e2ab3SBen Gras #define EOT tmode.c_cc[VEOF] 135*a06e2ab3SBen Gras 136*a06e2ab3SBen Gras static void clearscreen(void); 137*a06e2ab3SBen Gras 138*a06e2ab3SBen Gras jmp_buf timeout; 139*a06e2ab3SBen Gras 140*a06e2ab3SBen Gras static void 141*a06e2ab3SBen Gras /*ARGSUSED*/ 142*a06e2ab3SBen Gras dingdong(int signo) 143*a06e2ab3SBen Gras { 144*a06e2ab3SBen Gras 145*a06e2ab3SBen Gras (void)alarm(0); 146*a06e2ab3SBen Gras (void)signal(SIGALRM, SIG_DFL); 147*a06e2ab3SBen Gras longjmp(timeout, 1); 148*a06e2ab3SBen Gras } 149*a06e2ab3SBen Gras 150*a06e2ab3SBen Gras jmp_buf intrupt; 151*a06e2ab3SBen Gras 152*a06e2ab3SBen Gras static void 153*a06e2ab3SBen Gras /*ARGSUSED*/ 154*a06e2ab3SBen Gras interrupt(int signo) 155*a06e2ab3SBen Gras { 156*a06e2ab3SBen Gras 157*a06e2ab3SBen Gras (void)signal(SIGINT, interrupt); 158*a06e2ab3SBen Gras longjmp(intrupt, 1); 159*a06e2ab3SBen Gras } 160*a06e2ab3SBen Gras 161*a06e2ab3SBen Gras #ifndef __minix 162*a06e2ab3SBen Gras /* 163*a06e2ab3SBen Gras * Action to take when getty is running too long. 164*a06e2ab3SBen Gras */ 165*a06e2ab3SBen Gras static void 166*a06e2ab3SBen Gras /*ARGSUSED*/ 167*a06e2ab3SBen Gras timeoverrun(int signo) 168*a06e2ab3SBen Gras { 169*a06e2ab3SBen Gras 170*a06e2ab3SBen Gras syslog(LOG_ERR, "getty exiting due to excessive running time"); 171*a06e2ab3SBen Gras exit(1); 172*a06e2ab3SBen Gras } 173*a06e2ab3SBen Gras #endif 174*a06e2ab3SBen Gras 175*a06e2ab3SBen Gras static int getname(void); 176*a06e2ab3SBen Gras static void oflush(void); 177*a06e2ab3SBen Gras static void prompt(void); 178*a06e2ab3SBen Gras static int putchr(int); 179*a06e2ab3SBen Gras static void putf(const char *); 180*a06e2ab3SBen Gras static void xputs(const char *); 181*a06e2ab3SBen Gras 182*a06e2ab3SBen Gras #define putpad(s) tputs(s, 1, putchr) 183*a06e2ab3SBen Gras 184*a06e2ab3SBen Gras int 185*a06e2ab3SBen Gras main(int argc, char *argv[], char *envp[]) 186*a06e2ab3SBen Gras { 187*a06e2ab3SBen Gras const char *progname; 188*a06e2ab3SBen Gras char *tname; 189*a06e2ab3SBen Gras int repcnt = 0, failopenlogged = 0, uugetty = 0, first_time = 1; 190*a06e2ab3SBen Gras struct rlimit limit; 191*a06e2ab3SBen Gras struct passwd *pw; 192*a06e2ab3SBen Gras int rval; 193*a06e2ab3SBen Gras 194*a06e2ab3SBen Gras (void)signal(SIGINT, SIG_IGN); 195*a06e2ab3SBen Gras openlog("getty", LOG_PID, LOG_AUTH); 196*a06e2ab3SBen Gras (void)gethostname(hostname, sizeof(hostname)); 197*a06e2ab3SBen Gras hostname[sizeof(hostname) - 1] = '\0'; 198*a06e2ab3SBen Gras if (hostname[0] == '\0') 199*a06e2ab3SBen Gras (void)strlcpy(hostname, "Amnesiac", sizeof(hostname)); 200*a06e2ab3SBen Gras (void)uname(&kerninfo); 201*a06e2ab3SBen Gras 202*a06e2ab3SBen Gras progname = getprogname(); 203*a06e2ab3SBen Gras if (progname[0] == 'u' && progname[1] == 'u') 204*a06e2ab3SBen Gras uugetty = 1; 205*a06e2ab3SBen Gras 206*a06e2ab3SBen Gras /* 207*a06e2ab3SBen Gras * Find id of uucp login (if present) so we can chown tty properly. 208*a06e2ab3SBen Gras */ 209*a06e2ab3SBen Gras if (uugetty && (pw = getpwnam("uucp"))) 210*a06e2ab3SBen Gras ttyowner = pw->pw_uid; 211*a06e2ab3SBen Gras else 212*a06e2ab3SBen Gras ttyowner = 0; 213*a06e2ab3SBen Gras 214*a06e2ab3SBen Gras /* 215*a06e2ab3SBen Gras * Limit running time to deal with broken or dead lines. 216*a06e2ab3SBen Gras */ 217*a06e2ab3SBen Gras #ifndef __minix 218*a06e2ab3SBen Gras (void)signal(SIGXCPU, timeoverrun); 219*a06e2ab3SBen Gras limit.rlim_max = RLIM_INFINITY; 220*a06e2ab3SBen Gras limit.rlim_cur = GETTY_TIMEOUT; 221*a06e2ab3SBen Gras (void)setrlimit(RLIMIT_CPU, &limit); 222*a06e2ab3SBen Gras #endif 223*a06e2ab3SBen Gras 224*a06e2ab3SBen Gras /* 225*a06e2ab3SBen Gras * The following is a work around for vhangup interactions 226*a06e2ab3SBen Gras * which cause great problems getting window systems started. 227*a06e2ab3SBen Gras * If the tty line is "-", we do the old style getty presuming 228*a06e2ab3SBen Gras * that the file descriptors are already set up for us. 229*a06e2ab3SBen Gras * J. Gettys - MIT Project Athena. 230*a06e2ab3SBen Gras */ 231*a06e2ab3SBen Gras if (argc <= 2 || strcmp(argv[2], "-") == 0) { 232*a06e2ab3SBen Gras (void)strlcpy(ttyn, ttyname(0), sizeof(ttyn)); 233*a06e2ab3SBen Gras } 234*a06e2ab3SBen Gras else { 235*a06e2ab3SBen Gras int i; 236*a06e2ab3SBen Gras 237*a06e2ab3SBen Gras rawttyn = argv[2]; 238*a06e2ab3SBen Gras (void)strlcpy(ttyn, dev, sizeof(ttyn)); 239*a06e2ab3SBen Gras (void)strlcat(ttyn, argv[2], sizeof(ttyn)); 240*a06e2ab3SBen Gras if (uugetty) { 241*a06e2ab3SBen Gras (void)chown(ttyn, ttyowner, 0); 242*a06e2ab3SBen Gras (void)strlcpy(lockfile, _PATH_LOCK, 243*a06e2ab3SBen Gras sizeof(lockfile)); 244*a06e2ab3SBen Gras (void)strlcat(lockfile, argv[2], 245*a06e2ab3SBen Gras sizeof(lockfile)); 246*a06e2ab3SBen Gras /* 247*a06e2ab3SBen Gras * wait for lockfiles to go away before we try 248*a06e2ab3SBen Gras * to open 249*a06e2ab3SBen Gras */ 250*a06e2ab3SBen Gras if (pidlock(lockfile, 0, 0, 0) != 0) { 251*a06e2ab3SBen Gras syslog(LOG_ERR, 252*a06e2ab3SBen Gras "%s: can't create lockfile", ttyn); 253*a06e2ab3SBen Gras exit(1); 254*a06e2ab3SBen Gras } 255*a06e2ab3SBen Gras (void)unlink(lockfile); 256*a06e2ab3SBen Gras } 257*a06e2ab3SBen Gras if (strcmp(argv[0], "+") != 0) { 258*a06e2ab3SBen Gras (void)chown(ttyn, ttyowner, 0); 259*a06e2ab3SBen Gras (void)chmod(ttyn, 0600); 260*a06e2ab3SBen Gras #ifndef __minix 261*a06e2ab3SBen Gras (void)revoke(ttyn); 262*a06e2ab3SBen Gras #endif 263*a06e2ab3SBen Gras if (ttyaction(ttyn, "getty", "root")) 264*a06e2ab3SBen Gras syslog(LOG_WARNING, "%s: ttyaction failed", 265*a06e2ab3SBen Gras ttyn); 266*a06e2ab3SBen Gras /* 267*a06e2ab3SBen Gras * Delay the open so DTR stays down long enough 268*a06e2ab3SBen Gras * to be detected. 269*a06e2ab3SBen Gras */ 270*a06e2ab3SBen Gras (void)sleep(2); 271*a06e2ab3SBen Gras while ((i = open(ttyn, O_RDWR)) == -1) { 272*a06e2ab3SBen Gras if ((repcnt % 10 == 0) && 273*a06e2ab3SBen Gras (errno != ENXIO || !failopenlogged)) { 274*a06e2ab3SBen Gras syslog(LOG_WARNING, "%s: %m", ttyn); 275*a06e2ab3SBen Gras closelog(); 276*a06e2ab3SBen Gras failopenlogged = 1; 277*a06e2ab3SBen Gras } 278*a06e2ab3SBen Gras repcnt++; 279*a06e2ab3SBen Gras (void)sleep(60); 280*a06e2ab3SBen Gras } 281*a06e2ab3SBen Gras if (uugetty && pidlock(lockfile, 0, 0, 0) != 0) { 282*a06e2ab3SBen Gras syslog(LOG_ERR, "%s: can't create lockfile", 283*a06e2ab3SBen Gras ttyn); 284*a06e2ab3SBen Gras exit(1); 285*a06e2ab3SBen Gras } 286*a06e2ab3SBen Gras if (uugetty) 287*a06e2ab3SBen Gras (void)chown(lockfile, ttyowner, 0); 288*a06e2ab3SBen Gras (void)login_tty(i); 289*a06e2ab3SBen Gras } 290*a06e2ab3SBen Gras } 291*a06e2ab3SBen Gras 292*a06e2ab3SBen Gras /* Start with default tty settings */ 293*a06e2ab3SBen Gras if (tcgetattr(0, &tmode) < 0) { 294*a06e2ab3SBen Gras syslog(LOG_ERR, "%s: %m", ttyn); 295*a06e2ab3SBen Gras exit(1); 296*a06e2ab3SBen Gras } 297*a06e2ab3SBen Gras omode = tmode; 298*a06e2ab3SBen Gras 299*a06e2ab3SBen Gras gettable("default", defent); 300*a06e2ab3SBen Gras gendefaults(); 301*a06e2ab3SBen Gras tname = "default"; 302*a06e2ab3SBen Gras if (argc > 1) 303*a06e2ab3SBen Gras tname = argv[1]; 304*a06e2ab3SBen Gras for (;;) { 305*a06e2ab3SBen Gras int off; 306*a06e2ab3SBen Gras 307*a06e2ab3SBen Gras rval = 0; 308*a06e2ab3SBen Gras gettable(tname, tabent); 309*a06e2ab3SBen Gras if (OPset || EPset || APset) 310*a06e2ab3SBen Gras APset++, OPset++, EPset++; 311*a06e2ab3SBen Gras setdefaults(); 312*a06e2ab3SBen Gras off = 0; 313*a06e2ab3SBen Gras (void)tcflush(0, TCIOFLUSH); /* clear out the crap */ 314*a06e2ab3SBen Gras #ifndef __minix 315*a06e2ab3SBen Gras (void)ioctl(0, FIONBIO, &off); /* turn off non-blocking mode */ 316*a06e2ab3SBen Gras (void)ioctl(0, FIOASYNC, &off); /* ditto for async mode */ 317*a06e2ab3SBen Gras #endif 318*a06e2ab3SBen Gras 319*a06e2ab3SBen Gras if (IS) 320*a06e2ab3SBen Gras (void)cfsetispeed(&tmode, (speed_t)IS); 321*a06e2ab3SBen Gras else if (SP) 322*a06e2ab3SBen Gras (void)cfsetispeed(&tmode, (speed_t)SP); 323*a06e2ab3SBen Gras if (OS) 324*a06e2ab3SBen Gras (void)cfsetospeed(&tmode, (speed_t)OS); 325*a06e2ab3SBen Gras else if (SP) 326*a06e2ab3SBen Gras (void)cfsetospeed(&tmode, (speed_t)SP); 327*a06e2ab3SBen Gras setflags(0); 328*a06e2ab3SBen Gras setchars(); 329*a06e2ab3SBen Gras if (tcsetattr(0, TCSANOW, &tmode) < 0) { 330*a06e2ab3SBen Gras syslog(LOG_ERR, "%s: %m", ttyn); 331*a06e2ab3SBen Gras exit(1); 332*a06e2ab3SBen Gras } 333*a06e2ab3SBen Gras if (AB) { 334*a06e2ab3SBen Gras tname = autobaud(); 335*a06e2ab3SBen Gras continue; 336*a06e2ab3SBen Gras } 337*a06e2ab3SBen Gras if (PS) { 338*a06e2ab3SBen Gras tname = portselector(); 339*a06e2ab3SBen Gras continue; 340*a06e2ab3SBen Gras } 341*a06e2ab3SBen Gras if (CS) 342*a06e2ab3SBen Gras clearscreen(); 343*a06e2ab3SBen Gras if (CL && *CL) 344*a06e2ab3SBen Gras putpad(CL); 345*a06e2ab3SBen Gras edithost(HE); 346*a06e2ab3SBen Gras 347*a06e2ab3SBen Gras /* 348*a06e2ab3SBen Gras * If this is the first time through this, and an 349*a06e2ab3SBen Gras * issue file has been given, then send it. 350*a06e2ab3SBen Gras */ 351*a06e2ab3SBen Gras if (first_time != 0 && IF != NULL) { 352*a06e2ab3SBen Gras char buf[_POSIX2_LINE_MAX]; 353*a06e2ab3SBen Gras FILE *fp; 354*a06e2ab3SBen Gras 355*a06e2ab3SBen Gras if ((fp = fopen(IF, "r")) != NULL) { 356*a06e2ab3SBen Gras while (fgets(buf, sizeof(buf) - 1, fp) != NULL) 357*a06e2ab3SBen Gras putf(buf); 358*a06e2ab3SBen Gras (void)fclose(fp); 359*a06e2ab3SBen Gras } 360*a06e2ab3SBen Gras } 361*a06e2ab3SBen Gras first_time = 0; 362*a06e2ab3SBen Gras 363*a06e2ab3SBen Gras if (IM && *IM) 364*a06e2ab3SBen Gras putf(IM); 365*a06e2ab3SBen Gras oflush(); 366*a06e2ab3SBen Gras if (setjmp(timeout)) { 367*a06e2ab3SBen Gras tmode.c_ispeed = tmode.c_ospeed = 0; 368*a06e2ab3SBen Gras (void)tcsetattr(0, TCSANOW, &tmode); 369*a06e2ab3SBen Gras exit(1); 370*a06e2ab3SBen Gras } 371*a06e2ab3SBen Gras if (TO) { 372*a06e2ab3SBen Gras (void)signal(SIGALRM, dingdong); 373*a06e2ab3SBen Gras (void)alarm((unsigned int)TO); 374*a06e2ab3SBen Gras } 375*a06e2ab3SBen Gras if (NN) { 376*a06e2ab3SBen Gras name[0] = '\0'; 377*a06e2ab3SBen Gras lower = 1; 378*a06e2ab3SBen Gras upper = digit_or_punc = 0; 379*a06e2ab3SBen Gras } else if (AL) { 380*a06e2ab3SBen Gras const char *p = AL; 381*a06e2ab3SBen Gras char *q = name; 382*a06e2ab3SBen Gras 383*a06e2ab3SBen Gras while (*p && q < &name[sizeof name - 1]) { 384*a06e2ab3SBen Gras if (isupper((unsigned char)*p)) 385*a06e2ab3SBen Gras upper = 1; 386*a06e2ab3SBen Gras else if (islower((unsigned char)*p)) 387*a06e2ab3SBen Gras lower = 1; 388*a06e2ab3SBen Gras else if (isdigit((unsigned char)*p)) 389*a06e2ab3SBen Gras digit_or_punc = 1; 390*a06e2ab3SBen Gras *q++ = *p++; 391*a06e2ab3SBen Gras } 392*a06e2ab3SBen Gras } else if ((rval = getname()) == 2) { 393*a06e2ab3SBen Gras setflags(2); 394*a06e2ab3SBen Gras (void)execle(PP, "ppplogin", ttyn, (char *) 0, env); 395*a06e2ab3SBen Gras syslog(LOG_ERR, "%s: %m", PP); 396*a06e2ab3SBen Gras exit(1); 397*a06e2ab3SBen Gras } 398*a06e2ab3SBen Gras 399*a06e2ab3SBen Gras if (rval || AL || NN) { 400*a06e2ab3SBen Gras int i; 401*a06e2ab3SBen Gras 402*a06e2ab3SBen Gras oflush(); 403*a06e2ab3SBen Gras (void)alarm(0); 404*a06e2ab3SBen Gras (void)signal(SIGALRM, SIG_DFL); 405*a06e2ab3SBen Gras if (name[0] == '-') { 406*a06e2ab3SBen Gras xputs("user names may not start with '-'."); 407*a06e2ab3SBen Gras continue; 408*a06e2ab3SBen Gras } 409*a06e2ab3SBen Gras if (!(upper || lower || digit_or_punc)) 410*a06e2ab3SBen Gras continue; 411*a06e2ab3SBen Gras setflags(2); 412*a06e2ab3SBen Gras if (crmod) { 413*a06e2ab3SBen Gras tmode.c_iflag |= ICRNL; 414*a06e2ab3SBen Gras tmode.c_oflag |= ONLCR; 415*a06e2ab3SBen Gras } 416*a06e2ab3SBen Gras #if XXX 417*a06e2ab3SBen Gras if (upper || UC) 418*a06e2ab3SBen Gras tmode.sg_flags |= LCASE; 419*a06e2ab3SBen Gras if (lower || LC) 420*a06e2ab3SBen Gras tmode.sg_flags &= ~LCASE; 421*a06e2ab3SBen Gras #endif 422*a06e2ab3SBen Gras if (tcsetattr(0, TCSANOW, &tmode) < 0) { 423*a06e2ab3SBen Gras syslog(LOG_ERR, "%s: %m", ttyn); 424*a06e2ab3SBen Gras exit(1); 425*a06e2ab3SBen Gras } 426*a06e2ab3SBen Gras (void)signal(SIGINT, SIG_DFL); 427*a06e2ab3SBen Gras for (i = 0; envp[i] != NULL; i++) 428*a06e2ab3SBen Gras env[i] = envp[i]; 429*a06e2ab3SBen Gras makeenv(&env[i]); 430*a06e2ab3SBen Gras 431*a06e2ab3SBen Gras limit.rlim_max = RLIM_INFINITY; 432*a06e2ab3SBen Gras limit.rlim_cur = RLIM_INFINITY; 433*a06e2ab3SBen Gras #ifndef __minix 434*a06e2ab3SBen Gras (void)setrlimit(RLIMIT_CPU, &limit); 435*a06e2ab3SBen Gras #endif 436*a06e2ab3SBen Gras if (NN) 437*a06e2ab3SBen Gras (void)execle(LO, "login", AL ? "-fp" : "-p", 438*a06e2ab3SBen Gras NULL, env); 439*a06e2ab3SBen Gras else 440*a06e2ab3SBen Gras (void)execle(LO, "login", AL ? "-fp" : "-p", 441*a06e2ab3SBen Gras "--", name, NULL, env); 442*a06e2ab3SBen Gras syslog(LOG_ERR, "%s: %m", LO); 443*a06e2ab3SBen Gras exit(1); 444*a06e2ab3SBen Gras } 445*a06e2ab3SBen Gras (void)alarm(0); 446*a06e2ab3SBen Gras (void)signal(SIGALRM, SIG_DFL); 447*a06e2ab3SBen Gras (void)signal(SIGINT, SIG_IGN); 448*a06e2ab3SBen Gras if (NX && *NX) 449*a06e2ab3SBen Gras tname = NX; 450*a06e2ab3SBen Gras if (uugetty) 451*a06e2ab3SBen Gras (void)unlink(lockfile); 452*a06e2ab3SBen Gras } 453*a06e2ab3SBen Gras } 454*a06e2ab3SBen Gras 455*a06e2ab3SBen Gras static int 456*a06e2ab3SBen Gras getname(void) 457*a06e2ab3SBen Gras { 458*a06e2ab3SBen Gras int c; 459*a06e2ab3SBen Gras char *np; 460*a06e2ab3SBen Gras unsigned char cs; 461*a06e2ab3SBen Gras int ppp_state, ppp_connection; 462*a06e2ab3SBen Gras 463*a06e2ab3SBen Gras /* 464*a06e2ab3SBen Gras * Interrupt may happen if we use CBREAK mode 465*a06e2ab3SBen Gras */ 466*a06e2ab3SBen Gras if (setjmp(intrupt)) { 467*a06e2ab3SBen Gras (void)signal(SIGINT, SIG_IGN); 468*a06e2ab3SBen Gras return (0); 469*a06e2ab3SBen Gras } 470*a06e2ab3SBen Gras (void)signal(SIGINT, interrupt); 471*a06e2ab3SBen Gras setflags(1); 472*a06e2ab3SBen Gras prompt(); 473*a06e2ab3SBen Gras if (PF > 0) { 474*a06e2ab3SBen Gras oflush(); 475*a06e2ab3SBen Gras (void)sleep((unsigned int)PF); 476*a06e2ab3SBen Gras PF = 0; 477*a06e2ab3SBen Gras } 478*a06e2ab3SBen Gras if (tcsetattr(0, TCSANOW, &tmode) < 0) { 479*a06e2ab3SBen Gras syslog(LOG_ERR, "%s: %m", ttyn); 480*a06e2ab3SBen Gras exit(1); 481*a06e2ab3SBen Gras } 482*a06e2ab3SBen Gras crmod = digit_or_punc = lower = upper = 0; 483*a06e2ab3SBen Gras ppp_state = ppp_connection = 0; 484*a06e2ab3SBen Gras np = name; 485*a06e2ab3SBen Gras for (;;) { 486*a06e2ab3SBen Gras oflush(); 487*a06e2ab3SBen Gras if (read(STDIN_FILENO, &cs, 1) <= 0) 488*a06e2ab3SBen Gras exit(0); 489*a06e2ab3SBen Gras if ((c = cs&0177) == 0) 490*a06e2ab3SBen Gras return (0); 491*a06e2ab3SBen Gras 492*a06e2ab3SBen Gras /* 493*a06e2ab3SBen Gras * PPP detection state machine.. 494*a06e2ab3SBen Gras * Look for sequences: 495*a06e2ab3SBen Gras * PPP_FRAME, PPP_STATION, PPP_ESCAPE, PPP_CONTROL_ESCAPED or 496*a06e2ab3SBen Gras * PPP_FRAME, PPP_STATION, PPP_CONTROL (deviant from RFC) 497*a06e2ab3SBen Gras * See RFC1662. 498*a06e2ab3SBen Gras * Derived from code from Michael Hancock <michaelh@cet.co.jp> 499*a06e2ab3SBen Gras * and Erik 'PPP' Olson <eriko@wrq.com> 500*a06e2ab3SBen Gras */ 501*a06e2ab3SBen Gras if (PP && cs == PPP_FRAME) { 502*a06e2ab3SBen Gras ppp_state = 1; 503*a06e2ab3SBen Gras } else if (ppp_state == 1 && cs == PPP_STATION) { 504*a06e2ab3SBen Gras ppp_state = 2; 505*a06e2ab3SBen Gras } else if (ppp_state == 2 && cs == PPP_ESCAPE) { 506*a06e2ab3SBen Gras ppp_state = 3; 507*a06e2ab3SBen Gras } else if ((ppp_state == 2 && cs == PPP_CONTROL) || 508*a06e2ab3SBen Gras (ppp_state == 3 && cs == PPP_CONTROL_ESCAPED)) { 509*a06e2ab3SBen Gras ppp_state = 4; 510*a06e2ab3SBen Gras } else if (ppp_state == 4 && cs == PPP_LCP_HI) { 511*a06e2ab3SBen Gras ppp_state = 5; 512*a06e2ab3SBen Gras } else if (ppp_state == 5 && cs == PPP_LCP_LOW) { 513*a06e2ab3SBen Gras ppp_connection = 1; 514*a06e2ab3SBen Gras break; 515*a06e2ab3SBen Gras } else { 516*a06e2ab3SBen Gras ppp_state = 0; 517*a06e2ab3SBen Gras } 518*a06e2ab3SBen Gras 519*a06e2ab3SBen Gras if (c == EOT) 520*a06e2ab3SBen Gras exit(1); 521*a06e2ab3SBen Gras if (c == '\r' || c == '\n' || 522*a06e2ab3SBen Gras np >= &name[LOGIN_NAME_MAX - 1]) { 523*a06e2ab3SBen Gras *np = '\0'; 524*a06e2ab3SBen Gras putf("\r\n"); 525*a06e2ab3SBen Gras break; 526*a06e2ab3SBen Gras } 527*a06e2ab3SBen Gras if (islower(c)) 528*a06e2ab3SBen Gras lower = 1; 529*a06e2ab3SBen Gras else if (isupper(c)) 530*a06e2ab3SBen Gras upper = 1; 531*a06e2ab3SBen Gras else if (c == ERASE || c == '#' || c == '\b') { 532*a06e2ab3SBen Gras if (np > name) { 533*a06e2ab3SBen Gras np--; 534*a06e2ab3SBen Gras if (cfgetospeed(&tmode) >= 1200) 535*a06e2ab3SBen Gras xputs("\b \b"); 536*a06e2ab3SBen Gras else 537*a06e2ab3SBen Gras putchr(cs); 538*a06e2ab3SBen Gras } 539*a06e2ab3SBen Gras continue; 540*a06e2ab3SBen Gras } else if (c == KILL || c == '@') { 541*a06e2ab3SBen Gras putchr(cs); 542*a06e2ab3SBen Gras putchr('\r'); 543*a06e2ab3SBen Gras if (cfgetospeed(&tmode) < 1200) 544*a06e2ab3SBen Gras putchr('\n'); 545*a06e2ab3SBen Gras /* this is the way they do it down under ... */ 546*a06e2ab3SBen Gras else if (np > name) 547*a06e2ab3SBen Gras xputs( 548*a06e2ab3SBen Gras " \r"); 549*a06e2ab3SBen Gras prompt(); 550*a06e2ab3SBen Gras np = name; 551*a06e2ab3SBen Gras continue; 552*a06e2ab3SBen Gras } else if (isdigit(c) || c == '_') 553*a06e2ab3SBen Gras digit_or_punc = 1; 554*a06e2ab3SBen Gras if (IG && (c <= ' ' || c > 0176)) 555*a06e2ab3SBen Gras continue; 556*a06e2ab3SBen Gras *np++ = c; 557*a06e2ab3SBen Gras putchr(cs); 558*a06e2ab3SBen Gras 559*a06e2ab3SBen Gras /* 560*a06e2ab3SBen Gras * An MS-Windows direct connect PPP "client" won't send its 561*a06e2ab3SBen Gras * first PPP packet until we respond to its "CLIENT" poll 562*a06e2ab3SBen Gras * with a CRLF sequence. We cater to yet another broken 563*a06e2ab3SBen Gras * implementation of a previously-standard protocol... 564*a06e2ab3SBen Gras */ 565*a06e2ab3SBen Gras *np = '\0'; 566*a06e2ab3SBen Gras if (strstr(name, "CLIENT")) 567*a06e2ab3SBen Gras putf("\r\n"); 568*a06e2ab3SBen Gras } 569*a06e2ab3SBen Gras (void)signal(SIGINT, SIG_IGN); 570*a06e2ab3SBen Gras *np = 0; 571*a06e2ab3SBen Gras if (c == '\r') 572*a06e2ab3SBen Gras crmod = 1; 573*a06e2ab3SBen Gras if ((upper && !lower && !LC) || UC) 574*a06e2ab3SBen Gras for (np = name; *np; np++) 575*a06e2ab3SBen Gras *np = tolower((unsigned char)*np); 576*a06e2ab3SBen Gras return (1 + ppp_connection); 577*a06e2ab3SBen Gras } 578*a06e2ab3SBen Gras 579*a06e2ab3SBen Gras static void 580*a06e2ab3SBen Gras xputs(const char *s) 581*a06e2ab3SBen Gras { 582*a06e2ab3SBen Gras while (*s) 583*a06e2ab3SBen Gras putchr(*s++); 584*a06e2ab3SBen Gras } 585*a06e2ab3SBen Gras 586*a06e2ab3SBen Gras char outbuf[OBUFSIZ]; 587*a06e2ab3SBen Gras size_t obufcnt = 0; 588*a06e2ab3SBen Gras 589*a06e2ab3SBen Gras static int 590*a06e2ab3SBen Gras putchr(int cc) 591*a06e2ab3SBen Gras { 592*a06e2ab3SBen Gras unsigned char c; 593*a06e2ab3SBen Gras 594*a06e2ab3SBen Gras c = cc; 595*a06e2ab3SBen Gras if (!NP) { 596*a06e2ab3SBen Gras c |= partab[c&0177] & 0200; 597*a06e2ab3SBen Gras if (OP) 598*a06e2ab3SBen Gras c ^= 0200; 599*a06e2ab3SBen Gras } 600*a06e2ab3SBen Gras if (!UB) { 601*a06e2ab3SBen Gras outbuf[obufcnt++] = c; 602*a06e2ab3SBen Gras if (obufcnt >= OBUFSIZ) 603*a06e2ab3SBen Gras oflush(); 604*a06e2ab3SBen Gras return 1; 605*a06e2ab3SBen Gras } 606*a06e2ab3SBen Gras return write(STDOUT_FILENO, &c, 1); 607*a06e2ab3SBen Gras } 608*a06e2ab3SBen Gras 609*a06e2ab3SBen Gras static void 610*a06e2ab3SBen Gras oflush(void) 611*a06e2ab3SBen Gras { 612*a06e2ab3SBen Gras if (obufcnt) 613*a06e2ab3SBen Gras (void)write(STDOUT_FILENO, outbuf, obufcnt); 614*a06e2ab3SBen Gras obufcnt = 0; 615*a06e2ab3SBen Gras } 616*a06e2ab3SBen Gras 617*a06e2ab3SBen Gras static void 618*a06e2ab3SBen Gras prompt(void) 619*a06e2ab3SBen Gras { 620*a06e2ab3SBen Gras 621*a06e2ab3SBen Gras putf(LM); 622*a06e2ab3SBen Gras if (CO) 623*a06e2ab3SBen Gras putchr('\n'); 624*a06e2ab3SBen Gras } 625*a06e2ab3SBen Gras 626*a06e2ab3SBen Gras static void 627*a06e2ab3SBen Gras putf(const char *cp) 628*a06e2ab3SBen Gras { 629*a06e2ab3SBen Gras time_t t; 630*a06e2ab3SBen Gras char *slash, db[100]; 631*a06e2ab3SBen Gras 632*a06e2ab3SBen Gras while (*cp) { 633*a06e2ab3SBen Gras if (*cp != '%') { 634*a06e2ab3SBen Gras putchr(*cp++); 635*a06e2ab3SBen Gras continue; 636*a06e2ab3SBen Gras } 637*a06e2ab3SBen Gras switch (*++cp) { 638*a06e2ab3SBen Gras 639*a06e2ab3SBen Gras case 't': 640*a06e2ab3SBen Gras if ((slash = strstr(ttyn, "/pts/")) == NULL) 641*a06e2ab3SBen Gras slash = strrchr(ttyn, '/'); 642*a06e2ab3SBen Gras if (slash == NULL) 643*a06e2ab3SBen Gras xputs(ttyn); 644*a06e2ab3SBen Gras else 645*a06e2ab3SBen Gras xputs(&slash[1]); 646*a06e2ab3SBen Gras break; 647*a06e2ab3SBen Gras 648*a06e2ab3SBen Gras case 'h': 649*a06e2ab3SBen Gras xputs(editedhost); 650*a06e2ab3SBen Gras break; 651*a06e2ab3SBen Gras 652*a06e2ab3SBen Gras case 'd': 653*a06e2ab3SBen Gras (void)time(&t); 654*a06e2ab3SBen Gras (void)strftime(db, sizeof(db), 655*a06e2ab3SBen Gras "%l:%M%p on %A, %d %B %Y", localtime(&t)); 656*a06e2ab3SBen Gras xputs(db); 657*a06e2ab3SBen Gras break; 658*a06e2ab3SBen Gras 659*a06e2ab3SBen Gras case 's': 660*a06e2ab3SBen Gras xputs(kerninfo.sysname); 661*a06e2ab3SBen Gras break; 662*a06e2ab3SBen Gras 663*a06e2ab3SBen Gras case 'm': 664*a06e2ab3SBen Gras xputs(kerninfo.machine); 665*a06e2ab3SBen Gras break; 666*a06e2ab3SBen Gras 667*a06e2ab3SBen Gras case 'r': 668*a06e2ab3SBen Gras xputs(kerninfo.release); 669*a06e2ab3SBen Gras break; 670*a06e2ab3SBen Gras 671*a06e2ab3SBen Gras case 'v': 672*a06e2ab3SBen Gras xputs(kerninfo.version); 673*a06e2ab3SBen Gras break; 674*a06e2ab3SBen Gras 675*a06e2ab3SBen Gras case '%': 676*a06e2ab3SBen Gras putchr('%'); 677*a06e2ab3SBen Gras break; 678*a06e2ab3SBen Gras } 679*a06e2ab3SBen Gras if (*cp) 680*a06e2ab3SBen Gras cp++; 681*a06e2ab3SBen Gras } 682*a06e2ab3SBen Gras } 683*a06e2ab3SBen Gras 684*a06e2ab3SBen Gras static void 685*a06e2ab3SBen Gras clearscreen(void) 686*a06e2ab3SBen Gras { 687*a06e2ab3SBen Gras struct ttyent *typ; 688*a06e2ab3SBen Gras int err; 689*a06e2ab3SBen Gras 690*a06e2ab3SBen Gras if (rawttyn == NULL) 691*a06e2ab3SBen Gras return; 692*a06e2ab3SBen Gras 693*a06e2ab3SBen Gras typ = getttynam(rawttyn); 694*a06e2ab3SBen Gras 695*a06e2ab3SBen Gras if ((typ == NULL) || (typ->ty_type == NULL) || 696*a06e2ab3SBen Gras (typ->ty_type[0] == 0)) 697*a06e2ab3SBen Gras return; 698*a06e2ab3SBen Gras 699*a06e2ab3SBen Gras if (setupterm(typ->ty_type, 0, &err) == ERR) 700*a06e2ab3SBen Gras return; 701*a06e2ab3SBen Gras 702*a06e2ab3SBen Gras if (clear_screen) 703*a06e2ab3SBen Gras putpad(clear_screen); 704*a06e2ab3SBen Gras 705*a06e2ab3SBen Gras del_curterm(cur_term); 706*a06e2ab3SBen Gras cur_term = NULL; 707*a06e2ab3SBen Gras } 708