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