add EGP
[unix-history] / usr / src / old / init / init.c
CommitLineData
37c640e2 1#ifndef lint
9479aa87 2static char *sccsid = "@(#)init.c 4.13 (Berkeley) %G%";
37c640e2
SL
3#endif
4
7c8ab0e6
BJ
5#include <signal.h>
6#include <sys/types.h>
7#include <utmp.h>
8#include <setjmp.h>
215943cc 9#include <sys/reboot.h>
f570e1ff 10#include <errno.h>
d0ca48ff 11#include <sys/file.h>
9479aa87 12#include <ttyent.h>
7c8ab0e6
BJ
13
14#define LINSIZ sizeof(wtmp.ut_line)
9479aa87 15#define TTYSIZ 16
7c8ab0e6
BJ
16#define TABSIZ 100
17#define ALL p = &itab[0]; p < &itab[TABSIZ]; p++
18#define EVER ;;
19#define SCPYN(a, b) strncpy(a, b, sizeof(a))
20#define SCMPN(a, b) strncmp(a, b, sizeof(a))
d0ca48ff 21#define mask(s) (1 << ((s)-1))
7c8ab0e6
BJ
22
23char shell[] = "/bin/sh";
215943cc 24char getty[] = "/etc/getty";
7c8ab0e6
BJ
25char minus[] = "-";
26char runc[] = "/etc/rc";
7c8ab0e6
BJ
27char utmp[] = "/etc/utmp";
28char wtmpf[] = "/usr/adm/wtmp";
29char ctty[] = "/dev/console";
30char dev[] = "/dev/";
31
32struct utmp wtmp;
7c8ab0e6
BJ
33struct tab
34{
35 char line[LINSIZ];
9479aa87 36 char comn[TTYSIZ];
7c8ab0e6
BJ
37 char xflag;
38 int pid;
43236707
BJ
39 time_t gettytime;
40 int gettycnt;
7c8ab0e6
BJ
41} itab[TABSIZ];
42
43int fi;
44int mergflag;
45char tty[20];
abf0db3c 46jmp_buf sjbuf, shutpass;
f570e1ff 47time_t time0;
7c8ab0e6
BJ
48
49int reset();
f570e1ff 50int idle();
7c8ab0e6
BJ
51char *strcpy(), *strcat();
52long lseek();
53
d0ca48ff
SL
54struct sigvec rvec = { reset, mask(SIGHUP), 0 };
55
56#ifdef vax
7c8ab0e6
BJ
57main()
58{
215943cc 59 register int r11; /* passed thru from boot */
d0ca48ff 60#else
8d3a6b89
TL
61main(argc, argv)
62 char **argv;
63{
d0ca48ff 64#endif
215943cc
BJ
65 int howto, oldhowto;
66
f570e1ff 67 time0 = time(0);
d0ca48ff 68#ifdef vax
215943cc 69 howto = r11;
d0ca48ff 70#else
8d3a6b89
TL
71 if (argc > 1 && argv[1][0] == '-') {
72 char *cp;
73
74 howto = 0;
75 cp = &argv[1][1];
76 while (*cp) switch (*cp++) {
77 case 'a':
78 howto |= RB_ASKNAME;
79 break;
80 case 's':
81 howto |= RB_SINGLE;
82 break;
83 }
84 } else {
85 howto = RB_SINGLE;
86 }
d0ca48ff
SL
87#endif
88 sigvec(SIGTERM, &rvec, (struct sigvec *)0);
f570e1ff 89 signal(SIGTSTP, idle);
7c8ab0e6 90 signal(SIGSTOP, SIG_IGN);
7c8ab0e6
BJ
91 signal(SIGTTIN, SIG_IGN);
92 signal(SIGTTOU, SIG_IGN);
d0ca48ff
SL
93 (void) setjmp(sjbuf);
94 for (EVER) {
215943cc
BJ
95 oldhowto = howto;
96 howto = RB_SINGLE;
abf0db3c
BJ
97 if (setjmp(shutpass) == 0)
98 shutdown();
215943cc
BJ
99 if (oldhowto & RB_SINGLE)
100 single();
101 if (runcom(oldhowto) == 0)
102 continue;
7c8ab0e6
BJ
103 merge();
104 multiple();
105 }
106}
107
abf0db3c
BJ
108int shutreset();
109
7c8ab0e6
BJ
110shutdown()
111{
112 register i;
113 register struct tab *p;
114
115 close(creat(utmp, 0644));
116 signal(SIGHUP, SIG_IGN);
d0ca48ff 117 for (ALL) {
7c8ab0e6
BJ
118 term(p);
119 p->line[0] = 0;
120 }
abf0db3c
BJ
121 signal(SIGALRM, shutreset);
122 alarm(30);
d0ca48ff 123 for (i = 0; i < 5; i++)
7c8ab0e6 124 kill(-1, SIGKILL);
d0ca48ff 125 while (wait((int *)0) != -1)
7c8ab0e6
BJ
126 ;
127 alarm(0);
abf0db3c
BJ
128 shutend();
129}
130
131char shutfailm[] = "WARNING: Something is hung (wont die); ps axl advised\n";
132
133shutreset()
134{
135 int status;
136
137 if (fork() == 0) {
138 int ct = open(ctty, 1);
139 write(ct, shutfailm, sizeof (shutfailm));
140 sleep(5);
141 exit(1);
142 }
143 sleep(5);
144 shutend();
145 longjmp(shutpass, 1);
146}
147
148shutend()
149{
f570e1ff 150 register i, f;
abf0db3c 151
f570e1ff 152 acct(0);
7c8ab0e6 153 signal(SIGALRM, SIG_DFL);
d0ca48ff 154 for (i = 0; i < 10; i++)
7c8ab0e6 155 close(i);
d0ca48ff 156 f = open(wtmpf, O_WRONLY|O_APPEND);
f570e1ff 157 if (f >= 0) {
f570e1ff
BJ
158 SCPYN(wtmp.ut_line, "~");
159 SCPYN(wtmp.ut_name, "shutdown");
37c640e2 160 SCPYN(wtmp.ut_host, "");
f570e1ff
BJ
161 time(&wtmp.ut_time);
162 write(f, (char *)&wtmp, sizeof(wtmp));
163 close(f);
164 }
d0ca48ff 165 return (1);
7c8ab0e6
BJ
166}
167
168single()
169{
170 register pid;
f570e1ff
BJ
171 register xpid;
172 extern errno;
7c8ab0e6 173
d0ca48ff
SL
174 do {
175 pid = fork();
176 if (pid == 0) {
177 signal(SIGTERM, SIG_DFL);
178 signal(SIGHUP, SIG_DFL);
179 signal(SIGALRM, SIG_DFL);
9479aa87 180 signal(SIGTSTP, SIG_IGN);
d0ca48ff
SL
181 (void) open(ctty, O_RDWR);
182 dup2(0, 1);
183 dup2(0, 2);
184 execl(shell, minus, (char *)0);
185 exit(0);
186 }
187 while ((xpid = wait((int *)0)) != pid)
188 if (xpid == -1 && errno == ECHILD)
189 break;
190 } while (xpid == -1);
7c8ab0e6
BJ
191}
192
215943cc
BJ
193runcom(oldhowto)
194 int oldhowto;
7c8ab0e6
BJ
195{
196 register pid, f;
215943cc 197 int status;
7c8ab0e6
BJ
198
199 pid = fork();
d0ca48ff
SL
200 if (pid == 0) {
201 (void) open("/", O_RDONLY);
202 dup2(0, 1);
203 dup2(0, 2);
215943cc
BJ
204 if (oldhowto & RB_SINGLE)
205 execl(shell, shell, runc, (char *)0);
206 else
207 execl(shell, shell, runc, "autoboot", (char *)0);
208 exit(1);
7c8ab0e6 209 }
d0ca48ff 210 while (wait(&status) != pid)
7c8ab0e6 211 ;
d0ca48ff
SL
212 if (status)
213 return (0);
214 f = open(wtmpf, O_WRONLY|O_APPEND);
7c8ab0e6 215 if (f >= 0) {
7c8ab0e6
BJ
216 SCPYN(wtmp.ut_line, "~");
217 SCPYN(wtmp.ut_name, "reboot");
37c640e2 218 SCPYN(wtmp.ut_host, "");
f570e1ff
BJ
219 if (time0) {
220 wtmp.ut_time = time0;
221 time0 = 0;
222 } else
223 time(&wtmp.ut_time);
7c8ab0e6
BJ
224 write(f, (char *)&wtmp, sizeof(wtmp));
225 close(f);
226 }
d0ca48ff 227 return (1);
7c8ab0e6
BJ
228}
229
d0ca48ff
SL
230struct sigvec mvec = { merge, mask(SIGTERM), 0 };
231/*
232 * Multi-user. Listen for users leaving, SIGHUP's
233 * which indicate ttys has changed, and SIGTERM's which
234 * are used to shutdown the system.
235 */
7c8ab0e6
BJ
236multiple()
237{
238 register struct tab *p;
239 register pid;
240
d0ca48ff
SL
241 sigvec(SIGHUP, &mvec, (struct sigvec *)0);
242 for (EVER) {
7c8ab0e6 243 pid = wait((int *)0);
d0ca48ff 244 if (pid == -1)
7c8ab0e6 245 return;
d0ca48ff
SL
246 for (ALL)
247 if (p->pid == pid || p->pid == -1) {
7c8ab0e6
BJ
248 rmut(p);
249 dfork(p);
250 }
251 }
252}
253
d0ca48ff
SL
254/*
255 * Merge current contents of ttys file
256 * into in-core table of configured tty lines.
257 * Entered as signal handler for SIGHUP.
258 */
259#define FOUND 1
260#define CHANGE 2
261
262merge()
263{
264 register struct tab *p;
9479aa87 265 register struct ttyent *t;
d0ca48ff 266
d0ca48ff
SL
267 for (ALL)
268 p->xflag = 0;
9479aa87
BJ
269 setttyent();
270 while (t = getttyent()) {
271 if ((t->ty_status & TTY_ON) == 0)
272 continue;
273 strcpy(tty, dev);
274 strcat(tty, t->ty_name);
275 if (access(tty, R_OK|W_OK) < 0)
276 continue;
d0ca48ff 277 for (ALL) {
9479aa87 278 if (SCMPN(p->line, t->ty_name))
d0ca48ff
SL
279 continue;
280 p->xflag |= FOUND;
9479aa87 281 if (SCMPN(p->comn, t->ty_getty)) {
d0ca48ff 282 p->xflag |= CHANGE;
9479aa87 283 SCPYN(p->comn, t->ty_getty);
d0ca48ff
SL
284 }
285 goto contin1;
286 }
287 for (ALL) {
288 if (p->line[0] != 0)
289 continue;
9479aa87 290 SCPYN(p->line, t->ty_name);
d0ca48ff 291 p->xflag |= FOUND|CHANGE;
9479aa87 292 SCPYN(p->comn, t->ty_getty);
d0ca48ff
SL
293 goto contin1;
294 }
295 contin1:
296 ;
297 }
9479aa87 298 endttyent();
d0ca48ff
SL
299 for (ALL) {
300 if ((p->xflag&FOUND) == 0) {
301 term(p);
302 p->line[0] = 0;
303 }
304 if (p->xflag&CHANGE) {
305 term(p);
306 dfork(p);
307 }
308 }
309}
310
7c8ab0e6 311term(p)
d0ca48ff 312 register struct tab *p;
7c8ab0e6
BJ
313{
314
d0ca48ff 315 if (p->pid != 0) {
7c8ab0e6
BJ
316 rmut(p);
317 kill(p->pid, SIGKILL);
318 }
319 p->pid = 0;
320}
321
30e1f894
SL
322#include <sys/ioctl.h>
323
7c8ab0e6 324dfork(p)
d0ca48ff 325 struct tab *p;
7c8ab0e6
BJ
326{
327 register pid;
43236707
BJ
328 time_t t;
329 int dowait = 0;
cce8e495 330 extern char *sys_errlist[];
43236707
BJ
331
332 time(&t);
333 p->gettycnt++;
334 if ((t - p->gettytime) >= 60) {
335 p->gettytime = t;
336 p->gettycnt = 1;
337 } else {
338 if (p->gettycnt >= 5) {
339 dowait = 1;
340 p->gettytime = t;
341 p->gettycnt = 1;
342 }
343 }
7c8ab0e6 344 pid = fork();
d0ca48ff 345 if (pid == 0) {
30e1f894
SL
346 int oerrno, f;
347 extern int errno;
348
349 signal(SIGTERM, SIG_DFL);
350 signal(SIGHUP, SIG_IGN);
cce8e495
TL
351 strcpy(tty, dev);
352 strncat(tty, p->line, LINSIZ);
43236707 353 if (dowait) {
d0ca48ff 354 f = open("/dev/console", O_WRONLY);
43236707
BJ
355 write(f, "init: ", 6);
356 write(f, tty, strlen(tty));
357 write(f, ": getty failing, sleeping\n\r", 27);
358 close(f);
359 sleep(30);
d0ca48ff 360 if ((f = open("/dev/tty", O_RDWR)) >= 0) {
30e1f894
SL
361 ioctl(f, TIOCNOTTY, 0);
362 close(f);
363 }
43236707 364 }
7c8ab0e6
BJ
365 chown(tty, 0, 0);
366 chmod(tty, 0622);
d0ca48ff 367 if (open(tty, O_RDWR) < 0) {
ef9abb5f
BJ
368 int repcnt = 0;
369 do {
30e1f894 370 oerrno = errno;
ef9abb5f 371 if (repcnt % 10 == 0) {
d0ca48ff 372 f = open("/dev/console", O_WRONLY);
ef9abb5f 373 write(f, "init: ", 6);
cce8e495
TL
374 write(f, tty, strlen(tty));
375 write(f, ": ", 2);
376 write(f, sys_errlist[oerrno],
377 strlen(sys_errlist[oerrno]));
378 write(f, "\n", 1);
ef9abb5f 379 close(f);
30e1f894
SL
380 if ((f = open("/dev/tty", 2)) >= 0) {
381 ioctl(f, TIOCNOTTY, 0);
382 close(f);
383 }
ef9abb5f
BJ
384 }
385 repcnt++;
386 sleep(60);
d0ca48ff 387 } while (open(tty, O_RDWR) < 0);
ef9abb5f
BJ
388 exit(0); /* have wrong control tty, start over */
389 }
7c8ab0e6
BJ
390 vhangup();
391 signal(SIGHUP, SIG_DFL);
d0ca48ff 392 (void) open(tty, O_RDWR);
7c8ab0e6
BJ
393 close(0);
394 dup(1);
395 dup(0);
9479aa87
BJ
396 strncpy(tty, p->comn, sizeof(p->comn));
397 tty[sizeof(p->comn)] = 0;
7c8ab0e6
BJ
398 execl(getty, minus, tty, (char *)0);
399 exit(0);
400 }
401 p->pid = pid;
402}
403
d0ca48ff
SL
404/*
405 * Remove utmp entry.
406 */
7c8ab0e6 407rmut(p)
d0ca48ff 408 register struct tab *p;
7c8ab0e6
BJ
409{
410 register f;
ef9abb5f 411 int found = 0;
7c8ab0e6 412
d0ca48ff
SL
413 f = open(utmp, O_RDWR);
414 if (f >= 0) {
415 while (read(f, (char *)&wtmp, sizeof(wtmp)) == sizeof(wtmp)) {
ef9abb5f 416 if (SCMPN(wtmp.ut_line, p->line) || wtmp.ut_name[0]==0)
7c8ab0e6
BJ
417 continue;
418 lseek(f, -(long)sizeof(wtmp), 1);
419 SCPYN(wtmp.ut_name, "");
37c640e2 420 SCPYN(wtmp.ut_host, "");
7c8ab0e6
BJ
421 time(&wtmp.ut_time);
422 write(f, (char *)&wtmp, sizeof(wtmp));
ef9abb5f 423 found++;
7c8ab0e6
BJ
424 }
425 close(f);
426 }
ef9abb5f 427 if (found) {
d0ca48ff 428 f = open(wtmpf, O_WRONLY|O_APPEND);
ef9abb5f
BJ
429 if (f >= 0) {
430 SCPYN(wtmp.ut_line, p->line);
431 SCPYN(wtmp.ut_name, "");
37c640e2 432 SCPYN(wtmp.ut_host, "");
ef9abb5f 433 time(&wtmp.ut_time);
ef9abb5f
BJ
434 write(f, (char *)&wtmp, sizeof(wtmp));
435 close(f);
436 }
7c8ab0e6
BJ
437 }
438}
439
440reset()
441{
d0ca48ff 442
7c8ab0e6
BJ
443 longjmp(sjbuf, 1);
444}
f570e1ff 445
d0ca48ff
SL
446jmp_buf idlebuf;
447
448idlehup()
449{
450
451 longjmp(idlebuf, 1);
452}
453
f570e1ff
BJ
454idle()
455{
456 register struct tab *p;
457 register pid;
458
d0ca48ff 459 signal(SIGHUP, idlehup);
f570e1ff 460 for (;;) {
d0ca48ff 461 if (setjmp(idlebuf))
f570e1ff 462 return;
d0ca48ff
SL
463 pid = wait((int *) 0);
464 if (pid == -1) {
465 sigpause(0);
466 continue;
f570e1ff 467 }
d0ca48ff
SL
468 for (ALL)
469 if (p->pid == pid) {
470 rmut(p);
471 p->pid = -1;
472 }
f570e1ff
BJ
473 }
474}