added PDX constant
[unix-history] / usr / src / usr.bin / login / login.c
CommitLineData
5f87416f 1static char *sccsid = "@(#)login.c 4.11 (Berkeley) 81/07/05";
88a01c09
BJ
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>
ed2fd28a 14#include <whoami.h>
f570e1ff
BJ
15#ifdef UNAME
16#include <sys/utsname.h>
17#endif
18
19#define SCPYN(a, b) strncpy(a, b, sizeof(a))
88a01c09
BJ
20
21#define NMAX sizeof(utmp.ut_name)
22#define LMAX sizeof(utmp.ut_line)
23
f570e1ff
BJ
24#define FALSE 0
25#define TRUE -1
26
27char nolog[] = "/etc/nologin";
28char qlog[] = ".hushlogin";
29char securetty[] = "/etc/securetty";
88a01c09
BJ
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=";
f570e1ff
BJ
39char user[20] = "USER=";
40char *envinit[] = {homedir, shell, "PATH=:/usr/ucb:/bin:/usr/bin", term, user, 0};
88a01c09
BJ
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
841d84b0
BJ
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};
f570e1ff 65#ifdef TIOCLSET
841d84b0 66struct ltchars ltc = {
1113d588 67 CTRL(z), CTRL(y), CTRL(r), CTRL(o), CTRL(w), CTRL(v)
841d84b0 68};
f570e1ff 69#endif
841d84b0 70
88a01c09
BJ
71main(argc, argv)
72char **argv;
73{
74 register char *namep;
75 int t, f, c;
f570e1ff
BJ
76 int invalid;
77 int quietlog;
78 int i;
79 FILE *nlfd;
88a01c09 80 char *ttyn;
f570e1ff
BJ
81 int ldisc = 0;
82#ifdef UNAME
83 struct utsname uts;
84#endif
88a01c09
BJ
85
86 alarm(60);
87 signal(SIGQUIT, SIG_IGN);
88 signal(SIGINT, SIG_IGN);
89 nice(-100);
90 nice(20);
91 nice(0);
f570e1ff 92#ifdef TIOCLSET
88a01c09 93 ioctl(0, TIOCLSET, 0);
f570e1ff 94#endif
c95ed2b2 95 ioctl(0, TIOCNXCL, 0);
88a01c09 96 gtty(0, &ttyb);
f570e1ff
BJ
97 ttyb.sg_erase = CERASE;
98 ttyb.sg_kill = CKILL;
88a01c09 99 stty(0, &ttyb);
841d84b0 100 ioctl(0, TIOCSETC, &tc);
f570e1ff 101#ifdef TIOCLSET
841d84b0 102 ioctl(0, TIOCSLTC, &ltc);
f570e1ff 103#endif
88a01c09
BJ
104 for (t=3; t<20; t++)
105 close(t);
106 ttyn = ttyname(0);
f570e1ff 107 if (ttyn==(char *)0)
88a01c09
BJ
108 ttyn = "/dev/tty??";
109
f570e1ff
BJ
110 do {
111 ldisc = 0;
c95ed2b2 112 ioctl(0, TIOCSETD, &ldisc);
f570e1ff
BJ
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) {
88a01c09 171 printf("Login incorrect\n");
f570e1ff 172 if (ttyn[sizeof("/dev/tty")-1] == 'd') {
88a01c09
BJ
173 FILE *console = fopen("/dev/console", "w");
174 if (console != NULL) {
f570e1ff
BJ
175 fprintf(console, "\r\nBADDIALUP %s %s\r\n"
176 , ttyn+sizeof("/dev/")-1
177 , utmp.ut_name);
88a01c09
BJ
178 fclose(console);
179 }
180 }
88a01c09 181 }
f570e1ff
BJ
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 }
88a01c09 193 }
f570e1ff 194 } while (invalid);
88a01c09 195
88a01c09
BJ
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 }
f570e1ff
BJ
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 }
88a01c09
BJ
231 chown(ttyn, pwd->pw_uid, pwd->pw_gid);
232 setgid(pwd->pw_gid);
233 setuid(pwd->pw_uid);
88a01c09
BJ
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);
f570e1ff 238 strncat(user, pwd->pw_name, sizeof(user)-6);
88a01c09
BJ
239 if ((namep = rindex(pwd->pw_shell, '/')) == NULL)
240 namep = pwd->pw_shell;
241 else
242 namep++;
243 strcat(minusnam, namep);
244 alarm(0);
6f01c426 245#ifdef ARPAVAX
f570e1ff 246 if (pwd->pw_gid == 27) /* UGLY ! */
6f01c426
BJ
247 umask(2);
248 else
6f01c426 249#endif
f570e1ff
BJ
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 }
88a01c09 260 }
f570e1ff
BJ
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
88a01c09
BJ
272 signal(SIGQUIT, SIG_DFL);
273 signal(SIGINT, SIG_DFL);
5f87416f 274 signal(SIGTSTP, SIG_IGN);
88a01c09 275 execlp(pwd->pw_shell, minusnam, 0);
f570e1ff 276 perror(pwd->pw_shell);
88a01c09
BJ
277 printf("No shell\n");
278 exit(0);
279}
280
281int stopmotd;
282catch()
283{
284 signal(SIGINT, SIG_IGN);
285 stopmotd++;
286}
287
f570e1ff
BJ
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
88a01c09
BJ
310showmotd()
311{
312 FILE *mf;
313 register c;
314
315 signal(SIGINT, catch);
f570e1ff
BJ
316 if ((mf = fopen("/etc/motd","r")) != NULL) {
317 while ((c = getc(mf)) != EOF && stopmotd == 0)
88a01c09
BJ
318 putchar(c);
319 fclose(mf);
320 }
321 signal(SIGINT, SIG_IGN);
322}
323
f570e1ff 324#undef UNKNOWN
88a01c09
BJ
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 {
f570e1ff 349 for (t=buf; *t!=' ' && *t != '\t'; t++)
88a01c09
BJ
350 ;
351 *t++ = 0;
f570e1ff
BJ
352 while (*t == ' ' || *t == '\t')
353 t++;
88a01c09
BJ
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}