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