xref: /csrg-svn/usr.bin/login/login.c (revision 32313)
119843Sdist /*
231695Skarels  * 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*32313Sbostic static char sccsid[] = "@(#)login.c	5.20 (Berkeley) 10/01/87";
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>
3012687Ssam 
311043Sbill #include <sgtty.h>
321043Sbill #include <utmp.h>
331043Sbill #include <signal.h>
341043Sbill #include <pwd.h>
351043Sbill #include <stdio.h>
361043Sbill #include <lastlog.h>
3712678Ssam #include <errno.h>
3816453Sroot #include <ttyent.h>
3916453Sroot #include <syslog.h>
4026862Smckusick #include <grp.h>
411043Sbill 
4227056Skarels #define TTYGRPNAME	"tty"		/* name of group to own ttys */
4327056Skarels #define TTYGID(gid)	tty_gid(gid)	/* gid that owns all ttys */
4426862Smckusick 
4516453Sroot #define	SCMPN(a, b)	strncmp(a, b, sizeof(a))
462822Swnj #define	SCPYN(a, b)	strncpy(a, b, sizeof(a))
472822Swnj 
486197Sroot #define NMAX	sizeof(utmp.ut_name)
4925230Smckusick #define HMAX	sizeof(utmp.ut_host)
501043Sbill 
512822Swnj #define	FALSE	0
522822Swnj #define	TRUE	-1
532822Swnj 
542822Swnj char	nolog[] =	"/etc/nologin";
552822Swnj char	qlog[]  =	".hushlogin";
561043Sbill char	maildir[30] =	"/usr/spool/mail/";
571043Sbill char	lastlog[] =	"/usr/adm/lastlog";
589867Ssam struct	passwd nouser = {"", "nope", -1, -1, -1, "", "", "", "" };
591043Sbill struct	sgttyb ttyb;
601043Sbill struct	utmp utmp;
611043Sbill char	minusnam[16] = "-";
6230606Sbostic char	*envinit[1];			/* now set by setenv calls */
6312687Ssam /*
6412687Ssam  * This bounds the time given to login.  We initialize it here
6512687Ssam  * so it can be patched on machines where it's too small.
6612687Ssam  */
6731509Sbostic int	timeout = 300;
686005Swnj 
6918549Ssam char	term[64];
706005Swnj 
711043Sbill struct	passwd *pwd;
7230606Sbostic char	*strcat(), *rindex(), *index();
7312687Ssam int	timedout();
741043Sbill char	*ttyname();
751043Sbill char	*crypt();
761043Sbill char	*getpass();
771043Sbill char	*stypeof();
7812678Ssam extern	int errno;
791043Sbill 
8013074Ssam struct	tchars tc = {
8113074Ssam 	CINTR, CQUIT, CSTART, CSTOP, CEOT, CBRK
821365Sbill };
8313074Ssam struct	ltchars ltc = {
8413074Ssam 	CSUSP, CDSUSP, CRPRNT, CFLUSH, CWERASE, CLNEXT
8513074Ssam };
861365Sbill 
8718549Ssam struct winsize win = { 0, 0, 0, 0 };
8818549Ssam 
896005Swnj int	rflag;
9024712Sbloom int	usererr = -1;
916197Sroot char	rusername[NMAX+1], lusername[NMAX+1];
926005Swnj char	rpassword[NMAX+1];
936878Smckusick char	name[NMAX+1];
9429992Skarels char	me[MAXHOSTNAMELEN];
956197Sroot char	*rhost;
966005Swnj 
971043Sbill main(argc, argv)
9812687Ssam 	char *argv[];
991043Sbill {
10030606Sbostic 	extern	char **environ;
1011043Sbill 	register char *namep;
10231695Skarels 	int pflag = 0, hflag = 0, fflag = 0, t, f, c;
10312687Ssam 	int invalid, quietlog;
1042822Swnj 	FILE *nlfd;
10516453Sroot 	char *ttyn, *tty;
10618549Ssam 	int ldisc = 0, zero = 0, i;
10729992Skarels 	char *p, *domain, *index();
1081043Sbill 
10912687Ssam 	signal(SIGALRM, timedout);
11012687Ssam 	alarm(timeout);
1111043Sbill 	signal(SIGQUIT, SIG_IGN);
1121043Sbill 	signal(SIGINT, SIG_IGN);
11312687Ssam 	setpriority(PRIO_PROCESS, 0, 0);
11412678Ssam 	quota(Q_SETUID, 0, 0, 0);
11512687Ssam 	/*
11618549Ssam 	 * -p is used by getty to tell login not to destroy the environment
11712687Ssam 	 * -r is used by rlogind to cause the autologin protocol;
11831695Skarels  	 * -f is used to skip a second login authentication
11912687Ssam 	 * -h is used by other servers to pass the name of the
12012687Ssam 	 * remote host to login so that it may be placed in utmp and wtmp
12112687Ssam 	 */
12229992Skarels 	(void) gethostname(me, sizeof(me));
12329992Skarels 	domain = index(me, '.');
12424712Sbloom 	while (argc > 1) {
12512687Ssam 		if (strcmp(argv[1], "-r") == 0) {
12631695Skarels 			if (rflag || hflag || fflag) {
12731695Skarels 				printf("Other options not allowed with -r\n");
12824712Sbloom 				exit(1);
12924712Sbloom 			}
130*32313Sbostic 			if (argv[2] == 0)
131*32313Sbostic 				exit(1);
13224712Sbloom 			rflag = 1;
13324712Sbloom 			usererr = doremotelogin(argv[2]);
13429992Skarels 			if ((p = index(argv[2], '.')) && strcmp(p, domain) == 0)
13529992Skarels 				*p = 0;
13612687Ssam 			SCPYN(utmp.ut_host, argv[2]);
13724712Sbloom 			argc -= 2;
13824712Sbloom 			argv += 2;
13924712Sbloom 			continue;
1406197Sroot 		}
14131695Skarels 		if (strcmp(argv[1], "-h") == 0) {
14231695Skarels 			if (getuid() == 0) {
14331695Skarels 				if (rflag || hflag) {
14431695Skarels 				    printf("Only one of -r and -h allowed\n");
14531695Skarels 				    exit(1);
14631695Skarels 				}
14731695Skarels 				hflag = 1;
14831695Skarels 				if ((p = index(argv[2], '.')) &&
14931695Skarels 				    strcmp(p, domain) == 0)
15031695Skarels 					*p = 0;
15131695Skarels 				SCPYN(utmp.ut_host, argv[2]);
15231695Skarels 			}
15331695Skarels 			argc -= 2;
15431695Skarels 			argv += 2;
15531695Skarels 			continue;
15631695Skarels 		}
15731695Skarels 		if (strcmp(argv[1], "-f") == 0 && argc > 2) {
15831695Skarels 			if (rflag) {
15931695Skarels 				printf("Only one of -r and -f allowed\n");
16024712Sbloom 				exit(1);
16124712Sbloom 			}
16231695Skarels 			fflag = 1;
16331695Skarels 			SCPYN(utmp.ut_name, argv[2]);
16424712Sbloom 			argc -= 2;
16524712Sbloom 			argv += 2;
16624712Sbloom 			continue;
1676197Sroot 		}
16818549Ssam 		if (strcmp(argv[1], "-p") == 0) {
16918549Ssam 			argc--;
17018549Ssam 			argv++;
17118549Ssam 			pflag = 1;
17224712Sbloom 			continue;
17318549Ssam 		}
17424712Sbloom 		break;
1756005Swnj 	}
17613074Ssam 	ioctl(0, TIOCLSET, &zero);
1771547Sbill 	ioctl(0, TIOCNXCL, 0);
1786329Swnj 	ioctl(0, FIONBIO, &zero);
1796329Swnj 	ioctl(0, FIOASYNC, &zero);
18013074Ssam 	ioctl(0, TIOCGETP, &ttyb);
18112687Ssam 	/*
18212687Ssam 	 * If talking to an rlogin process,
18312687Ssam 	 * propagate the terminal type and
18412687Ssam 	 * baud rate across the network.
18512687Ssam 	 */
18612687Ssam 	if (rflag)
18712687Ssam 		doremoteterm(term, &ttyb);
18826482Skarels 	ttyb.sg_erase = CERASE;
18926482Skarels 	ttyb.sg_kill = CKILL;
19013074Ssam 	ioctl(0, TIOCSLTC, &ltc);
19113074Ssam 	ioctl(0, TIOCSETC, &tc);
19213074Ssam 	ioctl(0, TIOCSETP, &ttyb);
19324849Smckusick 	for (t = getdtablesize(); t > 2; t--)
1941043Sbill 		close(t);
1951043Sbill 	ttyn = ttyname(0);
19625426Sbloom 	if (ttyn == (char *)0 || *ttyn == '\0')
1971043Sbill 		ttyn = "/dev/tty??";
19816453Sroot 	tty = rindex(ttyn, '/');
19916453Sroot 	if (tty == NULL)
20016453Sroot 		tty = ttyn;
20116453Sroot 	else
20216453Sroot 		tty++;
20324852Seric 	openlog("login", LOG_ODELAY, LOG_AUTH);
20416453Sroot 	t = 0;
20525163Sbloom 	invalid = FALSE;
2062822Swnj 	do {
2072822Swnj 		ldisc = 0;
2082822Swnj 		ioctl(0, TIOCSETD, &ldisc);
20931695Skarels 		if (fflag == 0)
21031695Skarels 			SCPYN(utmp.ut_name, "");
21112687Ssam 		/*
21212687Ssam 		 * Name specified, take it.
21312687Ssam 		 */
21412687Ssam 		if (argc > 1) {
2152822Swnj 			SCPYN(utmp.ut_name, argv[1]);
2162822Swnj 			argc = 0;
2171043Sbill 		}
21812687Ssam 		/*
21912687Ssam 		 * If remote login take given name,
22012687Ssam 		 * otherwise prompt user for something.
22112687Ssam 		 */
22225163Sbloom 		if (rflag && !invalid)
2239867Ssam 			SCPYN(utmp.ut_name, lusername);
224*32313Sbostic 		else {
22512687Ssam 			getloginname(&utmp);
226*32313Sbostic 			if (utmp.ut_name[0] == '-') {
227*32313Sbostic 				puts("login names may not start with '-'.");
228*32313Sbostic 				invalid = TRUE;
229*32313Sbostic 				continue;
230*32313Sbostic 			}
231*32313Sbostic 		}
23225163Sbloom 		invalid = FALSE;
2332822Swnj 		if (!strcmp(pwd->pw_shell, "/bin/csh")) {
2342822Swnj 			ldisc = NTTYDISC;
2352822Swnj 			ioctl(0, TIOCSETD, &ldisc);
2362822Swnj 		}
23731695Skarels 		if (fflag) {
23831695Skarels 			int uid = getuid();
23931695Skarels 
24031695Skarels 			if (uid != 0 && uid != pwd->pw_uid)
24131695Skarels 				fflag = 0;
24231695Skarels 			/*
24331695Skarels 			 * Disallow automatic login for root.
24431695Skarels 			 */
24531695Skarels 			if (pwd->pw_uid == 0)
24631695Skarels 				fflag = 0;
24731695Skarels 		}
24812687Ssam 		/*
24912687Ssam 		 * If no remote login authentication and
25012687Ssam 		 * a password exists for this user, prompt
25112687Ssam 		 * for one and verify it.
25212687Ssam 		 */
25331695Skarels 		if (usererr == -1 && fflag == 0 && *pwd->pw_passwd != '\0') {
25412687Ssam 			char *pp;
25512687Ssam 
25612687Ssam 			setpriority(PRIO_PROCESS, 0, -4);
25712687Ssam 			pp = getpass("Password:");
25812687Ssam 			namep = crypt(pp, pwd->pw_passwd);
25912687Ssam 			setpriority(PRIO_PROCESS, 0, 0);
26012687Ssam 			if (strcmp(namep, pwd->pw_passwd))
26112687Ssam 				invalid = TRUE;
2622822Swnj 		}
26312687Ssam 		/*
26412687Ssam 		 * If user not super-user, check for logins disabled.
26512687Ssam 		 */
2662822Swnj 		if (pwd->pw_uid != 0 && (nlfd = fopen(nolog, "r")) > 0) {
2672822Swnj 			while ((c = getc(nlfd)) != EOF)
2682822Swnj 				putchar(c);
2692822Swnj 			fflush(stdout);
2702822Swnj 			sleep(5);
2712822Swnj 			exit(0);
2722822Swnj 		}
27312687Ssam 		/*
27412687Ssam 		 * If valid so far and root is logging in,
27512687Ssam 		 * see if root logins on this terminal are permitted.
27612687Ssam 		 */
27716453Sroot 		if (!invalid && pwd->pw_uid == 0 && !rootterm(tty)) {
27825230Smckusick 			if (utmp.ut_host[0])
27925230Smckusick 				syslog(LOG_CRIT,
28025230Smckusick 				    "ROOT LOGIN REFUSED ON %s FROM %.*s",
28125230Smckusick 				    tty, HMAX, utmp.ut_host);
28225230Smckusick 			else
28325230Smckusick 				syslog(LOG_CRIT,
28425230Smckusick 				    "ROOT LOGIN REFUSED ON %s", tty);
2852822Swnj 			invalid = TRUE;
2862822Swnj 		}
2872822Swnj 		if (invalid) {
2881043Sbill 			printf("Login incorrect\n");
28916453Sroot 			if (++t >= 5) {
29025230Smckusick 				if (utmp.ut_host[0])
29131695Skarels 					syslog(LOG_ERR,
29231695Skarels 			    "REPEATED LOGIN FAILURES ON %s FROM %.*s, %.*s",
29325230Smckusick 					    tty, HMAX, utmp.ut_host,
29425230Smckusick 					    NMAX, utmp.ut_name);
29525230Smckusick 				else
29631695Skarels 					syslog(LOG_ERR,
29731695Skarels 				    "REPEATED LOGIN FAILURES ON %s, %.*s",
29825230Smckusick 						tty, NMAX, utmp.ut_name);
29916453Sroot 				ioctl(0, TIOCHPCL, (struct sgttyb *) 0);
30018549Ssam 				close(0), close(1), close(2);
30116453Sroot 				sleep(10);
30216453Sroot 				exit(1);
30316453Sroot 			}
3041043Sbill 		}
3052822Swnj 		if (*pwd->pw_shell == '\0')
3062822Swnj 			pwd->pw_shell = "/bin/sh";
3072822Swnj 		if (chdir(pwd->pw_dir) < 0 && !invalid ) {
3082822Swnj 			if (chdir("/") < 0) {
3092822Swnj 				printf("No directory!\n");
3102822Swnj 				invalid = TRUE;
3112822Swnj 			} else {
31212687Ssam 				printf("No directory! %s\n",
31312687Ssam 				   "Logging in with home=/");
3142822Swnj 				pwd->pw_dir = "/";
3152822Swnj 			}
3161043Sbill 		}
31712687Ssam 		/*
31812687Ssam 		 * Remote login invalid must have been because
31912687Ssam 		 * of a restriction of some sort, no extra chances.
32012687Ssam 		 */
32124712Sbloom 		if (!usererr && invalid)
3226005Swnj 			exit(1);
3232822Swnj 	} while (invalid);
32412687Ssam /* committed to login turn off timeout */
32512687Ssam 	alarm(0);
3261043Sbill 
32721083Smckusick 	if (quota(Q_SETUID, pwd->pw_uid, 0, 0) < 0 && errno != EINVAL) {
32812678Ssam 		if (errno == EUSERS)
32912678Ssam 			printf("%s.\n%s.\n",
33012678Ssam 			   "Too many users logged on already",
33112678Ssam 			   "Try again later");
33212678Ssam 		else if (errno == EPROCLIM)
33312678Ssam 			printf("You have too many processes running.\n");
33412678Ssam 		else
33517664Sserge 			perror("quota (Q_SETUID)");
33612678Ssam 		sleep(5);
33712678Ssam 		exit(0);
33812678Ssam 	}
3391043Sbill 	time(&utmp.ut_time);
3401043Sbill 	t = ttyslot();
34116453Sroot 	if (t > 0 && (f = open("/etc/utmp", O_WRONLY)) >= 0) {
3421043Sbill 		lseek(f, (long)(t*sizeof(utmp)), 0);
34316453Sroot 		SCPYN(utmp.ut_line, tty);
3441043Sbill 		write(f, (char *)&utmp, sizeof(utmp));
3451043Sbill 		close(f);
3461043Sbill 	}
34716453Sroot 	if ((f = open("/usr/adm/wtmp", O_WRONLY|O_APPEND)) >= 0) {
3481043Sbill 		write(f, (char *)&utmp, sizeof(utmp));
3491043Sbill 		close(f);
3501043Sbill 	}
35116453Sroot 	quietlog = access(qlog, F_OK) == 0;
35216453Sroot 	if ((f = open(lastlog, O_RDWR)) >= 0) {
3532822Swnj 		struct lastlog ll;
3542822Swnj 
3552822Swnj 		lseek(f, (long)pwd->pw_uid * sizeof (struct lastlog), 0);
3562822Swnj 		if (read(f, (char *) &ll, sizeof ll) == sizeof ll &&
35712687Ssam 		    ll.ll_time != 0 && !quietlog) {
35812687Ssam 			printf("Last login: %.*s ",
35912687Ssam 			    24-5, (char *)ctime(&ll.ll_time));
36012687Ssam 			if (*ll.ll_host != '\0')
36112687Ssam 				printf("from %.*s\n",
36212687Ssam 				    sizeof (ll.ll_host), ll.ll_host);
36312687Ssam 			else
36412687Ssam 				printf("on %.*s\n",
36512687Ssam 				    sizeof (ll.ll_line), ll.ll_line);
3662822Swnj 		}
3672822Swnj 		lseek(f, (long)pwd->pw_uid * sizeof (struct lastlog), 0);
3682822Swnj 		time(&ll.ll_time);
36916453Sroot 		SCPYN(ll.ll_line, tty);
37012687Ssam 		SCPYN(ll.ll_host, utmp.ut_host);
3712822Swnj 		write(f, (char *) &ll, sizeof ll);
3722822Swnj 		close(f);
3732822Swnj 	}
37427056Skarels 	chown(ttyn, pwd->pw_uid, TTYGID(pwd->pw_gid));
37524849Smckusick 	if (!hflag && !rflag)					/* XXX */
37618549Ssam 		ioctl(0, TIOCSWINSZ, &win);
37726862Smckusick 	chmod(ttyn, 0620);
3781043Sbill 	setgid(pwd->pw_gid);
3796878Smckusick 	strncpy(name, utmp.ut_name, NMAX);
3806878Smckusick 	name[NMAX] = '\0';
3819224Ssam 	initgroups(name, pwd->pw_gid);
38212678Ssam 	quota(Q_DOWARN, pwd->pw_uid, (dev_t)-1, 0);
3831043Sbill 	setuid(pwd->pw_uid);
38430606Sbostic 
38518549Ssam 	/* destroy environment unless user has asked to preserve it */
38618549Ssam 	if (!pflag)
38718549Ssam 		environ = envinit;
38830606Sbostic 	setenv("HOME", pwd->pw_dir, 1);
38930606Sbostic 	setenv("SHELL", pwd->pw_shell, 1);
39018549Ssam 	if (term[0] == '\0')
39118549Ssam 		strncpy(term, stypeof(tty), sizeof(term));
39230606Sbostic 	setenv("TERM", term, 0);
39330606Sbostic 	setenv("USER", pwd->pw_name, 1);
39430606Sbostic 	setenv("PATH", ":/usr/ucb:/bin:/usr/bin", 0);
39518549Ssam 
3961043Sbill 	if ((namep = rindex(pwd->pw_shell, '/')) == NULL)
3971043Sbill 		namep = pwd->pw_shell;
3981043Sbill 	else
3991043Sbill 		namep++;
4001043Sbill 	strcat(minusnam, namep);
40116453Sroot 	if (tty[sizeof("tty")-1] == 'd')
40218549Ssam 		syslog(LOG_INFO, "DIALUP %s, %s", tty, pwd->pw_name);
40318549Ssam 	if (pwd->pw_uid == 0)
40425230Smckusick 		if (utmp.ut_host[0])
40525230Smckusick 			syslog(LOG_NOTICE, "ROOT LOGIN %s FROM %.*s",
40625230Smckusick 			    tty, HMAX, utmp.ut_host);
40725230Smckusick 		else
40825230Smckusick 			syslog(LOG_NOTICE, "ROOT LOGIN %s", tty);
4096329Swnj 	if (!quietlog) {
41017664Sserge 		struct stat st;
41118549Ssam 
4122822Swnj 		showmotd();
4132822Swnj 		strcat(maildir, pwd->pw_name);
41417664Sserge 		if (stat(maildir, &st) == 0 && st.st_size != 0)
41517664Sserge 			printf("You have %smail.\n",
41618549Ssam 				(st.st_mtime > st.st_atime) ? "new " : "");
4172822Swnj 	}
41812687Ssam 	signal(SIGALRM, SIG_DFL);
4191043Sbill 	signal(SIGQUIT, SIG_DFL);
4201043Sbill 	signal(SIGINT, SIG_DFL);
4213935Sroot 	signal(SIGTSTP, SIG_IGN);
4221043Sbill 	execlp(pwd->pw_shell, minusnam, 0);
4232822Swnj 	perror(pwd->pw_shell);
4241043Sbill 	printf("No shell\n");
4251043Sbill 	exit(0);
4261043Sbill }
4271043Sbill 
42812687Ssam getloginname(up)
42912687Ssam 	register struct utmp *up;
43012687Ssam {
43112687Ssam 	register char *namep;
43212712Ssam 	char c;
43312687Ssam 
43412687Ssam 	while (up->ut_name[0] == '\0') {
43514897Sedward 		namep = up->ut_name;
43612712Ssam 		printf("login: ");
43712687Ssam 		while ((c = getchar()) != '\n') {
43812687Ssam 			if (c == ' ')
43912687Ssam 				c = '_';
44012687Ssam 			if (c == EOF)
44112687Ssam 				exit(0);
44212687Ssam 			if (namep < up->ut_name+NMAX)
44312687Ssam 				*namep++ = c;
44412687Ssam 		}
44512687Ssam 	}
44614897Sedward 	strncpy(lusername, up->ut_name, NMAX);
44714897Sedward 	lusername[NMAX] = 0;
44814897Sedward 	if ((pwd = getpwnam(lusername)) == NULL)
44912687Ssam 		pwd = &nouser;
45012687Ssam }
45112687Ssam 
45212687Ssam timedout()
45312687Ssam {
45412687Ssam 
45512687Ssam 	printf("Login timed out after %d seconds\n", timeout);
45612687Ssam 	exit(0);
45712687Ssam }
45812687Ssam 
4591043Sbill int	stopmotd;
4601043Sbill catch()
4611043Sbill {
4626466Swnj 
4631043Sbill 	signal(SIGINT, SIG_IGN);
4641043Sbill 	stopmotd++;
4651043Sbill }
4661043Sbill 
4672822Swnj rootterm(tty)
4686466Swnj 	char *tty;
4692822Swnj {
47016453Sroot 	register struct ttyent *t;
4712822Swnj 
47216453Sroot 	if ((t = getttynam(tty)) != NULL) {
47316453Sroot 		if (t->ty_status & TTY_SECURE)
47416453Sroot 			return (1);
4752822Swnj 	}
47616453Sroot 	return (0);
4772822Swnj }
4782822Swnj 
4791043Sbill showmotd()
4801043Sbill {
4811043Sbill 	FILE *mf;
4821043Sbill 	register c;
4831043Sbill 
4841043Sbill 	signal(SIGINT, catch);
48516453Sroot 	if ((mf = fopen("/etc/motd", "r")) != NULL) {
4862822Swnj 		while ((c = getc(mf)) != EOF && stopmotd == 0)
4871043Sbill 			putchar(c);
4881043Sbill 		fclose(mf);
4891043Sbill 	}
4901043Sbill 	signal(SIGINT, SIG_IGN);
4911043Sbill }
4921043Sbill 
4932822Swnj #undef	UNKNOWN
4941043Sbill #define UNKNOWN "su"
4951043Sbill 
4961043Sbill char *
4971043Sbill stypeof(ttyid)
49812687Ssam 	char *ttyid;
4991043Sbill {
50016453Sroot 	register struct ttyent *t;
5011043Sbill 
50216453Sroot 	if (ttyid == NULL || (t = getttynam(ttyid)) == NULL)
5031043Sbill 		return (UNKNOWN);
50416453Sroot 	return (t->ty_type);
5051043Sbill }
5066005Swnj 
50712687Ssam doremotelogin(host)
50812687Ssam 	char *host;
50912687Ssam {
51012687Ssam 	getstr(rusername, sizeof (rusername), "remuser");
51112687Ssam 	getstr(lusername, sizeof (lusername), "locuser");
51218549Ssam 	getstr(term, sizeof(term), "Terminal type");
51313470Ssam 	if (getuid()) {
51413470Ssam 		pwd = &nouser;
51524712Sbloom 		return(-1);
51613470Ssam 	}
51712687Ssam 	pwd = getpwnam(lusername);
51813470Ssam 	if (pwd == NULL) {
51913470Ssam 		pwd = &nouser;
52024712Sbloom 		return(-1);
52113470Ssam 	}
52224712Sbloom 	return(ruserok(host, (pwd->pw_uid == 0), rusername, lusername));
52312687Ssam }
52412687Ssam 
5256005Swnj getstr(buf, cnt, err)
5266005Swnj 	char *buf;
5276005Swnj 	int cnt;
5286005Swnj 	char *err;
5296005Swnj {
5306005Swnj 	char c;
5316005Swnj 
5326005Swnj 	do {
5336005Swnj 		if (read(0, &c, 1) != 1)
5346005Swnj 			exit(1);
5356005Swnj 		if (--cnt < 0) {
5366005Swnj 			printf("%s too long\r\n", err);
5376005Swnj 			exit(1);
5386005Swnj 		}
5396005Swnj 		*buf++ = c;
5406005Swnj 	} while (c != 0);
5416005Swnj }
5426329Swnj 
54312687Ssam char	*speeds[] =
54412687Ssam     { "0", "50", "75", "110", "134", "150", "200", "300",
54512687Ssam       "600", "1200", "1800", "2400", "4800", "9600", "19200", "38400" };
54612687Ssam #define	NSPEEDS	(sizeof (speeds) / sizeof (speeds[0]))
54712687Ssam 
54812687Ssam doremoteterm(term, tp)
54912687Ssam 	char *term;
55012687Ssam 	struct sgttyb *tp;
55112687Ssam {
55218549Ssam 	register char *cp = index(term, '/'), **cpp;
55318549Ssam 	char *speed;
55412687Ssam 
55512687Ssam 	if (cp) {
55618549Ssam 		*cp++ = '\0';
55718549Ssam 		speed = cp;
55818549Ssam 		cp = index(speed, '/');
55918549Ssam 		if (cp)
56018549Ssam 			*cp++ = '\0';
56118549Ssam 		for (cpp = speeds; cpp < &speeds[NSPEEDS]; cpp++)
56218549Ssam 			if (strcmp(*cpp, speed) == 0) {
56318549Ssam 				tp->sg_ispeed = tp->sg_ospeed = cpp-speeds;
56412687Ssam 				break;
56512687Ssam 			}
56612687Ssam 	}
56712687Ssam 	tp->sg_flags = ECHO|CRMOD|ANYP|XTABS;
56812687Ssam }
56918549Ssam 
57027056Skarels tty_gid(default_gid)
57126876Smckusick 	int default_gid;
57226862Smckusick {
57326862Smckusick 	struct group *getgrnam(), *gr;
57426876Smckusick 	int gid = default_gid;
57526862Smckusick 
57627056Skarels 	gr = getgrnam(TTYGRPNAME);
57726862Smckusick 	if (gr != (struct group *) 0)
57826862Smckusick 		gid = gr->gr_gid;
57926862Smckusick 
58026862Smckusick 	endgrent();
58126862Smckusick 
58226876Smckusick 	return (gid);
58326862Smckusick }
584