Home | History | Annotate | Line # | Download | only in login
login.c revision 1.12
      1 /*	$NetBSD: login.c,v 1.12 1994/12/23 06:53:01 jtc Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 1980, 1987, 1988, 1991, 1993, 1994
      5  *	The Regents of the University of California.  All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. All advertising materials mentioning features or use of this software
     16  *    must display the following acknowledgement:
     17  *	This product includes software developed by the University of
     18  *	California, Berkeley and its contributors.
     19  * 4. Neither the name of the University nor the names of its contributors
     20  *    may be used to endorse or promote products derived from this software
     21  *    without specific prior written permission.
     22  *
     23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     33  * SUCH DAMAGE.
     34  */
     35 
     36 #ifndef lint
     37 static char copyright[] =
     38 "@(#) Copyright (c) 1980, 1987, 1988, 1991, 1993, 1994\n\
     39 	The Regents of the University of California.  All rights reserved.\n";
     40 #endif /* not lint */
     41 
     42 #ifndef lint
     43 #if 0
     44 static char sccsid[] = "@(#)login.c	8.4 (Berkeley) 4/2/94";
     45 #endif
     46 static char rcsid[] = "$NetBSD: login.c,v 1.12 1994/12/23 06:53:01 jtc Exp $";
     47 #endif /* not lint */
     48 
     49 /*
     50  * login [ name ]
     51  * login -h hostname	(for telnetd, etc.)
     52  * login -f name	(for pre-authenticated login: datakit, xterm, etc.)
     53  */
     54 
     55 #include <sys/param.h>
     56 #include <sys/stat.h>
     57 #include <sys/time.h>
     58 #include <sys/resource.h>
     59 #include <sys/file.h>
     60 
     61 #include <err.h>
     62 #include <errno.h>
     63 #include <grp.h>
     64 #include <pwd.h>
     65 #include <setjmp.h>
     66 #include <signal.h>
     67 #include <stdio.h>
     68 #include <stdlib.h>
     69 #include <string.h>
     70 #include <syslog.h>
     71 #include <ttyent.h>
     72 #include <tzfile.h>
     73 #include <unistd.h>
     74 #include <utmp.h>
     75 
     76 #include "pathnames.h"
     77 
     78 void	 badlogin __P((char *));
     79 void	 checknologin __P((void));
     80 void	 dolastlog __P((int));
     81 void	 getloginname __P((void));
     82 void	 motd __P((void));
     83 int	 rootterm __P((char *));
     84 void	 sigint __P((int));
     85 void	 sleepexit __P((int));
     86 char	*stypeof __P((char *));
     87 void	 timedout __P((int));
     88 int	 pwcheck __P((char *, char *, char *, char *));
     89 #if defined(KERBEROS) || defined(KERBEROS5)
     90 int	 klogin __P((struct passwd *, char *, char *, char *));
     91 void	 kdestroy __P((void));
     92 void	 dofork __P((void));
     93 #endif
     94 
     95 extern void login __P((struct utmp *));
     96 
     97 #define	TTYGRPNAME	"tty"		/* name of group to own ttys */
     98 
     99 /*
    100  * This bounds the time given to login.  Not a define so it can
    101  * be patched on machines where it's too small.
    102  */
    103 u_int	timeout = 300;
    104 
    105 #if defined(KERBEROS) || defined(KERBEROS5)
    106 int	notickets = 1;
    107 char	*instance;
    108 char	*krbtkfile_env;
    109 int	authok;
    110 #endif
    111 
    112 struct	passwd *pwd;
    113 int	failures;
    114 char	term[64], *envinit[1], *hostname, *username, *tty;
    115 
    116 int
    117 main(argc, argv)
    118 	int argc;
    119 	char *argv[];
    120 {
    121 	extern char **environ;
    122 	struct group *gr;
    123 	struct stat st;
    124 	struct timeval tp;
    125 	struct utmp utmp;
    126 	int ask, ch, cnt, fflag, hflag, pflag, quietlog, rootlogin, rval;
    127 	uid_t uid;
    128 	char *domain, *p, *salt, *ttyn;
    129 	char tbuf[MAXPATHLEN + 2], tname[sizeof(_PATH_TTY) + 10];
    130 	char localhost[MAXHOSTNAMELEN];
    131 
    132 	(void)signal(SIGALRM, timedout);
    133 	(void)alarm(timeout);
    134 	(void)signal(SIGQUIT, SIG_IGN);
    135 	(void)signal(SIGINT, SIG_IGN);
    136 	(void)setpriority(PRIO_PROCESS, 0, 0);
    137 
    138 	openlog("login", LOG_ODELAY, LOG_AUTH);
    139 
    140 	/*
    141 	 * -p is used by getty to tell login not to destroy the environment
    142 	 * -f is used to skip a second login authentication
    143 	 * -h is used by other servers to pass the name of the remote
    144 	 *    host to login so that it may be placed in utmp and wtmp
    145 	 */
    146 	domain = NULL;
    147 	if (gethostname(localhost, sizeof(localhost)) < 0)
    148 		syslog(LOG_ERR, "couldn't get local hostname: %m");
    149 	else
    150 		domain = strchr(localhost, '.');
    151 
    152 	fflag = hflag = pflag = 0;
    153 	uid = getuid();
    154 	while ((ch = getopt(argc, argv, "fh:p")) != EOF)
    155 		switch (ch) {
    156 		case 'f':
    157 			fflag = 1;
    158 			break;
    159 		case 'h':
    160 			if (uid)
    161 				errx(1, "-h option: %s", strerror(EPERM));
    162 			hflag = 1;
    163 			if (domain && (p = strchr(optarg, '.')) &&
    164 			    strcasecmp(p, domain) == 0)
    165 				*p = 0;
    166 			hostname = optarg;
    167 			break;
    168 		case 'p':
    169 			pflag = 1;
    170 			break;
    171 		case '?':
    172 		default:
    173 			if (!uid)
    174 				syslog(LOG_ERR, "invalid flag %c", ch);
    175 			(void)fprintf(stderr,
    176 			    "usage: login [-fp] [-h hostname] [username]\n");
    177 			exit(1);
    178 		}
    179 	argc -= optind;
    180 	argv += optind;
    181 
    182 	if (*argv) {
    183 		username = *argv;
    184 		ask = 0;
    185 	} else
    186 		ask = 1;
    187 
    188 	for (cnt = getdtablesize(); cnt > 2; cnt--)
    189 		(void)close(cnt);
    190 
    191 	ttyn = ttyname(STDIN_FILENO);
    192 	if (ttyn == NULL || *ttyn == '\0') {
    193 		(void)snprintf(tname, sizeof(tname), "%s??", _PATH_TTY);
    194 		ttyn = tname;
    195 	}
    196 	if (tty = strrchr(ttyn, '/'))
    197 		++tty;
    198 	else
    199 		tty = ttyn;
    200 
    201 	for (cnt = 0;; ask = 1) {
    202 #if defined(KERBEROS) || defined(KERBEROS5)
    203 	        kdestroy();
    204 #endif
    205 		if (ask) {
    206 			fflag = 0;
    207 			getloginname();
    208 		}
    209 		rootlogin = 0;
    210 #ifdef	KERBEROS
    211 		if ((instance = strchr(username, '.')) != NULL) {
    212 			if (strncmp(instance, ".root", 5) == 0)
    213 				rootlogin = 1;
    214 			*instance++ = '\0';
    215 		} else
    216 			instance = "";
    217 #endif
    218 #ifdef KERBEROS5
    219 		if ((instance = strchr(username, '/')) != NULL) {
    220 			if (strncmp(instance, "/root", 5) == 0)
    221 				rootlogin = 1;
    222 			*instance++ = '\0';
    223 		} else
    224 			instance = "";
    225 #endif
    226 		if (strlen(username) > UT_NAMESIZE)
    227 			username[UT_NAMESIZE] = '\0';
    228 
    229 		/*
    230 		 * Note if trying multiple user names; log failures for
    231 		 * previous user name, but don't bother logging one failure
    232 		 * for nonexistent name (mistyped username).
    233 		 */
    234 		if (failures && strcmp(tbuf, username)) {
    235 			if (failures > (pwd ? 0 : 1))
    236 				badlogin(tbuf);
    237 			failures = 0;
    238 		}
    239 		(void)strcpy(tbuf, username);
    240 
    241 		if (pwd = getpwnam(username))
    242 			salt = pwd->pw_passwd;
    243 		else
    244 			salt = "xx";
    245 
    246 		/*
    247 		 * if we have a valid account name, and it doesn't have a
    248 		 * password, or the -f option was specified and the caller
    249 		 * is root or the caller isn't changing their uid, don't
    250 		 * authenticate.
    251 		 */
    252 		if (pwd) {
    253 			if (pwd->pw_uid == 0)
    254 				rootlogin = 1;
    255 
    256 			if (fflag && (uid == 0 || uid == pwd->pw_uid)) {
    257 				/* already authenticated */
    258 				break;
    259 			} else if (pwd->pw_passwd[0] == '\0') {
    260 				/* pretend password okay */
    261 				rval = 0;
    262 				goto ttycheck;
    263 			}
    264 		}
    265 
    266 		fflag = 0;
    267 
    268 		(void)setpriority(PRIO_PROCESS, 0, -4);
    269 
    270 		p = getpass("Password:");
    271 
    272 		if (pwd) {
    273 #if defined(KERBEROS) || defined(KERBEROS5)
    274 			rval = klogin(pwd, instance, localhost, p);
    275 			if (rval != 0 && rootlogin && pwd->pw_uid != 0)
    276 				rootlogin = 0;
    277 			if (rval == 0)
    278 				authok = 1;
    279 			else if (rval == 1) {
    280 				if (pwd->pw_uid != 0)
    281 					rootlogin = 0;
    282 				rval = pwcheck(username, p, salt, pwd->pw_passwd);
    283 			}
    284 #else
    285 			rval = pwcheck(username, p, salt, pwd->pw_passwd);
    286 #endif
    287 		}
    288 		memset(p, 0, strlen(p));
    289 
    290 		(void)setpriority(PRIO_PROCESS, 0, 0);
    291 
    292 	ttycheck:
    293 		/*
    294 		 * If trying to log in as root without Kerberos,
    295 		 * but with insecure terminal, refuse the login attempt.
    296 		 */
    297 #if defined(KERBEROS) || defined(KERBEROS5)
    298 		if (authok == 0)
    299 #endif
    300 		if (pwd && !rval && rootlogin && !rootterm(tty)) {
    301 			(void)fprintf(stderr,
    302 			    "%s login refused on this terminal.\n",
    303 			    pwd->pw_name);
    304 			if (hostname)
    305 				syslog(LOG_NOTICE,
    306 				    "LOGIN %s REFUSED FROM %s ON TTY %s",
    307 				    pwd->pw_name, hostname, tty);
    308 			else
    309 				syslog(LOG_NOTICE,
    310 				    "LOGIN %s REFUSED ON TTY %s",
    311 				     pwd->pw_name, tty);
    312 			continue;
    313 		}
    314 
    315 		if (pwd && !rval)
    316 			break;
    317 
    318 		(void)printf("Login incorrect\n");
    319 		failures++;
    320 		/* we allow 10 tries, but after 3 we start backing off */
    321 		if (++cnt > 3) {
    322 			if (cnt >= 10) {
    323 				badlogin(username);
    324 				sleepexit(1);
    325 			}
    326 			sleep((u_int)((cnt - 3) * 5));
    327 		}
    328 	}
    329 
    330 	/* committed to login -- turn off timeout */
    331 	(void)alarm((u_int)0);
    332 
    333 	endpwent();
    334 
    335 	/* if user not super-user, check for disabled logins */
    336 	if (!rootlogin)
    337 		checknologin();
    338 
    339 	if (chdir(pwd->pw_dir) < 0) {
    340 		(void)printf("No home directory %s!\n", pwd->pw_dir);
    341 		if (chdir("/"))
    342 			exit(0);
    343 		pwd->pw_dir = "/";
    344 		(void)printf("Logging in with home = \"/\".\n");
    345 	}
    346 
    347 	quietlog = access(_PATH_HUSHLOGIN, F_OK) == 0;
    348 
    349 	if (pwd->pw_change || pwd->pw_expire)
    350 		(void)gettimeofday(&tp, (struct timezone *)NULL);
    351 	if (pwd->pw_change)
    352 		if (tp.tv_sec >= pwd->pw_change) {
    353 			(void)printf("Sorry -- your password has expired.\n");
    354 			sleepexit(1);
    355 		} else if (pwd->pw_change - tp.tv_sec <
    356 		    2 * DAYSPERWEEK * SECSPERDAY && !quietlog)
    357 			(void)printf("Warning: your password expires on %s",
    358 			    ctime(&pwd->pw_change));
    359 	if (pwd->pw_expire)
    360 		if (tp.tv_sec >= pwd->pw_expire) {
    361 			(void)printf("Sorry -- your account has expired.\n");
    362 			sleepexit(1);
    363 		} else if (pwd->pw_expire - tp.tv_sec <
    364 		    2 * DAYSPERWEEK * SECSPERDAY && !quietlog)
    365 			(void)printf("Warning: your account expires on %s",
    366 			    ctime(&pwd->pw_expire));
    367 
    368 	/* Nothing else left to fail -- really log in. */
    369 	memset((void *)&utmp, 0, sizeof(utmp));
    370 	(void)time(&utmp.ut_time);
    371 	(void)strncpy(utmp.ut_name, username, sizeof(utmp.ut_name));
    372 	if (hostname)
    373 		(void)strncpy(utmp.ut_host, hostname, sizeof(utmp.ut_host));
    374 	(void)strncpy(utmp.ut_line, tty, sizeof(utmp.ut_line));
    375 	login(&utmp);
    376 
    377 	dolastlog(quietlog);
    378 
    379 	(void)chown(ttyn, pwd->pw_uid,
    380 	    (gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid);
    381 #if defined(KERBEROS) || defined(KERBEROS5)
    382 	/* Fork so that we can call kdestroy */
    383 	if (krbtkfile_env)
    384 	    dofork();
    385 #endif
    386 	(void)setgid(pwd->pw_gid);
    387 
    388 	initgroups(username, pwd->pw_gid);
    389 
    390 	if (*pwd->pw_shell == '\0')
    391 		pwd->pw_shell = _PATH_BSHELL;
    392 
    393 	/* Destroy environment unless user has requested its preservation. */
    394 	if (!pflag)
    395 		environ = envinit;
    396 	(void)setenv("HOME", pwd->pw_dir, 1);
    397 	(void)setenv("SHELL", pwd->pw_shell, 1);
    398 	if (term[0] == '\0')
    399 		(void)strncpy(term, stypeof(tty), sizeof(term));
    400 	(void)setenv("TERM", term, 0);
    401 	(void)setenv("LOGNAME", pwd->pw_name, 1);
    402 	(void)setenv("USER", pwd->pw_name, 1);
    403 	(void)setenv("PATH", _PATH_DEFPATH, 0);
    404 #ifdef KERBEROS
    405 	if (krbtkfile_env)
    406 		(void)setenv("KRBTKFILE", krbtkfile_env, 1);
    407 #endif
    408 #ifdef KERBEROS5
    409 	if (krbtkfile_env)
    410 		(void)setenv("KRB5CCNAME", krbtkfile_env, 1);
    411 #endif
    412 
    413 	if (tty[sizeof("tty")-1] == 'd')
    414 		syslog(LOG_INFO, "DIALUP %s, %s", tty, pwd->pw_name);
    415 
    416 	/* If fflag is on, assume caller/authenticator has logged root login. */
    417 	if (rootlogin && fflag == 0)
    418 		if (hostname)
    419 			syslog(LOG_NOTICE, "ROOT LOGIN (%s) ON %s FROM %s",
    420 			    username, tty, hostname);
    421 		else
    422 			syslog(LOG_NOTICE, "ROOT LOGIN (%s) ON %s", username, tty);
    423 
    424 #if defined(KERBEROS) || defined(KERBEROS5)
    425 	if (!quietlog && notickets == 1)
    426 		(void)printf("Warning: no Kerberos tickets issued.\n");
    427 #endif
    428 
    429 	if (!quietlog) {
    430 		(void)printf("%s\n\t%s  %s\n\n",
    431 	    "Copyright (c) 1980, 1983, 1986, 1988, 1990, 1991, 1993, 1994",
    432 		    "The Regents of the University of California. ",
    433 		    "All rights reserved.");
    434 		motd();
    435 		(void)snprintf(tbuf,
    436 		    sizeof(tbuf), "%s/%s", _PATH_MAILDIR, pwd->pw_name);
    437 		if (stat(tbuf, &st) == 0 && st.st_size != 0)
    438 			(void)printf("You have %smail.\n",
    439 			    (st.st_mtime > st.st_atime) ? "new " : "");
    440 	}
    441 
    442 	(void)signal(SIGALRM, SIG_DFL);
    443 	(void)signal(SIGQUIT, SIG_DFL);
    444 	(void)signal(SIGINT, SIG_DFL);
    445 	(void)signal(SIGTSTP, SIG_IGN);
    446 
    447 	tbuf[0] = '-';
    448 	(void)strcpy(tbuf + 1, (p = strrchr(pwd->pw_shell, '/')) ?
    449 	    p + 1 : pwd->pw_shell);
    450 
    451 	if (setlogin(pwd->pw_name) < 0)
    452 		syslog(LOG_ERR, "setlogin() failure: %m");
    453 
    454 	/* Discard permissions last so can't get killed and drop core. */
    455 	if (rootlogin)
    456 		(void) setuid(0);
    457 	else
    458 		(void) setuid(pwd->pw_uid);
    459 
    460 	execlp(pwd->pw_shell, tbuf, 0);
    461 	err(1, "%s", pwd->pw_shell);
    462 }
    463 
    464 int
    465 pwcheck(user, p, salt, passwd)
    466 	char *user, *p, *salt, *passwd;
    467 {
    468 #ifdef SKEY
    469 	if (strcasecmp(p, "s/key") == 0) {
    470 		if (skey_haskey(user)) {
    471 			fprintf(stderr, "You have no s/key. ");
    472 			return 1;
    473 		} else {
    474 			return skey_authenticate(user);
    475 		}
    476 	}
    477 #endif
    478 	return strcmp(crypt(p, salt), passwd);
    479 }
    480 
    481 #if defined(KERBEROS) || defined(KERBEROS5)
    482 #define	NBUFSIZ		(UT_NAMESIZE + 1 + 5)	/* .root suffix */
    483 #else
    484 #define	NBUFSIZ		(UT_NAMESIZE + 1)
    485 #endif
    486 
    487 #if defined(KERBEROS) || defined(KERBEROS5)
    488 /*
    489  * This routine handles cleanup stuff, and the like.
    490  * It exists only in the child process.
    491  */
    492 #include <sys/wait.h>
    493 void
    494 dofork()
    495 {
    496     int child;
    497 
    498     if (!(child = fork()))
    499 	    return; /* Child process */
    500 
    501     /* Setup stuff?  This would be things we could do in parallel with login */
    502     (void) chdir("/");	/* Let's not keep the fs busy... */
    503 
    504     /* If we're the parent, watch the child until it dies */
    505     while (wait(0) != child)
    506 	    ;
    507 
    508     /* Cleanup stuff */
    509     /* Run kdestroy to destroy tickets */
    510     kdestroy();
    511 
    512     /* Leave */
    513     exit(0);
    514 }
    515 #endif
    516 
    517 void
    518 getloginname()
    519 {
    520 	int ch;
    521 	char *p;
    522 	static char nbuf[NBUFSIZ];
    523 
    524 	for (;;) {
    525 		(void)printf("login: ");
    526 		for (p = nbuf; (ch = getchar()) != '\n'; ) {
    527 			if (ch == EOF) {
    528 				badlogin(username);
    529 				exit(0);
    530 			}
    531 			if (p < nbuf + (NBUFSIZ - 1))
    532 				*p++ = ch;
    533 		}
    534 		if (p > nbuf)
    535 			if (nbuf[0] == '-')
    536 				(void)fprintf(stderr,
    537 				    "login names may not start with '-'.\n");
    538 			else {
    539 				*p = '\0';
    540 				username = nbuf;
    541 				break;
    542 			}
    543 	}
    544 }
    545 
    546 int
    547 rootterm(ttyn)
    548 	char *ttyn;
    549 {
    550 	struct ttyent *t;
    551 
    552 	return ((t = getttynam(ttyn)) && t->ty_status & TTY_SECURE);
    553 }
    554 
    555 jmp_buf motdinterrupt;
    556 
    557 void
    558 motd()
    559 {
    560 	int fd, nchars;
    561 	sig_t oldint;
    562 	char tbuf[8192];
    563 
    564 	if ((fd = open(_PATH_MOTDFILE, O_RDONLY, 0)) < 0)
    565 		return;
    566 	oldint = signal(SIGINT, sigint);
    567 	if (setjmp(motdinterrupt) == 0)
    568 		while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0)
    569 			(void)write(fileno(stdout), tbuf, nchars);
    570 	(void)signal(SIGINT, oldint);
    571 	(void)close(fd);
    572 }
    573 
    574 /* ARGSUSED */
    575 void
    576 sigint(signo)
    577 	int signo;
    578 {
    579 	longjmp(motdinterrupt, 1);
    580 }
    581 
    582 /* ARGSUSED */
    583 void
    584 timedout(signo)
    585 	int signo;
    586 {
    587 	(void)fprintf(stderr, "Login timed out after %d seconds\n", timeout);
    588 	exit(0);
    589 }
    590 
    591 void
    592 checknologin()
    593 {
    594 	int fd, nchars;
    595 	char tbuf[8192];
    596 
    597 	if ((fd = open(_PATH_NOLOGIN, O_RDONLY, 0)) >= 0) {
    598 		while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0)
    599 			(void)write(fileno(stdout), tbuf, nchars);
    600 		sleepexit(0);
    601 	}
    602 }
    603 
    604 void
    605 dolastlog(quiet)
    606 	int quiet;
    607 {
    608 	struct lastlog ll;
    609 	int fd;
    610 
    611 	if ((fd = open(_PATH_LASTLOG, O_RDWR, 0)) >= 0) {
    612 		(void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), L_SET);
    613 		if (!quiet) {
    614 			if (read(fd, (char *)&ll, sizeof(ll)) == sizeof(ll) &&
    615 			    ll.ll_time != 0) {
    616 				(void)printf("Last login: %.*s ",
    617 				    24-5, (char *)ctime(&ll.ll_time));
    618 				if (*ll.ll_host != '\0')
    619 					(void)printf("from %.*s\n",
    620 					    (int)sizeof(ll.ll_host),
    621 					    ll.ll_host);
    622 				else
    623 					(void)printf("on %.*s\n",
    624 					    (int)sizeof(ll.ll_line),
    625 					    ll.ll_line);
    626 			}
    627 			(void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), L_SET);
    628 		}
    629 		memset((void *)&ll, 0, sizeof(ll));
    630 		(void)time(&ll.ll_time);
    631 		(void)strncpy(ll.ll_line, tty, sizeof(ll.ll_line));
    632 		if (hostname)
    633 			(void)strncpy(ll.ll_host, hostname, sizeof(ll.ll_host));
    634 		(void)write(fd, (char *)&ll, sizeof(ll));
    635 		(void)close(fd);
    636 	}
    637 }
    638 
    639 void
    640 badlogin(name)
    641 	char *name;
    642 {
    643 	if (failures == 0)
    644 		return;
    645 	if (hostname) {
    646 		syslog(LOG_NOTICE, "%d LOGIN FAILURE%s FROM %s",
    647 		    failures, failures > 1 ? "S" : "", hostname);
    648 		syslog(LOG_AUTHPRIV|LOG_NOTICE,
    649 		    "%d LOGIN FAILURE%s FROM %s, %s",
    650 		    failures, failures > 1 ? "S" : "", hostname, name);
    651 	} else {
    652 		syslog(LOG_NOTICE, "%d LOGIN FAILURE%s ON %s",
    653 		    failures, failures > 1 ? "S" : "", tty);
    654 		syslog(LOG_AUTHPRIV|LOG_NOTICE,
    655 		    "%d LOGIN FAILURE%s ON %s, %s",
    656 		    failures, failures > 1 ? "S" : "", tty, name);
    657 	}
    658 }
    659 
    660 #undef	UNKNOWN
    661 #define	UNKNOWN	"su"
    662 
    663 char *
    664 stypeof(ttyid)
    665 	char *ttyid;
    666 {
    667 	struct ttyent *t;
    668 
    669 	return (ttyid && (t = getttynam(ttyid)) ? t->ty_type : UNKNOWN);
    670 }
    671 
    672 void
    673 sleepexit(eval)
    674 	int eval;
    675 {
    676 	(void)sleep(5);
    677 	exit(eval);
    678 }
    679