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