add lint entry; fix depend entry
[unix-history] / usr / src / sbin / init / init.c
CommitLineData
37c640e2 1#ifndef lint
d0ca48ff 2static char *sccsid = "@(#)init.c 4.12 (Berkeley) %G%";
37c640e2
SL
3#endif
4
7c8ab0e6
BJ
5#include <signal.h>
6#include <sys/types.h>
7#include <utmp.h>
8#include <setjmp.h>
215943cc 9#include <sys/reboot.h>
f570e1ff 10#include <errno.h>
d0ca48ff 11#include <sys/file.h>
7c8ab0e6
BJ
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))
d0ca48ff 19#define mask(s) (1 << ((s)-1))
7c8ab0e6
BJ
20
21char shell[] = "/bin/sh";
215943cc 22char getty[] = "/etc/getty";
7c8ab0e6
BJ
23char minus[] = "-";
24char runc[] = "/etc/rc";
25char ifile[] = "/etc/ttys";
26char utmp[] = "/etc/utmp";
27char wtmpf[] = "/usr/adm/wtmp";
28char ctty[] = "/dev/console";
29char dev[] = "/dev/";
30
31struct utmp wtmp;
32struct
33{
34 char line[LINSIZ];
35 char comn;
36 char flag;
37} line;
38struct tab
39{
40 char line[LINSIZ];
41 char comn;
42 char xflag;
43 int pid;
43236707
BJ
44 time_t gettytime;
45 int gettycnt;
7c8ab0e6
BJ
46} itab[TABSIZ];
47
48int fi;
49int mergflag;
50char tty[20];
abf0db3c 51jmp_buf sjbuf, shutpass;
f570e1ff 52time_t time0;
7c8ab0e6
BJ
53
54int reset();
f570e1ff 55int idle();
7c8ab0e6
BJ
56char *strcpy(), *strcat();
57long lseek();
58
d0ca48ff
SL
59struct sigvec rvec = { reset, mask(SIGHUP), 0 };
60
61#ifdef vax
7c8ab0e6
BJ
62main()
63{
215943cc 64 register int r11; /* passed thru from boot */
d0ca48ff 65#else
8d3a6b89
TL
66main(argc, argv)
67 char **argv;
68{
d0ca48ff 69#endif
215943cc
BJ
70 int howto, oldhowto;
71
f570e1ff 72 time0 = time(0);
d0ca48ff 73#ifdef vax
215943cc 74 howto = r11;
d0ca48ff 75#else
8d3a6b89
TL
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 }
d0ca48ff
SL
92#endif
93 sigvec(SIGTERM, &rvec, (struct sigvec *)0);
f570e1ff 94 signal(SIGTSTP, idle);
7c8ab0e6 95 signal(SIGSTOP, SIG_IGN);
7c8ab0e6
BJ
96 signal(SIGTTIN, SIG_IGN);
97 signal(SIGTTOU, SIG_IGN);
d0ca48ff
SL
98 (void) setjmp(sjbuf);
99 for (EVER) {
215943cc
BJ
100 oldhowto = howto;
101 howto = RB_SINGLE;
abf0db3c
BJ
102 if (setjmp(shutpass) == 0)
103 shutdown();
215943cc
BJ
104 if (oldhowto & RB_SINGLE)
105 single();
106 if (runcom(oldhowto) == 0)
107 continue;
7c8ab0e6
BJ
108 merge();
109 multiple();
110 }
111}
112
abf0db3c
BJ
113int shutreset();
114
7c8ab0e6
BJ
115shutdown()
116{
117 register i;
118 register struct tab *p;
119
120 close(creat(utmp, 0644));
121 signal(SIGHUP, SIG_IGN);
d0ca48ff 122 for (ALL) {
7c8ab0e6
BJ
123 term(p);
124 p->line[0] = 0;
125 }
abf0db3c
BJ
126 signal(SIGALRM, shutreset);
127 alarm(30);
d0ca48ff 128 for (i = 0; i < 5; i++)
7c8ab0e6 129 kill(-1, SIGKILL);
d0ca48ff 130 while (wait((int *)0) != -1)
7c8ab0e6
BJ
131 ;
132 alarm(0);
abf0db3c
BJ
133 shutend();
134}
135
136char shutfailm[] = "WARNING: Something is hung (wont die); ps axl advised\n";
137
138shutreset()
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
153shutend()
154{
f570e1ff 155 register i, f;
abf0db3c 156
f570e1ff 157 acct(0);
7c8ab0e6 158 signal(SIGALRM, SIG_DFL);
d0ca48ff 159 for (i = 0; i < 10; i++)
7c8ab0e6 160 close(i);
d0ca48ff 161 f = open(wtmpf, O_WRONLY|O_APPEND);
f570e1ff 162 if (f >= 0) {
f570e1ff
BJ
163 SCPYN(wtmp.ut_line, "~");
164 SCPYN(wtmp.ut_name, "shutdown");
37c640e2 165 SCPYN(wtmp.ut_host, "");
f570e1ff
BJ
166 time(&wtmp.ut_time);
167 write(f, (char *)&wtmp, sizeof(wtmp));
168 close(f);
169 }
d0ca48ff 170 return (1);
7c8ab0e6
BJ
171}
172
173single()
174{
175 register pid;
f570e1ff
BJ
176 register xpid;
177 extern errno;
7c8ab0e6 178
d0ca48ff
SL
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);
7c8ab0e6
BJ
195}
196
215943cc
BJ
197runcom(oldhowto)
198 int oldhowto;
7c8ab0e6
BJ
199{
200 register pid, f;
215943cc 201 int status;
7c8ab0e6
BJ
202
203 pid = fork();
d0ca48ff
SL
204 if (pid == 0) {
205 (void) open("/", O_RDONLY);
206 dup2(0, 1);
207 dup2(0, 2);
215943cc
BJ
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);
7c8ab0e6 213 }
d0ca48ff 214 while (wait(&status) != pid)
7c8ab0e6 215 ;
d0ca48ff
SL
216 if (status)
217 return (0);
218 f = open(wtmpf, O_WRONLY|O_APPEND);
7c8ab0e6 219 if (f >= 0) {
7c8ab0e6
BJ
220 SCPYN(wtmp.ut_line, "~");
221 SCPYN(wtmp.ut_name, "reboot");
37c640e2 222 SCPYN(wtmp.ut_host, "");
f570e1ff
BJ
223 if (time0) {
224 wtmp.ut_time = time0;
225 time0 = 0;
226 } else
227 time(&wtmp.ut_time);
7c8ab0e6
BJ
228 write(f, (char *)&wtmp, sizeof(wtmp));
229 close(f);
230 }
d0ca48ff 231 return (1);
7c8ab0e6
BJ
232}
233
d0ca48ff
SL
234struct 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 */
7c8ab0e6
BJ
240multiple()
241{
242 register struct tab *p;
243 register pid;
244
d0ca48ff
SL
245 sigvec(SIGHUP, &mvec, (struct sigvec *)0);
246 for (EVER) {
7c8ab0e6 247 pid = wait((int *)0);
d0ca48ff 248 if (pid == -1)
7c8ab0e6 249 return;
d0ca48ff
SL
250 for (ALL)
251 if (p->pid == pid || p->pid == -1) {
7c8ab0e6
BJ
252 rmut(p);
253 dfork(p);
254 }
255 }
256}
257
d0ca48ff
SL
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
266merge()
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
7c8ab0e6 310term(p)
d0ca48ff 311 register struct tab *p;
7c8ab0e6
BJ
312{
313
d0ca48ff 314 if (p->pid != 0) {
7c8ab0e6
BJ
315 rmut(p);
316 kill(p->pid, SIGKILL);
317 }
318 p->pid = 0;
319}
320
321rline()
322{
323 register c, i;
324
325loop:
326 c = get();
d0ca48ff 327 if (c < 0)
7c8ab0e6 328 return(0);
d0ca48ff 329 if (c == 0)
7c8ab0e6
BJ
330 goto loop;
331 line.flag = c;
332 c = get();
d0ca48ff 333 if (c <= 0)
7c8ab0e6
BJ
334 goto loop;
335 line.comn = c;
336 SCPYN(line.line, "");
d0ca48ff 337 for (i = 0; i < LINSIZ; i++) {
7c8ab0e6 338 c = get();
d0ca48ff 339 if (c <= 0)
7c8ab0e6
BJ
340 break;
341 line.line[i] = c;
342 }
d0ca48ff 343 while (c > 0)
7c8ab0e6 344 c = get();
d0ca48ff 345 if (line.line[0] == 0)
7c8ab0e6 346 goto loop;
d0ca48ff 347 if (line.flag == '0')
7c8ab0e6
BJ
348 goto loop;
349 strcpy(tty, dev);
350 strncat(tty, line.line, LINSIZ);
d0ca48ff 351 if (access(tty, 06) < 0)
7c8ab0e6 352 goto loop;
d0ca48ff 353 return (1);
7c8ab0e6
BJ
354}
355
356get()
357{
358 char b;
359
d0ca48ff
SL
360 if (read(fi, &b, 1) != 1)
361 return (-1);
362 if (b == '\n')
363 return (0);
364 return (b);
7c8ab0e6
BJ
365}
366
30e1f894
SL
367#include <sys/ioctl.h>
368
7c8ab0e6 369dfork(p)
d0ca48ff 370 struct tab *p;
7c8ab0e6
BJ
371{
372 register pid;
43236707
BJ
373 time_t t;
374 int dowait = 0;
cce8e495 375 extern char *sys_errlist[];
43236707
BJ
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 }
7c8ab0e6 389 pid = fork();
d0ca48ff 390 if (pid == 0) {
30e1f894
SL
391 int oerrno, f;
392 extern int errno;
393
394 signal(SIGTERM, SIG_DFL);
395 signal(SIGHUP, SIG_IGN);
cce8e495
TL
396 strcpy(tty, dev);
397 strncat(tty, p->line, LINSIZ);
43236707 398 if (dowait) {
d0ca48ff 399 f = open("/dev/console", O_WRONLY);
43236707
BJ
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);
d0ca48ff 405 if ((f = open("/dev/tty", O_RDWR)) >= 0) {
30e1f894
SL
406 ioctl(f, TIOCNOTTY, 0);
407 close(f);
408 }
43236707 409 }
7c8ab0e6
BJ
410 chown(tty, 0, 0);
411 chmod(tty, 0622);
d0ca48ff 412 if (open(tty, O_RDWR) < 0) {
ef9abb5f
BJ
413 int repcnt = 0;
414 do {
30e1f894 415 oerrno = errno;
ef9abb5f 416 if (repcnt % 10 == 0) {
d0ca48ff 417 f = open("/dev/console", O_WRONLY);
ef9abb5f 418 write(f, "init: ", 6);
cce8e495
TL
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);
ef9abb5f 424 close(f);
30e1f894
SL
425 if ((f = open("/dev/tty", 2)) >= 0) {
426 ioctl(f, TIOCNOTTY, 0);
427 close(f);
428 }
ef9abb5f
BJ
429 }
430 repcnt++;
431 sleep(60);
d0ca48ff 432 } while (open(tty, O_RDWR) < 0);
ef9abb5f
BJ
433 exit(0); /* have wrong control tty, start over */
434 }
7c8ab0e6
BJ
435 vhangup();
436 signal(SIGHUP, SIG_DFL);
d0ca48ff 437 (void) open(tty, O_RDWR);
7c8ab0e6
BJ
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
d0ca48ff
SL
449/*
450 * Remove utmp entry.
451 */
7c8ab0e6 452rmut(p)
d0ca48ff 453 register struct tab *p;
7c8ab0e6
BJ
454{
455 register f;
ef9abb5f 456 int found = 0;
7c8ab0e6 457
d0ca48ff
SL
458 f = open(utmp, O_RDWR);
459 if (f >= 0) {
460 while (read(f, (char *)&wtmp, sizeof(wtmp)) == sizeof(wtmp)) {
ef9abb5f 461 if (SCMPN(wtmp.ut_line, p->line) || wtmp.ut_name[0]==0)
7c8ab0e6
BJ
462 continue;
463 lseek(f, -(long)sizeof(wtmp), 1);
464 SCPYN(wtmp.ut_name, "");
37c640e2 465 SCPYN(wtmp.ut_host, "");
7c8ab0e6
BJ
466 time(&wtmp.ut_time);
467 write(f, (char *)&wtmp, sizeof(wtmp));
ef9abb5f 468 found++;
7c8ab0e6
BJ
469 }
470 close(f);
471 }
ef9abb5f 472 if (found) {
d0ca48ff 473 f = open(wtmpf, O_WRONLY|O_APPEND);
ef9abb5f
BJ
474 if (f >= 0) {
475 SCPYN(wtmp.ut_line, p->line);
476 SCPYN(wtmp.ut_name, "");
37c640e2 477 SCPYN(wtmp.ut_host, "");
ef9abb5f 478 time(&wtmp.ut_time);
ef9abb5f
BJ
479 write(f, (char *)&wtmp, sizeof(wtmp));
480 close(f);
481 }
7c8ab0e6
BJ
482 }
483}
484
485reset()
486{
d0ca48ff 487
7c8ab0e6
BJ
488 longjmp(sjbuf, 1);
489}
f570e1ff 490
d0ca48ff
SL
491jmp_buf idlebuf;
492
493idlehup()
494{
495
496 longjmp(idlebuf, 1);
497}
498
f570e1ff
BJ
499idle()
500{
501 register struct tab *p;
502 register pid;
503
d0ca48ff 504 signal(SIGHUP, idlehup);
f570e1ff 505 for (;;) {
d0ca48ff 506 if (setjmp(idlebuf))
f570e1ff 507 return;
d0ca48ff
SL
508 pid = wait((int *) 0);
509 if (pid == -1) {
510 sigpause(0);
511 continue;
f570e1ff 512 }
d0ca48ff
SL
513 for (ALL)
514 if (p->pid == pid) {
515 rmut(p);
516 p->pid = -1;
517 }
f570e1ff
BJ
518 }
519}