xref: /csrg-svn/usr.bin/login/login.c (revision 36460)
119843Sdist /*
2*36460Sbostic  * Copyright (c) 1980, 1987 Regents of the University of California.
319843Sdist  * All rights reserved.  The Berkeley software License Agreement
419843Sdist  * specifies the terms and conditions for redistribution.
519843Sdist  */
619843Sdist 
712678Ssam #ifndef lint
819843Sdist char copyright[] =
919843Sdist "@(#) Copyright (c) 1980 Regents of the University of California.\n\
1019843Sdist  All rights reserved.\n";
1119843Sdist #endif not lint
1212678Ssam 
1319843Sdist #ifndef lint
14*36460Sbostic static char sccsid[] = "@(#)login.c	5.24 (Berkeley) 12/21/88";
1519843Sdist #endif not lint
1619843Sdist 
171043Sbill /*
181043Sbill  * login [ name ]
1931695Skarels  * login -r hostname	(for rlogind)
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/quota.h>
2612687Ssam #include <sys/stat.h>
2712687Ssam #include <sys/time.h>
2812687Ssam #include <sys/resource.h>
2916453Sroot #include <sys/file.h>
30*36460Sbostic #include <sys/termios.h>
31*36460Sbostic #include <sys/ioctl.h>
3212687Ssam 
331043Sbill #include <utmp.h>
341043Sbill #include <signal.h>
351043Sbill #include <lastlog.h>
3612678Ssam #include <errno.h>
3716453Sroot #include <ttyent.h>
3816453Sroot #include <syslog.h>
3926862Smckusick #include <grp.h>
40*36460Sbostic #include <pwd.h>
41*36460Sbostic #include <stdio.h>
42*36460Sbostic #include <strings.h>
431043Sbill 
44*36460Sbostic #define	TTYGRPNAME	"tty"		/* name of group to own ttys */
4526862Smckusick 
46*36460Sbostic #define	MOTDFILE	"/etc/motd"
47*36460Sbostic #define	MAILDIR		"/usr/spool/mail"
48*36460Sbostic #define	NOLOGIN		"/etc/nologin"
49*36460Sbostic #define	HUSHLOGIN	".hushlogin"
50*36460Sbostic #define	LASTLOG		"/usr/adm/lastlog"
51*36460Sbostic #define	BSHELL		"/bin/sh"
522822Swnj 
5312687Ssam /*
54*36460Sbostic  * This bounds the time given to login.  Not a define so it can
55*36460Sbostic  * be patched on machines where it's too small.
5612687Ssam  */
5731509Sbostic int	timeout = 300;
586005Swnj 
59*36460Sbostic struct passwd nouser = {"", "NOLOGIN", -1, -1, -1, "", "", "", "" };
60*36460Sbostic struct sgttyb ttyb;
61*36460Sbostic struct passwd *pwd;
62*36460Sbostic char term[64], *hostname, *username;
636005Swnj 
64*36460Sbostic struct tchars tc = {
6513074Ssam 	CINTR, CQUIT, CSTART, CSTOP, CEOT, CBRK
661365Sbill };
67*36460Sbostic struct ltchars ltc = {
6813074Ssam 	CSUSP, CDSUSP, CRPRNT, CFLUSH, CWERASE, CLNEXT
6913074Ssam };
701365Sbill 
711043Sbill main(argc, argv)
72*36460Sbostic 	int argc;
73*36460Sbostic 	char **argv;
741043Sbill {
75*36460Sbostic 	extern int errno, optind;
76*36460Sbostic 	extern char *optarg, **environ;
77*36460Sbostic 	struct group *gr;
78*36460Sbostic 	register int ch;
79*36460Sbostic 	register char *p;
80*36460Sbostic 	int fflag, hflag, pflag, rflag, cnt;
81*36460Sbostic 	int quietlog, passwd_req, ioctlval, timedout();
82*36460Sbostic 	char *domain, *envinit[1], *ttyn, *tty;
83*36460Sbostic 	char tbuf[MAXPATHLEN + 2];
84*36460Sbostic 	char *ttyname(), *stypeof(), *crypt(), *getpass();
85*36460Sbostic 	time_t time();
86*36460Sbostic 	off_t lseek();
871043Sbill 
88*36460Sbostic 	(void)signal(SIGALRM, timedout);
89*36460Sbostic 	(void)alarm((u_int)timeout);
90*36460Sbostic 	(void)signal(SIGQUIT, SIG_IGN);
91*36460Sbostic 	(void)signal(SIGINT, SIG_IGN);
92*36460Sbostic 	(void)setpriority(PRIO_PROCESS, 0, 0);
93*36460Sbostic 	(void)quota(Q_SETUID, 0, 0, 0);
94*36460Sbostic 
9512687Ssam 	/*
9618549Ssam 	 * -p is used by getty to tell login not to destroy the environment
9712687Ssam 	 * -r is used by rlogind to cause the autologin protocol;
9831695Skarels  	 * -f is used to skip a second login authentication
9912687Ssam 	 * -h is used by other servers to pass the name of the
10012687Ssam 	 * remote host to login so that it may be placed in utmp and wtmp
10112687Ssam 	 */
102*36460Sbostic 	(void)gethostname(tbuf, sizeof(tbuf));
103*36460Sbostic 	domain = index(tbuf, '.');
104*36460Sbostic 
105*36460Sbostic 	fflag = hflag = pflag = rflag = 0;
106*36460Sbostic 	passwd_req = 1;
107*36460Sbostic 	while ((ch = getopt(argc, argv, "f:h:pr:")) != EOF)
108*36460Sbostic 		switch(ch) {
109*36460Sbostic 		case 'f':
110*36460Sbostic 			if (rflag) {
111*36460Sbostic 				fprintf(stderr,
112*36460Sbostic 				    "login: only one of -r and -f allowed.\n");
11324712Sbloom 				exit(1);
11424712Sbloom 			}
115*36460Sbostic 			fflag = 1;
116*36460Sbostic 			username = optarg;
117*36460Sbostic 			break;
118*36460Sbostic 		case 'h':
119*36460Sbostic 			if (getuid()) {
120*36460Sbostic 				fprintf(stderr,
121*36460Sbostic 				    "login: -h for super-user only.\n");
12232313Sbostic 				exit(1);
12331695Skarels 			}
12431695Skarels 			if (rflag) {
125*36460Sbostic 				fprintf(stderr,
126*36460Sbostic 				    "login: only one of -r and -h allowed.\n");
12724712Sbloom 				exit(1);
12824712Sbloom 			}
129*36460Sbostic 			hflag = 1;
130*36460Sbostic 			if (domain && (p = index(optarg, '.')) &&
131*36460Sbostic 			    strcmp(p, domain) == 0)
132*36460Sbostic 				*p = 0;
133*36460Sbostic 			hostname = optarg;
134*36460Sbostic 			break;
135*36460Sbostic 		case 'p':
13618549Ssam 			pflag = 1;
137*36460Sbostic 			break;
138*36460Sbostic 		case 'r':
139*36460Sbostic 			if (hflag || fflag) {
140*36460Sbostic 				fprintf(stderr,
141*36460Sbostic 				    "login: -f and -h not allowed with -r.\n");
142*36460Sbostic 				exit(1);
143*36460Sbostic 			}
144*36460Sbostic 			rflag = 1;
145*36460Sbostic 			passwd_req = doremotelogin(optarg);
146*36460Sbostic 			if (domain && (p = index(optarg, '.')) &&
147*36460Sbostic 			    !strcmp(p, domain))
148*36460Sbostic 				*p = '\0';
149*36460Sbostic 			hostname = optarg;
150*36460Sbostic 			break;
151*36460Sbostic 		case '?':
152*36460Sbostic 		default:
153*36460Sbostic 			fprintf(stderr, "usage: login [-p] [username]\n");
154*36460Sbostic 			exit(1);
15518549Ssam 		}
156*36460Sbostic 	argc -= optind;
157*36460Sbostic 	argv += optind;
158*36460Sbostic 	if (*argv)
159*36460Sbostic 		username = *argv;
160*36460Sbostic 
161*36460Sbostic 	ioctlval = 0;
162*36460Sbostic 	(void)ioctl(0, TIOCLSET, &ioctlval);
163*36460Sbostic 	(void)ioctl(0, TIOCNXCL, 0);
164*36460Sbostic 	(void)ioctl(0, FIONBIO, &ioctlval);
165*36460Sbostic 	(void)ioctl(0, FIOASYNC, &ioctlval);
166*36460Sbostic 	(void)ioctl(0, TIOCGETP, &ttyb);
167*36460Sbostic 
16812687Ssam 	/*
169*36460Sbostic 	 * If talking to an rlogin process, propagate the terminal type and
17012687Ssam 	 * baud rate across the network.
17112687Ssam 	 */
17212687Ssam 	if (rflag)
173*36460Sbostic 		doremoteterm(&ttyb);
17426482Skarels 	ttyb.sg_erase = CERASE;
17526482Skarels 	ttyb.sg_kill = CKILL;
176*36460Sbostic 	(void)ioctl(0, TIOCSLTC, &ltc);
177*36460Sbostic 	(void)ioctl(0, TIOCSETC, &tc);
178*36460Sbostic 	(void)ioctl(0, TIOCSETP, &ttyb);
179*36460Sbostic 
180*36460Sbostic 	for (cnt = getdtablesize(); cnt > 2; cnt--)
181*36460Sbostic 		close(cnt);
182*36460Sbostic 
1831043Sbill 	ttyn = ttyname(0);
184*36460Sbostic 	if (ttyn == NULL || *ttyn == '\0')
1851043Sbill 		ttyn = "/dev/tty??";
186*36460Sbostic 	if (tty = rindex(ttyn, '/'))
187*36460Sbostic 		++tty;
188*36460Sbostic 	else
18916453Sroot 		tty = ttyn;
190*36460Sbostic 
19124852Seric 	openlog("login", LOG_ODELAY, LOG_AUTH);
192*36460Sbostic 
193*36460Sbostic 	for (cnt = 0;; username = NULL) {
194*36460Sbostic 		ioctlval = 0;
195*36460Sbostic 		(void)ioctl(0, TIOCSETD, &ioctlval);
196*36460Sbostic 
197*36460Sbostic 		if (!username)
198*36460Sbostic 			getloginname();
199*36460Sbostic 		if ((pwd = getpwnam(username)) == NULL)
200*36460Sbostic 			pwd = &nouser;
201*36460Sbostic 
202*36460Sbostic 		/* if user not super-user, check for disabled logins */
203*36460Sbostic 		if (pwd->pw_uid)
204*36460Sbostic 			checknologin();
205*36460Sbostic 
206*36460Sbostic 		if (!strcmp(pwd->pw_shell, "/bin/csh")) {
207*36460Sbostic 			ioctlval = NTTYDISC;
208*36460Sbostic 			(void)ioctl(0, TIOCSETD, &ioctlval);
2091043Sbill 		}
210*36460Sbostic 
21112687Ssam 		/*
212*36460Sbostic 		 * disallow automatic login to root, or if not root
213*36460Sbostic 		 * and the uid's differ
21412687Ssam 		 */
21531695Skarels 		if (fflag) {
21631695Skarels 			int uid = getuid();
21731695Skarels 
218*36460Sbostic 			passwd_req = !pwd->pw_uid || uid && uid != pwd->pw_uid;
21931695Skarels 		}
220*36460Sbostic 
22112687Ssam 		/*
222*36460Sbostic 		 * If no remote login authentication and a password exists
223*36460Sbostic 		 * for this user, prompt for one and verify it.
22412687Ssam 		 */
225*36460Sbostic 		if (!passwd_req || !*pwd->pw_passwd)
226*36460Sbostic 			break;
22712687Ssam 
228*36460Sbostic 		setpriority(PRIO_PROCESS, 0, -4);
229*36460Sbostic 		p = getpass("Password:");
230*36460Sbostic 		p = crypt(p, pwd->pw_passwd);
231*36460Sbostic 		setpriority(PRIO_PROCESS, 0, 0);
232*36460Sbostic 		if (!strcmp(p, pwd->pw_passwd))
233*36460Sbostic 			break;
234*36460Sbostic 
235*36460Sbostic 		printf("Login incorrect\n");
236*36460Sbostic 		if (++cnt >= 5) {
237*36460Sbostic 			if (hostname)
238*36460Sbostic 			    syslog(LOG_ERR,
239*36460Sbostic 				"REPEATED LOGIN FAILURES ON %s FROM %.*s, %.*s",
240*36460Sbostic 				tty, UT_HOSTSIZE, hostname, UT_NAMESIZE,
241*36460Sbostic 				username);
24225230Smckusick 			else
243*36460Sbostic 			    syslog(LOG_ERR,
244*36460Sbostic 				"REPEATED LOGIN FAILURES ON %s, %.*s",
245*36460Sbostic 				tty, UT_NAMESIZE, username);
246*36460Sbostic 			(void)ioctl(0, TIOCHPCL, (struct sgttyb *)NULL);
247*36460Sbostic 			sleepexit(1);
2482822Swnj 		}
249*36460Sbostic 	}
2501043Sbill 
251*36460Sbostic 	/* committed to login -- turn off timeout */
252*36460Sbostic 	(void)alarm((u_int)0);
253*36460Sbostic 
254*36460Sbostic 	/*
255*36460Sbostic 	 * If valid so far and root is logging in, see if root logins on
256*36460Sbostic 	 * this terminal are permitted.
257*36460Sbostic 	 */
258*36460Sbostic 	if (!pwd->pw_uid && !rootterm(tty)) {
259*36460Sbostic 		if (hostname)
260*36460Sbostic 			syslog(LOG_CRIT, "ROOT LOGIN REFUSED ON %s FROM %.*s",
261*36460Sbostic 			    tty, UT_HOSTSIZE, hostname);
26212678Ssam 		else
263*36460Sbostic 			syslog(LOG_CRIT, "ROOT LOGIN REFUSED ON %s", tty);
264*36460Sbostic 		printf("Login incorrect\n");
265*36460Sbostic 		sleepexit(1);
26612678Ssam 	}
2672822Swnj 
268*36460Sbostic 	if (*pwd->pw_shell == '\0')
269*36460Sbostic 		pwd->pw_shell = BSHELL;
270*36460Sbostic 
271*36460Sbostic 	if (chdir(pwd->pw_dir) < 0) {
272*36460Sbostic 		printf("No directory %s!\n", pwd->pw_dir);
273*36460Sbostic 		if (chdir("/"))
274*36460Sbostic 			exit(0);
275*36460Sbostic 		pwd->pw_dir = "/";
276*36460Sbostic 		printf("Logging in with home = \"/\".\n");
277*36460Sbostic 	}
278*36460Sbostic 
279*36460Sbostic 	if (quota(Q_SETUID, pwd->pw_uid, 0, 0) < 0 && errno != EINVAL) {
280*36460Sbostic 		switch(errno) {
281*36460Sbostic 		case EUSERS:
282*36460Sbostic 			fprintf(stderr,
283*36460Sbostic 		"Too many users logged on already.\nTry again later.\n");
284*36460Sbostic 			break;
285*36460Sbostic 		case EPROCLIM:
286*36460Sbostic 			fprintf(stderr,
287*36460Sbostic 			    "You have too many processes running.\n");
288*36460Sbostic 			break;
289*36460Sbostic 		default:
290*36460Sbostic 			perror("quota (Q_SETUID)");
2912822Swnj 		}
292*36460Sbostic 		sleepexit(0);
2932822Swnj 	}
294*36460Sbostic 
295*36460Sbostic 	{
296*36460Sbostic 		struct utmp utmp;
297*36460Sbostic 
298*36460Sbostic 		(void)time(&utmp.ut_time);
299*36460Sbostic 		strncpy(utmp.ut_name, username, sizeof(utmp.ut_name));
300*36460Sbostic 		strncpy(utmp.ut_host, hostname, sizeof(utmp.ut_host));
301*36460Sbostic 		strncpy(utmp.ut_line, tty, sizeof(utmp.ut_line));
302*36460Sbostic 		login(&utmp);
303*36460Sbostic 	}
304*36460Sbostic 
305*36460Sbostic 	quietlog = access(HUSHLOGIN, F_OK) == 0;
306*36460Sbostic 	dolastlog(quietlog, tty);
307*36460Sbostic 
308*36460Sbostic 	if (!hflag && !rflag) {					/* XXX */
309*36460Sbostic 		static struct winsize win = { 0, 0, 0, 0 };
310*36460Sbostic 
311*36460Sbostic 		(void)ioctl(0, TIOCSWINSZ, &win);
312*36460Sbostic 	}
313*36460Sbostic 
314*36460Sbostic 	(void)chown(ttyn, pwd->pw_uid,
315*36460Sbostic 	    (gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid);
316*36460Sbostic 	(void)chmod(ttyn, 0620);
317*36460Sbostic 	(void)setgid(pwd->pw_gid);
318*36460Sbostic 
319*36460Sbostic 	initgroups(username, pwd->pw_gid);
320*36460Sbostic 
32112678Ssam 	quota(Q_DOWARN, pwd->pw_uid, (dev_t)-1, 0);
322*36460Sbostic 	(void)setuid(pwd->pw_uid);
32330606Sbostic 
324*36460Sbostic 	/* destroy environment unless user has requested preservation */
32518549Ssam 	if (!pflag)
32618549Ssam 		environ = envinit;
32730606Sbostic 	setenv("HOME", pwd->pw_dir, 1);
32830606Sbostic 	setenv("SHELL", pwd->pw_shell, 1);
32918549Ssam 	if (term[0] == '\0')
33018549Ssam 		strncpy(term, stypeof(tty), sizeof(term));
33130606Sbostic 	setenv("TERM", term, 0);
33230606Sbostic 	setenv("USER", pwd->pw_name, 1);
33330606Sbostic 	setenv("PATH", ":/usr/ucb:/bin:/usr/bin", 0);
33418549Ssam 
33516453Sroot 	if (tty[sizeof("tty")-1] == 'd')
33618549Ssam 		syslog(LOG_INFO, "DIALUP %s, %s", tty, pwd->pw_name);
33718549Ssam 	if (pwd->pw_uid == 0)
338*36460Sbostic 		if (hostname)
33925230Smckusick 			syslog(LOG_NOTICE, "ROOT LOGIN %s FROM %.*s",
340*36460Sbostic 			    tty, UT_HOSTSIZE, hostname);
34125230Smckusick 		else
34225230Smckusick 			syslog(LOG_NOTICE, "ROOT LOGIN %s", tty);
343*36460Sbostic 
3446329Swnj 	if (!quietlog) {
34517664Sserge 		struct stat st;
34618549Ssam 
347*36460Sbostic 		motd();
348*36460Sbostic 		(void)sprintf(tbuf, "%s/%s", MAILDIR, pwd->pw_name);
349*36460Sbostic 		if (stat(tbuf, &st) == 0 && st.st_size != 0)
35017664Sserge 			printf("You have %smail.\n",
351*36460Sbostic 			    (st.st_mtime > st.st_atime) ? "new " : "");
3522822Swnj 	}
353*36460Sbostic 
354*36460Sbostic 	(void)signal(SIGALRM, SIG_DFL);
355*36460Sbostic 	(void)signal(SIGQUIT, SIG_DFL);
356*36460Sbostic 	(void)signal(SIGINT, SIG_DFL);
357*36460Sbostic 	(void)signal(SIGTSTP, SIG_IGN);
358*36460Sbostic 
359*36460Sbostic 	tbuf[0] = '-';
360*36460Sbostic 	strcpy(tbuf + 1, (p = rindex(pwd->pw_shell, '/')) ?
361*36460Sbostic 	    p + 1 : pwd->pw_shell);
362*36460Sbostic 	execlp(pwd->pw_shell, tbuf, 0);
3632822Swnj 	perror(pwd->pw_shell);
364*36460Sbostic 	fprintf(stderr, "login: no shell\n");
3651043Sbill 	exit(0);
3661043Sbill }
3671043Sbill 
368*36460Sbostic getloginname()
36912687Ssam {
370*36460Sbostic 	register int ch;
371*36460Sbostic 	register char *p;
372*36460Sbostic 	static char nbuf[UT_NAMESIZE + 1];
37312687Ssam 
374*36460Sbostic 	for (;;) {
375*36460Sbostic 		p = nbuf;
37612712Ssam 		printf("login: ");
377*36460Sbostic 		while ((ch = getchar()) != '\n') {
378*36460Sbostic 			if (ch == ' ')
379*36460Sbostic 				ch = '_';
380*36460Sbostic 			if (ch == EOF)
38112687Ssam 				exit(0);
382*36460Sbostic 			if (p < nbuf+UT_NAMESIZE)
383*36460Sbostic 				*p++ = ch;
38412687Ssam 		}
385*36460Sbostic 		if (p > nbuf)
386*36460Sbostic 			if (nbuf[0] == '-')
387*36460Sbostic 				fprintf(stderr,
388*36460Sbostic 				    "login names may not start with '-'.\n");
389*36460Sbostic 			else {
390*36460Sbostic 				*p = '\0';
391*36460Sbostic 				username = nbuf;
392*36460Sbostic 				return;
393*36460Sbostic 			}
39412687Ssam 	}
395*36460Sbostic 	/* NOTREACHED */
39612687Ssam }
39712687Ssam 
39812687Ssam timedout()
39912687Ssam {
400*36460Sbostic 	fprintf(stderr, "Login timed out after %d seconds\n", timeout);
40112687Ssam 	exit(0);
40212687Ssam }
40312687Ssam 
404*36460Sbostic rootterm(tty)
405*36460Sbostic 	char *tty;
4061043Sbill {
407*36460Sbostic 	struct ttyent *t;
4086466Swnj 
409*36460Sbostic 	return((t = getttynam(tty)) && t->ty_status&TTY_SECURE);
4101043Sbill }
4111043Sbill 
412*36460Sbostic int motdinterrupt;
413*36460Sbostic motd()
4142822Swnj {
415*36460Sbostic 	register int ch;
416*36460Sbostic 	FILE *fp;
417*36460Sbostic 	int (*oldint)(), sigint();
4182822Swnj 
419*36460Sbostic 	if ((fp = fopen(MOTDFILE, "r")) == NULL)
420*36460Sbostic 		return;
421*36460Sbostic 	oldint = signal(SIGINT, sigint);
422*36460Sbostic 	while ((ch = getc(fp)) != EOF && !motdinterrupt)
423*36460Sbostic 		(void)putchar(ch);
424*36460Sbostic 	(void)signal(SIGINT, oldint);
425*36460Sbostic 	if (motdinterrupt)
426*36460Sbostic 		fpurge(fp);
427*36460Sbostic 	(void)fclose(fp);
428*36460Sbostic }
429*36460Sbostic 
430*36460Sbostic sigint()
431*36460Sbostic {
432*36460Sbostic 	motdinterrupt = 1;
433*36460Sbostic }
434*36460Sbostic 
435*36460Sbostic checknologin()
436*36460Sbostic {
437*36460Sbostic 	register int fd, nchars;
438*36460Sbostic 	char tbuf[1024];
439*36460Sbostic 
440*36460Sbostic 	if ((fd = open(NOLOGIN, O_RDONLY, 0)) >= 0) {
441*36460Sbostic 		while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0)
442*36460Sbostic 			(void)write(fileno(stdout), tbuf, nchars);
443*36460Sbostic 		sleepexit(0);
4442822Swnj 	}
4452822Swnj }
4462822Swnj 
447*36460Sbostic dolastlog(quiet, tty)
448*36460Sbostic 	int quiet;
449*36460Sbostic 	char *tty;
4501043Sbill {
451*36460Sbostic 	struct lastlog ll;
452*36460Sbostic 	int fd;
4531043Sbill 
454*36460Sbostic 	if ((fd = open(LASTLOG, O_RDWR, 0)) >= 0) {
455*36460Sbostic 		(void)lseek(fd, (long)pwd->pw_uid * sizeof(ll), L_SET);
456*36460Sbostic 		if (!quiet) {
457*36460Sbostic 			if (read(fd, (char *)&ll, sizeof(ll)) == sizeof(ll) &&
458*36460Sbostic 			    ll.ll_time != 0) {
459*36460Sbostic 				printf("Last login: %.*s ",
460*36460Sbostic 				    24-5, (char *)ctime(&ll.ll_time));
461*36460Sbostic 				if (*ll.ll_host != '\0')
462*36460Sbostic 					printf("from %.*s\n",
463*36460Sbostic 					    sizeof(ll.ll_host), ll.ll_host);
464*36460Sbostic 				else
465*36460Sbostic 					printf("on %.*s\n",
466*36460Sbostic 					    sizeof(ll.ll_line), ll.ll_line);
467*36460Sbostic 			}
468*36460Sbostic 			(void)lseek(fd, (long)pwd->pw_uid * sizeof(ll), L_SET);
469*36460Sbostic 		}
470*36460Sbostic 		(void)time(&ll.ll_time);
471*36460Sbostic 		strncpy(ll.ll_line, tty, sizeof(ll.ll_line));
472*36460Sbostic 		strncpy(ll.ll_host, hostname, sizeof(ll.ll_host));
473*36460Sbostic 		(void)write(fd, (char *)&ll, sizeof(ll));
474*36460Sbostic 		(void)close(fd);
4751043Sbill 	}
4761043Sbill }
4771043Sbill 
4782822Swnj #undef	UNKNOWN
479*36460Sbostic #define	UNKNOWN	"su"
4801043Sbill 
4811043Sbill char *
4821043Sbill stypeof(ttyid)
48312687Ssam 	char *ttyid;
4841043Sbill {
485*36460Sbostic 	struct ttyent *t;
4861043Sbill 
487*36460Sbostic 	return(ttyid && (t = getttynam(ttyid)) ? t->ty_type : UNKNOWN);
4881043Sbill }
4896005Swnj 
49012687Ssam doremotelogin(host)
49112687Ssam 	char *host;
49212687Ssam {
493*36460Sbostic 	static char lusername[UT_NAMESIZE+1];
494*36460Sbostic 	char rusername[UT_NAMESIZE+1];
495*36460Sbostic 
496*36460Sbostic 	getstr(rusername, sizeof(rusername), "remuser");
497*36460Sbostic 	getstr(lusername, sizeof(lusername), "locuser");
49818549Ssam 	getstr(term, sizeof(term), "Terminal type");
499*36460Sbostic 	username = lusername;
50013470Ssam 	if (getuid()) {
50113470Ssam 		pwd = &nouser;
50224712Sbloom 		return(-1);
50313470Ssam 	}
504*36460Sbostic 	pwd = getpwnam(username);
50513470Ssam 	if (pwd == NULL) {
50613470Ssam 		pwd = &nouser;
50724712Sbloom 		return(-1);
50813470Ssam 	}
509*36460Sbostic 	return(ruserok(host, (pwd->pw_uid == 0), rusername, username));
51012687Ssam }
51112687Ssam 
5126005Swnj getstr(buf, cnt, err)
513*36460Sbostic 	char *buf, *err;
5146005Swnj 	int cnt;
5156005Swnj {
516*36460Sbostic 	char ch;
5176005Swnj 
5186005Swnj 	do {
519*36460Sbostic 		if (read(0, &ch, sizeof(ch)) != sizeof(ch))
5206005Swnj 			exit(1);
5216005Swnj 		if (--cnt < 0) {
522*36460Sbostic 			fprintf(stderr, "%s too long\r\n", err);
523*36460Sbostic 			sleepexit(1);
5246005Swnj 		}
525*36460Sbostic 		*buf++ = ch;
526*36460Sbostic 	} while (ch);
5276005Swnj }
5286329Swnj 
529*36460Sbostic char *speeds[] = {
530*36460Sbostic 	"0", "50", "75", "110", "134", "150", "200", "300", "600",
531*36460Sbostic 	"1200", "1800", "2400", "4800", "9600", "19200", "38400",
532*36460Sbostic };
533*36460Sbostic #define	NSPEEDS	(sizeof(speeds) / sizeof(speeds[0]))
53412687Ssam 
535*36460Sbostic doremoteterm(tp)
53612687Ssam 	struct sgttyb *tp;
53712687Ssam {
53818549Ssam 	register char *cp = index(term, '/'), **cpp;
53918549Ssam 	char *speed;
54012687Ssam 
54112687Ssam 	if (cp) {
54218549Ssam 		*cp++ = '\0';
54318549Ssam 		speed = cp;
54418549Ssam 		cp = index(speed, '/');
54518549Ssam 		if (cp)
54618549Ssam 			*cp++ = '\0';
54718549Ssam 		for (cpp = speeds; cpp < &speeds[NSPEEDS]; cpp++)
54818549Ssam 			if (strcmp(*cpp, speed) == 0) {
54918549Ssam 				tp->sg_ispeed = tp->sg_ospeed = cpp-speeds;
55012687Ssam 				break;
55112687Ssam 			}
55212687Ssam 	}
55312687Ssam 	tp->sg_flags = ECHO|CRMOD|ANYP|XTABS;
55412687Ssam }
55518549Ssam 
556*36460Sbostic sleepexit(eval)
557*36460Sbostic 	int eval;
55826862Smckusick {
559*36460Sbostic 	sleep((u_int)5);
560*36460Sbostic 	exit(eval);
56126862Smckusick }
562