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