xref: /original-bsd/usr.bin/login/login.c (revision ba72ef4c)
1 static	char *sccsid = "@(#)login.c	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 
19 char	user[20];
20 char	maildir[30] =	"/usr/spool/mail/";
21 char	lastlog[] =	"/usr/adm/lastlog";
22 struct	passwd nouser = {"", "nope"};
23 struct	sgttyb ttyb;
24 struct	utmp utmp;
25 char	minusnam[16] = "-";
26 char	homedir[64] = "HOME=";
27 char	shell[64] = "SHELL=";
28 char	term[64] = "TERM=";
29 char	*envinit[] = {homedir, shell, "PATH=:/usr/ucb:/bin:/usr/bin", term, user,0};
30 struct	passwd *pwd;
31 
32 struct	passwd *getpwnam();
33 char	*strcat();
34 int	setpwent();
35 char	*ttyname();
36 char	*crypt();
37 char	*getpass();
38 char	*rindex();
39 char	*stypeof();
40 extern	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
51 struct	tchars tc = {
52 	CINTR, CQUIT, CSTART, CSTOP, CEOT, CBRK
53 };
54 struct	ltchars ltc = {
55 	CTRL(z), CTRL(y), CTRL(r), CTRL(o), CTRL(w), CTRL(v), CTRL(h), CTRL(u),
56 	CTRL(c)
57 };
58 
59 main(argc, argv)
60 char **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)) {
112 bad:
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 
198 int	stopmotd;
199 catch()
200 {
201 	signal(SIGINT, SIG_IGN);
202 	stopmotd++;
203 }
204 
205 showmotd()
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 
221 char *
222 stypeof(ttyid)
223 char	*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