main.c revision 2391
11592Srgrimes/*-
22286Sjkh * Copyright (c) 1980 The Regents of the University of California.
32286Sjkh * All rights reserved.
41592Srgrimes *
51592Srgrimes * Redistribution and use in source and binary forms, with or without
61592Srgrimes * modification, are permitted provided that the following conditions
71592Srgrimes * are met:
81592Srgrimes * 1. Redistributions of source code must retain the above copyright
91592Srgrimes *    notice, this list of conditions and the following disclaimer.
101592Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111592Srgrimes *    notice, this list of conditions and the following disclaimer in the
121592Srgrimes *    documentation and/or other materials provided with the distribution.
131592Srgrimes * 3. All advertising materials mentioning features or use of this software
141592Srgrimes *    must display the following acknowledgement:
151592Srgrimes *	This product includes software developed by the University of
161592Srgrimes *	California, Berkeley and its contributors.
171592Srgrimes * 4. Neither the name of the University nor the names of its contributors
181592Srgrimes *    may be used to endorse or promote products derived from this software
191592Srgrimes *    without specific prior written permission.
201592Srgrimes *
211592Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
221592Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
231592Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
241592Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
251592Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
261592Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
271592Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
281592Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
291592Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
301592Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
311592Srgrimes * SUCH DAMAGE.
321592Srgrimes */
331592Srgrimes
341592Srgrimes#ifndef lint
352286Sjkhchar copyright[] =
362286Sjkh"@(#) Copyright (c) 1980 The Regents of the University of California.\n\
372286Sjkh All rights reserved.\n";
381592Srgrimes#endif /* not lint */
391592Srgrimes
401592Srgrimes#ifndef lint
412286Sjkhstatic char sccsid[] = "@(#)main.c	5.16 (Berkeley) 3/27/91";
421592Srgrimes#endif /* not lint */
431592Srgrimes
441592Srgrimes#define USE_OLD_TTY
451592Srgrimes
461592Srgrimes#include <sys/param.h>
471592Srgrimes#include <sys/stat.h>
482286Sjkh#include <signal.h>
492286Sjkh#include <fcntl.h>
502286Sjkh#include <sgtty.h>
512286Sjkh#include <time.h>
521592Srgrimes#include <ctype.h>
532286Sjkh#include <setjmp.h>
542286Sjkh#include <syslog.h>
552286Sjkh#include <unistd.h>
561592Srgrimes#include <ctype.h>
571592Srgrimes#include <stdlib.h>
581592Srgrimes#include <string.h>
591592Srgrimes#include "gettytab.h"
601592Srgrimes#include "pathnames.h"
611592Srgrimes
621592Srgrimesstruct	sgttyb tmode = {
631592Srgrimes	0, 0, CERASE, CKILL, 0
641592Srgrimes};
651592Srgrimesstruct	tchars tc = {
661592Srgrimes	CINTR, CQUIT, CSTART,
671592Srgrimes	CSTOP, CEOF, CBRK,
681592Srgrimes};
691592Srgrimesstruct	ltchars ltc = {
701592Srgrimes	CSUSP, CDSUSP, CRPRNT,
711592Srgrimes	CFLUSH, CWERASE, CLNEXT
721592Srgrimes};
731592Srgrimes
741592Srgrimesint crmod, digit, lower, upper;
751592Srgrimes
761592Srgrimeschar	hostname[MAXHOSTNAMELEN];
771592Srgrimeschar	name[16];
781592Srgrimeschar	dev[] = _PATH_DEV;
791592Srgrimeschar	ttyn[32];
801592Srgrimeschar	*portselector();
811592Srgrimeschar	*ttyname();
821592Srgrimes
831592Srgrimes#define	OBUFSIZ		128
841592Srgrimes#define	TABBUFSIZ	512
851592Srgrimes
861592Srgrimeschar	defent[TABBUFSIZ];
872286Sjkhchar	defstrs[TABBUFSIZ];
881592Srgrimeschar	tabent[TABBUFSIZ];
892286Sjkhchar	tabstrs[TABBUFSIZ];
901592Srgrimes
911592Srgrimeschar	*env[128];
921592Srgrimes
931592Srgrimeschar partab[] = {
941592Srgrimes	0001,0201,0201,0001,0201,0001,0001,0201,
951592Srgrimes	0202,0004,0003,0205,0005,0206,0201,0001,
961592Srgrimes	0201,0001,0001,0201,0001,0201,0201,0001,
971592Srgrimes	0001,0201,0201,0001,0201,0001,0001,0201,
981592Srgrimes	0200,0000,0000,0200,0000,0200,0200,0000,
991592Srgrimes	0000,0200,0200,0000,0200,0000,0000,0200,
1001592Srgrimes	0000,0200,0200,0000,0200,0000,0000,0200,
1011592Srgrimes	0200,0000,0000,0200,0000,0200,0200,0000,
1021592Srgrimes	0200,0000,0000,0200,0000,0200,0200,0000,
1031592Srgrimes	0000,0200,0200,0000,0200,0000,0000,0200,
1041592Srgrimes	0000,0200,0200,0000,0200,0000,0000,0200,
1051592Srgrimes	0200,0000,0000,0200,0000,0200,0200,0000,
1061592Srgrimes	0000,0200,0200,0000,0200,0000,0000,0200,
1071592Srgrimes	0200,0000,0000,0200,0000,0200,0200,0000,
1081592Srgrimes	0200,0000,0000,0200,0000,0200,0200,0000,
1091592Srgrimes	0000,0200,0200,0000,0200,0000,0000,0201
1101592Srgrimes};
1111592Srgrimes
1121592Srgrimes#define	ERASE	tmode.sg_erase
1131592Srgrimes#define	KILL	tmode.sg_kill
1141592Srgrimes#define	EOT	tc.t_eofc
1151592Srgrimes
1161592Srgrimesjmp_buf timeout;
1171592Srgrimes
1181592Srgrimesstatic void
1191592Srgrimesdingdong()
1201592Srgrimes{
1211592Srgrimes
1221592Srgrimes	alarm(0);
1231592Srgrimes	signal(SIGALRM, SIG_DFL);
1241592Srgrimes	longjmp(timeout, 1);
1251592Srgrimes}
1261592Srgrimes
1271592Srgrimesjmp_buf	intrupt;
1281592Srgrimes
1291592Srgrimesstatic void
1301592Srgrimesinterrupt()
1311592Srgrimes{
1321592Srgrimes
1331592Srgrimes	signal(SIGINT, interrupt);
1341592Srgrimes	longjmp(intrupt, 1);
1351592Srgrimes}
1361592Srgrimes
1371592Srgrimesmain(argc, argv)
1381592Srgrimes	int argc;
1392286Sjkh	char **argv;
1401592Srgrimes{
1412286Sjkh	extern	char **environ;
1421592Srgrimes	char *tname;
1431592Srgrimes	int repcnt = 0;
1441592Srgrimes
1451592Srgrimes	signal(SIGINT, SIG_IGN);
1462391Sache	signal(SIGQUIT, SIG_IGN);
1472286Sjkh
1481592Srgrimes	openlog("getty", LOG_ODELAY|LOG_CONS, LOG_AUTH);
1491592Srgrimes	gethostname(hostname, sizeof(hostname));
1501592Srgrimes	if (hostname[0] == '\0')
1511592Srgrimes		strcpy(hostname, "Amnesiac");
1521592Srgrimes	/*
1531592Srgrimes	 * The following is a work around for vhangup interactions
1541592Srgrimes	 * which cause great problems getting window systems started.
1551592Srgrimes	 * If the tty line is "-", we do the old style getty presuming
1561592Srgrimes	 * that the file descriptors are already set up for us.
1571592Srgrimes	 * J. Gettys - MIT Project Athena.
1581592Srgrimes	 */
1591592Srgrimes	if (argc <= 2 || strcmp(argv[2], "-") == 0)
1601592Srgrimes	    strcpy(ttyn, ttyname(0));
1611592Srgrimes	else {
1621592Srgrimes	    int i;
1631592Srgrimes
1641592Srgrimes	    strcpy(ttyn, dev);
1651592Srgrimes	    strncat(ttyn, argv[2], sizeof(ttyn)-sizeof(dev));
1661592Srgrimes	    if (strcmp(argv[0], "+") != 0) {
1671592Srgrimes		chown(ttyn, 0, 0);
1681592Srgrimes		chmod(ttyn, 0600);
1691592Srgrimes		revoke(ttyn);
1701592Srgrimes		while ((i = open(ttyn, O_RDWR)) == -1) {
1711592Srgrimes			if (repcnt % 10 == 0) {
1721592Srgrimes				syslog(LOG_ERR, "%s: %m", ttyn);
1731592Srgrimes				closelog();
1741592Srgrimes			}
1751592Srgrimes			repcnt++;
1761592Srgrimes			sleep(60);
1771592Srgrimes		}
1781592Srgrimes		login_tty(i);
1791592Srgrimes	    }
1801592Srgrimes	}
1811592Srgrimes
1822286Sjkh	gettable("default", defent, defstrs);
1831592Srgrimes	gendefaults();
1841592Srgrimes	tname = "default";
1851592Srgrimes	if (argc > 1)
1861592Srgrimes		tname = argv[1];
1871592Srgrimes	for (;;) {
1882286Sjkh		int off = 0;
1892286Sjkh		int flushboth = 0;
1902286Sjkh		struct sgttyb fake;
1911592Srgrimes
1922286Sjkh		gettable(tname, tabent, tabstrs);
1931592Srgrimes		if (OPset || EPset || APset)
1941592Srgrimes			APset++, OPset++, EPset++;
1951592Srgrimes		setdefaults();
1962286Sjkh		ioctl(0, TIOCFLUSH, &flushboth);         /* clear out the crap */
1971592Srgrimes		ioctl(0, FIONBIO, &off);	/* turn off non-blocking mode */
1981592Srgrimes		ioctl(0, FIOASYNC, &off);	/* ditto for async mode */
1992286Sjkh		ioctl(0, TIOCGETP, &fake);      /* initialize kernel termios */
2001592Srgrimes		if (IS)
2011592Srgrimes			tmode.sg_ispeed = speed(IS);
2021592Srgrimes		else if (SP)
2031592Srgrimes			tmode.sg_ispeed = speed(SP);
2041592Srgrimes		if (OS)
2051592Srgrimes			tmode.sg_ospeed = speed(OS);
2061592Srgrimes		else if (SP)
2071592Srgrimes			tmode.sg_ospeed = speed(SP);
2082286Sjkh		set_tmode(0);
2091592Srgrimes		setchars();
2101592Srgrimes		ioctl(0, TIOCSETC, &tc);
2111592Srgrimes		if (HC)
2121592Srgrimes			ioctl(0, TIOCHPCL, 0);
2131592Srgrimes		if (AB) {
2141592Srgrimes			extern char *autobaud();
2151592Srgrimes
2161592Srgrimes			tname = autobaud();
2171592Srgrimes			continue;
2181592Srgrimes		}
2191592Srgrimes		if (PS) {
2201592Srgrimes			tname = portselector();
2211592Srgrimes			continue;
2221592Srgrimes		}
2231592Srgrimes		if (CL && *CL)
2241592Srgrimes			putpad(CL);
2251592Srgrimes		edithost(HE);
2261592Srgrimes		if (IM && *IM)
2271592Srgrimes			putf(IM);
2281592Srgrimes		if (setjmp(timeout)) {
2291592Srgrimes			tmode.sg_ispeed = tmode.sg_ospeed = 0;
2301592Srgrimes			ioctl(0, TIOCSETP, &tmode);
2311592Srgrimes			exit(1);
2321592Srgrimes		}
2331592Srgrimes		if (TO) {
2341592Srgrimes			signal(SIGALRM, dingdong);
2351592Srgrimes			alarm(TO);
2361592Srgrimes		}
2371592Srgrimes		if (getname()) {
2381592Srgrimes			register int i;
2391592Srgrimes
2401592Srgrimes			alarm(0);
2411592Srgrimes			signal(SIGALRM, SIG_DFL);
2422286Sjkh			oflush();
2431592Srgrimes			if (name[0] == '-') {
2441592Srgrimes				puts("user names may not start with '-'.");
2451592Srgrimes				continue;
2461592Srgrimes			}
2471592Srgrimes			if (!(upper || lower || digit))
2481592Srgrimes				continue;
2492286Sjkh			set_tmode(2);
2501592Srgrimes			ioctl(0, TIOCSLTC, &ltc);
2511592Srgrimes			for (i = 0; environ[i] != (char *)0; i++)
2521592Srgrimes				env[i] = environ[i];
2531592Srgrimes			makeenv(&env[i]);
2541592Srgrimes
2551592Srgrimes			execle(LO, "login", "-p", name, (char *) 0, env);
2561592Srgrimes			syslog(LOG_ERR, "%s: %m", LO);
2571592Srgrimes			exit(1);
2581592Srgrimes		}
2592286Sjkh		signal(SIGINT, SIG_IGN);
2601592Srgrimes		alarm(0);
2611592Srgrimes		signal(SIGALRM, SIG_DFL);
2621592Srgrimes		if (NX && *NX)
2631592Srgrimes			tname = NX;
2641592Srgrimes	}
2651592Srgrimes}
2661592Srgrimes
2671592Srgrimesgetname()
2681592Srgrimes{
2691592Srgrimes	register int c;
2701592Srgrimes	register char *np;
2711592Srgrimes	char cs;
2722286Sjkh	int flushin = 1 /*FREAD*/;
2731592Srgrimes
2741592Srgrimes	/*
2751592Srgrimes	 * Interrupt may happen if we use CBREAK mode
2761592Srgrimes	 */
2771592Srgrimes	if (setjmp(intrupt)) {
2781592Srgrimes		signal(SIGINT, SIG_IGN);
2791592Srgrimes		return (0);
2801592Srgrimes	}
2811592Srgrimes	signal(SIGINT, interrupt);
2822286Sjkh	ioctl(0, TIOCFLUSH, &flushin);         /* purge any input */
2831592Srgrimes	prompt();
2842286Sjkh	oflush();
2851592Srgrimes	if (PF > 0) {
2861592Srgrimes		sleep(PF);
2871592Srgrimes		PF = 0;
2881592Srgrimes	}
2892286Sjkh	set_tmode(1);
2901592Srgrimes	crmod = digit = lower = upper = 0;
2911592Srgrimes	np = name;
2921592Srgrimes	for (;;) {
2931592Srgrimes		oflush();
2941592Srgrimes		if (read(STDIN_FILENO, &cs, 1) <= 0)
2951592Srgrimes			exit(0);
2961592Srgrimes		if ((c = cs&0177) == 0)
2971592Srgrimes			return (0);
2982286Sjkh		if (c == EOT || c == 4 /*^D*/)
2991592Srgrimes			exit(1);
3001592Srgrimes		if (c == '\r' || c == '\n' || np >= &name[sizeof name]) {
3011592Srgrimes			putf("\r\n");
3021592Srgrimes			break;
3031592Srgrimes		}
3041592Srgrimes		if (islower(c))
3051592Srgrimes			lower = 1;
3061592Srgrimes		else if (isupper(c))
3071592Srgrimes			upper = 1;
3082286Sjkh		else if (c == ERASE || c == '\b' || c == 0177) {
3091592Srgrimes			if (np > name) {
3101592Srgrimes				np--;
3111592Srgrimes				if (tmode.sg_ospeed >= B1200)
3121592Srgrimes					puts("\b \b");
3131592Srgrimes				else
3141592Srgrimes					putchr(cs);
3151592Srgrimes			}
3161592Srgrimes			continue;
3172286Sjkh		} else if (c == KILL || c == 025 /*^U*/) {
3181592Srgrimes			putchr('\r');
3191592Srgrimes			if (tmode.sg_ospeed < B1200)
3201592Srgrimes				putchr('\n');
3211592Srgrimes			/* this is the way they do it down under ... */
3221592Srgrimes			else if (np > name)
3231592Srgrimes				puts("                                     \r");
3241592Srgrimes			prompt();
3251592Srgrimes			np = name;
3261592Srgrimes			continue;
3271592Srgrimes		} else if (isdigit(c))
3281592Srgrimes			digit++;
3291592Srgrimes		if (IG && (c <= ' ' || c > 0176))
3301592Srgrimes			continue;
3311592Srgrimes		*np++ = c;
3321592Srgrimes		putchr(cs);
3331592Srgrimes	}
3341592Srgrimes	signal(SIGINT, SIG_IGN);
3351592Srgrimes	*np = 0;
3361592Srgrimes	if (c == '\r')
3371592Srgrimes		crmod = 1;
3381592Srgrimes	if (upper && !lower && !LC || UC)
3391592Srgrimes		for (np = name; *np; np++)
3401592Srgrimes			if (isupper(*np))
3411592Srgrimes				*np = tolower(*np);
3421592Srgrimes	return (1);
3431592Srgrimes}
3441592Srgrimes
3451592Srgrimesstatic
3461592Srgrimesshort	tmspc10[] = {
3471592Srgrimes	0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5, 15
3481592Srgrimes};
3491592Srgrimes
3501592Srgrimesputpad(s)
3511592Srgrimes	register char *s;
3521592Srgrimes{
3531592Srgrimes	register pad = 0;
3541592Srgrimes	register mspc10;
3551592Srgrimes
3561592Srgrimes	if (isdigit(*s)) {
3571592Srgrimes		while (isdigit(*s)) {
3581592Srgrimes			pad *= 10;
3591592Srgrimes			pad += *s++ - '0';
3601592Srgrimes		}
3611592Srgrimes		pad *= 10;
3621592Srgrimes		if (*s == '.' && isdigit(s[1])) {
3631592Srgrimes			pad += s[1] - '0';
3641592Srgrimes			s += 2;
3651592Srgrimes		}
3661592Srgrimes	}
3671592Srgrimes
3681592Srgrimes	puts(s);
3691592Srgrimes	/*
3701592Srgrimes	 * If no delay needed, or output speed is
3711592Srgrimes	 * not comprehensible, then don't try to delay.
3721592Srgrimes	 */
3731592Srgrimes	if (pad == 0)
3741592Srgrimes		return;
3751592Srgrimes	if (tmode.sg_ospeed <= 0 ||
3761592Srgrimes	    tmode.sg_ospeed >= (sizeof tmspc10 / sizeof tmspc10[0]))
3771592Srgrimes		return;
3781592Srgrimes
3791592Srgrimes	/*
3801592Srgrimes	 * Round up by a half a character frame, and then do the delay.
3811592Srgrimes	 * Too bad there are no user program accessible programmed delays.
3821592Srgrimes	 * Transmitting pad characters slows many terminals down and also
3831592Srgrimes	 * loads the system.
3841592Srgrimes	 */
3851592Srgrimes	mspc10 = tmspc10[tmode.sg_ospeed];
3861592Srgrimes	pad += mspc10 / 2;
3871592Srgrimes	for (pad /= mspc10; pad > 0; pad--)
3881592Srgrimes		putchr(*PC);
3891592Srgrimes}
3901592Srgrimes
3911592Srgrimesputs(s)
3921592Srgrimes	register char *s;
3931592Srgrimes{
3941592Srgrimes	while (*s)
3951592Srgrimes		putchr(*s++);
3961592Srgrimes}
3971592Srgrimes
3981592Srgrimeschar	outbuf[OBUFSIZ];
3991592Srgrimesint	obufcnt = 0;
4001592Srgrimes
4011592Srgrimesputchr(cc)
4021592Srgrimes{
4031592Srgrimes	char c;
4041592Srgrimes
4051592Srgrimes	c = cc;
4061592Srgrimes	if (!NP) {
4071592Srgrimes		c |= partab[c&0177] & 0200;
4081592Srgrimes		if (OP)
4091592Srgrimes			c ^= 0200;
4101592Srgrimes	}
4111592Srgrimes	if (!UB) {
4121592Srgrimes		outbuf[obufcnt++] = c;
4131592Srgrimes		if (obufcnt >= OBUFSIZ)
4141592Srgrimes			oflush();
4151592Srgrimes	} else
4161592Srgrimes		write(STDOUT_FILENO, &c, 1);
4171592Srgrimes}
4181592Srgrimes
4191592Srgrimesoflush()
4201592Srgrimes{
4211592Srgrimes	if (obufcnt)
4221592Srgrimes		write(STDOUT_FILENO, outbuf, obufcnt);
4231592Srgrimes	obufcnt = 0;
4241592Srgrimes}
4251592Srgrimes
4261592Srgrimesprompt()
4271592Srgrimes{
4281592Srgrimes
4291592Srgrimes	putf(LM);
4301592Srgrimes	if (CO)
4311592Srgrimes		putchr('\n');
4321592Srgrimes}
4331592Srgrimes
4341592Srgrimesputf(cp)
4351592Srgrimes	register char *cp;
4361592Srgrimes{
4371592Srgrimes	extern char editedhost[];
4381592Srgrimes	time_t t;
4391592Srgrimes	char *slash, db[100];
4401592Srgrimes
4411592Srgrimes	while (*cp) {
4421592Srgrimes		if (*cp != '%') {
4431592Srgrimes			putchr(*cp++);
4441592Srgrimes			continue;
4451592Srgrimes		}
4461592Srgrimes		switch (*++cp) {
4471592Srgrimes
4481592Srgrimes		case 't':
4492286Sjkh			slash = rindex(ttyn, '/');
4501592Srgrimes			if (slash == (char *) 0)
4511592Srgrimes				puts(ttyn);
4521592Srgrimes			else
4531592Srgrimes				puts(&slash[1]);
4541592Srgrimes			break;
4551592Srgrimes
4561592Srgrimes		case 'h':
4571592Srgrimes			puts(editedhost);
4581592Srgrimes			break;
4591592Srgrimes
4601592Srgrimes		case 'd': {
4611592Srgrimes			static char fmt[] = "%l:% %P on %A, %d %B %Y";
4621592Srgrimes
4631592Srgrimes			fmt[4] = 'M';		/* I *hate* SCCS... */
4641592Srgrimes			(void)time(&t);
4651592Srgrimes			(void)strftime(db, sizeof(db), fmt, localtime(&t));
4661592Srgrimes			puts(db);
4671592Srgrimes			break;
4681592Srgrimes		}
4691592Srgrimes
4701592Srgrimes		case '%':
4711592Srgrimes			putchr('%');
4721592Srgrimes			break;
4731592Srgrimes		}
4741592Srgrimes		cp++;
4751592Srgrimes	}
4761592Srgrimes}
4772286Sjkh
4782286Sjkh/*
4792286Sjkh * The conversions from sgttyb to termios make LITOUT and PASS8 affect
4802286Sjkh * the parity.  So every TIOCSETP ioctl has to be paired with a TIOCLSET
4812286Sjkh * ioctl (at least if LITOUT or PASS8 has changed, and PASS8 may vary
4822286Sjkh * with 'n').
4832286Sjkh */
4842286Sjkhset_tmode(n)
4852286Sjkh	int n;
4862286Sjkh{
4872286Sjkh	long allflags;
4882286Sjkh
4892286Sjkh	allflags = setflags(n);
4902286Sjkh	tmode.sg_flags = allflags & 0xffff;
4912286Sjkh	allflags >>= 16;
4922286Sjkh	if (n == 2) {
4932286Sjkh		if (crmod || NL)
4942286Sjkh			tmode.sg_flags |= CRMOD;
4952286Sjkh		if (upper || UC)
4962286Sjkh			tmode.sg_flags |= LCASE;
4972286Sjkh		if (lower || LC)
4982286Sjkh			tmode.sg_flags &= ~LCASE;
4992286Sjkh	}
5002286Sjkh	ioctl(0, TIOCSETP, &tmode);
5012286Sjkh	ioctl(0, TIOCLSET, &allflags);
5022286Sjkh}
503