xref: /original-bsd/usr.bin/login/login.c.1 (revision 552e81d8)
1static char *sccsid = "@(#)login.c.1	4.1 (Berkeley) 10/01/80";
2/*
3 * login [ name ]
4 */
5
6#include <sys/types.h>
7#include <sgtty.h>
8#include <utmp.h>
9#include <signal.h>
10#include <pwd.h>
11#include <stdio.h>
12#include <sys/stat.h>
13#include <lastlog.h>
14#define SCPYN(a, b)	strncpy(a, b, sizeof(a))
15
16#define NMAX sizeof(utmp.ut_name)
17#define LMAX sizeof(utmp.ut_line)
18
19char	user[20];
20char	maildir[30] =	"/usr/spool/mail/";
21char	lastlog[] =	"/usr/adm/lastlog";
22struct	passwd nouser = {"", "nope"};
23struct	sgttyb ttyb;
24struct	utmp utmp;
25char	minusnam[16] = "-";
26char	homedir[64] = "HOME=";
27char	shell[64] = "SHELL=";
28char	term[64] = "TERM=";
29char	*envinit[] = {homedir, shell, "PATH=:/usr/ucb:/bin:/usr/bin", term, user,0};
30struct	passwd *pwd;
31
32struct	passwd *getpwnam();
33char	*strcat();
34int	setpwent();
35char	*ttyname();
36char	*crypt();
37char	*getpass();
38char	*rindex();
39char	*stypeof();
40extern	char **environ;
41
42main(argc, argv)
43char **argv;
44{
45	register char *namep;
46	int t, f, c;
47	char *ttyn;
48	int ldisc = 0;
49
50	alarm(60);
51	signal(SIGQUIT, SIG_IGN);
52	signal(SIGINT, SIG_IGN);
53	nice(-100);
54	nice(20);
55	nice(0);
56	ioctl(0, TIOCLSET, 0);
57	ioctl(0, TIOCNXCL, 0);
58	gtty(0, &ttyb);
59	ttyb.sg_erase = '#';
60	ttyb.sg_kill = '@';
61	stty(0, &ttyb);
62	for (t=3; t<20; t++)
63		close(t);
64	ttyn = ttyname(0);
65	if (ttyn==0)
66		ttyn = "/dev/tty??";
67
68    loop:
69	ldisc = 0;
70	ioctl(0, TIOCSETD, &ldisc);
71	SCPYN(utmp.ut_name, "");
72	if (argc>1) {
73		SCPYN(utmp.ut_name, argv[1]);
74		argc = 0;
75	}
76	while (utmp.ut_name[0] == '\0') {
77		namep = utmp.ut_name;
78		printf("login: ");
79		while ((c = getchar()) != '\n') {
80			if(c == ' ')
81				c = '_';
82			if (c == EOF)
83				exit(0);
84			if (namep < utmp.ut_name+NMAX)
85				*namep++ = c;
86		}
87	}
88	setpwent();
89	if ((pwd = getpwnam(utmp.ut_name)) == NULL)
90		pwd = &nouser;
91	endpwent();
92	if (!strcmp(pwd->pw_shell, "/bin/csh")) {
93		ldisc = NTTYDISC;
94		ioctl(0, TIOCSETD, &ldisc);
95	}
96	if (*pwd->pw_passwd != '\0') {
97		nice(-4);
98		namep = crypt(getpass("Password:"),pwd->pw_passwd);
99		nice(4);
100		if (strcmp(namep, pwd->pw_passwd)) {
101bad:
102			printf("Login incorrect\n");
103			if (ttyn[LMAX] == 'd') {
104				FILE *console = fopen("/dev/console", "w");
105				if (console != NULL) {
106					fprintf(console, "\r\nBADDIALUP %s %s\r\n", ttyn+5, utmp.ut_name);
107					fclose(console);
108				}
109			}
110			goto loop;
111		}
112	}
113	sprintf(user, "USER=%.*s", NMAX, pwd->pw_name);
114	if (pwd->pw_uid == 0 && ttyn[5] != 'c')
115		goto bad;
116	if (ttyn[LMAX] == 'd') {
117		FILE *console = fopen("/dev/console", "w");
118		if (console != NULL) {
119			fprintf(console, "\r\nDIALUP %s %s\r\n", ttyn+5, pwd->pw_name);
120			fclose(console);
121		}
122	}
123	if((f = open(lastlog, 2)) >= 0) {
124		struct lastlog ll;
125
126		lseek(f, pwd->pw_uid * sizeof (struct lastlog), 0);
127		if (read(f, (char *) &ll, sizeof ll) == sizeof ll && ll.ll_time != 0) {
128			register char *ep = (char *) ctime(&ll.ll_time);
129			printf("Last login: ");
130			ep[24 - 5] = 0;
131			printf("%s on %.*s\n", ep, LMAX, ll.ll_line);
132		}
133		lseek(f, pwd->pw_uid * sizeof (struct lastlog), 0);
134		time(&ll.ll_time);
135		strcpyn(ll.ll_line, ttyn+5, LMAX);
136		write(f, (char *) &ll, sizeof ll);
137		close(f);
138	}
139	if(chdir(pwd->pw_dir) < 0) {
140		printf("No directory\n");
141		goto loop;
142	}
143	time(&utmp.ut_time);
144	t = ttyslot();
145	if (t>0 && (f = open("/etc/utmp", 1)) >= 0) {
146		lseek(f, (long)(t*sizeof(utmp)), 0);
147		SCPYN(utmp.ut_line, rindex(ttyn, '/')+1);
148		write(f, (char *)&utmp, sizeof(utmp));
149		close(f);
150	}
151	if (t>0 && (f = open("/usr/adm/wtmp", 1)) >= 0) {
152		lseek(f, 0L, 2);
153		write(f, (char *)&utmp, sizeof(utmp));
154		close(f);
155	}
156	chown(ttyn, pwd->pw_uid, pwd->pw_gid);
157	setgid(pwd->pw_gid);
158	setuid(pwd->pw_uid);
159	if (*pwd->pw_shell == '\0')
160		pwd->pw_shell = "/bin/sh";
161	environ = envinit;
162	strncat(homedir, pwd->pw_dir, sizeof(homedir)-6);
163	strncat(shell, pwd->pw_shell, sizeof(shell)-7);
164	strncat(term, stypeof(ttyn), sizeof(term)-6);
165	if ((namep = rindex(pwd->pw_shell, '/')) == NULL)
166		namep = pwd->pw_shell;
167	else
168		namep++;
169	strcat(minusnam, namep);
170	alarm(0);
171	umask(022);
172	showmotd();
173	strcat(maildir, pwd->pw_name);
174	if(access(maildir,4)==0) {
175		struct stat statb;
176		stat(maildir, &statb);
177		if (statb.st_size)
178			printf("You have mail.\n");
179	}
180	signal(SIGQUIT, SIG_DFL);
181	signal(SIGINT, SIG_DFL);
182	execlp(pwd->pw_shell, minusnam, 0);
183	printf("No shell\n");
184	exit(0);
185}
186
187int	stopmotd;
188catch()
189{
190	signal(SIGINT, SIG_IGN);
191	stopmotd++;
192}
193
194showmotd()
195{
196	FILE *mf;
197	register c;
198
199	signal(SIGINT, catch);
200	if((mf = fopen("/etc/motd","r")) != NULL) {
201		while((c = getc(mf)) != EOF && stopmotd == 0)
202			putchar(c);
203		fclose(mf);
204	}
205	signal(SIGINT, SIG_IGN);
206}
207
208#define UNKNOWN "su"
209
210char *
211stypeof(ttyid)
212char	*ttyid;
213{
214	static char	typebuf[16];
215	char		buf[50];
216	register FILE	*f;
217	register char	*p, *t, *q;
218
219	if (ttyid == NULL)
220		return (UNKNOWN);
221	f = fopen("/etc/ttytype", "r");
222	if (f == NULL)
223		return (UNKNOWN);
224	/* split off end of name */
225	for (p = q = ttyid; *p != 0; p++)
226		if (*p == '/')
227			q = p + 1;
228
229	/* scan the file */
230	while (fgets(buf, sizeof buf, f) != NULL)
231	{
232		for (t=buf; *t!=' '; t++)
233			;
234		*t++ = 0;
235		for (p=t; *p>' '; p++)
236			;
237		*p = 0;
238		if (strcmp(q,t)==0) {
239			strcpy(typebuf, buf);
240			fclose(f);
241			return (typebuf);
242		}
243	}
244	fclose (f);
245	return (UNKNOWN);
246}
247