speed-ups and clean-ups
[unix-history] / usr / src / sbin / init / init.c
CommitLineData
8d3a6b89 1static 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
16char shell[] = "/bin/sh";
215943cc 17char getty[] = "/etc/getty";
7c8ab0e6
BJ
18char minus[] = "-";
19char runc[] = "/etc/rc";
20char ifile[] = "/etc/ttys";
21char utmp[] = "/etc/utmp";
22char wtmpf[] = "/usr/adm/wtmp";
23char ctty[] = "/dev/console";
24char dev[] = "/dev/";
25
26struct utmp wtmp;
27struct
28{
29 char line[LINSIZ];
30 char comn;
31 char flag;
32} line;
33struct 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
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
8d3a6b89 54#ifndef sun
7c8ab0e6
BJ
55main()
56{
215943cc 57 register int r11; /* passed thru from boot */
8d3a6b89
TL
58#else sun
59main(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
106int shutreset();
107
7c8ab0e6
BJ
108shutdown()
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
129char shutfailm[] = "WARNING: Something is hung (wont die); ps axl advised\n";
130
131shutreset()
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
146shutend()
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
166single()
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
193runcom(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
230setmerge()
231{
232
233 signal(SIGHUP, setmerge);
234 mergflag = 1;
235}
236
237multiple()
238{
239 register struct tab *p;
240 register pid;
241
242loop:
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
261term(p)
262register 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
272rline()
273{
274 register c, i;
275
276loop:
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
307get()
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
321merge()
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
367dfork(p)
368struct 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
447rmut(p)
448register 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
479reset()
480{
481 longjmp(sjbuf, 1);
482}
f570e1ff
BJ
483
484idle()
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}