bug fix in umount
[unix-history] / usr / src / usr.bin / login / login.c
CommitLineData
6f01c426 1static char *sccsid = "@(#)login.c 4.9 (Berkeley) %G%";
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>
88a01c09
BJ
15#define SCPYN(a, b) strncpy(a, b, sizeof(a))
16
17#define NMAX sizeof(utmp.ut_name)
18#define LMAX sizeof(utmp.ut_line)
19
20char user[20];
21char maildir[30] = "/usr/spool/mail/";
22char lastlog[] = "/usr/adm/lastlog";
23struct passwd nouser = {"", "nope"};
24struct sgttyb ttyb;
25struct utmp utmp;
26char minusnam[16] = "-";
27char homedir[64] = "HOME=";
28char shell[64] = "SHELL=";
29char term[64] = "TERM=";
30char *envinit[] = {homedir, shell, "PATH=:/usr/ucb:/bin:/usr/bin", term, user,0};
31struct passwd *pwd;
32
33struct passwd *getpwnam();
34char *strcat();
35int setpwent();
36char *ttyname();
37char *crypt();
38char *getpass();
39char *rindex();
40char *stypeof();
41extern char **environ;
42
841d84b0
BJ
43#define CTRL(c) ('c'&037)
44#define CERASE '#'
45#define CEOT CTRL(d)
46#define CKILL '@'
47#define CQUIT 034 /* FS, cntl shift L */
48#define CINTR 0177 /* DEL */
49#define CSTOP CTRL(s)
50#define CSTART CTRL(q)
51#define CBRK 0377
52struct tchars tc = {
53 CINTR, CQUIT, CSTART, CSTOP, CEOT, CBRK
54};
55struct ltchars ltc = {
1113d588 56 CTRL(z), CTRL(y), CTRL(r), CTRL(o), CTRL(w), CTRL(v)
841d84b0
BJ
57};
58
88a01c09
BJ
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, TIOCLSET, 0);
c95ed2b2 74 ioctl(0, TIOCNXCL, 0);
88a01c09
BJ
75 gtty(0, &ttyb);
76 ttyb.sg_erase = '#';
77 ttyb.sg_kill = '@';
78 stty(0, &ttyb);
841d84b0
BJ
79 ioctl(0, TIOCSETC, &tc);
80 ioctl(0, TIOCSLTC, &ltc);
88a01c09
BJ
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:
c95ed2b2
BJ
88 ldisc = 0;
89 ioctl(0, TIOCSETD, &ldisc);
88a01c09
BJ
90 SCPYN(utmp.ut_name, "");
91 if (argc>1) {
92 SCPYN(utmp.ut_name, argv[1]);
93 argc = 0;
94 }
95 while (utmp.ut_name[0] == '\0') {
96 namep = utmp.ut_name;
97 printf("login: ");
98 while ((c = getchar()) != '\n') {
99 if(c == ' ')
100 c = '_';
101 if (c == EOF)
102 exit(0);
103 if (namep < utmp.ut_name+NMAX)
104 *namep++ = c;
105 }
106 }
107 setpwent();
108 if ((pwd = getpwnam(utmp.ut_name)) == NULL)
109 pwd = &nouser;
110 endpwent();
c95ed2b2
BJ
111 if (!strcmp(pwd->pw_shell, "/bin/csh")) {
112 ldisc = NTTYDISC;
113 ioctl(0, TIOCSETD, &ldisc);
114 }
88a01c09 115 if (*pwd->pw_passwd != '\0') {
c95ed2b2 116 nice(-4);
88a01c09 117 namep = crypt(getpass("Password:"),pwd->pw_passwd);
c95ed2b2 118 nice(4);
88a01c09
BJ
119 if (strcmp(namep, pwd->pw_passwd)) {
120bad:
121 printf("Login incorrect\n");
122 if (ttyn[LMAX] == 'd') {
123 FILE *console = fopen("/dev/console", "w");
124 if (console != NULL) {
125 fprintf(console, "\r\nBADDIALUP %s %s\r\n", ttyn+5, utmp.ut_name);
126 fclose(console);
127 }
128 }
129 goto loop;
130 }
131 }
132 sprintf(user, "USER=%.*s", NMAX, pwd->pw_name);
ed2fd28a 133#ifdef ERNIE
88a01c09
BJ
134 if (pwd->pw_uid == 0 && ttyn[5] != 'c')
135 goto bad;
ed2fd28a 136#endif
88a01c09
BJ
137 if (ttyn[LMAX] == 'd') {
138 FILE *console = fopen("/dev/console", "w");
139 if (console != NULL) {
140 fprintf(console, "\r\nDIALUP %s %s\r\n", ttyn+5, pwd->pw_name);
141 fclose(console);
142 }
143 }
144 if((f = open(lastlog, 2)) >= 0) {
145 struct lastlog ll;
146
bb4438c6 147 lseek(f, (long) pwd->pw_uid * sizeof (struct lastlog), 0);
88a01c09
BJ
148 if (read(f, (char *) &ll, sizeof ll) == sizeof ll && ll.ll_time != 0) {
149 register char *ep = (char *) ctime(&ll.ll_time);
150 printf("Last login: ");
151 ep[24 - 5] = 0;
152 printf("%s on %.*s\n", ep, LMAX, ll.ll_line);
153 }
bb4438c6 154 lseek(f, (long) pwd->pw_uid * sizeof (struct lastlog), 0);
88a01c09
BJ
155 time(&ll.ll_time);
156 strcpyn(ll.ll_line, ttyn+5, LMAX);
157 write(f, (char *) &ll, sizeof ll);
158 close(f);
159 }
160 if(chdir(pwd->pw_dir) < 0) {
2263b1b2
BJ
161 printf("Logging with home=/\n");
162 pwd->pw_dir = "/";
163 if(chdir("/") < 0) {
88a01c09
BJ
164 printf("No directory\n");
165 goto loop;
006867f2 166 }
88a01c09
BJ
167 }
168 time(&utmp.ut_time);
169 t = ttyslot();
170 if (t>0 && (f = open("/etc/utmp", 1)) >= 0) {
171 lseek(f, (long)(t*sizeof(utmp)), 0);
172 SCPYN(utmp.ut_line, rindex(ttyn, '/')+1);
173 write(f, (char *)&utmp, sizeof(utmp));
174 close(f);
175 }
176 if (t>0 && (f = open("/usr/adm/wtmp", 1)) >= 0) {
177 lseek(f, 0L, 2);
178 write(f, (char *)&utmp, sizeof(utmp));
179 close(f);
180 }
181 chown(ttyn, pwd->pw_uid, pwd->pw_gid);
182 setgid(pwd->pw_gid);
183 setuid(pwd->pw_uid);
184 if (*pwd->pw_shell == '\0')
185 pwd->pw_shell = "/bin/sh";
186 environ = envinit;
187 strncat(homedir, pwd->pw_dir, sizeof(homedir)-6);
188 strncat(shell, pwd->pw_shell, sizeof(shell)-7);
189 strncat(term, stypeof(ttyn), sizeof(term)-6);
190 if ((namep = rindex(pwd->pw_shell, '/')) == NULL)
191 namep = pwd->pw_shell;
192 else
193 namep++;
194 strcat(minusnam, namep);
195 alarm(0);
6f01c426
BJ
196#ifdef ARPAVAX
197 if (pwd->pw_gid == 31)
198 umask(2);
199 else
200#else
201 umask(022);
202#endif
88a01c09
BJ
203 showmotd();
204 strcat(maildir, pwd->pw_name);
205 if(access(maildir,4)==0) {
206 struct stat statb;
207 stat(maildir, &statb);
208 if (statb.st_size)
209 printf("You have mail.\n");
210 }
211 signal(SIGQUIT, SIG_DFL);
212 signal(SIGINT, SIG_DFL);
213 execlp(pwd->pw_shell, minusnam, 0);
214 printf("No shell\n");
215 exit(0);
216}
217
218int stopmotd;
219catch()
220{
221 signal(SIGINT, SIG_IGN);
222 stopmotd++;
223}
224
225showmotd()
226{
227 FILE *mf;
228 register c;
229
230 signal(SIGINT, catch);
231 if((mf = fopen("/etc/motd","r")) != NULL) {
232 while((c = getc(mf)) != EOF && stopmotd == 0)
233 putchar(c);
234 fclose(mf);
235 }
236 signal(SIGINT, SIG_IGN);
237}
238
239#define UNKNOWN "su"
240
241char *
242stypeof(ttyid)
243char *ttyid;
244{
245 static char typebuf[16];
246 char buf[50];
247 register FILE *f;
248 register char *p, *t, *q;
249
250 if (ttyid == NULL)
251 return (UNKNOWN);
252 f = fopen("/etc/ttytype", "r");
253 if (f == NULL)
254 return (UNKNOWN);
255 /* split off end of name */
256 for (p = q = ttyid; *p != 0; p++)
257 if (*p == '/')
258 q = p + 1;
259
260 /* scan the file */
261 while (fgets(buf, sizeof buf, f) != NULL)
262 {
263 for (t=buf; *t!=' '; t++)
264 ;
265 *t++ = 0;
266 for (p=t; *p>' '; p++)
267 ;
268 *p = 0;
269 if (strcmp(q,t)==0) {
270 strcpy(typebuf, buf);
271 fclose(f);
272 return (typebuf);
273 }
274 }
275 fclose (f);
276 return (UNKNOWN);
277}