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