xref: /csrg-svn/usr.bin/login/login.c (revision 66623)
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*66623Spendry static char sccsid[] = "@(#)login.c	8.3 (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 
30*66623Spendry #include <err.h>
3153274Sbostic #include <errno.h>
3226862Smckusick #include <grp.h>
3336460Sbostic #include <pwd.h>
34*66623Spendry #include <setjmp.h>
35*66623Spendry #include <signal.h>
3636460Sbostic #include <stdio.h>
3753274Sbostic #include <stdlib.h>
3842063Sbostic #include <string.h>
39*66623Spendry #include <syslog.h>
40*66623Spendry #include <ttyent.h>
41*66623Spendry #include <tzfile.h>
42*66623Spendry #include <unistd.h>
43*66623Spendry #include <utmp.h>
44*66623Spendry 
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 
61*66623Spendry extern void login __P((struct utmp *));
62*66623Spendry 
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  */
69*66623Spendry 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
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;
92*66623Spendry 	int ask, ch, cnt, fflag, hflag, pflag, quietlog, rootlogin, rval;
93*66623Spendry 	uid_t uid;
94*66623Spendry 	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);
99*66623Spendry 	(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
116*66623Spendry 		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':
126*66623Spendry 			if (uid)
127*66623Spendry 				errx(1, "-h option: %s", strerror(EPERM));
12836460Sbostic 			hflag = 1;
129*66623Spendry 			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 	}
162*66623Spendry 	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
174*66623Spendry 		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);
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 		}
229*66623Spendry 		memset(p, 0, 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. */
309*66623Spendry 	memset((void *)&utmp, 0, 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",
36266249Sbostic 	    "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] = '-';
379*66623Spendry 	(void)strcpy(tbuf + 1, (p = strrchr(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);
392*66623Spendry 	err(1, "%s", pwd->pw_shell);
3931043Sbill }
3941043Sbill 
39547685Skfall #ifdef	KERBEROS
39653274Sbostic #define	NBUFSIZ		(UT_NAMESIZE + 1 + 5)	/* .root suffix */
39747685Skfall #else
39847685Skfall #define	NBUFSIZ		(UT_NAMESIZE + 1)
39947685Skfall #endif
40047685Skfall 
40153274Sbostic void
40236460Sbostic getloginname()
40312687Ssam {
404*66623Spendry 	int ch;
405*66623Spendry 	char *p;
40647685Skfall 	static char nbuf[NBUFSIZ];
40712687Ssam 
40836460Sbostic 	for (;;) {
40937203Sbostic 		(void)printf("login: ");
41036515Sbostic 		for (p = nbuf; (ch = getchar()) != '\n'; ) {
41136549Sbostic 			if (ch == EOF) {
41236549Sbostic 				badlogin(username);
41312687Ssam 				exit(0);
41436549Sbostic 			}
41547685Skfall 			if (p < nbuf + (NBUFSIZ - 1))
41636460Sbostic 				*p++ = ch;
41712687Ssam 		}
41836460Sbostic 		if (p > nbuf)
41936460Sbostic 			if (nbuf[0] == '-')
42037203Sbostic 				(void)fprintf(stderr,
42136460Sbostic 				    "login names may not start with '-'.\n");
42236460Sbostic 			else {
42336460Sbostic 				*p = '\0';
42436460Sbostic 				username = nbuf;
42536515Sbostic 				break;
42636460Sbostic 			}
42712687Ssam 	}
42812687Ssam }
42912687Ssam 
43053274Sbostic int
43136647Skarels rootterm(ttyn)
43236647Skarels 	char *ttyn;
4331043Sbill {
43436460Sbostic 	struct ttyent *t;
4356466Swnj 
436*66623Spendry 	return ((t = getttynam(ttyn)) && t->ty_status & TTY_SECURE);
4371043Sbill }
4381043Sbill 
43936515Sbostic jmp_buf motdinterrupt;
44036515Sbostic 
44153274Sbostic void
44236460Sbostic motd()
4432822Swnj {
444*66623Spendry 	int fd, nchars;
44538726Skfall 	sig_t oldint;
44636515Sbostic 	char tbuf[8192];
4472822Swnj 
44837203Sbostic 	if ((fd = open(_PATH_MOTDFILE, O_RDONLY, 0)) < 0)
44936460Sbostic 		return;
45036460Sbostic 	oldint = signal(SIGINT, sigint);
45136515Sbostic 	if (setjmp(motdinterrupt) == 0)
45236515Sbostic 		while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0)
45336515Sbostic 			(void)write(fileno(stdout), tbuf, nchars);
45436460Sbostic 	(void)signal(SIGINT, oldint);
45536515Sbostic 	(void)close(fd);
45636460Sbostic }
45736460Sbostic 
45853274Sbostic /* ARGSUSED */
45946835Sbostic void
46053274Sbostic sigint(signo)
46153274Sbostic 	int signo;
46236460Sbostic {
463*66623Spendry 
46436515Sbostic 	longjmp(motdinterrupt, 1);
46536460Sbostic }
46636460Sbostic 
46753274Sbostic /* ARGSUSED */
46853274Sbostic void
46953274Sbostic timedout(signo)
47053274Sbostic 	int signo;
47153274Sbostic {
472*66623Spendry 
47353274Sbostic 	(void)fprintf(stderr, "Login timed out after %d seconds\n", timeout);
47453274Sbostic 	exit(0);
47553274Sbostic }
47653274Sbostic 
47753274Sbostic void
47836460Sbostic checknologin()
47936460Sbostic {
480*66623Spendry 	int fd, nchars;
48136515Sbostic 	char tbuf[8192];
48236460Sbostic 
48337203Sbostic 	if ((fd = open(_PATH_NOLOGIN, O_RDONLY, 0)) >= 0) {
48436460Sbostic 		while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0)
48536460Sbostic 			(void)write(fileno(stdout), tbuf, nchars);
48636460Sbostic 		sleepexit(0);
4872822Swnj 	}
4882822Swnj }
4892822Swnj 
49053274Sbostic void
49136549Sbostic dolastlog(quiet)
49236460Sbostic 	int quiet;
4931043Sbill {
49436460Sbostic 	struct lastlog ll;
49536460Sbostic 	int fd;
4961043Sbill 
49737203Sbostic 	if ((fd = open(_PATH_LASTLOG, O_RDWR, 0)) >= 0) {
49836515Sbostic 		(void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), L_SET);
49936460Sbostic 		if (!quiet) {
50036460Sbostic 			if (read(fd, (char *)&ll, sizeof(ll)) == sizeof(ll) &&
50136460Sbostic 			    ll.ll_time != 0) {
50237203Sbostic 				(void)printf("Last login: %.*s ",
50336460Sbostic 				    24-5, (char *)ctime(&ll.ll_time));
50436460Sbostic 				if (*ll.ll_host != '\0')
50537203Sbostic 					(void)printf("from %.*s\n",
50654549Sbostic 					    (int)sizeof(ll.ll_host),
50754549Sbostic 					    ll.ll_host);
50836460Sbostic 				else
50937203Sbostic 					(void)printf("on %.*s\n",
51054549Sbostic 					    (int)sizeof(ll.ll_line),
51154549Sbostic 					    ll.ll_line);
51236460Sbostic 			}
51336515Sbostic 			(void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), L_SET);
51436460Sbostic 		}
515*66623Spendry 		memset((void *)&ll, 0, sizeof(ll));
51636460Sbostic 		(void)time(&ll.ll_time);
51754549Sbostic 		(void)strncpy(ll.ll_line, tty, sizeof(ll.ll_line));
51836591Sbostic 		if (hostname)
51954549Sbostic 			(void)strncpy(ll.ll_host, hostname, sizeof(ll.ll_host));
52036460Sbostic 		(void)write(fd, (char *)&ll, sizeof(ll));
52136460Sbostic 		(void)close(fd);
5221043Sbill 	}
5231043Sbill }
5241043Sbill 
52553274Sbostic void
52636549Sbostic badlogin(name)
52736549Sbostic 	char *name;
52836549Sbostic {
529*66623Spendry 
53036647Skarels 	if (failures == 0)
53136549Sbostic 		return;
53245431Sbostic 	if (hostname) {
53345431Sbostic 		syslog(LOG_NOTICE, "%d LOGIN FAILURE%s FROM %s",
53445431Sbostic 		    failures, failures > 1 ? "S" : "", hostname);
53545431Sbostic 		syslog(LOG_AUTHPRIV|LOG_NOTICE,
53645431Sbostic 		    "%d LOGIN FAILURE%s FROM %s, %s",
53736647Skarels 		    failures, failures > 1 ? "S" : "", hostname, name);
53845431Sbostic 	} else {
53945431Sbostic 		syslog(LOG_NOTICE, "%d LOGIN FAILURE%s ON %s",
54045431Sbostic 		    failures, failures > 1 ? "S" : "", tty);
54145431Sbostic 		syslog(LOG_AUTHPRIV|LOG_NOTICE,
54245431Sbostic 		    "%d LOGIN FAILURE%s ON %s, %s",
54336647Skarels 		    failures, failures > 1 ? "S" : "", tty, name);
54445431Sbostic 	}
54536549Sbostic }
54636549Sbostic 
5472822Swnj #undef	UNKNOWN
54836460Sbostic #define	UNKNOWN	"su"
5491043Sbill 
5501043Sbill char *
55136647Skarels stypeof(ttyid)
55236647Skarels 	char *ttyid;
5531043Sbill {
55436460Sbostic 	struct ttyent *t;
5551043Sbill 
556*66623Spendry 	return (ttyid && (t = getttynam(ttyid)) ? t->ty_type : UNKNOWN);
5571043Sbill }
5586005Swnj 
55953274Sbostic void
56036460Sbostic sleepexit(eval)
56136460Sbostic 	int eval;
56226862Smckusick {
563*66623Spendry 
564*66623Spendry 	(void)sleep(5);
56536460Sbostic 	exit(eval);
56626862Smckusick }
567