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