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