xref: /original-bsd/usr.bin/login/login.c.1 (revision 1f3a482a)
1static	char *sccsid = "@(#)login.c.1	4.11 (Berkeley) 81/07/05";
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#include <whoami.h>
15#ifdef	UNAME
16#include <sys/utsname.h>
17#endif
18
19#define	SCPYN(a, b)	strncpy(a, b, sizeof(a))
20
21#define NMAX sizeof(utmp.ut_name)
22#define LMAX sizeof(utmp.ut_line)
23
24#define	FALSE	0
25#define	TRUE	-1
26
27char	nolog[] =	"/etc/nologin";
28char	qlog[]  =	".hushlogin";
29char	securetty[] =	"/etc/securetty";
30char	maildir[30] =	"/usr/spool/mail/";
31char	lastlog[] =	"/usr/adm/lastlog";
32struct	passwd nouser = {"", "nope"};
33struct	sgttyb ttyb;
34struct	utmp utmp;
35char	minusnam[16] = "-";
36char	homedir[64] = "HOME=";
37char	shell[64] = "SHELL=";
38char	term[64] = "TERM=";
39char	user[20] = "USER=";
40char	*envinit[] = {homedir, shell, "PATH=:/usr/ucb:/bin:/usr/bin", term, user, 0};
41struct	passwd *pwd;
42
43struct	passwd *getpwnam();
44char	*strcat();
45int	setpwent();
46char	*ttyname();
47char	*crypt();
48char	*getpass();
49char	*rindex();
50char	*stypeof();
51extern	char **environ;
52
53#define	CTRL(c)	('c'&037)
54#define	CERASE	'#'
55#define	CEOT	CTRL(d)
56#define	CKILL	'@'
57#define	CQUIT	034		/* FS, cntl shift L */
58#define	CINTR	0177		/* DEL */
59#define	CSTOP	CTRL(s)
60#define	CSTART	CTRL(q)
61#define	CBRK	0377
62struct	tchars tc = {
63	CINTR, CQUIT, CSTART, CSTOP, CEOT, CBRK
64};
65#ifdef	TIOCLSET
66struct	ltchars ltc = {
67	CTRL(z), CTRL(y), CTRL(r), CTRL(o), CTRL(w), CTRL(v)
68};
69#endif
70
71main(argc, argv)
72char **argv;
73{
74	register char *namep;
75	int t, f, c;
76	int invalid;
77	int quietlog;
78	int i;
79	FILE *nlfd;
80	char *ttyn;
81	int	ldisc = 0;
82#ifdef	UNAME
83	struct utsname uts;
84#endif
85
86	alarm(60);
87	signal(SIGQUIT, SIG_IGN);
88	signal(SIGINT, SIG_IGN);
89	nice(-100);
90	nice(20);
91	nice(0);
92#ifdef	TIOCLSET
93	ioctl(0, TIOCLSET, 0);
94#endif
95	ioctl(0, TIOCNXCL, 0);
96	gtty(0, &ttyb);
97	ttyb.sg_erase = CERASE;
98	ttyb.sg_kill = CKILL;
99	stty(0, &ttyb);
100	ioctl(0, TIOCSETC, &tc);
101#ifdef	TIOCLSET
102	ioctl(0, TIOCSLTC, &ltc);
103#endif
104	for (t=3; t<20; t++)
105		close(t);
106	ttyn = ttyname(0);
107	if (ttyn==(char *)0)
108		ttyn = "/dev/tty??";
109
110	do {
111		ldisc = 0;
112		ioctl(0, TIOCSETD, &ldisc);
113		invalid = FALSE;
114		SCPYN(utmp.ut_name, "");
115		if (argc>1) {
116			SCPYN(utmp.ut_name, argv[1]);
117			argc = 0;
118		}
119		while (utmp.ut_name[0] == '\0') {
120			namep = utmp.ut_name;
121#ifdef	UNAME
122			if (uname(&uts) != -1)
123				printf("%s login: ", uts.nodename);
124			else
125#endif
126				printf("login: ");
127			while ((c = getchar()) != '\n') {
128				if (c == ' ')
129					c = '_';
130				if (c == EOF)
131					exit(0);
132				if (namep < utmp.ut_name+NMAX)
133					*namep++ = c;
134			}
135		}
136		setpwent();
137		if ((pwd = getpwnam(utmp.ut_name)) == NULL)
138			pwd = &nouser;
139		endpwent();
140		if (!strcmp(pwd->pw_shell, "/bin/csh")) {
141			ldisc = NTTYDISC;
142			ioctl(0, TIOCSETD, &ldisc);
143		}
144		if (*pwd->pw_passwd != '\0') {
145			nice(-4);
146			namep = crypt(getpass("Password:"),pwd->pw_passwd);
147			nice(4);
148			if (strcmp(namep, pwd->pw_passwd))
149				invalid = TRUE;
150		}
151		if (pwd->pw_uid != 0 && (nlfd = fopen(nolog, "r")) > 0) {
152			/* logins are disabled except for root */
153			while ((c = getc(nlfd)) != EOF)
154				putchar(c);
155			fflush(stdout);
156			sleep(5);
157			exit(0);
158		}
159		if (!invalid && pwd->pw_uid == 0 &&
160		    !rootterm(ttyn+sizeof("/dev/")-1)) {
161			FILE *console = fopen("/dev/console", "w");
162			if (console != NULL) {
163				fprintf(console, "\r\nROOT LOGIN REFUSED %s\r\n"
164				    , ttyn+sizeof("/dev/")-1
165				);
166				fclose(console);
167			}
168			invalid = TRUE;
169		}
170		if (invalid) {
171			printf("Login incorrect\n");
172			if (ttyn[sizeof("/dev/tty")-1] == 'd') {
173				FILE *console = fopen("/dev/console", "w");
174				if (console != NULL) {
175					fprintf(console, "\r\nBADDIALUP %s %s\r\n"
176					    , ttyn+sizeof("/dev/")-1
177					    , utmp.ut_name);
178					fclose(console);
179				}
180			}
181		}
182		if (*pwd->pw_shell == '\0')
183			pwd->pw_shell = "/bin/sh";
184		i = strlen(pwd->pw_shell);
185		if (chdir(pwd->pw_dir) < 0 && !invalid ) {
186			if (chdir("/") < 0) {
187				printf("No directory!\n");
188				invalid = TRUE;
189			} else {
190				printf("No directory!  Logging in with home=/\n");
191				pwd->pw_dir = "/";
192			}
193		}
194	} while (invalid);
195
196	time(&utmp.ut_time);
197	t = ttyslot();
198	if (t>0 && (f = open("/etc/utmp", 1)) >= 0) {
199		lseek(f, (long)(t*sizeof(utmp)), 0);
200		SCPYN(utmp.ut_line, rindex(ttyn, '/')+1);
201		write(f, (char *)&utmp, sizeof(utmp));
202		close(f);
203	}
204	if (t>0 && (f = open("/usr/adm/wtmp", 1)) >= 0) {
205		lseek(f, 0L, 2);
206		write(f, (char *)&utmp, sizeof(utmp));
207		close(f);
208	}
209	quietlog = FALSE;
210	if (access(qlog, 0) == 0)
211		quietlog = TRUE;
212	if ( !quietlog && (f = open(lastlog, 2)) >= 0 ) {
213		struct lastlog ll;
214
215		lseek(f, (long)pwd->pw_uid * sizeof (struct lastlog), 0);
216		if (read(f, (char *) &ll, sizeof ll) == sizeof ll &&
217		    ll.ll_time != 0) {
218			printf("Last login: %.*s on %.*s\n"
219			    , 24-5
220			    , (char *) ctime(&ll.ll_time)
221			    , sizeof(ll.ll_line)
222			    , ll.ll_line
223			);
224		}
225		lseek(f, (long)pwd->pw_uid * sizeof (struct lastlog), 0);
226		time(&ll.ll_time);
227		SCPYN(ll.ll_line, rindex(ttyn, '/')+1);
228		write(f, (char *) &ll, sizeof ll);
229		close(f);
230	}
231	chown(ttyn, pwd->pw_uid, pwd->pw_gid);
232	setgid(pwd->pw_gid);
233	setuid(pwd->pw_uid);
234	environ = envinit;
235	strncat(homedir, pwd->pw_dir, sizeof(homedir)-6);
236	strncat(shell, pwd->pw_shell, sizeof(shell)-7);
237	strncat(term, stypeof(ttyn), sizeof(term)-6);
238	strncat(user, pwd->pw_name, sizeof(user)-6);
239	if ((namep = rindex(pwd->pw_shell, '/')) == NULL)
240		namep = pwd->pw_shell;
241	else
242		namep++;
243	strcat(minusnam, namep);
244	alarm(0);
245#ifdef ARPAVAX
246	if (pwd->pw_gid == 27)			/* UGLY ! */
247		umask(2);
248	else
249#endif
250		umask(022);
251	if (ttyn[sizeof("/dev/tty")-1] == 'd') {
252		FILE *console = fopen("/dev/console", "w");
253		if (console != NULL) {
254			fprintf(console, "\r\nDIALUP %s %s\r\n"
255			    , ttyn+sizeof("/dev/")-1
256			    , pwd->pw_name
257			);
258			fclose(console);
259		}
260	}
261	if ( !quietlog ) {
262		showmotd();
263		strcat(maildir, pwd->pw_name);
264		if (access(maildir,4)==0) {
265			struct stat statb;
266			stat(maildir, &statb);
267			if (statb.st_size)
268				printf("You have mail.\n");
269		}
270	}
271
272	signal(SIGQUIT, SIG_DFL);
273	signal(SIGINT, SIG_DFL);
274	signal(SIGTSTP, SIG_IGN);
275	execlp(pwd->pw_shell, minusnam, 0);
276	perror(pwd->pw_shell);
277	printf("No shell\n");
278	exit(0);
279}
280
281int	stopmotd;
282catch()
283{
284	signal(SIGINT, SIG_IGN);
285	stopmotd++;
286}
287
288/*
289 * return true if OK for root to login on this terminal
290 */
291rootterm(tty)
292	char	*tty;
293{
294	register FILE *fd;
295	char	buf[100];
296
297	if ((fd = fopen(securetty, "r")) == NULL)
298		return(1);
299	while (fgets(buf, sizeof buf, fd) != NULL) {
300		buf[strlen(buf)-1] = '\0';
301		if (strcmp(tty, buf) == 0) {
302			fclose(fd);
303			return(1);
304		}
305	}
306	fclose(fd);
307	return(0);
308}
309
310showmotd()
311{
312	FILE *mf;
313	register c;
314
315	signal(SIGINT, catch);
316	if ((mf = fopen("/etc/motd","r")) != NULL) {
317		while ((c = getc(mf)) != EOF && stopmotd == 0)
318			putchar(c);
319		fclose(mf);
320	}
321	signal(SIGINT, SIG_IGN);
322}
323
324#undef	UNKNOWN
325#define UNKNOWN "su"
326
327char *
328stypeof(ttyid)
329char	*ttyid;
330{
331	static char	typebuf[16];
332	char		buf[50];
333	register FILE	*f;
334	register char	*p, *t, *q;
335
336	if (ttyid == NULL)
337		return (UNKNOWN);
338	f = fopen("/etc/ttytype", "r");
339	if (f == NULL)
340		return (UNKNOWN);
341	/* split off end of name */
342	for (p = q = ttyid; *p != 0; p++)
343		if (*p == '/')
344			q = p + 1;
345
346	/* scan the file */
347	while (fgets(buf, sizeof buf, f) != NULL)
348	{
349		for (t=buf; *t!=' ' && *t != '\t'; t++)
350			;
351		*t++ = 0;
352		while (*t == ' ' || *t == '\t')
353			t++;
354		for (p=t; *p>' '; p++)
355			;
356		*p = 0;
357		if (strcmp(q,t)==0) {
358			strcpy(typebuf, buf);
359			fclose(f);
360			return (typebuf);
361		}
362	}
363	fclose (f);
364	return (UNKNOWN);
365}
366