xref: /csrg-svn/usr.bin/login/login.c.1 (revision 36515)
119843Sdist/*
2*36515Sbostic * Copyright (c) 1980, 1987, 1988 The Regents of the University of California.
3*36515Sbostic * All rights reserved.
4*36515Sbostic *
5*36515Sbostic * Redistribution and use in source and binary forms are permitted
6*36515Sbostic * provided that the above copyright notice and this paragraph are
7*36515Sbostic * duplicated in all such forms and that any documentation,
8*36515Sbostic * advertising materials, and other materials related to such
9*36515Sbostic * distribution and use acknowledge that the software was developed
10*36515Sbostic * by the University of California, Berkeley.  The name of the
11*36515Sbostic * University may not be used to endorse or promote products derived
12*36515Sbostic * from this software without specific prior written permission.
13*36515Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14*36515Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15*36515Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1619843Sdist */
1719843Sdist
1812678Ssam#ifndef lint
1919843Sdistchar copyright[] =
20*36515Sbostic"@(#) Copyright (c) 1980, 1987, 1988 The Regents of the University of California.\n\
2119843Sdist All rights reserved.\n";
22*36515Sbostic#endif /* not lint */
2312678Ssam
2419843Sdist#ifndef lint
25*36515Sbosticstatic char sccsid[] = "@(#)login.c.1	5.25 (Berkeley) 01/06/89";
26*36515Sbostic#endif /* not lint */
2719843Sdist
281043Sbill/*
291043Sbill * login [ name ]
3031695Skarels * login -r hostname	(for rlogind)
3131695Skarels * login -h hostname	(for telnetd, etc.)
3231695Skarels * login -f name	(for pre-authenticated login: datakit, xterm, etc.)
331043Sbill */
341043Sbill
3512984Ssam#include <sys/param.h>
3612687Ssam#include <sys/quota.h>
3712687Ssam#include <sys/stat.h>
3812687Ssam#include <sys/time.h>
3912687Ssam#include <sys/resource.h>
4016453Sroot#include <sys/file.h>
4136460Sbostic#include <sys/ioctl.h>
4212687Ssam
431043Sbill#include <utmp.h>
441043Sbill#include <signal.h>
451043Sbill#include <lastlog.h>
4612678Ssam#include <errno.h>
4716453Sroot#include <ttyent.h>
4816453Sroot#include <syslog.h>
4926862Smckusick#include <grp.h>
5036460Sbostic#include <pwd.h>
51*36515Sbostic#include <setjmp.h>
5236460Sbostic#include <stdio.h>
5336460Sbostic#include <strings.h>
541043Sbill
5536460Sbostic#define	TTYGRPNAME	"tty"		/* name of group to own ttys */
5626862Smckusick
5736460Sbostic#define	MOTDFILE	"/etc/motd"
5836460Sbostic#define	MAILDIR		"/usr/spool/mail"
5936460Sbostic#define	NOLOGIN		"/etc/nologin"
6036460Sbostic#define	HUSHLOGIN	".hushlogin"
6136460Sbostic#define	LASTLOG		"/usr/adm/lastlog"
6236460Sbostic#define	BSHELL		"/bin/sh"
632822Swnj
6412687Ssam/*
6536460Sbostic * This bounds the time given to login.  Not a define so it can
6636460Sbostic * be patched on machines where it's too small.
6712687Ssam */
6831509Sbosticint	timeout = 300;
696005Swnj
7036460Sbosticstruct passwd *pwd;
7136460Sbosticchar term[64], *hostname, *username;
726005Swnj
73*36515Sbosticstruct sgttyb sgttyb;
7436460Sbosticstruct tchars tc = {
7513074Ssam	CINTR, CQUIT, CSTART, CSTOP, CEOT, CBRK
761365Sbill};
7736460Sbosticstruct ltchars ltc = {
7813074Ssam	CSUSP, CDSUSP, CRPRNT, CFLUSH, CWERASE, CLNEXT
7913074Ssam};
801365Sbill
811043Sbillmain(argc, argv)
8236460Sbostic	int argc;
8336460Sbostic	char **argv;
841043Sbill{
8536460Sbostic	extern int errno, optind;
8636460Sbostic	extern char *optarg, **environ;
8736460Sbostic	struct group *gr;
8836460Sbostic	register int ch;
8936460Sbostic	register char *p;
9036460Sbostic	int fflag, hflag, pflag, rflag, cnt;
9136460Sbostic	int quietlog, passwd_req, ioctlval, timedout();
92*36515Sbostic	char *domain, *salt, *envinit[1], *ttyn, *tty;
9336460Sbostic	char tbuf[MAXPATHLEN + 2];
9436460Sbostic	char *ttyname(), *stypeof(), *crypt(), *getpass();
9536460Sbostic	time_t time();
9636460Sbostic	off_t lseek();
971043Sbill
9836460Sbostic	(void)signal(SIGALRM, timedout);
9936460Sbostic	(void)alarm((u_int)timeout);
10036460Sbostic	(void)signal(SIGQUIT, SIG_IGN);
10136460Sbostic	(void)signal(SIGINT, SIG_IGN);
10236460Sbostic	(void)setpriority(PRIO_PROCESS, 0, 0);
10336460Sbostic	(void)quota(Q_SETUID, 0, 0, 0);
10436460Sbostic
10512687Ssam	/*
10618549Ssam	 * -p is used by getty to tell login not to destroy the environment
10712687Ssam	 * -r is used by rlogind to cause the autologin protocol;
10831695Skarels 	 * -f is used to skip a second login authentication
10912687Ssam	 * -h is used by other servers to pass the name of the
11012687Ssam	 * remote host to login so that it may be placed in utmp and wtmp
11112687Ssam	 */
11236460Sbostic	(void)gethostname(tbuf, sizeof(tbuf));
11336460Sbostic	domain = index(tbuf, '.');
11436460Sbostic
11536460Sbostic	fflag = hflag = pflag = rflag = 0;
11636460Sbostic	passwd_req = 1;
117*36515Sbostic	while ((ch = getopt(argc, argv, "fh:pr:")) != EOF)
118*36515Sbostic		switch (ch) {
11936460Sbostic		case 'f':
12036460Sbostic			if (rflag) {
12136460Sbostic				fprintf(stderr,
12236460Sbostic				    "login: only one of -r and -f allowed.\n");
12324712Sbloom				exit(1);
12424712Sbloom			}
12536460Sbostic			fflag = 1;
12636460Sbostic			break;
12736460Sbostic		case 'h':
12836460Sbostic			if (getuid()) {
12936460Sbostic				fprintf(stderr,
13036460Sbostic				    "login: -h for super-user only.\n");
13132313Sbostic				exit(1);
13231695Skarels			}
13331695Skarels			if (rflag) {
13436460Sbostic				fprintf(stderr,
13536460Sbostic				    "login: only one of -r and -h allowed.\n");
13624712Sbloom				exit(1);
13724712Sbloom			}
13836460Sbostic			hflag = 1;
13936460Sbostic			if (domain && (p = index(optarg, '.')) &&
14036460Sbostic			    strcmp(p, domain) == 0)
14136460Sbostic				*p = 0;
14236460Sbostic			hostname = optarg;
14336460Sbostic			break;
14436460Sbostic		case 'p':
14518549Ssam			pflag = 1;
14636460Sbostic			break;
14736460Sbostic		case 'r':
14836460Sbostic			if (hflag || fflag) {
14936460Sbostic				fprintf(stderr,
15036460Sbostic				    "login: -f and -h not allowed with -r.\n");
15136460Sbostic				exit(1);
15236460Sbostic			}
153*36515Sbostic			if (getuid()) {
154*36515Sbostic				fprintf(stderr,
155*36515Sbostic				    "login: -r for super-user only.\n");
156*36515Sbostic				exit(1);
157*36515Sbostic			}
158*36515Sbostic			/* "-r hostname" must be last args */
159*36515Sbostic			if (optind != argc) {
160*36515Sbostic				fprintf(stderr, "Syntax error.\n");
161*36515Sbostic				exit(1);
162*36515Sbostic			}
16336460Sbostic			rflag = 1;
164*36515Sbostic			passwd_req = (doremotelogin(optarg) == -1);
16536460Sbostic			if (domain && (p = index(optarg, '.')) &&
16636460Sbostic			    !strcmp(p, domain))
16736460Sbostic				*p = '\0';
16836460Sbostic			hostname = optarg;
16936460Sbostic			break;
17036460Sbostic		case '?':
17136460Sbostic		default:
172*36515Sbostic			fprintf(stderr, "usage: login [-fp] [username]\n");
17336460Sbostic			exit(1);
17418549Ssam		}
17536460Sbostic	argc -= optind;
17636460Sbostic	argv += optind;
17736460Sbostic	if (*argv)
17836460Sbostic		username = *argv;
17936460Sbostic
18036460Sbostic	ioctlval = 0;
18136460Sbostic	(void)ioctl(0, TIOCLSET, &ioctlval);
18236460Sbostic	(void)ioctl(0, TIOCNXCL, 0);
183*36515Sbostic	(void)fcntl(0, F_SETFL, ioctlval);
184*36515Sbostic	(void)ioctl(0, TIOCGETP, &sgttyb);
18536460Sbostic
18612687Ssam	/*
18736460Sbostic	 * If talking to an rlogin process, propagate the terminal type and
18812687Ssam	 * baud rate across the network.
18912687Ssam	 */
19012687Ssam	if (rflag)
191*36515Sbostic		doremoteterm(&sgttyb);
192*36515Sbostic	sgttyb.sg_erase = CERASE;
193*36515Sbostic	sgttyb.sg_kill = CKILL;
19436460Sbostic	(void)ioctl(0, TIOCSLTC, &ltc);
19536460Sbostic	(void)ioctl(0, TIOCSETC, &tc);
196*36515Sbostic	(void)ioctl(0, TIOCSETP, &sgttyb);
19736460Sbostic
19836460Sbostic	for (cnt = getdtablesize(); cnt > 2; cnt--)
19936460Sbostic		close(cnt);
20036460Sbostic
2011043Sbill	ttyn = ttyname(0);
20236460Sbostic	if (ttyn == NULL || *ttyn == '\0')
2031043Sbill		ttyn = "/dev/tty??";
20436460Sbostic	if (tty = rindex(ttyn, '/'))
20536460Sbostic		++tty;
20636460Sbostic	else
20716453Sroot		tty = ttyn;
20836460Sbostic
20924852Seric	openlog("login", LOG_ODELAY, LOG_AUTH);
21036460Sbostic
21136460Sbostic	for (cnt = 0;; username = NULL) {
21236460Sbostic		ioctlval = 0;
21336460Sbostic		(void)ioctl(0, TIOCSETD, &ioctlval);
21436460Sbostic
215*36515Sbostic		if (username == NULL) {
216*36515Sbostic			fflag = 0;
21736460Sbostic			getloginname();
218*36515Sbostic		}
219*36515Sbostic		if (pwd = getpwnam(username))
220*36515Sbostic			salt = pwd->pw_passwd;
221*36515Sbostic		else
222*36515Sbostic			salt = "xx";
22336460Sbostic
22436460Sbostic		/* if user not super-user, check for disabled logins */
225*36515Sbostic		if (pwd == NULL || pwd->pw_uid)
22636460Sbostic			checknologin();
22736460Sbostic
22812687Ssam		/*
229*36515Sbostic		 * Disallow automatic login to root; if not invoked by
230*36515Sbostic		 * root, disallow if the uid's differ.
23112687Ssam		 */
232*36515Sbostic		if (fflag && pwd) {
23331695Skarels			int uid = getuid();
23431695Skarels
235*36515Sbostic			passwd_req = pwd->pw_uid == 0 ||
236*36515Sbostic			    (uid && uid != pwd->pw_uid);
23731695Skarels		}
23836460Sbostic
23912687Ssam		/*
24036460Sbostic		 * If no remote login authentication and a password exists
24136460Sbostic		 * for this user, prompt for one and verify it.
24212687Ssam		 */
243*36515Sbostic		if (!passwd_req || pwd && !*pwd->pw_passwd)
24436460Sbostic			break;
24512687Ssam
24636460Sbostic		setpriority(PRIO_PROCESS, 0, -4);
247*36515Sbostic		p = crypt(getpass("Password:"), salt);
24836460Sbostic		setpriority(PRIO_PROCESS, 0, 0);
249*36515Sbostic		if (pwd && !strcmp(p, pwd->pw_passwd))
25036460Sbostic			break;
25136460Sbostic
25236460Sbostic		printf("Login incorrect\n");
25336460Sbostic		if (++cnt >= 5) {
25436460Sbostic			if (hostname)
25536460Sbostic			    syslog(LOG_ERR,
25636460Sbostic				"REPEATED LOGIN FAILURES ON %s FROM %.*s, %.*s",
25736460Sbostic				tty, UT_HOSTSIZE, hostname, UT_NAMESIZE,
25836460Sbostic				username);
25925230Smckusick			else
26036460Sbostic			    syslog(LOG_ERR,
26136460Sbostic				"REPEATED LOGIN FAILURES ON %s, %.*s",
26236460Sbostic				tty, UT_NAMESIZE, username);
26336460Sbostic			(void)ioctl(0, TIOCHPCL, (struct sgttyb *)NULL);
26436460Sbostic			sleepexit(1);
2652822Swnj		}
26636460Sbostic	}
2671043Sbill
26836460Sbostic	/* committed to login -- turn off timeout */
26936460Sbostic	(void)alarm((u_int)0);
27036460Sbostic
27136460Sbostic	/*
27236460Sbostic	 * If valid so far and root is logging in, see if root logins on
27336460Sbostic	 * this terminal are permitted.
27436460Sbostic	 */
275*36515Sbostic	if (pwd->pw_uid == 0 && !rootterm(tty)) {
27636460Sbostic		if (hostname)
277*36515Sbostic			syslog(LOG_ERR, "ROOT LOGIN REFUSED ON %s FROM %.*s",
27836460Sbostic			    tty, UT_HOSTSIZE, hostname);
27912678Ssam		else
280*36515Sbostic			syslog(LOG_ERR, "ROOT LOGIN REFUSED ON %s", tty);
28136460Sbostic		printf("Login incorrect\n");
28236460Sbostic		sleepexit(1);
28312678Ssam	}
2842822Swnj
28536460Sbostic	if (quota(Q_SETUID, pwd->pw_uid, 0, 0) < 0 && errno != EINVAL) {
28636460Sbostic		switch(errno) {
28736460Sbostic		case EUSERS:
28836460Sbostic			fprintf(stderr,
28936460Sbostic		"Too many users logged on already.\nTry again later.\n");
29036460Sbostic			break;
29136460Sbostic		case EPROCLIM:
29236460Sbostic			fprintf(stderr,
29336460Sbostic			    "You have too many processes running.\n");
29436460Sbostic			break;
29536460Sbostic		default:
29636460Sbostic			perror("quota (Q_SETUID)");
2972822Swnj		}
29836460Sbostic		sleepexit(0);
2992822Swnj	}
30036460Sbostic
301*36515Sbostic	if (chdir(pwd->pw_dir) < 0) {
302*36515Sbostic		printf("No directory %s!\n", pwd->pw_dir);
303*36515Sbostic		if (chdir("/"))
304*36515Sbostic			exit(0);
305*36515Sbostic		pwd->pw_dir = "/";
306*36515Sbostic		printf("Logging in with home = \"/\".\n");
307*36515Sbostic	}
308*36515Sbostic
309*36515Sbostic	/* nothing else left to fail -- really log in */
31036460Sbostic	{
31136460Sbostic		struct utmp utmp;
31236460Sbostic
31336460Sbostic		(void)time(&utmp.ut_time);
31436460Sbostic		strncpy(utmp.ut_name, username, sizeof(utmp.ut_name));
31536460Sbostic		strncpy(utmp.ut_host, hostname, sizeof(utmp.ut_host));
31636460Sbostic		strncpy(utmp.ut_line, tty, sizeof(utmp.ut_line));
31736460Sbostic		login(&utmp);
31836460Sbostic	}
31936460Sbostic
32036460Sbostic	quietlog = access(HUSHLOGIN, F_OK) == 0;
32136460Sbostic	dolastlog(quietlog, tty);
32236460Sbostic
32336460Sbostic	if (!hflag && !rflag) {					/* XXX */
32436460Sbostic		static struct winsize win = { 0, 0, 0, 0 };
32536460Sbostic
32636460Sbostic		(void)ioctl(0, TIOCSWINSZ, &win);
32736460Sbostic	}
32836460Sbostic
32936460Sbostic	(void)chown(ttyn, pwd->pw_uid,
33036460Sbostic	    (gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid);
33136460Sbostic	(void)chmod(ttyn, 0620);
33236460Sbostic	(void)setgid(pwd->pw_gid);
33336460Sbostic
33436460Sbostic	initgroups(username, pwd->pw_gid);
33536460Sbostic
33612678Ssam	quota(Q_DOWARN, pwd->pw_uid, (dev_t)-1, 0);
33736460Sbostic	(void)setuid(pwd->pw_uid);
33830606Sbostic
339*36515Sbostic	if (*pwd->pw_shell == '\0')
340*36515Sbostic		pwd->pw_shell = BSHELL;
341*36515Sbostic	/* turn on new line discipline for the csh */
342*36515Sbostic	else if (!strcmp(pwd->pw_shell, "/bin/csh")) {
343*36515Sbostic		ioctlval = NTTYDISC;
344*36515Sbostic		(void)ioctl(0, TIOCSETD, &ioctlval);
345*36515Sbostic	}
346*36515Sbostic
34736460Sbostic	/* destroy environment unless user has requested preservation */
34818549Ssam	if (!pflag)
34918549Ssam		environ = envinit;
350*36515Sbostic	(void)setenv("HOME", pwd->pw_dir, 1);
351*36515Sbostic	(void)setenv("SHELL", pwd->pw_shell, 1);
35218549Ssam	if (term[0] == '\0')
35318549Ssam		strncpy(term, stypeof(tty), sizeof(term));
354*36515Sbostic	(void)setenv("TERM", term, 0);
355*36515Sbostic	(void)setenv("USER", pwd->pw_name, 1);
356*36515Sbostic	(void)setenv("PATH", "/usr/ucb:/bin:/usr/bin:", 0);
35718549Ssam
35816453Sroot	if (tty[sizeof("tty")-1] == 'd')
35918549Ssam		syslog(LOG_INFO, "DIALUP %s, %s", tty, pwd->pw_name);
36018549Ssam	if (pwd->pw_uid == 0)
36136460Sbostic		if (hostname)
36225230Smckusick			syslog(LOG_NOTICE, "ROOT LOGIN %s FROM %.*s",
36336460Sbostic			    tty, UT_HOSTSIZE, hostname);
36425230Smckusick		else
36525230Smckusick			syslog(LOG_NOTICE, "ROOT LOGIN %s", tty);
36636460Sbostic
3676329Swnj	if (!quietlog) {
36817664Sserge		struct stat st;
36918549Ssam
37036460Sbostic		motd();
37136460Sbostic		(void)sprintf(tbuf, "%s/%s", MAILDIR, pwd->pw_name);
37236460Sbostic		if (stat(tbuf, &st) == 0 && st.st_size != 0)
37317664Sserge			printf("You have %smail.\n",
37436460Sbostic			    (st.st_mtime > st.st_atime) ? "new " : "");
3752822Swnj	}
37636460Sbostic
37736460Sbostic	(void)signal(SIGALRM, SIG_DFL);
37836460Sbostic	(void)signal(SIGQUIT, SIG_DFL);
37936460Sbostic	(void)signal(SIGINT, SIG_DFL);
38036460Sbostic	(void)signal(SIGTSTP, SIG_IGN);
38136460Sbostic
38236460Sbostic	tbuf[0] = '-';
38336460Sbostic	strcpy(tbuf + 1, (p = rindex(pwd->pw_shell, '/')) ?
38436460Sbostic	    p + 1 : pwd->pw_shell);
38536460Sbostic	execlp(pwd->pw_shell, tbuf, 0);
386*36515Sbostic	fprintf(stderr, "login: no shell: ");
3872822Swnj	perror(pwd->pw_shell);
3881043Sbill	exit(0);
3891043Sbill}
3901043Sbill
39136460Sbosticgetloginname()
39212687Ssam{
39336460Sbostic	register int ch;
39436460Sbostic	register char *p;
39536460Sbostic	static char nbuf[UT_NAMESIZE + 1];
39612687Ssam
39736460Sbostic	for (;;) {
39812712Ssam		printf("login: ");
399*36515Sbostic		for (p = nbuf; (ch = getchar()) != '\n'; ) {
40036460Sbostic			if (ch == EOF)
40112687Ssam				exit(0);
402*36515Sbostic			if (p < nbuf + UT_NAMESIZE)
40336460Sbostic				*p++ = ch;
40412687Ssam		}
40536460Sbostic		if (p > nbuf)
40636460Sbostic			if (nbuf[0] == '-')
40736460Sbostic				fprintf(stderr,
40836460Sbostic				    "login names may not start with '-'.\n");
40936460Sbostic			else {
41036460Sbostic				*p = '\0';
41136460Sbostic				username = nbuf;
412*36515Sbostic				break;
41336460Sbostic			}
41412687Ssam	}
41512687Ssam}
41612687Ssam
41712687Ssamtimedout()
41812687Ssam{
41936460Sbostic	fprintf(stderr, "Login timed out after %d seconds\n", timeout);
42012687Ssam	exit(0);
42112687Ssam}
42212687Ssam
42336460Sbosticrootterm(tty)
42436460Sbostic	char *tty;
4251043Sbill{
42636460Sbostic	struct ttyent *t;
4276466Swnj
42836460Sbostic	return((t = getttynam(tty)) && t->ty_status&TTY_SECURE);
4291043Sbill}
4301043Sbill
431*36515Sbosticjmp_buf motdinterrupt;
432*36515Sbostic
43336460Sbosticmotd()
4342822Swnj{
435*36515Sbostic	register int fd, nchars;
43636460Sbostic	int (*oldint)(), sigint();
437*36515Sbostic	char tbuf[8192];
4382822Swnj
439*36515Sbostic	if ((fd = open(MOTDFILE, O_RDONLY, 0)) < 0)
44036460Sbostic		return;
44136460Sbostic	oldint = signal(SIGINT, sigint);
442*36515Sbostic	if (setjmp(motdinterrupt) == 0)
443*36515Sbostic		while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0)
444*36515Sbostic			(void)write(fileno(stdout), tbuf, nchars);
44536460Sbostic	(void)signal(SIGINT, oldint);
446*36515Sbostic	(void)close(fd);
44736460Sbostic}
44836460Sbostic
44936460Sbosticsigint()
45036460Sbostic{
451*36515Sbostic	longjmp(motdinterrupt, 1);
45236460Sbostic}
45336460Sbostic
45436460Sbosticchecknologin()
45536460Sbostic{
45636460Sbostic	register int fd, nchars;
457*36515Sbostic	char tbuf[8192];
45836460Sbostic
45936460Sbostic	if ((fd = open(NOLOGIN, O_RDONLY, 0)) >= 0) {
46036460Sbostic		while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0)
46136460Sbostic			(void)write(fileno(stdout), tbuf, nchars);
46236460Sbostic		sleepexit(0);
4632822Swnj	}
4642822Swnj}
4652822Swnj
46636460Sbosticdolastlog(quiet, tty)
46736460Sbostic	int quiet;
46836460Sbostic	char *tty;
4691043Sbill{
47036460Sbostic	struct lastlog ll;
47136460Sbostic	int fd;
4721043Sbill
47336460Sbostic	if ((fd = open(LASTLOG, O_RDWR, 0)) >= 0) {
474*36515Sbostic		(void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), L_SET);
47536460Sbostic		if (!quiet) {
47636460Sbostic			if (read(fd, (char *)&ll, sizeof(ll)) == sizeof(ll) &&
47736460Sbostic			    ll.ll_time != 0) {
47836460Sbostic				printf("Last login: %.*s ",
47936460Sbostic				    24-5, (char *)ctime(&ll.ll_time));
48036460Sbostic				if (*ll.ll_host != '\0')
48136460Sbostic					printf("from %.*s\n",
48236460Sbostic					    sizeof(ll.ll_host), ll.ll_host);
48336460Sbostic				else
48436460Sbostic					printf("on %.*s\n",
48536460Sbostic					    sizeof(ll.ll_line), ll.ll_line);
48636460Sbostic			}
487*36515Sbostic			(void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), L_SET);
48836460Sbostic		}
48936460Sbostic		(void)time(&ll.ll_time);
49036460Sbostic		strncpy(ll.ll_line, tty, sizeof(ll.ll_line));
49136460Sbostic		strncpy(ll.ll_host, hostname, sizeof(ll.ll_host));
49236460Sbostic		(void)write(fd, (char *)&ll, sizeof(ll));
49336460Sbostic		(void)close(fd);
4941043Sbill	}
4951043Sbill}
4961043Sbill
4972822Swnj#undef	UNKNOWN
49836460Sbostic#define	UNKNOWN	"su"
4991043Sbill
5001043Sbillchar *
5011043Sbillstypeof(ttyid)
50212687Ssam	char *ttyid;
5031043Sbill{
50436460Sbostic	struct ttyent *t;
5051043Sbill
50636460Sbostic	return(ttyid && (t = getttynam(ttyid)) ? t->ty_type : UNKNOWN);
5071043Sbill}
5086005Swnj
50912687Ssamdoremotelogin(host)
51012687Ssam	char *host;
51112687Ssam{
51236460Sbostic	static char lusername[UT_NAMESIZE+1];
51336460Sbostic	char rusername[UT_NAMESIZE+1];
51436460Sbostic
51536460Sbostic	getstr(rusername, sizeof(rusername), "remuser");
51636460Sbostic	getstr(lusername, sizeof(lusername), "locuser");
51718549Ssam	getstr(term, sizeof(term), "Terminal type");
51836460Sbostic	username = lusername;
51936460Sbostic	pwd = getpwnam(username);
520*36515Sbostic	if (pwd == NULL)
52124712Sbloom		return(-1);
52236460Sbostic	return(ruserok(host, (pwd->pw_uid == 0), rusername, username));
52312687Ssam}
52412687Ssam
5256005Swnjgetstr(buf, cnt, err)
52636460Sbostic	char *buf, *err;
5276005Swnj	int cnt;
5286005Swnj{
52936460Sbostic	char ch;
5306005Swnj
5316005Swnj	do {
53236460Sbostic		if (read(0, &ch, sizeof(ch)) != sizeof(ch))
5336005Swnj			exit(1);
5346005Swnj		if (--cnt < 0) {
53536460Sbostic			fprintf(stderr, "%s too long\r\n", err);
53636460Sbostic			sleepexit(1);
5376005Swnj		}
53836460Sbostic		*buf++ = ch;
53936460Sbostic	} while (ch);
5406005Swnj}
5416329Swnj
54236460Sbosticchar *speeds[] = {
54336460Sbostic	"0", "50", "75", "110", "134", "150", "200", "300", "600",
54436460Sbostic	"1200", "1800", "2400", "4800", "9600", "19200", "38400",
54536460Sbostic};
54636460Sbostic#define	NSPEEDS	(sizeof(speeds) / sizeof(speeds[0]))
54712687Ssam
54836460Sbosticdoremoteterm(tp)
54912687Ssam	struct sgttyb *tp;
55012687Ssam{
55118549Ssam	register char *cp = index(term, '/'), **cpp;
55218549Ssam	char *speed;
55312687Ssam
55412687Ssam	if (cp) {
55518549Ssam		*cp++ = '\0';
55618549Ssam		speed = cp;
55718549Ssam		cp = index(speed, '/');
55818549Ssam		if (cp)
55918549Ssam			*cp++ = '\0';
56018549Ssam		for (cpp = speeds; cpp < &speeds[NSPEEDS]; cpp++)
56118549Ssam			if (strcmp(*cpp, speed) == 0) {
56218549Ssam				tp->sg_ispeed = tp->sg_ospeed = cpp-speeds;
56312687Ssam				break;
56412687Ssam			}
56512687Ssam	}
56612687Ssam	tp->sg_flags = ECHO|CRMOD|ANYP|XTABS;
56712687Ssam}
56818549Ssam
56936460Sbosticsleepexit(eval)
57036460Sbostic	int eval;
57126862Smckusick{
57236460Sbostic	sleep((u_int)5);
57336460Sbostic	exit(eval);
57426862Smckusick}
575