xref: /csrg-svn/usr.bin/login/login.c (revision 66662)
143653Sbostic /*-
266249Sbostic  * Copyright (c) 1980, 1987, 1988, 1991, 1993, 1994
363063Sbostic  *	The Regents of the University of California.  All rights reserved.
436515Sbostic  *
543653Sbostic  * %sccs.include.redist.c%
619843Sdist  */
719843Sdist 
812678Ssam #ifndef lint
963063Sbostic static char copyright[] =
1066249Sbostic "@(#) Copyright (c) 1980, 1987, 1988, 1991, 1993, 1994\n\
1163063Sbostic 	The Regents of the University of California.  All rights reserved.\n";
1236515Sbostic #endif /* not lint */
1312678Ssam 
1419843Sdist #ifndef lint
15*66662Spendry static char sccsid[] = "@(#)login.c	8.4 (Berkeley) 04/02/94";
1636515Sbostic #endif /* not lint */
1719843Sdist 
181043Sbill /*
191043Sbill  * login [ name ]
2031695Skarels  * login -h hostname	(for telnetd, etc.)
2131695Skarels  * login -f name	(for pre-authenticated login: datakit, xterm, etc.)
221043Sbill  */
231043Sbill 
2412984Ssam #include <sys/param.h>
2512687Ssam #include <sys/stat.h>
2612687Ssam #include <sys/time.h>
2712687Ssam #include <sys/resource.h>
2816453Sroot #include <sys/file.h>
2912687Ssam 
3066623Spendry #include <err.h>
3153274Sbostic #include <errno.h>
3226862Smckusick #include <grp.h>
3336460Sbostic #include <pwd.h>
3466623Spendry #include <setjmp.h>
3566623Spendry #include <signal.h>
3636460Sbostic #include <stdio.h>
3753274Sbostic #include <stdlib.h>
3842063Sbostic #include <string.h>
3966623Spendry #include <syslog.h>
4066623Spendry #include <ttyent.h>
4166623Spendry #include <tzfile.h>
4266623Spendry #include <unistd.h>
4366623Spendry #include <utmp.h>
4466623Spendry 
4537203Sbostic #include "pathnames.h"
461043Sbill 
4753274Sbostic void	 badlogin __P((char *));
4853274Sbostic void	 checknologin __P((void));
4953274Sbostic void	 dolastlog __P((int));
5053274Sbostic void	 getloginname __P((void));
5153274Sbostic void	 motd __P((void));
5253274Sbostic int	 rootterm __P((char *));
5353274Sbostic void	 sigint __P((int));
5453274Sbostic void	 sleepexit __P((int));
5553274Sbostic char	*stypeof __P((char *));
5653274Sbostic void	 timedout __P((int));
5754549Sbostic #ifdef KERBEROS
5854549Sbostic int	 klogin __P((struct passwd *, char *, char *, char *));
5954549Sbostic #endif
6053274Sbostic 
6166623Spendry extern void login __P((struct utmp *));
6266623Spendry 
6336460Sbostic #define	TTYGRPNAME	"tty"		/* name of group to own ttys */
6426862Smckusick 
6512687Ssam /*
6636460Sbostic  * This bounds the time given to login.  Not a define so it can
6736460Sbostic  * be patched on machines where it's too small.
6812687Ssam  */
6966623Spendry u_int	timeout = 300;
7053274Sbostic 
7143653Sbostic #ifdef KERBEROS
7243653Sbostic int	notickets = 1;
7349957Skarels char	*instance;
7449957Skarels char	*krbtkfile_env;
7549957Skarels int	authok;
7643653Sbostic #endif
776005Swnj 
7836647Skarels struct	passwd *pwd;
7936647Skarels int	failures;
8040490Sbostic char	term[64], *envinit[1], *hostname, *username, *tty;
816005Swnj 
8253274Sbostic int
main(argc,argv)831043Sbill main(argc, argv)
8436460Sbostic 	int argc;
8553274Sbostic 	char *argv[];
861043Sbill {
8753274Sbostic 	extern char **environ;
8853274Sbostic 	struct group *gr;
8953274Sbostic 	struct stat st;
9053274Sbostic 	struct timeval tp;
9153274Sbostic 	struct utmp utmp;
9266623Spendry 	int ask, ch, cnt, fflag, hflag, pflag, quietlog, rootlogin, rval;
9366623Spendry 	uid_t uid;
9466623Spendry 	char *domain, *p, *salt, *ttyn;
9537692Sbostic 	char tbuf[MAXPATHLEN + 2], tname[sizeof(_PATH_TTY) + 10];
9638034Skfall 	char localhost[MAXHOSTNAMELEN];
971043Sbill 
9836460Sbostic 	(void)signal(SIGALRM, timedout);
9966623Spendry 	(void)alarm(timeout);
10036460Sbostic 	(void)signal(SIGQUIT, SIG_IGN);
10136460Sbostic 	(void)signal(SIGINT, SIG_IGN);
10236460Sbostic 	(void)setpriority(PRIO_PROCESS, 0, 0);
10336460Sbostic 
10442502Sbostic 	openlog("login", LOG_ODELAY, LOG_AUTH);
10542502Sbostic 
10612687Ssam 	/*
10718549Ssam 	 * -p is used by getty to tell login not to destroy the environment
10854549Sbostic 	 * -f is used to skip a second login authentication
10936523Skarels 	 * -h is used by other servers to pass the name of the remote
11036523Skarels 	 *    host to login so that it may be placed in utmp and wtmp
11112687Ssam 	 */
11238034Skfall 	domain = NULL;
11338034Skfall 	if (gethostname(localhost, sizeof(localhost)) < 0)
11438034Skfall 		syslog(LOG_ERR, "couldn't get local hostname: %m");
11538034Skfall 	else
11666623Spendry 		domain = strchr(localhost, '.');
11736460Sbostic 
11837203Sbostic 	fflag = hflag = pflag = 0;
11939271Skfall 	uid = getuid();
12037203Sbostic 	while ((ch = getopt(argc, argv, "fh:p")) != EOF)
12136515Sbostic 		switch (ch) {
12236460Sbostic 		case 'f':
12336460Sbostic 			fflag = 1;
12436460Sbostic 			break;
12536460Sbostic 		case 'h':
12666623Spendry 			if (uid)
12766623Spendry 				errx(1, "-h option: %s", strerror(EPERM));
12836460Sbostic 			hflag = 1;
12966623Spendry 			if (domain && (p = strchr(optarg, '.')) &&
13036553Sbostic 			    strcasecmp(p, domain) == 0)
13136460Sbostic 				*p = 0;
13236460Sbostic 			hostname = optarg;
13336460Sbostic 			break;
13436460Sbostic 		case 'p':
13518549Ssam 			pflag = 1;
13636460Sbostic 			break;
13736460Sbostic 		case '?':
13836460Sbostic 		default:
13939271Skfall 			if (!uid)
14039271Skfall 				syslog(LOG_ERR, "invalid flag %c", ch);
14137203Sbostic 			(void)fprintf(stderr,
14250274Sbostic 			    "usage: login [-fp] [-h hostname] [username]\n");
14336460Sbostic 			exit(1);
14418549Ssam 		}
14536460Sbostic 	argc -= optind;
14636460Sbostic 	argv += optind;
14753274Sbostic 
14836549Sbostic 	if (*argv) {
14936647Skarels 		username = *argv;
15036549Sbostic 		ask = 0;
15136647Skarels 	} else
15236549Sbostic 		ask = 1;
15336460Sbostic 
15436460Sbostic 	for (cnt = getdtablesize(); cnt > 2; cnt--)
15553274Sbostic 		(void)close(cnt);
15636460Sbostic 
15753274Sbostic 	ttyn = ttyname(STDIN_FILENO);
15837692Sbostic 	if (ttyn == NULL || *ttyn == '\0') {
15953274Sbostic 		(void)snprintf(tname, sizeof(tname), "%s??", _PATH_TTY);
16037692Sbostic 		ttyn = tname;
16137692Sbostic 	}
16266623Spendry 	if (tty = strrchr(ttyn, '/'))
16336460Sbostic 		++tty;
16436460Sbostic 	else
16516453Sroot 		tty = ttyn;
16636460Sbostic 
16736549Sbostic 	for (cnt = 0;; ask = 1) {
16836549Sbostic 		if (ask) {
16936515Sbostic 			fflag = 0;
17036460Sbostic 			getloginname();
17136515Sbostic 		}
17253273Sbostic 		rootlogin = 0;
17349957Skarels #ifdef	KERBEROS
17466623Spendry 		if ((instance = strchr(username, '.')) != NULL) {
17549957Skarels 			if (strncmp(instance, ".root", 5) == 0)
17653273Sbostic 				rootlogin = 1;
17749957Skarels 			*instance++ = '\0';
17853273Sbostic 		} else
17949957Skarels 			instance = "";
18049957Skarels #endif
18149957Skarels 		if (strlen(username) > UT_NAMESIZE)
18249957Skarels 			username[UT_NAMESIZE] = '\0';
18349957Skarels 
18436647Skarels 		/*
18539271Skfall 		 * Note if trying multiple user names; log failures for
18639271Skfall 		 * previous user name, but don't bother logging one failure
18736647Skarels 		 * for nonexistent name (mistyped username).
18836647Skarels 		 */
18936647Skarels 		if (failures && strcmp(tbuf, username)) {
19036647Skarels 			if (failures > (pwd ? 0 : 1))
19136549Sbostic 				badlogin(tbuf);
19236647Skarels 			failures = 0;
19336549Sbostic 		}
19436647Skarels 		(void)strcpy(tbuf, username);
19543659Sbostic 
19636515Sbostic 		if (pwd = getpwnam(username))
19736515Sbostic 			salt = pwd->pw_passwd;
19843659Sbostic 		else
19943659Sbostic 			salt = "xx";
20036460Sbostic 
20112687Ssam 		/*
20243674Sbostic 		 * if we have a valid account name, and it doesn't have a
20343674Sbostic 		 * password, or the -f option was specified and the caller
20443674Sbostic 		 * is root or the caller isn't changing their uid, don't
20543674Sbostic 		 * authenticate.
20612687Ssam 		 */
20743674Sbostic 		if (pwd && (*pwd->pw_passwd == '\0' ||
20843674Sbostic 		    fflag && (uid == 0 || uid == pwd->pw_uid)))
20936460Sbostic 			break;
21044348Skarels 		fflag = 0;
21149957Skarels 		if (pwd && pwd->pw_uid == 0)
21249957Skarels 			rootlogin = 1;
21312687Ssam 
21449957Skarels 		(void)setpriority(PRIO_PROCESS, 0, -4);
21549957Skarels 
21649957Skarels 		p = getpass("Password:");
21749957Skarels 
21849957Skarels 		if (pwd) {
21949957Skarels #ifdef KERBEROS
22049957Skarels 			rval = klogin(pwd, instance, localhost, p);
221*66662Spendry 			if (rval != 0 && rootlogin && pwd->pw_uid != 0)
222*66662Spendry 				rootlogin = 0;
22349957Skarels 			if (rval == 0)
22449957Skarels 				authok = 1;
22553273Sbostic 			else if (rval == 1)
22649957Skarels 				rval = strcmp(crypt(p, salt), pwd->pw_passwd);
22749957Skarels #else
22849957Skarels 			rval = strcmp(crypt(p, salt), pwd->pw_passwd);
22949957Skarels #endif
23049957Skarels 		}
23166623Spendry 		memset(p, 0, strlen(p));
23249957Skarels 
23349957Skarels 		(void)setpriority(PRIO_PROCESS, 0, 0);
23449957Skarels 
23539271Skfall 		/*
23649957Skarels 		 * If trying to log in as root without Kerberos,
23749957Skarels 		 * but with insecure terminal, refuse the login attempt.
23839271Skfall 		 */
23949957Skarels #ifdef KERBEROS
24049957Skarels 		if (authok == 0)
24149957Skarels #endif
24249957Skarels 		if (pwd && rootlogin && !rootterm(tty)) {
24339271Skfall 			(void)fprintf(stderr,
24439271Skfall 			    "%s login refused on this terminal.\n",
24539271Skfall 			    pwd->pw_name);
24639271Skfall 			if (hostname)
24739271Skfall 				syslog(LOG_NOTICE,
24839271Skfall 				    "LOGIN %s REFUSED FROM %s ON TTY %s",
24939271Skfall 				    pwd->pw_name, hostname, tty);
25039271Skfall 			else
25139271Skfall 				syslog(LOG_NOTICE,
25239271Skfall 				    "LOGIN %s REFUSED ON TTY %s",
25339271Skfall 				     pwd->pw_name, tty);
25439271Skfall 			continue;
25539271Skfall 		}
25639271Skfall 
25743659Sbostic 		if (pwd && !rval)
25836460Sbostic 			break;
25936460Sbostic 
26043659Sbostic 		(void)printf("Login incorrect\n");
26136647Skarels 		failures++;
26236549Sbostic 		/* we allow 10 tries, but after 3 we start backing off */
26336549Sbostic 		if (++cnt > 3) {
26436549Sbostic 			if (cnt >= 10) {
26536549Sbostic 				badlogin(username);
26636549Sbostic 				sleepexit(1);
26736549Sbostic 			}
26836549Sbostic 			sleep((u_int)((cnt - 3) * 5));
2692822Swnj 		}
27036460Sbostic 	}
2711043Sbill 
27236460Sbostic 	/* committed to login -- turn off timeout */
27336460Sbostic 	(void)alarm((u_int)0);
27436460Sbostic 
27537692Sbostic 	endpwent();
27637692Sbostic 
27743663Sbostic 	/* if user not super-user, check for disabled logins */
27850274Sbostic 	if (!rootlogin)
27943663Sbostic 		checknologin();
28043663Sbostic 
28136515Sbostic 	if (chdir(pwd->pw_dir) < 0) {
28250274Sbostic 		(void)printf("No home directory %s!\n", pwd->pw_dir);
28336515Sbostic 		if (chdir("/"))
28436515Sbostic 			exit(0);
28536515Sbostic 		pwd->pw_dir = "/";
28637203Sbostic 		(void)printf("Logging in with home = \"/\".\n");
28736515Sbostic 	}
28836515Sbostic 
28937203Sbostic 	quietlog = access(_PATH_HUSHLOGIN, F_OK) == 0;
29037203Sbostic 
29136880Sbostic 	if (pwd->pw_change || pwd->pw_expire)
29236880Sbostic 		(void)gettimeofday(&tp, (struct timezone *)NULL);
29336880Sbostic 	if (pwd->pw_change)
29436880Sbostic 		if (tp.tv_sec >= pwd->pw_change) {
29537203Sbostic 			(void)printf("Sorry -- your password has expired.\n");
29636880Sbostic 			sleepexit(1);
29749957Skarels 		} else if (pwd->pw_change - tp.tv_sec <
29843660Sbostic 		    2 * DAYSPERWEEK * SECSPERDAY && !quietlog)
29943660Sbostic 			(void)printf("Warning: your password expires on %s",
30050719Sbostic 			    ctime(&pwd->pw_change));
30136880Sbostic 	if (pwd->pw_expire)
30236880Sbostic 		if (tp.tv_sec >= pwd->pw_expire) {
30337203Sbostic 			(void)printf("Sorry -- your account has expired.\n");
30436880Sbostic 			sleepexit(1);
30549957Skarels 		} else if (pwd->pw_expire - tp.tv_sec <
30643660Sbostic 		    2 * DAYSPERWEEK * SECSPERDAY && !quietlog)
30743660Sbostic 			(void)printf("Warning: your account expires on %s",
30843660Sbostic 			    ctime(&pwd->pw_expire));
30936880Sbostic 
31053274Sbostic 	/* Nothing else left to fail -- really log in. */
31166623Spendry 	memset((void *)&utmp, 0, sizeof(utmp));
31253274Sbostic 	(void)time(&utmp.ut_time);
31354549Sbostic 	(void)strncpy(utmp.ut_name, username, sizeof(utmp.ut_name));
31453274Sbostic 	if (hostname)
31553274Sbostic 		(void)strncpy(utmp.ut_host, hostname, sizeof(utmp.ut_host));
31653274Sbostic 	(void)strncpy(utmp.ut_line, tty, sizeof(utmp.ut_line));
31753274Sbostic 	login(&utmp);
31836460Sbostic 
31936549Sbostic 	dolastlog(quietlog);
32036460Sbostic 
32136460Sbostic 	(void)chown(ttyn, pwd->pw_uid,
32236460Sbostic 	    (gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid);
32336460Sbostic 	(void)setgid(pwd->pw_gid);
32436460Sbostic 
32536460Sbostic 	initgroups(username, pwd->pw_gid);
32636460Sbostic 
32736515Sbostic 	if (*pwd->pw_shell == '\0')
32837203Sbostic 		pwd->pw_shell = _PATH_BSHELL;
32936515Sbostic 
33053274Sbostic 	/* Destroy environment unless user has requested its preservation. */
33118549Ssam 	if (!pflag)
33218549Ssam 		environ = envinit;
33336515Sbostic 	(void)setenv("HOME", pwd->pw_dir, 1);
33436515Sbostic 	(void)setenv("SHELL", pwd->pw_shell, 1);
33518549Ssam 	if (term[0] == '\0')
33654549Sbostic 		(void)strncpy(term, stypeof(tty), sizeof(term));
33736515Sbostic 	(void)setenv("TERM", term, 0);
33850249Sbostic 	(void)setenv("LOGNAME", pwd->pw_name, 1);
33936515Sbostic 	(void)setenv("USER", pwd->pw_name, 1);
34037252Sbostic 	(void)setenv("PATH", _PATH_DEFPATH, 0);
34149957Skarels #ifdef KERBEROS
34249957Skarels 	if (krbtkfile_env)
34349957Skarels 		(void)setenv("KRBTKFILE", krbtkfile_env, 1);
34449957Skarels #endif
34518549Ssam 
34616453Sroot 	if (tty[sizeof("tty")-1] == 'd')
34718549Ssam 		syslog(LOG_INFO, "DIALUP %s, %s", tty, pwd->pw_name);
34853274Sbostic 
34953274Sbostic 	/* If fflag is on, assume caller/authenticator has logged root login. */
35049957Skarels 	if (rootlogin && fflag == 0)
35136460Sbostic 		if (hostname)
35247685Skfall 			syslog(LOG_NOTICE, "ROOT LOGIN (%s) ON %s FROM %s",
35347685Skfall 			    username, tty, hostname);
35425230Smckusick 		else
35547685Skfall 			syslog(LOG_NOTICE, "ROOT LOGIN (%s) ON %s", username, tty);
35636460Sbostic 
35743653Sbostic #ifdef KERBEROS
35843653Sbostic 	if (!quietlog && notickets == 1)
35943653Sbostic 		(void)printf("Warning: no Kerberos tickets issued.\n");
36043653Sbostic #endif
36143653Sbostic 
3626329Swnj 	if (!quietlog) {
36360971Smckusick 		(void)printf("%s\n\t%s  %s\n\n",
36466249Sbostic 	    "Copyright (c) 1980, 1983, 1986, 1988, 1990, 1991, 1993, 1994",
36560971Smckusick 		    "The Regents of the University of California. ",
36660971Smckusick 		    "All rights reserved.");
36736460Sbostic 		motd();
36853274Sbostic 		(void)snprintf(tbuf,
36953274Sbostic 		    sizeof(tbuf), "%s/%s", _PATH_MAILDIR, pwd->pw_name);
37036460Sbostic 		if (stat(tbuf, &st) == 0 && st.st_size != 0)
37137203Sbostic 			(void)printf("You have %smail.\n",
37236460Sbostic 			    (st.st_mtime > st.st_atime) ? "new " : "");
3732822Swnj 	}
37436460Sbostic 
37536460Sbostic 	(void)signal(SIGALRM, SIG_DFL);
37636460Sbostic 	(void)signal(SIGQUIT, SIG_DFL);
37736460Sbostic 	(void)signal(SIGINT, SIG_DFL);
37836460Sbostic 	(void)signal(SIGTSTP, SIG_IGN);
37936460Sbostic 
38036460Sbostic 	tbuf[0] = '-';
38166623Spendry 	(void)strcpy(tbuf + 1, (p = strrchr(pwd->pw_shell, '/')) ?
38236460Sbostic 	    p + 1 : pwd->pw_shell);
38337203Sbostic 
38440009Ssklower 	if (setlogin(pwd->pw_name) < 0)
38540009Ssklower 		syslog(LOG_ERR, "setlogin() failure: %m");
38637692Sbostic 
38753273Sbostic 	/* Discard permissions last so can't get killed and drop core. */
38849957Skarels 	if (rootlogin)
38947685Skfall 		(void) setuid(0);
39047685Skfall 	else
39149957Skarels 		(void) setuid(pwd->pw_uid);
39237203Sbostic 
39336460Sbostic 	execlp(pwd->pw_shell, tbuf, 0);
39466623Spendry 	err(1, "%s", pwd->pw_shell);
3951043Sbill }
3961043Sbill 
39747685Skfall #ifdef	KERBEROS
39853274Sbostic #define	NBUFSIZ		(UT_NAMESIZE + 1 + 5)	/* .root suffix */
39947685Skfall #else
40047685Skfall #define	NBUFSIZ		(UT_NAMESIZE + 1)
40147685Skfall #endif
40247685Skfall 
40353274Sbostic void
getloginname()40436460Sbostic getloginname()
40512687Ssam {
40666623Spendry 	int ch;
40766623Spendry 	char *p;
40847685Skfall 	static char nbuf[NBUFSIZ];
40912687Ssam 
41036460Sbostic 	for (;;) {
41137203Sbostic 		(void)printf("login: ");
41236515Sbostic 		for (p = nbuf; (ch = getchar()) != '\n'; ) {
41336549Sbostic 			if (ch == EOF) {
41436549Sbostic 				badlogin(username);
41512687Ssam 				exit(0);
41636549Sbostic 			}
41747685Skfall 			if (p < nbuf + (NBUFSIZ - 1))
41836460Sbostic 				*p++ = ch;
41912687Ssam 		}
42036460Sbostic 		if (p > nbuf)
42136460Sbostic 			if (nbuf[0] == '-')
42237203Sbostic 				(void)fprintf(stderr,
42336460Sbostic 				    "login names may not start with '-'.\n");
42436460Sbostic 			else {
42536460Sbostic 				*p = '\0';
42636460Sbostic 				username = nbuf;
42736515Sbostic 				break;
42836460Sbostic 			}
42912687Ssam 	}
43012687Ssam }
43112687Ssam 
43253274Sbostic int
rootterm(ttyn)43336647Skarels rootterm(ttyn)
43436647Skarels 	char *ttyn;
4351043Sbill {
43636460Sbostic 	struct ttyent *t;
4376466Swnj 
43866623Spendry 	return ((t = getttynam(ttyn)) && t->ty_status & TTY_SECURE);
4391043Sbill }
4401043Sbill 
44136515Sbostic jmp_buf motdinterrupt;
44236515Sbostic 
44353274Sbostic void
motd()44436460Sbostic motd()
4452822Swnj {
44666623Spendry 	int fd, nchars;
44738726Skfall 	sig_t oldint;
44836515Sbostic 	char tbuf[8192];
4492822Swnj 
45037203Sbostic 	if ((fd = open(_PATH_MOTDFILE, O_RDONLY, 0)) < 0)
45136460Sbostic 		return;
45236460Sbostic 	oldint = signal(SIGINT, sigint);
45336515Sbostic 	if (setjmp(motdinterrupt) == 0)
45436515Sbostic 		while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0)
45536515Sbostic 			(void)write(fileno(stdout), tbuf, nchars);
45636460Sbostic 	(void)signal(SIGINT, oldint);
45736515Sbostic 	(void)close(fd);
45836460Sbostic }
45936460Sbostic 
46053274Sbostic /* ARGSUSED */
46146835Sbostic void
sigint(signo)46253274Sbostic sigint(signo)
46353274Sbostic 	int signo;
46436460Sbostic {
46566623Spendry 
46636515Sbostic 	longjmp(motdinterrupt, 1);
46736460Sbostic }
46836460Sbostic 
46953274Sbostic /* ARGSUSED */
47053274Sbostic void
timedout(signo)47153274Sbostic timedout(signo)
47253274Sbostic 	int signo;
47353274Sbostic {
47466623Spendry 
47553274Sbostic 	(void)fprintf(stderr, "Login timed out after %d seconds\n", timeout);
47653274Sbostic 	exit(0);
47753274Sbostic }
47853274Sbostic 
47953274Sbostic void
checknologin()48036460Sbostic checknologin()
48136460Sbostic {
48266623Spendry 	int fd, nchars;
48336515Sbostic 	char tbuf[8192];
48436460Sbostic 
48537203Sbostic 	if ((fd = open(_PATH_NOLOGIN, O_RDONLY, 0)) >= 0) {
48636460Sbostic 		while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0)
48736460Sbostic 			(void)write(fileno(stdout), tbuf, nchars);
48836460Sbostic 		sleepexit(0);
4892822Swnj 	}
4902822Swnj }
4912822Swnj 
49253274Sbostic void
dolastlog(quiet)49336549Sbostic dolastlog(quiet)
49436460Sbostic 	int quiet;
4951043Sbill {
49636460Sbostic 	struct lastlog ll;
49736460Sbostic 	int fd;
4981043Sbill 
49937203Sbostic 	if ((fd = open(_PATH_LASTLOG, O_RDWR, 0)) >= 0) {
50036515Sbostic 		(void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), L_SET);
50136460Sbostic 		if (!quiet) {
50236460Sbostic 			if (read(fd, (char *)&ll, sizeof(ll)) == sizeof(ll) &&
50336460Sbostic 			    ll.ll_time != 0) {
50437203Sbostic 				(void)printf("Last login: %.*s ",
50536460Sbostic 				    24-5, (char *)ctime(&ll.ll_time));
50636460Sbostic 				if (*ll.ll_host != '\0')
50737203Sbostic 					(void)printf("from %.*s\n",
50854549Sbostic 					    (int)sizeof(ll.ll_host),
50954549Sbostic 					    ll.ll_host);
51036460Sbostic 				else
51137203Sbostic 					(void)printf("on %.*s\n",
51254549Sbostic 					    (int)sizeof(ll.ll_line),
51354549Sbostic 					    ll.ll_line);
51436460Sbostic 			}
51536515Sbostic 			(void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), L_SET);
51636460Sbostic 		}
51766623Spendry 		memset((void *)&ll, 0, sizeof(ll));
51836460Sbostic 		(void)time(&ll.ll_time);
51954549Sbostic 		(void)strncpy(ll.ll_line, tty, sizeof(ll.ll_line));
52036591Sbostic 		if (hostname)
52154549Sbostic 			(void)strncpy(ll.ll_host, hostname, sizeof(ll.ll_host));
52236460Sbostic 		(void)write(fd, (char *)&ll, sizeof(ll));
52336460Sbostic 		(void)close(fd);
5241043Sbill 	}
5251043Sbill }
5261043Sbill 
52753274Sbostic void
badlogin(name)52836549Sbostic badlogin(name)
52936549Sbostic 	char *name;
53036549Sbostic {
53166623Spendry 
53236647Skarels 	if (failures == 0)
53336549Sbostic 		return;
53445431Sbostic 	if (hostname) {
53545431Sbostic 		syslog(LOG_NOTICE, "%d LOGIN FAILURE%s FROM %s",
53645431Sbostic 		    failures, failures > 1 ? "S" : "", hostname);
53745431Sbostic 		syslog(LOG_AUTHPRIV|LOG_NOTICE,
53845431Sbostic 		    "%d LOGIN FAILURE%s FROM %s, %s",
53936647Skarels 		    failures, failures > 1 ? "S" : "", hostname, name);
54045431Sbostic 	} else {
54145431Sbostic 		syslog(LOG_NOTICE, "%d LOGIN FAILURE%s ON %s",
54245431Sbostic 		    failures, failures > 1 ? "S" : "", tty);
54345431Sbostic 		syslog(LOG_AUTHPRIV|LOG_NOTICE,
54445431Sbostic 		    "%d LOGIN FAILURE%s ON %s, %s",
54536647Skarels 		    failures, failures > 1 ? "S" : "", tty, name);
54645431Sbostic 	}
54736549Sbostic }
54836549Sbostic 
5492822Swnj #undef	UNKNOWN
55036460Sbostic #define	UNKNOWN	"su"
5511043Sbill 
5521043Sbill char *
stypeof(ttyid)55336647Skarels stypeof(ttyid)
55436647Skarels 	char *ttyid;
5551043Sbill {
55636460Sbostic 	struct ttyent *t;
5571043Sbill 
55866623Spendry 	return (ttyid && (t = getttynam(ttyid)) ? t->ty_type : UNKNOWN);
5591043Sbill }
5606005Swnj 
56153274Sbostic void
sleepexit(eval)56236460Sbostic sleepexit(eval)
56336460Sbostic 	int eval;
56426862Smckusick {
56566623Spendry 
56666623Spendry 	(void)sleep(5);
56736460Sbostic 	exit(eval);
56826862Smckusick }
569