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