xref: /csrg-svn/usr.bin/login/login.c (revision 66249)
143653Sbostic /*-
2*66249Sbostic  * 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[] =
10*66249Sbostic "@(#) 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*66249Sbostic static char sccsid[] = "@(#)login.c	8.2 (Berkeley) 02/24/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 
301043Sbill #include <signal.h>
3116453Sroot #include <ttyent.h>
3216453Sroot #include <syslog.h>
3353274Sbostic #include <setjmp.h>
3453274Sbostic #include <tzfile.h>
3553274Sbostic #include <utmp.h>
3653274Sbostic #include <errno.h>
3726862Smckusick #include <grp.h>
3836460Sbostic #include <pwd.h>
3953274Sbostic #include <unistd.h>
4036460Sbostic #include <stdio.h>
4153274Sbostic #include <stdlib.h>
4242063Sbostic #include <string.h>
4337203Sbostic #include "pathnames.h"
441043Sbill 
4553274Sbostic void	 badlogin __P((char *));
4653274Sbostic void	 checknologin __P((void));
4753274Sbostic void	 dolastlog __P((int));
4853274Sbostic void	 getloginname __P((void));
4953274Sbostic void	 motd __P((void));
5053274Sbostic int	 rootterm __P((char *));
5153274Sbostic void	 sigint __P((int));
5253274Sbostic void	 sleepexit __P((int));
5353274Sbostic char	*stypeof __P((char *));
5453274Sbostic void	 timedout __P((int));
5554549Sbostic #ifdef KERBEROS
5654549Sbostic int	 klogin __P((struct passwd *, char *, char *, char *));
5754549Sbostic #endif
5853274Sbostic 
5936460Sbostic #define	TTYGRPNAME	"tty"		/* name of group to own ttys */
6026862Smckusick 
6112687Ssam /*
6236460Sbostic  * This bounds the time given to login.  Not a define so it can
6336460Sbostic  * be patched on machines where it's too small.
6412687Ssam  */
6531509Sbostic int	timeout = 300;
6653274Sbostic 
6743653Sbostic #ifdef KERBEROS
6843653Sbostic int	notickets = 1;
6949957Skarels char	*instance;
7049957Skarels char	*krbtkfile_env;
7149957Skarels int	authok;
7243653Sbostic #endif
736005Swnj 
7436647Skarels struct	passwd *pwd;
7536647Skarels int	failures;
7640490Sbostic char	term[64], *envinit[1], *hostname, *username, *tty;
776005Swnj 
7853274Sbostic int
791043Sbill main(argc, argv)
8036460Sbostic 	int argc;
8153274Sbostic 	char *argv[];
821043Sbill {
8353274Sbostic 	extern char **environ;
8436460Sbostic 	register int ch;
8536647Skarels 	register char *p;
8653274Sbostic 	struct group *gr;
8753274Sbostic 	struct stat st;
8853274Sbostic 	struct timeval tp;
8953274Sbostic 	struct utmp utmp;
9053274Sbostic 	int ask, cnt, fflag, hflag, pflag, quietlog, rootlogin, rval, uid;
9143653Sbostic 	char *domain, *salt, *ttyn;
9237692Sbostic 	char tbuf[MAXPATHLEN + 2], tname[sizeof(_PATH_TTY) + 10];
9338034Skfall 	char localhost[MAXHOSTNAMELEN];
941043Sbill 
9536460Sbostic 	(void)signal(SIGALRM, timedout);
9636460Sbostic 	(void)alarm((u_int)timeout);
9736460Sbostic 	(void)signal(SIGQUIT, SIG_IGN);
9836460Sbostic 	(void)signal(SIGINT, SIG_IGN);
9936460Sbostic 	(void)setpriority(PRIO_PROCESS, 0, 0);
10036460Sbostic 
10142502Sbostic 	openlog("login", LOG_ODELAY, LOG_AUTH);
10242502Sbostic 
10312687Ssam 	/*
10418549Ssam 	 * -p is used by getty to tell login not to destroy the environment
10554549Sbostic 	 * -f is used to skip a second login authentication
10636523Skarels 	 * -h is used by other servers to pass the name of the remote
10736523Skarels 	 *    host to login so that it may be placed in utmp and wtmp
10812687Ssam 	 */
10938034Skfall 	domain = NULL;
11038034Skfall 	if (gethostname(localhost, sizeof(localhost)) < 0)
11138034Skfall 		syslog(LOG_ERR, "couldn't get local hostname: %m");
11238034Skfall 	else
11338034Skfall 		domain = index(localhost, '.');
11436460Sbostic 
11537203Sbostic 	fflag = hflag = pflag = 0;
11639271Skfall 	uid = getuid();
11737203Sbostic 	while ((ch = getopt(argc, argv, "fh:p")) != EOF)
11836515Sbostic 		switch (ch) {
11936460Sbostic 		case 'f':
12036460Sbostic 			fflag = 1;
12136460Sbostic 			break;
12236460Sbostic 		case 'h':
12339271Skfall 			if (uid) {
12437203Sbostic 				(void)fprintf(stderr,
12550174Sbostic 				    "login: -h option: %s\n", strerror(EPERM));
12632313Sbostic 				exit(1);
12731695Skarels 			}
12836460Sbostic 			hflag = 1;
12936460Sbostic 			if (domain && (p = index(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 	}
16236460Sbostic 	if (tty = rindex(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
17449957Skarels 		if ((instance = index(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);
22149957Skarels 			if (rval == 0)
22249957Skarels 				authok = 1;
22353273Sbostic 			else if (rval == 1)
22449957Skarels 				rval = strcmp(crypt(p, salt), pwd->pw_passwd);
22549957Skarels #else
22649957Skarels 			rval = strcmp(crypt(p, salt), pwd->pw_passwd);
22749957Skarels #endif
22849957Skarels 		}
22949957Skarels 		bzero(p, strlen(p));
23049957Skarels 
23149957Skarels 		(void)setpriority(PRIO_PROCESS, 0, 0);
23249957Skarels 
23339271Skfall 		/*
23449957Skarels 		 * If trying to log in as root without Kerberos,
23549957Skarels 		 * but with insecure terminal, refuse the login attempt.
23639271Skfall 		 */
23749957Skarels #ifdef KERBEROS
23849957Skarels 		if (authok == 0)
23949957Skarels #endif
24049957Skarels 		if (pwd && rootlogin && !rootterm(tty)) {
24139271Skfall 			(void)fprintf(stderr,
24239271Skfall 			    "%s login refused on this terminal.\n",
24339271Skfall 			    pwd->pw_name);
24439271Skfall 			if (hostname)
24539271Skfall 				syslog(LOG_NOTICE,
24639271Skfall 				    "LOGIN %s REFUSED FROM %s ON TTY %s",
24739271Skfall 				    pwd->pw_name, hostname, tty);
24839271Skfall 			else
24939271Skfall 				syslog(LOG_NOTICE,
25039271Skfall 				    "LOGIN %s REFUSED ON TTY %s",
25139271Skfall 				     pwd->pw_name, tty);
25239271Skfall 			continue;
25339271Skfall 		}
25439271Skfall 
25543659Sbostic 		if (pwd && !rval)
25636460Sbostic 			break;
25736460Sbostic 
25843659Sbostic 		(void)printf("Login incorrect\n");
25936647Skarels 		failures++;
26036549Sbostic 		/* we allow 10 tries, but after 3 we start backing off */
26136549Sbostic 		if (++cnt > 3) {
26236549Sbostic 			if (cnt >= 10) {
26336549Sbostic 				badlogin(username);
26436549Sbostic 				sleepexit(1);
26536549Sbostic 			}
26636549Sbostic 			sleep((u_int)((cnt - 3) * 5));
2672822Swnj 		}
26836460Sbostic 	}
2691043Sbill 
27036460Sbostic 	/* committed to login -- turn off timeout */
27136460Sbostic 	(void)alarm((u_int)0);
27236460Sbostic 
27337692Sbostic 	endpwent();
27437692Sbostic 
27543663Sbostic 	/* if user not super-user, check for disabled logins */
27650274Sbostic 	if (!rootlogin)
27743663Sbostic 		checknologin();
27843663Sbostic 
27936515Sbostic 	if (chdir(pwd->pw_dir) < 0) {
28050274Sbostic 		(void)printf("No home directory %s!\n", pwd->pw_dir);
28136515Sbostic 		if (chdir("/"))
28236515Sbostic 			exit(0);
28336515Sbostic 		pwd->pw_dir = "/";
28437203Sbostic 		(void)printf("Logging in with home = \"/\".\n");
28536515Sbostic 	}
28636515Sbostic 
28737203Sbostic 	quietlog = access(_PATH_HUSHLOGIN, F_OK) == 0;
28837203Sbostic 
28936880Sbostic 	if (pwd->pw_change || pwd->pw_expire)
29036880Sbostic 		(void)gettimeofday(&tp, (struct timezone *)NULL);
29136880Sbostic 	if (pwd->pw_change)
29236880Sbostic 		if (tp.tv_sec >= pwd->pw_change) {
29337203Sbostic 			(void)printf("Sorry -- your password has expired.\n");
29436880Sbostic 			sleepexit(1);
29549957Skarels 		} else if (pwd->pw_change - tp.tv_sec <
29643660Sbostic 		    2 * DAYSPERWEEK * SECSPERDAY && !quietlog)
29743660Sbostic 			(void)printf("Warning: your password expires on %s",
29850719Sbostic 			    ctime(&pwd->pw_change));
29936880Sbostic 	if (pwd->pw_expire)
30036880Sbostic 		if (tp.tv_sec >= pwd->pw_expire) {
30137203Sbostic 			(void)printf("Sorry -- your account has expired.\n");
30236880Sbostic 			sleepexit(1);
30349957Skarels 		} else if (pwd->pw_expire - tp.tv_sec <
30443660Sbostic 		    2 * DAYSPERWEEK * SECSPERDAY && !quietlog)
30543660Sbostic 			(void)printf("Warning: your account expires on %s",
30643660Sbostic 			    ctime(&pwd->pw_expire));
30736880Sbostic 
30853274Sbostic 	/* Nothing else left to fail -- really log in. */
30953274Sbostic 	bzero((void *)&utmp, sizeof(utmp));
31053274Sbostic 	(void)time(&utmp.ut_time);
31154549Sbostic 	(void)strncpy(utmp.ut_name, username, sizeof(utmp.ut_name));
31253274Sbostic 	if (hostname)
31353274Sbostic 		(void)strncpy(utmp.ut_host, hostname, sizeof(utmp.ut_host));
31453274Sbostic 	(void)strncpy(utmp.ut_line, tty, sizeof(utmp.ut_line));
31553274Sbostic 	login(&utmp);
31636460Sbostic 
31736549Sbostic 	dolastlog(quietlog);
31836460Sbostic 
31936460Sbostic 	(void)chown(ttyn, pwd->pw_uid,
32036460Sbostic 	    (gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid);
32136460Sbostic 	(void)setgid(pwd->pw_gid);
32236460Sbostic 
32336460Sbostic 	initgroups(username, pwd->pw_gid);
32436460Sbostic 
32536515Sbostic 	if (*pwd->pw_shell == '\0')
32637203Sbostic 		pwd->pw_shell = _PATH_BSHELL;
32736515Sbostic 
32853274Sbostic 	/* Destroy environment unless user has requested its preservation. */
32918549Ssam 	if (!pflag)
33018549Ssam 		environ = envinit;
33136515Sbostic 	(void)setenv("HOME", pwd->pw_dir, 1);
33236515Sbostic 	(void)setenv("SHELL", pwd->pw_shell, 1);
33318549Ssam 	if (term[0] == '\0')
33454549Sbostic 		(void)strncpy(term, stypeof(tty), sizeof(term));
33536515Sbostic 	(void)setenv("TERM", term, 0);
33650249Sbostic 	(void)setenv("LOGNAME", pwd->pw_name, 1);
33736515Sbostic 	(void)setenv("USER", pwd->pw_name, 1);
33837252Sbostic 	(void)setenv("PATH", _PATH_DEFPATH, 0);
33949957Skarels #ifdef KERBEROS
34049957Skarels 	if (krbtkfile_env)
34149957Skarels 		(void)setenv("KRBTKFILE", krbtkfile_env, 1);
34249957Skarels #endif
34318549Ssam 
34416453Sroot 	if (tty[sizeof("tty")-1] == 'd')
34518549Ssam 		syslog(LOG_INFO, "DIALUP %s, %s", tty, pwd->pw_name);
34653274Sbostic 
34753274Sbostic 	/* If fflag is on, assume caller/authenticator has logged root login. */
34849957Skarels 	if (rootlogin && fflag == 0)
34936460Sbostic 		if (hostname)
35047685Skfall 			syslog(LOG_NOTICE, "ROOT LOGIN (%s) ON %s FROM %s",
35147685Skfall 			    username, tty, hostname);
35225230Smckusick 		else
35347685Skfall 			syslog(LOG_NOTICE, "ROOT LOGIN (%s) ON %s", username, tty);
35436460Sbostic 
35543653Sbostic #ifdef KERBEROS
35643653Sbostic 	if (!quietlog && notickets == 1)
35743653Sbostic 		(void)printf("Warning: no Kerberos tickets issued.\n");
35843653Sbostic #endif
35943653Sbostic 
3606329Swnj 	if (!quietlog) {
36160971Smckusick 		(void)printf("%s\n\t%s  %s\n\n",
362*66249Sbostic 	    "Copyright (c) 1980, 1983, 1986, 1988, 1990, 1991, 1993, 1994",
36360971Smckusick 		    "The Regents of the University of California. ",
36460971Smckusick 		    "All rights reserved.");
36536460Sbostic 		motd();
36653274Sbostic 		(void)snprintf(tbuf,
36753274Sbostic 		    sizeof(tbuf), "%s/%s", _PATH_MAILDIR, pwd->pw_name);
36836460Sbostic 		if (stat(tbuf, &st) == 0 && st.st_size != 0)
36937203Sbostic 			(void)printf("You have %smail.\n",
37036460Sbostic 			    (st.st_mtime > st.st_atime) ? "new " : "");
3712822Swnj 	}
37236460Sbostic 
37336460Sbostic 	(void)signal(SIGALRM, SIG_DFL);
37436460Sbostic 	(void)signal(SIGQUIT, SIG_DFL);
37536460Sbostic 	(void)signal(SIGINT, SIG_DFL);
37636460Sbostic 	(void)signal(SIGTSTP, SIG_IGN);
37736460Sbostic 
37836460Sbostic 	tbuf[0] = '-';
37953274Sbostic 	(void)strcpy(tbuf + 1, (p = rindex(pwd->pw_shell, '/')) ?
38036460Sbostic 	    p + 1 : pwd->pw_shell);
38137203Sbostic 
38240009Ssklower 	if (setlogin(pwd->pw_name) < 0)
38340009Ssklower 		syslog(LOG_ERR, "setlogin() failure: %m");
38437692Sbostic 
38553273Sbostic 	/* Discard permissions last so can't get killed and drop core. */
38649957Skarels 	if (rootlogin)
38747685Skfall 		(void) setuid(0);
38847685Skfall 	else
38949957Skarels 		(void) setuid(pwd->pw_uid);
39037203Sbostic 
39136460Sbostic 	execlp(pwd->pw_shell, tbuf, 0);
39250274Sbostic 	(void)fprintf(stderr, "%s: %s\n", pwd->pw_shell, strerror(errno));
39350274Sbostic 	exit(1);
3941043Sbill }
3951043Sbill 
39647685Skfall #ifdef	KERBEROS
39753274Sbostic #define	NBUFSIZ		(UT_NAMESIZE + 1 + 5)	/* .root suffix */
39847685Skfall #else
39947685Skfall #define	NBUFSIZ		(UT_NAMESIZE + 1)
40047685Skfall #endif
40147685Skfall 
40253274Sbostic void
40336460Sbostic getloginname()
40412687Ssam {
40536460Sbostic 	register int ch;
40649957Skarels 	register char *p;
40747685Skfall 	static char nbuf[NBUFSIZ];
40812687Ssam 
40936460Sbostic 	for (;;) {
41037203Sbostic 		(void)printf("login: ");
41136515Sbostic 		for (p = nbuf; (ch = getchar()) != '\n'; ) {
41236549Sbostic 			if (ch == EOF) {
41336549Sbostic 				badlogin(username);
41412687Ssam 				exit(0);
41536549Sbostic 			}
41647685Skfall 			if (p < nbuf + (NBUFSIZ - 1))
41736460Sbostic 				*p++ = ch;
41812687Ssam 		}
41936460Sbostic 		if (p > nbuf)
42036460Sbostic 			if (nbuf[0] == '-')
42137203Sbostic 				(void)fprintf(stderr,
42236460Sbostic 				    "login names may not start with '-'.\n");
42336460Sbostic 			else {
42436460Sbostic 				*p = '\0';
42536460Sbostic 				username = nbuf;
42636515Sbostic 				break;
42736460Sbostic 			}
42812687Ssam 	}
42912687Ssam }
43012687Ssam 
43153274Sbostic int
43236647Skarels rootterm(ttyn)
43336647Skarels 	char *ttyn;
4341043Sbill {
43536460Sbostic 	struct ttyent *t;
4366466Swnj 
43753274Sbostic 	return((t = getttynam(ttyn)) && t->ty_status & TTY_SECURE);
4381043Sbill }
4391043Sbill 
44036515Sbostic jmp_buf motdinterrupt;
44136515Sbostic 
44253274Sbostic void
44336460Sbostic motd()
4442822Swnj {
44536515Sbostic 	register int fd, nchars;
44638726Skfall 	sig_t oldint;
44736515Sbostic 	char tbuf[8192];
4482822Swnj 
44937203Sbostic 	if ((fd = open(_PATH_MOTDFILE, O_RDONLY, 0)) < 0)
45036460Sbostic 		return;
45136460Sbostic 	oldint = signal(SIGINT, sigint);
45236515Sbostic 	if (setjmp(motdinterrupt) == 0)
45336515Sbostic 		while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0)
45436515Sbostic 			(void)write(fileno(stdout), tbuf, nchars);
45536460Sbostic 	(void)signal(SIGINT, oldint);
45636515Sbostic 	(void)close(fd);
45736460Sbostic }
45836460Sbostic 
45953274Sbostic /* ARGSUSED */
46046835Sbostic void
46153274Sbostic sigint(signo)
46253274Sbostic 	int signo;
46336460Sbostic {
46436515Sbostic 	longjmp(motdinterrupt, 1);
46536460Sbostic }
46636460Sbostic 
46753274Sbostic /* ARGSUSED */
46853274Sbostic void
46953274Sbostic timedout(signo)
47053274Sbostic 	int signo;
47153274Sbostic {
47253274Sbostic 	(void)fprintf(stderr, "Login timed out after %d seconds\n", timeout);
47353274Sbostic 	exit(0);
47453274Sbostic }
47553274Sbostic 
47653274Sbostic void
47736460Sbostic checknologin()
47836460Sbostic {
47936460Sbostic 	register int fd, nchars;
48036515Sbostic 	char tbuf[8192];
48136460Sbostic 
48237203Sbostic 	if ((fd = open(_PATH_NOLOGIN, O_RDONLY, 0)) >= 0) {
48336460Sbostic 		while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0)
48436460Sbostic 			(void)write(fileno(stdout), tbuf, nchars);
48536460Sbostic 		sleepexit(0);
4862822Swnj 	}
4872822Swnj }
4882822Swnj 
48953274Sbostic void
49036549Sbostic dolastlog(quiet)
49136460Sbostic 	int quiet;
4921043Sbill {
49336460Sbostic 	struct lastlog ll;
49436460Sbostic 	int fd;
4951043Sbill 
49637203Sbostic 	if ((fd = open(_PATH_LASTLOG, O_RDWR, 0)) >= 0) {
49736515Sbostic 		(void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), L_SET);
49836460Sbostic 		if (!quiet) {
49936460Sbostic 			if (read(fd, (char *)&ll, sizeof(ll)) == sizeof(ll) &&
50036460Sbostic 			    ll.ll_time != 0) {
50137203Sbostic 				(void)printf("Last login: %.*s ",
50236460Sbostic 				    24-5, (char *)ctime(&ll.ll_time));
50336460Sbostic 				if (*ll.ll_host != '\0')
50437203Sbostic 					(void)printf("from %.*s\n",
50554549Sbostic 					    (int)sizeof(ll.ll_host),
50654549Sbostic 					    ll.ll_host);
50736460Sbostic 				else
50837203Sbostic 					(void)printf("on %.*s\n",
50954549Sbostic 					    (int)sizeof(ll.ll_line),
51054549Sbostic 					    ll.ll_line);
51136460Sbostic 			}
51236515Sbostic 			(void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), L_SET);
51336460Sbostic 		}
51443653Sbostic 		bzero((void *)&ll, sizeof(ll));
51536460Sbostic 		(void)time(&ll.ll_time);
51654549Sbostic 		(void)strncpy(ll.ll_line, tty, sizeof(ll.ll_line));
51736591Sbostic 		if (hostname)
51854549Sbostic 			(void)strncpy(ll.ll_host, hostname, sizeof(ll.ll_host));
51936460Sbostic 		(void)write(fd, (char *)&ll, sizeof(ll));
52036460Sbostic 		(void)close(fd);
5211043Sbill 	}
5221043Sbill }
5231043Sbill 
52453274Sbostic void
52536549Sbostic badlogin(name)
52636549Sbostic 	char *name;
52736549Sbostic {
52836647Skarels 	if (failures == 0)
52936549Sbostic 		return;
53045431Sbostic 	if (hostname) {
53145431Sbostic 		syslog(LOG_NOTICE, "%d LOGIN FAILURE%s FROM %s",
53245431Sbostic 		    failures, failures > 1 ? "S" : "", hostname);
53345431Sbostic 		syslog(LOG_AUTHPRIV|LOG_NOTICE,
53445431Sbostic 		    "%d LOGIN FAILURE%s FROM %s, %s",
53536647Skarels 		    failures, failures > 1 ? "S" : "", hostname, name);
53645431Sbostic 	} else {
53745431Sbostic 		syslog(LOG_NOTICE, "%d LOGIN FAILURE%s ON %s",
53845431Sbostic 		    failures, failures > 1 ? "S" : "", tty);
53945431Sbostic 		syslog(LOG_AUTHPRIV|LOG_NOTICE,
54045431Sbostic 		    "%d LOGIN FAILURE%s ON %s, %s",
54136647Skarels 		    failures, failures > 1 ? "S" : "", tty, name);
54245431Sbostic 	}
54336549Sbostic }
54436549Sbostic 
5452822Swnj #undef	UNKNOWN
54636460Sbostic #define	UNKNOWN	"su"
5471043Sbill 
5481043Sbill char *
54936647Skarels stypeof(ttyid)
55036647Skarels 	char *ttyid;
5511043Sbill {
55236460Sbostic 	struct ttyent *t;
5531043Sbill 
55436647Skarels 	return(ttyid && (t = getttynam(ttyid)) ? t->ty_type : UNKNOWN);
5551043Sbill }
5566005Swnj 
55753274Sbostic void
55836460Sbostic sleepexit(eval)
55936460Sbostic 	int eval;
56026862Smckusick {
56153274Sbostic 	(void)sleep((u_int)5);
56236460Sbostic 	exit(eval);
56326862Smckusick }
564