Home | History | Annotate | Line # | Download | only in getty
main.c revision 1.9.2.2
      1  1.9.2.2  mycroft /*-
      2  1.9.2.2  mycroft  * Copyright (c) 1980, 1993
      3  1.9.2.2  mycroft  *	The Regents of the University of California.  All rights reserved.
      4  1.9.2.2  mycroft  *
      5  1.9.2.2  mycroft  * Redistribution and use in source and binary forms, with or without
      6  1.9.2.2  mycroft  * modification, are permitted provided that the following conditions
      7  1.9.2.2  mycroft  * are met:
      8  1.9.2.2  mycroft  * 1. Redistributions of source code must retain the above copyright
      9  1.9.2.2  mycroft  *    notice, this list of conditions and the following disclaimer.
     10  1.9.2.2  mycroft  * 2. Redistributions in binary form must reproduce the above copyright
     11  1.9.2.2  mycroft  *    notice, this list of conditions and the following disclaimer in the
     12  1.9.2.2  mycroft  *    documentation and/or other materials provided with the distribution.
     13  1.9.2.2  mycroft  * 3. All advertising materials mentioning features or use of this software
     14  1.9.2.2  mycroft  *    must display the following acknowledgement:
     15  1.9.2.2  mycroft  *	This product includes software developed by the University of
     16  1.9.2.2  mycroft  *	California, Berkeley and its contributors.
     17  1.9.2.2  mycroft  * 4. Neither the name of the University nor the names of its contributors
     18  1.9.2.2  mycroft  *    may be used to endorse or promote products derived from this software
     19  1.9.2.2  mycroft  *    without specific prior written permission.
     20  1.9.2.2  mycroft  *
     21  1.9.2.2  mycroft  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     22  1.9.2.2  mycroft  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     23  1.9.2.2  mycroft  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     24  1.9.2.2  mycroft  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     25  1.9.2.2  mycroft  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     26  1.9.2.2  mycroft  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     27  1.9.2.2  mycroft  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     28  1.9.2.2  mycroft  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     29  1.9.2.2  mycroft  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     30  1.9.2.2  mycroft  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     31  1.9.2.2  mycroft  * SUCH DAMAGE.
     32  1.9.2.2  mycroft  */
     33  1.9.2.2  mycroft 
     34  1.9.2.2  mycroft #ifndef lint
     35  1.9.2.2  mycroft static char copyright[] =
     36  1.9.2.2  mycroft "@(#) Copyright (c) 1980, 1993\n\
     37  1.9.2.2  mycroft 	The Regents of the University of California.  All rights reserved.\n";
     38  1.9.2.2  mycroft #endif /* not lint */
     39  1.9.2.2  mycroft 
     40  1.9.2.2  mycroft #ifndef lint
     41  1.9.2.2  mycroft /*static char sccsid[] = "from: @(#)main.c	8.1 (Berkeley) 6/20/93";*/
     42  1.9.2.2  mycroft static char rcsid[] = "$Id: main.c,v 1.9.2.2 1994/08/24 17:12:38 mycroft Exp $";
     43  1.9.2.2  mycroft #endif /* not lint */
     44  1.9.2.2  mycroft 
     45  1.9.2.2  mycroft #include <sys/param.h>
     46  1.9.2.2  mycroft #include <sys/stat.h>
     47  1.9.2.2  mycroft #include <sys/termios.h>
     48  1.9.2.2  mycroft #include <sys/ioctl.h>
     49  1.9.2.2  mycroft #include <sys/resource.h>
     50  1.9.2.2  mycroft #include <sys/utsname.h>
     51  1.9.2.2  mycroft #include <signal.h>
     52  1.9.2.2  mycroft #include <fcntl.h>
     53  1.9.2.2  mycroft #include <time.h>
     54  1.9.2.2  mycroft #include <ctype.h>
     55  1.9.2.2  mycroft #include <fcntl.h>
     56  1.9.2.2  mycroft #include <setjmp.h>
     57  1.9.2.2  mycroft #include <signal.h>
     58  1.9.2.2  mycroft #include <stdlib.h>
     59  1.9.2.2  mycroft #include <string.h>
     60  1.9.2.2  mycroft #include <syslog.h>
     61  1.9.2.2  mycroft #include <time.h>
     62  1.9.2.2  mycroft #include <unistd.h>
     63  1.9.2.2  mycroft 
     64  1.9.2.2  mycroft #include "gettytab.h"
     65  1.9.2.2  mycroft #include "pathnames.h"
     66  1.9.2.2  mycroft #include "extern.h"
     67  1.9.2.2  mycroft 
     68  1.9.2.2  mycroft /*
     69  1.9.2.2  mycroft  * Set the amount of running time that getty should accumulate
     70  1.9.2.2  mycroft  * before deciding that something is wrong and exit.
     71  1.9.2.2  mycroft  */
     72  1.9.2.2  mycroft #define GETTY_TIMEOUT	60 /* seconds */
     73  1.9.2.2  mycroft 
     74  1.9.2.2  mycroft struct termios tmode, omode;
     75  1.9.2.2  mycroft 
     76  1.9.2.2  mycroft int crmod, digit, lower, upper;
     77  1.9.2.2  mycroft 
     78  1.9.2.2  mycroft char	hostname[MAXHOSTNAMELEN];
     79  1.9.2.2  mycroft struct	utsname kerninfo;
     80  1.9.2.2  mycroft char	name[16];
     81  1.9.2.2  mycroft char	dev[] = _PATH_DEV;
     82  1.9.2.2  mycroft char	ttyn[32];
     83  1.9.2.2  mycroft char	*portselector();
     84  1.9.2.2  mycroft char	*ttyname();
     85  1.9.2.2  mycroft 
     86  1.9.2.2  mycroft #define	OBUFSIZ		128
     87  1.9.2.2  mycroft #define	TABBUFSIZ	512
     88  1.9.2.2  mycroft 
     89  1.9.2.2  mycroft char	defent[TABBUFSIZ];
     90  1.9.2.2  mycroft char	tabent[TABBUFSIZ];
     91  1.9.2.2  mycroft 
     92  1.9.2.2  mycroft char	*env[128];
     93  1.9.2.2  mycroft 
     94  1.9.2.2  mycroft char partab[] = {
     95  1.9.2.2  mycroft 	0001,0201,0201,0001,0201,0001,0001,0201,
     96  1.9.2.2  mycroft 	0202,0004,0003,0205,0005,0206,0201,0001,
     97  1.9.2.2  mycroft 	0201,0001,0001,0201,0001,0201,0201,0001,
     98  1.9.2.2  mycroft 	0001,0201,0201,0001,0201,0001,0001,0201,
     99  1.9.2.2  mycroft 	0200,0000,0000,0200,0000,0200,0200,0000,
    100  1.9.2.2  mycroft 	0000,0200,0200,0000,0200,0000,0000,0200,
    101  1.9.2.2  mycroft 	0000,0200,0200,0000,0200,0000,0000,0200,
    102  1.9.2.2  mycroft 	0200,0000,0000,0200,0000,0200,0200,0000,
    103  1.9.2.2  mycroft 	0200,0000,0000,0200,0000,0200,0200,0000,
    104  1.9.2.2  mycroft 	0000,0200,0200,0000,0200,0000,0000,0200,
    105  1.9.2.2  mycroft 	0000,0200,0200,0000,0200,0000,0000,0200,
    106  1.9.2.2  mycroft 	0200,0000,0000,0200,0000,0200,0200,0000,
    107  1.9.2.2  mycroft 	0000,0200,0200,0000,0200,0000,0000,0200,
    108  1.9.2.2  mycroft 	0200,0000,0000,0200,0000,0200,0200,0000,
    109  1.9.2.2  mycroft 	0200,0000,0000,0200,0000,0200,0200,0000,
    110  1.9.2.2  mycroft 	0000,0200,0200,0000,0200,0000,0000,0201
    111  1.9.2.2  mycroft };
    112  1.9.2.2  mycroft 
    113  1.9.2.2  mycroft #define	ERASE	tmode.c_cc[VERASE]
    114  1.9.2.2  mycroft #define	KILL	tmode.c_cc[VKILL]
    115  1.9.2.2  mycroft #define	EOT	tmode.c_cc[VEOF]
    116  1.9.2.2  mycroft 
    117  1.9.2.2  mycroft jmp_buf timeout;
    118  1.9.2.2  mycroft 
    119  1.9.2.2  mycroft static void
    120  1.9.2.2  mycroft dingdong()
    121  1.9.2.2  mycroft {
    122  1.9.2.2  mycroft 
    123  1.9.2.2  mycroft 	alarm(0);
    124  1.9.2.2  mycroft 	signal(SIGALRM, SIG_DFL);
    125  1.9.2.2  mycroft 	longjmp(timeout, 1);
    126  1.9.2.2  mycroft }
    127  1.9.2.2  mycroft 
    128  1.9.2.2  mycroft jmp_buf	intrupt;
    129  1.9.2.2  mycroft 
    130  1.9.2.2  mycroft static void
    131  1.9.2.2  mycroft interrupt()
    132  1.9.2.2  mycroft {
    133  1.9.2.2  mycroft 
    134  1.9.2.2  mycroft 	signal(SIGINT, interrupt);
    135  1.9.2.2  mycroft 	longjmp(intrupt, 1);
    136  1.9.2.2  mycroft }
    137  1.9.2.2  mycroft 
    138  1.9.2.2  mycroft /*
    139  1.9.2.2  mycroft  * Action to take when getty is running too long.
    140  1.9.2.2  mycroft  */
    141  1.9.2.2  mycroft void
    142  1.9.2.2  mycroft timeoverrun(signo)
    143  1.9.2.2  mycroft 	int signo;
    144  1.9.2.2  mycroft {
    145  1.9.2.2  mycroft 
    146  1.9.2.2  mycroft 	syslog(LOG_ERR, "getty exiting due to excessive running time\n");
    147  1.9.2.2  mycroft 	exit(1);
    148  1.9.2.2  mycroft }
    149  1.9.2.2  mycroft 
    150  1.9.2.2  mycroft static int	getname __P((void));
    151  1.9.2.2  mycroft static void	oflush __P((void));
    152  1.9.2.2  mycroft static void	prompt __P((void));
    153  1.9.2.2  mycroft static void	putchr __P((int));
    154  1.9.2.2  mycroft static void	putf __P((char *));
    155  1.9.2.2  mycroft static void	putpad __P((char *));
    156  1.9.2.2  mycroft static void	puts __P((char *));
    157  1.9.2.2  mycroft 
    158  1.9.2.2  mycroft int
    159  1.9.2.2  mycroft main(argc, argv)
    160  1.9.2.2  mycroft 	int argc;
    161  1.9.2.2  mycroft 	char *argv[];
    162  1.9.2.2  mycroft {
    163  1.9.2.2  mycroft 	extern char **environ;
    164  1.9.2.2  mycroft 	char *tname;
    165  1.9.2.2  mycroft 	long allflags;
    166  1.9.2.2  mycroft 	int repcnt = 0;
    167  1.9.2.2  mycroft 	struct rlimit limit;
    168  1.9.2.2  mycroft 
    169  1.9.2.2  mycroft 	signal(SIGINT, SIG_IGN);
    170  1.9.2.2  mycroft /*
    171  1.9.2.2  mycroft 	signal(SIGQUIT, SIG_DFL);
    172  1.9.2.2  mycroft */
    173  1.9.2.2  mycroft 	openlog("getty", LOG_ODELAY|LOG_CONS, LOG_AUTH);
    174  1.9.2.2  mycroft 	gethostname(hostname, sizeof(hostname));
    175  1.9.2.2  mycroft 	if (hostname[0] == '\0')
    176  1.9.2.2  mycroft 		strcpy(hostname, "Amnesiac");
    177  1.9.2.2  mycroft 	uname(&kerninfo);
    178  1.9.2.2  mycroft 
    179  1.9.2.2  mycroft 	/*
    180  1.9.2.2  mycroft 	 * Limit running time to deal with broken or dead lines.
    181  1.9.2.2  mycroft 	 */
    182  1.9.2.2  mycroft 	(void)signal(SIGXCPU, timeoverrun);
    183  1.9.2.2  mycroft 	limit.rlim_max = RLIM_INFINITY;
    184  1.9.2.2  mycroft 	limit.rlim_cur = GETTY_TIMEOUT;
    185  1.9.2.2  mycroft 	(void)setrlimit(RLIMIT_CPU, &limit);
    186  1.9.2.2  mycroft 
    187  1.9.2.2  mycroft 	/*
    188  1.9.2.2  mycroft 	 * The following is a work around for vhangup interactions
    189  1.9.2.2  mycroft 	 * which cause great problems getting window systems started.
    190  1.9.2.2  mycroft 	 * If the tty line is "-", we do the old style getty presuming
    191  1.9.2.2  mycroft 	 * that the file descriptors are already set up for us.
    192  1.9.2.2  mycroft 	 * J. Gettys - MIT Project Athena.
    193  1.9.2.2  mycroft 	 */
    194  1.9.2.2  mycroft 	if (argc <= 2 || strcmp(argv[2], "-") == 0)
    195  1.9.2.2  mycroft 	    strcpy(ttyn, ttyname(0));
    196  1.9.2.2  mycroft 	else {
    197  1.9.2.2  mycroft 	    int i;
    198  1.9.2.2  mycroft 
    199  1.9.2.2  mycroft 	    strcpy(ttyn, dev);
    200  1.9.2.2  mycroft 	    strncat(ttyn, argv[2], sizeof(ttyn)-sizeof(dev));
    201  1.9.2.2  mycroft 	    if (strcmp(argv[0], "+") != 0) {
    202  1.9.2.2  mycroft 		chown(ttyn, 0, 0);
    203  1.9.2.2  mycroft 		chmod(ttyn, 0600);
    204  1.9.2.2  mycroft 		revoke(ttyn);
    205  1.9.2.2  mycroft 		/*
    206  1.9.2.2  mycroft 		 * Delay the open so DTR stays down long enough to be detected.
    207  1.9.2.2  mycroft 		 */
    208  1.9.2.2  mycroft 		sleep(2);
    209  1.9.2.2  mycroft 		while ((i = open(ttyn, O_RDWR)) == -1) {
    210  1.9.2.2  mycroft 			if (repcnt % 10 == 0) {
    211  1.9.2.2  mycroft 				syslog(LOG_ERR, "%s: %m", ttyn);
    212  1.9.2.2  mycroft 				closelog();
    213  1.9.2.2  mycroft 			}
    214  1.9.2.2  mycroft 			repcnt++;
    215  1.9.2.2  mycroft 			sleep(60);
    216  1.9.2.2  mycroft 		}
    217  1.9.2.2  mycroft 		login_tty(i);
    218  1.9.2.2  mycroft 	    }
    219  1.9.2.2  mycroft 	}
    220  1.9.2.2  mycroft 
    221  1.9.2.2  mycroft 	/* Start with default tty settings */
    222  1.9.2.2  mycroft 	if (tcgetattr(0, &tmode) < 0) {
    223  1.9.2.2  mycroft 		syslog(LOG_ERR, "%s: %m", ttyn);
    224  1.9.2.2  mycroft 		exit(1);
    225  1.9.2.2  mycroft 	}
    226  1.9.2.2  mycroft 	omode = tmode;
    227  1.9.2.2  mycroft 
    228  1.9.2.2  mycroft 	gettable("default", defent);
    229  1.9.2.2  mycroft 	gendefaults();
    230  1.9.2.2  mycroft 	tname = "default";
    231  1.9.2.2  mycroft 	if (argc > 1)
    232  1.9.2.2  mycroft 		tname = argv[1];
    233  1.9.2.2  mycroft 	for (;;) {
    234  1.9.2.2  mycroft 		int off;
    235  1.9.2.2  mycroft 
    236  1.9.2.2  mycroft 		gettable(tname, tabent);
    237  1.9.2.2  mycroft 		if (OPset || EPset || APset)
    238  1.9.2.2  mycroft 			APset++, OPset++, EPset++;
    239  1.9.2.2  mycroft 		setdefaults();
    240  1.9.2.2  mycroft 		off = 0;
    241  1.9.2.2  mycroft 		ioctl(0, TIOCFLUSH, &off);	/* clear out the crap */
    242  1.9.2.2  mycroft 		ioctl(0, FIONBIO, &off);	/* turn off non-blocking mode */
    243  1.9.2.2  mycroft 		ioctl(0, FIOASYNC, &off);	/* ditto for async mode */
    244  1.9.2.2  mycroft 
    245  1.9.2.2  mycroft 		if (IS)
    246  1.9.2.2  mycroft 			cfsetispeed(&tmode, IS);
    247  1.9.2.2  mycroft 		else if (SP)
    248  1.9.2.2  mycroft 			cfsetispeed(&tmode, SP);
    249  1.9.2.2  mycroft 		if (OS)
    250  1.9.2.2  mycroft 			cfsetospeed(&tmode, OS);
    251  1.9.2.2  mycroft 		else if (SP)
    252  1.9.2.2  mycroft 			cfsetospeed(&tmode, SP);
    253  1.9.2.2  mycroft 		setflags(0);
    254  1.9.2.2  mycroft 		setchars();
    255  1.9.2.2  mycroft 		if (tcsetattr(0, TCSANOW, &tmode) < 0) {
    256  1.9.2.2  mycroft 			syslog(LOG_ERR, "%s: %m", ttyn);
    257  1.9.2.2  mycroft 			exit(1);
    258  1.9.2.2  mycroft 		}
    259  1.9.2.2  mycroft 		if (AB) {
    260  1.9.2.2  mycroft 			extern char *autobaud();
    261  1.9.2.2  mycroft 
    262  1.9.2.2  mycroft 			tname = autobaud();
    263  1.9.2.2  mycroft 			continue;
    264  1.9.2.2  mycroft 		}
    265  1.9.2.2  mycroft 		if (PS) {
    266  1.9.2.2  mycroft 			tname = portselector();
    267  1.9.2.2  mycroft 			continue;
    268  1.9.2.2  mycroft 		}
    269  1.9.2.2  mycroft 		if (CL && *CL)
    270  1.9.2.2  mycroft 			putpad(CL);
    271  1.9.2.2  mycroft 		edithost(HE);
    272  1.9.2.2  mycroft 		if (IM && *IM)
    273  1.9.2.2  mycroft 			putf(IM);
    274  1.9.2.2  mycroft 		if (setjmp(timeout)) {
    275  1.9.2.2  mycroft 			tmode.c_ispeed = tmode.c_ospeed = 0;
    276  1.9.2.2  mycroft 			(void)tcsetattr(0, TCSANOW, &tmode);
    277  1.9.2.2  mycroft 			exit(1);
    278  1.9.2.2  mycroft 		}
    279  1.9.2.2  mycroft 		if (TO) {
    280  1.9.2.2  mycroft 			signal(SIGALRM, dingdong);
    281  1.9.2.2  mycroft 			alarm(TO);
    282  1.9.2.2  mycroft 		}
    283  1.9.2.2  mycroft 		if (getname()) {
    284  1.9.2.2  mycroft 			register int i;
    285  1.9.2.2  mycroft 
    286  1.9.2.2  mycroft 			oflush();
    287  1.9.2.2  mycroft 			alarm(0);
    288  1.9.2.2  mycroft 			signal(SIGALRM, SIG_DFL);
    289  1.9.2.2  mycroft 			if (name[0] == '-') {
    290  1.9.2.2  mycroft 				puts("user names may not start with '-'.");
    291  1.9.2.2  mycroft 				continue;
    292  1.9.2.2  mycroft 			}
    293  1.9.2.2  mycroft 			if (!(upper || lower || digit))
    294  1.9.2.2  mycroft 				continue;
    295  1.9.2.2  mycroft 			setflags(2);
    296  1.9.2.2  mycroft 			if (crmod) {
    297  1.9.2.2  mycroft 				tmode.c_iflag |= ICRNL;
    298  1.9.2.2  mycroft 				tmode.c_oflag |= ONLCR;
    299  1.9.2.2  mycroft 			}
    300  1.9.2.2  mycroft #if XXX
    301  1.9.2.2  mycroft 			if (upper || UC)
    302  1.9.2.2  mycroft 				tmode.sg_flags |= LCASE;
    303  1.9.2.2  mycroft 			if (lower || LC)
    304  1.9.2.2  mycroft 				tmode.sg_flags &= ~LCASE;
    305  1.9.2.2  mycroft #endif
    306  1.9.2.2  mycroft 			if (tcsetattr(0, TCSANOW, &tmode) < 0) {
    307  1.9.2.2  mycroft 				syslog(LOG_ERR, "%s: %m", ttyn);
    308  1.9.2.2  mycroft 				exit(1);
    309  1.9.2.2  mycroft 			}
    310  1.9.2.2  mycroft 			signal(SIGINT, SIG_DFL);
    311  1.9.2.2  mycroft 			for (i = 0; environ[i] != (char *)0; i++)
    312  1.9.2.2  mycroft 				env[i] = environ[i];
    313  1.9.2.2  mycroft 			makeenv(&env[i]);
    314  1.9.2.2  mycroft 
    315  1.9.2.2  mycroft 			limit.rlim_max = RLIM_INFINITY;
    316  1.9.2.2  mycroft 			limit.rlim_cur = RLIM_INFINITY;
    317  1.9.2.2  mycroft 			(void)setrlimit(RLIMIT_CPU, &limit);
    318  1.9.2.2  mycroft 			execle(LO, "login", "-p", name, (char *) 0, env);
    319  1.9.2.2  mycroft 			syslog(LOG_ERR, "%s: %m", LO);
    320  1.9.2.2  mycroft 			exit(1);
    321  1.9.2.2  mycroft 		}
    322  1.9.2.2  mycroft 		alarm(0);
    323  1.9.2.2  mycroft 		signal(SIGALRM, SIG_DFL);
    324  1.9.2.2  mycroft 		signal(SIGINT, SIG_IGN);
    325  1.9.2.2  mycroft 		if (NX && *NX)
    326  1.9.2.2  mycroft 			tname = NX;
    327  1.9.2.2  mycroft 	}
    328  1.9.2.2  mycroft }
    329  1.9.2.2  mycroft 
    330  1.9.2.2  mycroft static int
    331  1.9.2.2  mycroft getname()
    332  1.9.2.2  mycroft {
    333  1.9.2.2  mycroft 	register int c;
    334  1.9.2.2  mycroft 	register char *np;
    335  1.9.2.2  mycroft 	char cs;
    336  1.9.2.2  mycroft 
    337  1.9.2.2  mycroft 	/*
    338  1.9.2.2  mycroft 	 * Interrupt may happen if we use CBREAK mode
    339  1.9.2.2  mycroft 	 */
    340  1.9.2.2  mycroft 	if (setjmp(intrupt)) {
    341  1.9.2.2  mycroft 		signal(SIGINT, SIG_IGN);
    342  1.9.2.2  mycroft 		return (0);
    343  1.9.2.2  mycroft 	}
    344  1.9.2.2  mycroft 	signal(SIGINT, interrupt);
    345  1.9.2.2  mycroft 	setflags(1);
    346  1.9.2.2  mycroft 	prompt();
    347  1.9.2.2  mycroft 	if (PF > 0) {
    348  1.9.2.2  mycroft 		oflush();
    349  1.9.2.2  mycroft 		sleep(PF);
    350  1.9.2.2  mycroft 		PF = 0;
    351  1.9.2.2  mycroft 	}
    352  1.9.2.2  mycroft 	if (tcsetattr(0, TCSANOW, &tmode) < 0) {
    353  1.9.2.2  mycroft 		syslog(LOG_ERR, "%s: %m", ttyn);
    354  1.9.2.2  mycroft 		exit(1);
    355  1.9.2.2  mycroft 	}
    356  1.9.2.2  mycroft 	crmod = digit = lower = upper = 0;
    357  1.9.2.2  mycroft 	np = name;
    358  1.9.2.2  mycroft 	for (;;) {
    359  1.9.2.2  mycroft 		oflush();
    360  1.9.2.2  mycroft 		if (read(STDIN_FILENO, &cs, 1) <= 0)
    361  1.9.2.2  mycroft 			exit(0);
    362  1.9.2.2  mycroft 		if ((c = cs&0177) == 0)
    363  1.9.2.2  mycroft 			return (0);
    364  1.9.2.2  mycroft 		if (c == EOT)
    365  1.9.2.2  mycroft 			exit(1);
    366  1.9.2.2  mycroft 		if (c == '\r' || c == '\n' || np >= &name[sizeof name]) {
    367  1.9.2.2  mycroft 			putf("\r\n");
    368  1.9.2.2  mycroft 			break;
    369  1.9.2.2  mycroft 		}
    370  1.9.2.2  mycroft 		if (islower(c))
    371  1.9.2.2  mycroft 			lower = 1;
    372  1.9.2.2  mycroft 		else if (isupper(c))
    373  1.9.2.2  mycroft 			upper = 1;
    374  1.9.2.2  mycroft 		else if (c == ERASE || c == '#' || c == '\b') {
    375  1.9.2.2  mycroft 			if (np > name) {
    376  1.9.2.2  mycroft 				np--;
    377  1.9.2.2  mycroft 				if (cfgetospeed(&tmode) >= 1200)
    378  1.9.2.2  mycroft 					puts("\b \b");
    379  1.9.2.2  mycroft 				else
    380  1.9.2.2  mycroft 					putchr(cs);
    381  1.9.2.2  mycroft 			}
    382  1.9.2.2  mycroft 			continue;
    383  1.9.2.2  mycroft 		} else if (c == KILL || c == '@') {
    384  1.9.2.2  mycroft 			putchr(cs);
    385  1.9.2.2  mycroft 			putchr('\r');
    386  1.9.2.2  mycroft 			if (cfgetospeed(&tmode) < 1200)
    387  1.9.2.2  mycroft 				putchr('\n');
    388  1.9.2.2  mycroft 			/* this is the way they do it down under ... */
    389  1.9.2.2  mycroft 			else if (np > name)
    390  1.9.2.2  mycroft 				puts("                                     \r");
    391  1.9.2.2  mycroft 			prompt();
    392  1.9.2.2  mycroft 			np = name;
    393  1.9.2.2  mycroft 			continue;
    394  1.9.2.2  mycroft 		} else if (isdigit(c))
    395  1.9.2.2  mycroft 			digit++;
    396  1.9.2.2  mycroft 		if (IG && (c <= ' ' || c > 0176))
    397  1.9.2.2  mycroft 			continue;
    398  1.9.2.2  mycroft 		*np++ = c;
    399  1.9.2.2  mycroft 		putchr(cs);
    400  1.9.2.2  mycroft 	}
    401  1.9.2.2  mycroft 	signal(SIGINT, SIG_IGN);
    402  1.9.2.2  mycroft 	*np = 0;
    403  1.9.2.2  mycroft 	if (c == '\r')
    404  1.9.2.2  mycroft 		crmod = 1;
    405  1.9.2.2  mycroft 	if (upper && !lower && !LC || UC)
    406  1.9.2.2  mycroft 		for (np = name; *np; np++)
    407  1.9.2.2  mycroft 			if (isupper(*np))
    408  1.9.2.2  mycroft 				*np = tolower(*np);
    409  1.9.2.2  mycroft 	return (1);
    410  1.9.2.2  mycroft }
    411  1.9.2.2  mycroft 
    412  1.9.2.2  mycroft static void
    413  1.9.2.2  mycroft putpad(s)
    414  1.9.2.2  mycroft 	register char *s;
    415  1.9.2.2  mycroft {
    416  1.9.2.2  mycroft 	register pad = 0;
    417  1.9.2.2  mycroft 	speed_t ospeed = cfgetospeed(&tmode);
    418  1.9.2.2  mycroft 
    419  1.9.2.2  mycroft 	if (isdigit(*s)) {
    420  1.9.2.2  mycroft 		while (isdigit(*s)) {
    421  1.9.2.2  mycroft 			pad *= 10;
    422  1.9.2.2  mycroft 			pad += *s++ - '0';
    423  1.9.2.2  mycroft 		}
    424  1.9.2.2  mycroft 		pad *= 10;
    425  1.9.2.2  mycroft 		if (*s == '.' && isdigit(s[1])) {
    426  1.9.2.2  mycroft 			pad += s[1] - '0';
    427  1.9.2.2  mycroft 			s += 2;
    428  1.9.2.2  mycroft 		}
    429  1.9.2.2  mycroft 	}
    430  1.9.2.2  mycroft 
    431  1.9.2.2  mycroft 	puts(s);
    432  1.9.2.2  mycroft 	/*
    433  1.9.2.2  mycroft 	 * If no delay needed, or output speed is
    434  1.9.2.2  mycroft 	 * not comprehensible, then don't try to delay.
    435  1.9.2.2  mycroft 	 */
    436  1.9.2.2  mycroft 	if (pad == 0 || ospeed <= 0)
    437  1.9.2.2  mycroft 		return;
    438  1.9.2.2  mycroft 
    439  1.9.2.2  mycroft 	/*
    440  1.9.2.2  mycroft 	 * Round up by a half a character frame, and then do the delay.
    441  1.9.2.2  mycroft 	 * Too bad there are no user program accessible programmed delays.
    442  1.9.2.2  mycroft 	 * Transmitting pad characters slows many terminals down and also
    443  1.9.2.2  mycroft 	 * loads the system.
    444  1.9.2.2  mycroft 	 */
    445  1.9.2.2  mycroft 	pad = (pad * ospeed + 50000) / 100000;
    446  1.9.2.2  mycroft 	while (pad--)
    447  1.9.2.2  mycroft 		putchr(*PC);
    448  1.9.2.2  mycroft }
    449  1.9.2.2  mycroft 
    450  1.9.2.2  mycroft static void
    451  1.9.2.2  mycroft puts(s)
    452  1.9.2.2  mycroft 	register char *s;
    453  1.9.2.2  mycroft {
    454  1.9.2.2  mycroft 	while (*s)
    455  1.9.2.2  mycroft 		putchr(*s++);
    456  1.9.2.2  mycroft }
    457  1.9.2.2  mycroft 
    458  1.9.2.2  mycroft char	outbuf[OBUFSIZ];
    459  1.9.2.2  mycroft int	obufcnt = 0;
    460  1.9.2.2  mycroft 
    461  1.9.2.2  mycroft static void
    462  1.9.2.2  mycroft putchr(cc)
    463  1.9.2.2  mycroft 	int cc;
    464  1.9.2.2  mycroft {
    465  1.9.2.2  mycroft 	char c;
    466  1.9.2.2  mycroft 
    467  1.9.2.2  mycroft 	c = cc;
    468  1.9.2.2  mycroft 	if (!NP) {
    469  1.9.2.2  mycroft 		c |= partab[c&0177] & 0200;
    470  1.9.2.2  mycroft 		if (OP)
    471  1.9.2.2  mycroft 			c ^= 0200;
    472  1.9.2.2  mycroft 	}
    473  1.9.2.2  mycroft 	if (!UB) {
    474  1.9.2.2  mycroft 		outbuf[obufcnt++] = c;
    475  1.9.2.2  mycroft 		if (obufcnt >= OBUFSIZ)
    476  1.9.2.2  mycroft 			oflush();
    477  1.9.2.2  mycroft 	} else
    478  1.9.2.2  mycroft 		write(STDOUT_FILENO, &c, 1);
    479  1.9.2.2  mycroft }
    480  1.9.2.2  mycroft 
    481  1.9.2.2  mycroft static void
    482  1.9.2.2  mycroft oflush()
    483  1.9.2.2  mycroft {
    484  1.9.2.2  mycroft 	if (obufcnt)
    485  1.9.2.2  mycroft 		write(STDOUT_FILENO, outbuf, obufcnt);
    486  1.9.2.2  mycroft 	obufcnt = 0;
    487  1.9.2.2  mycroft }
    488  1.9.2.2  mycroft 
    489  1.9.2.2  mycroft static void
    490  1.9.2.2  mycroft prompt()
    491  1.9.2.2  mycroft {
    492  1.9.2.2  mycroft 
    493  1.9.2.2  mycroft 	putf(LM);
    494  1.9.2.2  mycroft 	if (CO)
    495  1.9.2.2  mycroft 		putchr('\n');
    496  1.9.2.2  mycroft }
    497  1.9.2.2  mycroft 
    498  1.9.2.2  mycroft static void
    499  1.9.2.2  mycroft putf(cp)
    500  1.9.2.2  mycroft 	register char *cp;
    501  1.9.2.2  mycroft {
    502  1.9.2.2  mycroft 	extern char editedhost[];
    503  1.9.2.2  mycroft 	time_t t;
    504  1.9.2.2  mycroft 	char *slash, db[100];
    505  1.9.2.2  mycroft 
    506  1.9.2.2  mycroft 	while (*cp) {
    507  1.9.2.2  mycroft 		if (*cp != '%') {
    508  1.9.2.2  mycroft 			putchr(*cp++);
    509  1.9.2.2  mycroft 			continue;
    510  1.9.2.2  mycroft 		}
    511  1.9.2.2  mycroft 		switch (*++cp) {
    512  1.9.2.2  mycroft 
    513  1.9.2.2  mycroft 		case 't':
    514  1.9.2.2  mycroft 			slash = strrchr(ttyn, '/');
    515  1.9.2.2  mycroft 			if (slash == (char *) 0)
    516  1.9.2.2  mycroft 				puts(ttyn);
    517  1.9.2.2  mycroft 			else
    518  1.9.2.2  mycroft 				puts(&slash[1]);
    519  1.9.2.2  mycroft 			break;
    520  1.9.2.2  mycroft 
    521  1.9.2.2  mycroft 		case 'h':
    522  1.9.2.2  mycroft 			puts(editedhost);
    523  1.9.2.2  mycroft 			break;
    524  1.9.2.2  mycroft 
    525  1.9.2.2  mycroft 		case 'd': {
    526  1.9.2.2  mycroft 			static char fmt[] = "%l:% %P on %A, %d %B %Y";
    527  1.9.2.2  mycroft 
    528  1.9.2.2  mycroft 			fmt[4] = 'M';		/* I *hate* SCCS... */
    529  1.9.2.2  mycroft 			(void)time(&t);
    530  1.9.2.2  mycroft 			(void)strftime(db, sizeof(db), fmt, localtime(&t));
    531  1.9.2.2  mycroft 			puts(db);
    532  1.9.2.2  mycroft 			break;
    533  1.9.2.2  mycroft 
    534  1.9.2.2  mycroft 		case 's':
    535  1.9.2.2  mycroft 			puts(kerninfo.sysname);
    536  1.9.2.2  mycroft 			break;
    537  1.9.2.2  mycroft 
    538  1.9.2.2  mycroft 		case 'm':
    539  1.9.2.2  mycroft 			puts(kerninfo.machine);
    540  1.9.2.2  mycroft 			break;
    541  1.9.2.2  mycroft 
    542  1.9.2.2  mycroft 		case 'r':
    543  1.9.2.2  mycroft 			puts(kerninfo.release);
    544  1.9.2.2  mycroft 			break;
    545  1.9.2.2  mycroft 
    546  1.9.2.2  mycroft 		case 'v':
    547  1.9.2.2  mycroft 			puts(kerninfo.version);
    548  1.9.2.2  mycroft 			break;
    549  1.9.2.2  mycroft 		}
    550  1.9.2.2  mycroft 
    551  1.9.2.2  mycroft 		case '%':
    552  1.9.2.2  mycroft 			putchr('%');
    553  1.9.2.2  mycroft 			break;
    554  1.9.2.2  mycroft 		}
    555  1.9.2.2  mycroft 		cp++;
    556  1.9.2.2  mycroft 	}
    557  1.9.2.2  mycroft }
    558