xref: /csrg-svn/usr.bin/login/login.c (revision 1546)
1*1546Sbill static	char *sccsid = "@(#)login.c	4.3 (Berkeley) 10/19/80";
21043Sbill /*
31043Sbill  * login [ name ]
41043Sbill  */
51043Sbill 
61043Sbill #include <sys/types.h>
71043Sbill #include <sgtty.h>
81043Sbill #include <utmp.h>
91043Sbill #include <signal.h>
101043Sbill #include <pwd.h>
111043Sbill #include <stdio.h>
121043Sbill #include <sys/stat.h>
131043Sbill #include <lastlog.h>
141043Sbill #define SCPYN(a, b)	strncpy(a, b, sizeof(a))
151043Sbill 
161043Sbill #define NMAX sizeof(utmp.ut_name)
171043Sbill #define LMAX sizeof(utmp.ut_line)
181043Sbill 
191043Sbill char	user[20];
201043Sbill char	maildir[30] =	"/usr/spool/mail/";
211043Sbill char	lastlog[] =	"/usr/adm/lastlog";
221043Sbill struct	passwd nouser = {"", "nope"};
231043Sbill struct	sgttyb ttyb;
241043Sbill struct	utmp utmp;
251043Sbill char	minusnam[16] = "-";
261043Sbill char	homedir[64] = "HOME=";
271043Sbill char	shell[64] = "SHELL=";
281043Sbill char	term[64] = "TERM=";
291043Sbill char	*envinit[] = {homedir, shell, "PATH=:/usr/ucb:/bin:/usr/bin", term, user,0};
301043Sbill struct	passwd *pwd;
311043Sbill 
321043Sbill struct	passwd *getpwnam();
331043Sbill char	*strcat();
341043Sbill int	setpwent();
351043Sbill char	*ttyname();
361043Sbill char	*crypt();
371043Sbill char	*getpass();
381043Sbill char	*rindex();
391043Sbill char	*stypeof();
401043Sbill extern	char **environ;
411043Sbill 
421365Sbill #define	CTRL(c)	('c'&037)
431365Sbill #define	CERASE	'#'
441365Sbill #define	CEOT	CTRL(d)
451365Sbill #define	CKILL	'@'
461365Sbill #define	CQUIT	034		/* FS, cntl shift L */
471365Sbill #define	CINTR	0177		/* DEL */
481365Sbill #define	CSTOP	CTRL(s)
491365Sbill #define	CSTART	CTRL(q)
501365Sbill #define	CBRK	0377
511365Sbill struct	tchars tc = {
521365Sbill 	CINTR, CQUIT, CSTART, CSTOP, CEOT, CBRK
531365Sbill };
541365Sbill struct	ltchars ltc = {
55*1546Sbill 	CTRL(z), CTRL(y), CTRL(r), CTRL(o), CTRL(w), CTRL(v)
561365Sbill };
571365Sbill 
581043Sbill main(argc, argv)
591043Sbill char **argv;
601043Sbill {
611043Sbill 	register char *namep;
621043Sbill 	int t, f, c;
631043Sbill 	char *ttyn;
641043Sbill 	int ldisc = 0;
651043Sbill 
661043Sbill 	alarm(60);
671043Sbill 	signal(SIGQUIT, SIG_IGN);
681043Sbill 	signal(SIGINT, SIG_IGN);
691043Sbill 	nice(-100);
701043Sbill 	nice(20);
711043Sbill 	nice(0);
721365Sbill 	ioctl(0, TIOCSETD, &ldisc);
731043Sbill 	ioctl(0, TIOCLSET, 0);
741043Sbill 	gtty(0, &ttyb);
751043Sbill 	ttyb.sg_erase = '#';
761043Sbill 	ttyb.sg_kill = '@';
771043Sbill 	stty(0, &ttyb);
781365Sbill 	ioctl(0, TIOCSETC, &tc);
791365Sbill 	ioctl(0, TIOCSLTC, &ltc);
801043Sbill 	for (t=3; t<20; t++)
811043Sbill 		close(t);
821043Sbill 	ttyn = ttyname(0);
831043Sbill 	if (ttyn==0)
841043Sbill 		ttyn = "/dev/tty??";
851043Sbill 
861043Sbill     loop:
871043Sbill 	SCPYN(utmp.ut_name, "");
881043Sbill 	if (argc>1) {
891043Sbill 		SCPYN(utmp.ut_name, argv[1]);
901043Sbill 		argc = 0;
911043Sbill 	}
921043Sbill 	while (utmp.ut_name[0] == '\0') {
931043Sbill 		namep = utmp.ut_name;
941043Sbill 		printf("login: ");
951043Sbill 		while ((c = getchar()) != '\n') {
961043Sbill 			if(c == ' ')
971043Sbill 				c = '_';
981043Sbill 			if (c == EOF)
991043Sbill 				exit(0);
1001043Sbill 			if (namep < utmp.ut_name+NMAX)
1011043Sbill 				*namep++ = c;
1021043Sbill 		}
1031043Sbill 	}
1041043Sbill 	setpwent();
1051043Sbill 	if ((pwd = getpwnam(utmp.ut_name)) == NULL)
1061043Sbill 		pwd = &nouser;
1071043Sbill 	endpwent();
1081043Sbill 	if (*pwd->pw_passwd != '\0') {
1091043Sbill 		namep = crypt(getpass("Password:"),pwd->pw_passwd);
1101043Sbill 		if (strcmp(namep, pwd->pw_passwd)) {
1111043Sbill bad:
1121043Sbill 			printf("Login incorrect\n");
1131043Sbill 			if (ttyn[LMAX] == 'd') {
1141043Sbill 				FILE *console = fopen("/dev/console", "w");
1151043Sbill 				if (console != NULL) {
1161043Sbill 					fprintf(console, "\r\nBADDIALUP %s %s\r\n", ttyn+5, utmp.ut_name);
1171043Sbill 					fclose(console);
1181043Sbill 				}
1191043Sbill 			}
1201043Sbill 			goto loop;
1211043Sbill 		}
1221043Sbill 	}
1231043Sbill 	sprintf(user, "USER=%.*s", NMAX, pwd->pw_name);
1241043Sbill 	if (pwd->pw_uid == 0 && ttyn[5] != 'c')
1251043Sbill 		goto bad;
1261043Sbill 	if (ttyn[LMAX] == 'd') {
1271043Sbill 		FILE *console = fopen("/dev/console", "w");
1281043Sbill 		if (console != NULL) {
1291043Sbill 			fprintf(console, "\r\nDIALUP %s %s\r\n", ttyn+5, pwd->pw_name);
1301043Sbill 			fclose(console);
1311043Sbill 		}
1321043Sbill 	}
1331043Sbill 	if((f = open(lastlog, 2)) >= 0) {
1341043Sbill 		struct lastlog ll;
1351043Sbill 
1361043Sbill 		lseek(f, pwd->pw_uid * sizeof (struct lastlog), 0);
1371043Sbill 		if (read(f, (char *) &ll, sizeof ll) == sizeof ll && ll.ll_time != 0) {
1381043Sbill 			register char *ep = (char *) ctime(&ll.ll_time);
1391043Sbill 			printf("Last login: ");
1401043Sbill 			ep[24 - 5] = 0;
1411043Sbill 			printf("%s on %.*s\n", ep, LMAX, ll.ll_line);
1421043Sbill 		}
1431043Sbill 		lseek(f, pwd->pw_uid * sizeof (struct lastlog), 0);
1441043Sbill 		time(&ll.ll_time);
1451043Sbill 		strcpyn(ll.ll_line, ttyn+5, LMAX);
1461043Sbill 		write(f, (char *) &ll, sizeof ll);
1471043Sbill 		close(f);
1481043Sbill 	}
1491043Sbill 	if(chdir(pwd->pw_dir) < 0) {
1501043Sbill 		printf("No directory\n");
1511043Sbill 		goto loop;
1521043Sbill 	}
1531043Sbill 	time(&utmp.ut_time);
1541043Sbill 	t = ttyslot();
1551043Sbill 	if (t>0 && (f = open("/etc/utmp", 1)) >= 0) {
1561043Sbill 		lseek(f, (long)(t*sizeof(utmp)), 0);
1571043Sbill 		SCPYN(utmp.ut_line, rindex(ttyn, '/')+1);
1581043Sbill 		write(f, (char *)&utmp, sizeof(utmp));
1591043Sbill 		close(f);
1601043Sbill 	}
1611043Sbill 	if (t>0 && (f = open("/usr/adm/wtmp", 1)) >= 0) {
1621043Sbill 		lseek(f, 0L, 2);
1631043Sbill 		write(f, (char *)&utmp, sizeof(utmp));
1641043Sbill 		close(f);
1651043Sbill 	}
1661043Sbill 	chown(ttyn, pwd->pw_uid, pwd->pw_gid);
1671043Sbill 	setgid(pwd->pw_gid);
1681043Sbill 	setuid(pwd->pw_uid);
1691043Sbill 	if (*pwd->pw_shell == '\0')
1701043Sbill 		pwd->pw_shell = "/bin/sh";
1711043Sbill 	environ = envinit;
1721043Sbill 	strncat(homedir, pwd->pw_dir, sizeof(homedir)-6);
1731043Sbill 	strncat(shell, pwd->pw_shell, sizeof(shell)-7);
1741043Sbill 	strncat(term, stypeof(ttyn), sizeof(term)-6);
1751043Sbill 	if ((namep = rindex(pwd->pw_shell, '/')) == NULL)
1761043Sbill 		namep = pwd->pw_shell;
1771043Sbill 	else
1781043Sbill 		namep++;
1791043Sbill 	strcat(minusnam, namep);
1801043Sbill 	alarm(0);
1811043Sbill 	umask(022);
1821043Sbill 	showmotd();
1831043Sbill 	strcat(maildir, pwd->pw_name);
1841043Sbill 	if(access(maildir,4)==0) {
1851043Sbill 		struct stat statb;
1861043Sbill 		stat(maildir, &statb);
1871043Sbill 		if (statb.st_size)
1881043Sbill 			printf("You have mail.\n");
1891043Sbill 	}
1901043Sbill 	signal(SIGQUIT, SIG_DFL);
1911043Sbill 	signal(SIGINT, SIG_DFL);
1921043Sbill 	execlp(pwd->pw_shell, minusnam, 0);
1931043Sbill 	printf("No shell\n");
1941043Sbill 	exit(0);
1951043Sbill }
1961043Sbill 
1971043Sbill int	stopmotd;
1981043Sbill catch()
1991043Sbill {
2001043Sbill 	signal(SIGINT, SIG_IGN);
2011043Sbill 	stopmotd++;
2021043Sbill }
2031043Sbill 
2041043Sbill showmotd()
2051043Sbill {
2061043Sbill 	FILE *mf;
2071043Sbill 	register c;
2081043Sbill 
2091043Sbill 	signal(SIGINT, catch);
2101043Sbill 	if((mf = fopen("/etc/motd","r")) != NULL) {
2111043Sbill 		while((c = getc(mf)) != EOF && stopmotd == 0)
2121043Sbill 			putchar(c);
2131043Sbill 		fclose(mf);
2141043Sbill 	}
2151043Sbill 	signal(SIGINT, SIG_IGN);
2161043Sbill }
2171043Sbill 
2181043Sbill #define UNKNOWN "su"
2191043Sbill 
2201043Sbill char *
2211043Sbill stypeof(ttyid)
2221043Sbill char	*ttyid;
2231043Sbill {
2241043Sbill 	static char	typebuf[16];
2251043Sbill 	char		buf[50];
2261043Sbill 	register FILE	*f;
2271043Sbill 	register char	*p, *t, *q;
2281043Sbill 
2291043Sbill 	if (ttyid == NULL)
2301043Sbill 		return (UNKNOWN);
2311043Sbill 	f = fopen("/etc/ttytype", "r");
2321043Sbill 	if (f == NULL)
2331043Sbill 		return (UNKNOWN);
2341043Sbill 	/* split off end of name */
2351043Sbill 	for (p = q = ttyid; *p != 0; p++)
2361043Sbill 		if (*p == '/')
2371043Sbill 			q = p + 1;
2381043Sbill 
2391043Sbill 	/* scan the file */
2401043Sbill 	while (fgets(buf, sizeof buf, f) != NULL)
2411043Sbill 	{
2421043Sbill 		for (t=buf; *t!=' '; t++)
2431043Sbill 			;
2441043Sbill 		*t++ = 0;
2451043Sbill 		for (p=t; *p>' '; p++)
2461043Sbill 			;
2471043Sbill 		*p = 0;
2481043Sbill 		if (strcmp(q,t)==0) {
2491043Sbill 			strcpy(typebuf, buf);
2501043Sbill 			fclose(f);
2511043Sbill 			return (typebuf);
2521043Sbill 		}
2531043Sbill 	}
2541043Sbill 	fclose (f);
2551043Sbill 	return (UNKNOWN);
2561043Sbill }
257