Hide unused variable when not building with WITH_SELINUX.
[sysvinit.git] / src / init.c
CommitLineData
a74aeac6
PR
1/*
2 * Init A System-V Init Clone.
3 *
4 * Usage: /sbin/init
5 * init [0123456SsQqAaBbCc]
6 * telinit [0123456SsQqAaBbCc]
7 *
8 * Version: @(#)init.c 2.86 30-Jul-2004 miquels@cistron.nl
9 */
0e6cb480 10#define VERSION "2.88"
a74aeac6
PR
11#define DATE "31-Jul-2004"
12/*
13 * This file is part of the sysvinit suite,
14 * Copyright (C) 1991-2004 Miquel van Smoorenburg.
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29 *
30 */
31
32#include <sys/types.h>
33#include <sys/stat.h>
34#include <sys/ioctl.h>
35#include <sys/wait.h>
36#ifdef __linux__
37#include <sys/kd.h>
38#endif
39#include <sys/resource.h>
40#include <stdlib.h>
41#include <unistd.h>
42#include <errno.h>
43#include <stdio.h>
44#include <time.h>
45#include <fcntl.h>
46#include <string.h>
47#include <signal.h>
48#include <termios.h>
49#include <utmp.h>
50#include <ctype.h>
51#include <stdarg.h>
52#include <sys/syslog.h>
53#include <sys/time.h>
54
55#ifdef WITH_SELINUX
56#include <selinux/selinux.h>
57#endif
58
59
60#ifdef __i386__
61# if (__GLIBC__ >= 2)
62 /* GNU libc 2.x */
63# define STACK_DEBUG 1
64# if (__GLIBC__ == 2 && __GLIBC_MINOR__ == 0)
65 /* Only glibc 2.0 needs this */
66# include <sigcontext.h>
67# endif
68# endif
69#endif
70
71#include "init.h"
72#include "initreq.h"
73#include "paths.h"
74#include "reboot.h"
75#include "set.h"
76
77#ifndef SIGPWR
78# define SIGPWR SIGUSR2
79#endif
80
81#ifndef CBAUD
82# define CBAUD 0
83#endif
84#ifndef CBAUDEX
85# define CBAUDEX 0
86#endif
87
88/* Set a signal handler. */
89#define SETSIG(sa, sig, fun, flags) \
90 do { \
91 sa.sa_handler = fun; \
92 sa.sa_flags = flags; \
93 sigemptyset(&sa.sa_mask); \
94 sigaction(sig, &sa, NULL); \
95 } while(0)
96
97/* Version information */
98char *Version = "@(#) init " VERSION " " DATE " miquels@cistron.nl";
99char *bootmsg = "version " VERSION " %s";
100#define E_VERSION "INIT_VERSION=sysvinit-" VERSION
101
102CHILD *family = NULL; /* The linked list of all entries */
103CHILD *newFamily = NULL; /* The list after inittab re-read */
104
105CHILD ch_emerg = { /* Emergency shell */
106 WAITING, 0, 0, 0, 0,
107 "~~",
108 "S",
109 3,
110 "/sbin/sulogin",
111 NULL,
112 NULL
113};
114
115char runlevel = 'S'; /* The current run level */
116char thislevel = 'S'; /* The current runlevel */
117char prevlevel = 'N'; /* Previous runlevel */
118int dfl_level = 0; /* Default runlevel */
119sig_atomic_t got_cont = 0; /* Set if we received the SIGCONT signal */
120sig_atomic_t got_signals; /* Set if we received a signal. */
121int emerg_shell = 0; /* Start emergency shell? */
122int wrote_wtmp_reboot = 1; /* Set when we wrote the reboot record */
123int wrote_utmp_reboot = 1; /* Set when we wrote the reboot record */
124int sltime = 5; /* Sleep time between TERM and KILL */
125char *argv0; /* First arguments; show up in ps listing */
126int maxproclen; /* Maximal length of argv[0] with \0 */
127struct utmp utproto; /* Only used for sizeof(utproto.ut_id) */
a74aeac6
PR
128char *console_dev; /* Console device. */
129int pipe_fd = -1; /* /dev/initctl */
130int did_boot = 0; /* Did we already do BOOT* stuff? */
131int main(int, char **);
132
133/* Used by re-exec part */
134int reload = 0; /* Should we do initialization stuff? */
135char *myname="/sbin/init"; /* What should we exec */
136int oops_error; /* Used by some of the re-exec code. */
137const char *Signature = "12567362"; /* Signature for re-exec fd */
138
139/* Macro to see if this is a special action */
140#define ISPOWER(i) ((i) == POWERWAIT || (i) == POWERFAIL || \
141 (i) == POWEROKWAIT || (i) == POWERFAILNOW || \
142 (i) == CTRLALTDEL)
143
144/* ascii values for the `action' field. */
145struct actions {
146 char *name;
147 int act;
148} actions[] = {
149 { "respawn", RESPAWN },
150 { "wait", WAIT },
151 { "once", ONCE },
152 { "boot", BOOT },
153 { "bootwait", BOOTWAIT },
154 { "powerfail", POWERFAIL },
155 { "powerfailnow",POWERFAILNOW },
156 { "powerwait", POWERWAIT },
157 { "powerokwait", POWEROKWAIT },
158 { "ctrlaltdel", CTRLALTDEL },
159 { "off", OFF },
160 { "ondemand", ONDEMAND },
161 { "initdefault", INITDEFAULT },
162 { "sysinit", SYSINIT },
163 { "kbrequest", KBREQUEST },
164 { NULL, 0 },
165};
166
167/*
168 * State parser token table (see receive_state)
169 */
170struct {
171 char name[4];
172 int cmd;
173} cmds[] = {
174 { "VER", C_VER },
175 { "END", C_END },
176 { "REC", C_REC },
177 { "EOR", C_EOR },
178 { "LEV", C_LEV },
179 { "FL ", C_FLAG },
180 { "AC ", C_ACTION },
181 { "CMD", C_PROCESS },
182 { "PID", C_PID },
183 { "EXS", C_EXS },
184 { "-RL", D_RUNLEVEL },
185 { "-TL", D_THISLEVEL },
186 { "-PL", D_PREVLEVEL },
187 { "-SI", D_GOTSIGN },
188 { "-WR", D_WROTE_WTMP_REBOOT},
189 { "-WU", D_WROTE_UTMP_REBOOT},
190 { "-ST", D_SLTIME },
191 { "-DB", D_DIDBOOT },
192 { "", 0 }
193};
194struct {
195 char *name;
196 int mask;
197} flags[]={
198 {"RU",RUNNING},
199 {"DE",DEMAND},
200 {"XD",XECUTED},
201 {"WT",WAITING},
202 {NULL,0}
203};
204
205#define NR_EXTRA_ENV 16
206char *extra_env[NR_EXTRA_ENV];
207
208
209/*
210 * Sleep a number of seconds.
211 *
212 * This only works correctly because the linux select updates
213 * the elapsed time in the struct timeval passed to select!
214 */
215void do_sleep(int sec)
216{
217 struct timeval tv;
218
219 tv.tv_sec = sec;
220 tv.tv_usec = 0;
221
222 while(select(0, NULL, NULL, NULL, &tv) < 0 && errno == EINTR)
223 ;
224}
225
226
227/*
228 * Non-failing allocation routines (init cannot fail).
229 */
230void *imalloc(size_t size)
231{
232 void *m;
233
234 while ((m = malloc(size)) == NULL) {
235 initlog(L_VB, "out of memory");
236 do_sleep(5);
237 }
238 memset(m, 0, size);
239 return m;
240}
241
242
243char *istrdup(char *s)
244{
245 char *m;
246 int l;
247
248 l = strlen(s) + 1;
249 m = imalloc(l);
250 memcpy(m, s, l);
251 return m;
252}
253
254
255/*
256 * Send the state info of the previous running init to
257 * the new one, in a version-independant way.
258 */
259void send_state(int fd)
260{
261 FILE *fp;
262 CHILD *p;
263 int i,val;
264
265 fp = fdopen(fd,"w");
266
267 fprintf(fp, "VER%s\n", Version);
268 fprintf(fp, "-RL%c\n", runlevel);
269 fprintf(fp, "-TL%c\n", thislevel);
270 fprintf(fp, "-PL%c\n", prevlevel);
271 fprintf(fp, "-SI%u\n", got_signals);
272 fprintf(fp, "-WR%d\n", wrote_wtmp_reboot);
273 fprintf(fp, "-WU%d\n", wrote_utmp_reboot);
274 fprintf(fp, "-ST%d\n", sltime);
275 fprintf(fp, "-DB%d\n", did_boot);
276
277 for (p = family; p; p = p->next) {
278 fprintf(fp, "REC%s\n", p->id);
279 fprintf(fp, "LEV%s\n", p->rlevel);
280 for (i = 0, val = p->flags; flags[i].mask; i++)
281 if (val & flags[i].mask) {
282 val &= ~flags[i].mask;
283 fprintf(fp, "FL %s\n",flags[i].name);
284 }
285 fprintf(fp, "PID%d\n",p->pid);
286 fprintf(fp, "EXS%u\n",p->exstat);
287 for(i = 0; actions[i].act; i++)
288 if (actions[i].act == p->action) {
289 fprintf(fp, "AC %s\n", actions[i].name);
290 break;
291 }
292 fprintf(fp, "CMD%s\n", p->process);
293 fprintf(fp, "EOR\n");
294 }
295 fprintf(fp, "END\n");
296 fclose(fp);
297}
298
299/*
300 * Read a string from a file descriptor.
301 * FIXME: why not use fgets() ?
302 */
303static int get_string(char *p, int size, FILE *f)
304{
305 int c;
306
307 while ((c = getc(f)) != EOF && c != '\n') {
308 if (--size > 0)
309 *p++ = c;
310 }
311 *p = '\0';
312 return (c != EOF) && (size > 0);
313}
314
315/*
316 * Read trailing data from the state pipe until we see a newline.
317 */
318static int get_void(FILE *f)
319{
320 int c;
321
322 while ((c = getc(f)) != EOF && c != '\n')
323 ;
324
325 return (c != EOF);
326}
327
328/*
329 * Read the next "command" from the state pipe.
330 */
331static int get_cmd(FILE *f)
332{
333 char cmd[4] = " ";
334 int i;
335
336 if (fread(cmd, 1, sizeof(cmd) - 1, f) != sizeof(cmd) - 1)
337 return C_EOF;
338
339 for(i = 0; cmds[i].cmd && strcmp(cmds[i].name, cmd) != 0; i++)
340 ;
341 return cmds[i].cmd;
342}
343
344/*
345 * Read a CHILD * from the state pipe.
346 */
347static CHILD *get_record(FILE *f)
348{
349 int cmd;
350 char s[32];
351 int i;
352 CHILD *p;
353
354 do {
355 switch (cmd = get_cmd(f)) {
356 case C_END:
357 get_void(f);
358 return NULL;
359 case 0:
360 get_void(f);
361 break;
362 case C_REC:
363 break;
364 case D_RUNLEVEL:
365 fscanf(f, "%c\n", &runlevel);
366 break;
367 case D_THISLEVEL:
368 fscanf(f, "%c\n", &thislevel);
369 break;
370 case D_PREVLEVEL:
371 fscanf(f, "%c\n", &prevlevel);
372 break;
373 case D_GOTSIGN:
374 fscanf(f, "%u\n", &got_signals);
375 break;
376 case D_WROTE_WTMP_REBOOT:
377 fscanf(f, "%d\n", &wrote_wtmp_reboot);
378 break;
379 case D_WROTE_UTMP_REBOOT:
380 fscanf(f, "%d\n", &wrote_utmp_reboot);
381 break;
382 case D_SLTIME:
383 fscanf(f, "%d\n", &sltime);
384 break;
385 case D_DIDBOOT:
386 fscanf(f, "%d\n", &did_boot);
387 break;
388 default:
389 if (cmd > 0 || cmd == C_EOF) {
390 oops_error = -1;
391 return NULL;
392 }
393 }
394 } while (cmd != C_REC);
395
396 p = imalloc(sizeof(CHILD));
397 get_string(p->id, sizeof(p->id), f);
398
399 do switch(cmd = get_cmd(f)) {
400 case 0:
401 case C_EOR:
402 get_void(f);
403 break;
404 case C_PID:
405 fscanf(f, "%d\n", &(p->pid));
406 break;
407 case C_EXS:
408 fscanf(f, "%u\n", &(p->exstat));
409 break;
410 case C_LEV:
411 get_string(p->rlevel, sizeof(p->rlevel), f);
412 break;
413 case C_PROCESS:
414 get_string(p->process, sizeof(p->process), f);
415 break;
416 case C_FLAG:
417 get_string(s, sizeof(s), f);
418 for(i = 0; flags[i].name; i++) {
419 if (strcmp(flags[i].name,s) == 0)
420 break;
421 }
422 p->flags |= flags[i].mask;
423 break;
424 case C_ACTION:
425 get_string(s, sizeof(s), f);
426 for(i = 0; actions[i].name; i++) {
427 if (strcmp(actions[i].name, s) == 0)
428 break;
429 }
430 p->action = actions[i].act ? actions[i].act : OFF;
431 break;
432 default:
433 free(p);
434 oops_error = -1;
435 return NULL;
436 } while( cmd != C_EOR);
437
438 return p;
439}
440
441/*
442 * Read the complete state info from the state pipe.
443 * Returns 0 on success
444 */
445int receive_state(int fd)
446{
447 FILE *f;
448 char old_version[256];
449 CHILD **pp;
450
451 f = fdopen(fd, "r");
452
453 if (get_cmd(f) != C_VER)
454 return -1;
455 get_string(old_version, sizeof(old_version), f);
456 oops_error = 0;
457 for (pp = &family; (*pp = get_record(f)) != NULL; pp = &((*pp)->next))
458 ;
459 fclose(f);
460 return oops_error;
461}
462
463/*
464 * Set the process title.
465 */
466#ifdef __GNUC__
467__attribute__ ((format (printf, 1, 2)))
468#endif
469static int setproctitle(char *fmt, ...)
470{
471 va_list ap;
472 int len;
473 char buf[256];
474
475 buf[0] = 0;
476
477 va_start(ap, fmt);
478 len = vsnprintf(buf, sizeof(buf), fmt, ap);
479 va_end(ap);
480
481 if (maxproclen > 1) {
482 memset(argv0, 0, maxproclen);
483 strncpy(argv0, buf, maxproclen - 1);
484 }
485
486 return len;
487}
488
489/*
490 * Set console_dev to a working console.
491 */
492void console_init(void)
493{
494 int fd;
495 int tried_devcons = 0;
496 int tried_vtmaster = 0;
497 char *s;
498
a33820c3 499 if ((s = getenv("CONSOLE")) != NULL)
a74aeac6
PR
500 console_dev = s;
501 else {
502 console_dev = CONSOLE;
503 tried_devcons++;
504 }
505
506 while ((fd = open(console_dev, O_RDONLY|O_NONBLOCK)) < 0) {
507 if (!tried_devcons) {
508 tried_devcons++;
509 console_dev = CONSOLE;
510 continue;
511 }
512 if (!tried_vtmaster) {
513 tried_vtmaster++;
514 console_dev = VT_MASTER;
515 continue;
516 }
517 break;
518 }
519 if (fd < 0)
520 console_dev = "/dev/null";
521 else
522 close(fd);
523}
524
525
526/*
527 * Open the console with retries.
528 */
529int console_open(int mode)
530{
531 int f, fd = -1;
532 int m;
533
534 /*
535 * Open device in nonblocking mode.
536 */
537 m = mode | O_NONBLOCK;
538
539 /*
540 * Retry the open five times.
541 */
542 for(f = 0; f < 5; f++) {
543 if ((fd = open(console_dev, m)) >= 0) break;
544 usleep(100);
545 }
546
547 if (fd < 0) return fd;
548
549 /*
550 * Set original flags.
551 */
552 if (m != mode)
553 fcntl(fd, F_SETFL, mode);
554 return fd;
555}
556
557/*
558 * We got a signal (HUP PWR WINCH ALRM INT)
559 */
560void signal_handler(int sig)
561{
562 ADDSET(got_signals, sig);
563}
564
565/*
566 * SIGCHLD: one of our children has died.
567 */
568void chld_handler()
569{
570 CHILD *ch;
571 int pid, st;
572 int saved_errno = errno;
573
574 /*
575 * Find out which process(es) this was (were)
576 */
577 while((pid = waitpid(-1, &st, WNOHANG)) != 0) {
578 if (errno == ECHILD) break;
579 for( ch = family; ch; ch = ch->next )
580 if ( ch->pid == pid && (ch->flags & RUNNING) ) {
581 INITDBG(L_VB,
582 "chld_handler: marked %d as zombie",
583 ch->pid);
584 ADDSET(got_signals, SIGCHLD);
585 ch->exstat = st;
586 ch->flags |= ZOMBIE;
587 if (ch->new) {
588 ch->new->exstat = st;
589 ch->new->flags |= ZOMBIE;
590 }
591 break;
592 }
593 if (ch == NULL) {
594 INITDBG(L_VB, "chld_handler: unknown child %d exited.",
595 pid);
596 }
597 }
598 errno = saved_errno;
599}
600
601/*
602 * Linux ignores all signals sent to init when the
603 * SIG_DFL handler is installed. Therefore we must catch SIGTSTP
604 * and SIGCONT, or else they won't work....
605 *
606 * The SIGCONT handler
607 */
608void cont_handler()
609{
610 got_cont = 1;
611}
612
613/*
614 * Fork and dump core in /.
615 */
616void coredump(void)
617{
618 static int dumped = 0;
619 struct rlimit rlim;
620 sigset_t mask;
621
622 if (dumped) return;
623 dumped = 1;
624
625 if (fork() != 0) return;
626
627 sigfillset(&mask);
628 sigprocmask(SIG_SETMASK, &mask, NULL);
629
630 rlim.rlim_cur = RLIM_INFINITY;
631 rlim.rlim_max = RLIM_INFINITY;
632 setrlimit(RLIMIT_CORE, &rlim);
633 chdir("/");
634
635 signal(SIGSEGV, SIG_DFL);
636 raise(SIGSEGV);
637 sigdelset(&mask, SIGSEGV);
638 sigprocmask(SIG_SETMASK, &mask, NULL);
639
640 do_sleep(5);
641 exit(0);
642}
643
644/*
645 * OOPS: segmentation violation!
646 * If we have the info, print where it occured.
647 * Then sleep 30 seconds and try to continue.
648 */
649#if defined(STACK_DEBUG) && defined(__linux__)
650void segv_handler(int sig, struct sigcontext ctx)
651{
652 char *p = "";
653 int saved_errno = errno;
654
655 if ((void *)ctx.eip >= (void *)do_sleep &&
656 (void *)ctx.eip < (void *)main)
657 p = " (code)";
658 initlog(L_VB, "PANIC: segmentation violation at %p%s! "
659 "sleeping for 30 seconds.", (void *)ctx.eip, p);
660 coredump();
661 do_sleep(30);
662 errno = saved_errno;
663}
664#else
665void segv_handler()
666{
667 int saved_errno = errno;
668
669 initlog(L_VB,
670 "PANIC: segmentation violation! sleeping for 30 seconds.");
671 coredump();
672 do_sleep(30);
673 errno = saved_errno;
674}
675#endif
676
677/*
678 * The SIGSTOP & SIGTSTP handler
679 */
680void stop_handler()
681{
682 int saved_errno = errno;
683
684 got_cont = 0;
685 while(!got_cont) pause();
686 got_cont = 0;
687 errno = saved_errno;
688}
689
690/*
691 * Set terminal settings to reasonable defaults
692 */
693void console_stty(void)
694{
695 struct termios tty;
696 int fd;
697
698 if ((fd = console_open(O_RDWR|O_NOCTTY)) < 0) {
699 initlog(L_VB, "can't open %s", console_dev);
700 return;
701 }
702
703 (void) tcgetattr(fd, &tty);
704
705 tty.c_cflag &= CBAUD|CBAUDEX|CSIZE|CSTOPB|PARENB|PARODD;
706 tty.c_cflag |= HUPCL|CLOCAL|CREAD;
707
708 tty.c_cc[VINTR] = 3; /* ctrl('c') */
709 tty.c_cc[VQUIT] = 28; /* ctrl('\\') */
710 tty.c_cc[VERASE] = 127;
711 tty.c_cc[VKILL] = 24; /* ctrl('x') */
712 tty.c_cc[VEOF] = 4; /* ctrl('d') */
713 tty.c_cc[VTIME] = 0;
714 tty.c_cc[VMIN] = 1;
715 tty.c_cc[VSTART] = 17; /* ctrl('q') */
716 tty.c_cc[VSTOP] = 19; /* ctrl('s') */
717 tty.c_cc[VSUSP] = 26; /* ctrl('z') */
718
719 /*
720 * Set pre and post processing
721 */
334256b0
PR
722 tty.c_iflag = IGNPAR|ICRNL|IXON|IXANY
723#ifdef IUTF8 /* Not defined on FreeBSD */
724 | (tty.c_iflag & IUTF8)
725#endif /* IUTF8 */
726 ;
a74aeac6
PR
727 tty.c_oflag = OPOST|ONLCR;
728 tty.c_lflag = ISIG|ICANON|ECHO|ECHOCTL|ECHOPRT|ECHOKE;
729
730 /*
731 * Now set the terminal line.
732 * We don't care about non-transmitted output data
733 * and non-read input data.
734 */
735 (void) tcsetattr(fd, TCSANOW, &tty);
736 (void) tcflush(fd, TCIOFLUSH);
737 (void) close(fd);
738}
739
740/*
741 * Print to the system console
742 */
743void print(char *s)
744{
745 int fd;
746
747 if ((fd = console_open(O_WRONLY|O_NOCTTY|O_NDELAY)) >= 0) {
748 write(fd, s, strlen(s));
749 close(fd);
750 }
751}
752
753/*
754 * Log something to a logfile and the console.
755 */
756#ifdef __GNUC__
757__attribute__ ((format (printf, 2, 3)))
758#endif
759void initlog(int loglevel, char *s, ...)
760{
761 va_list va_alist;
762 char buf[256];
763 sigset_t nmask, omask;
764
765 va_start(va_alist, s);
766 vsnprintf(buf, sizeof(buf), s, va_alist);
767 va_end(va_alist);
768
769 if (loglevel & L_SY) {
770 /*
771 * Re-establish connection with syslogd every time.
772 * Block signals while talking to syslog.
773 */
774 sigfillset(&nmask);
775 sigprocmask(SIG_BLOCK, &nmask, &omask);
776 openlog("init", 0, LOG_DAEMON);
777 syslog(LOG_INFO, "%s", buf);
778 closelog();
779 sigprocmask(SIG_SETMASK, &omask, NULL);
780 }
781
782 /*
783 * And log to the console.
784 */
785 if (loglevel & L_CO) {
786 print("\rINIT: ");
787 print(buf);
788 print("\r\n");
789 }
790}
791
792
793/*
794 * Build a new environment for execve().
795 */
796char **init_buildenv(int child)
797{
798 char i_lvl[] = "RUNLEVEL=x";
799 char i_prev[] = "PREVLEVEL=x";
800 char i_cons[32];
801 char **e;
802 int n, i;
803
804 for (n = 0; environ[n]; n++)
805 ;
806 n += NR_EXTRA_ENV + 8;
807 e = calloc(n, sizeof(char *));
808
809 for (n = 0; environ[n]; n++)
810 e[n] = istrdup(environ[n]);
811
812 for (i = 0; i < NR_EXTRA_ENV; i++)
813 if (extra_env[i])
814 e[n++] = istrdup(extra_env[i]);
815
816 if (child) {
817 snprintf(i_cons, sizeof(i_cons), "CONSOLE=%s", console_dev);
818 i_lvl[9] = thislevel;
819 i_prev[10] = prevlevel;
820 e[n++] = istrdup(i_lvl);
821 e[n++] = istrdup(i_prev);
822 e[n++] = istrdup(i_cons);
823 e[n++] = istrdup(E_VERSION);
824 }
825
826 e[n++] = NULL;
827
828 return e;
829}
830
831
832void init_freeenv(char **e)
833{
834 int n;
835
836 for (n = 0; e[n]; n++)
837 free(e[n]);
838 free(e);
839}
840
841
842/*
843 * Fork and execute.
844 *
845 * This function is too long and indents too deep.
846 *
847 */
848int spawn(CHILD *ch, int *res)
849{
850 char *args[16]; /* Argv array */
851 char buf[136]; /* Line buffer */
852 int f, st, rc; /* Scratch variables */
853 char *ptr; /* Ditto */
854 time_t t; /* System time */
855 int oldAlarm; /* Previous alarm value */
856 char *proc = ch->process; /* Command line */
857 pid_t pid, pgrp; /* child, console process group. */
858 sigset_t nmask, omask; /* For blocking SIGCHLD */
859 struct sigaction sa;
860
861 *res = -1;
862 buf[sizeof(buf) - 1] = 0;
863
864 /* Skip '+' if it's there */
865 if (proc[0] == '+') proc++;
866
867 ch->flags |= XECUTED;
868
869 if (ch->action == RESPAWN || ch->action == ONDEMAND) {
870 /* Is the date stamp from less than 2 minutes ago? */
871 time(&t);
872 if (ch->tm + TESTTIME > t) {
873 ch->count++;
874 } else {
875 ch->count = 0;
876 ch->tm = t;
877 }
878
879 /* Do we try to respawn too fast? */
880 if (ch->count >= MAXSPAWN) {
881
882 initlog(L_VB,
883 "Id \"%s\" respawning too fast: disabled for %d minutes",
884 ch->id, SLEEPTIME / 60);
885 ch->flags &= ~RUNNING;
886 ch->flags |= FAILING;
887
888 /* Remember the time we stopped */
889 ch->tm = t;
890
891 /* Try again in 5 minutes */
892 oldAlarm = alarm(0);
893 if (oldAlarm > SLEEPTIME || oldAlarm <= 0) oldAlarm = SLEEPTIME;
894 alarm(oldAlarm);
895 return(-1);
896 }
897 }
898
899 /* See if there is an "initscript" (except in single user mode). */
900 if (access(INITSCRIPT, R_OK) == 0 && runlevel != 'S') {
901 /* Build command line using "initscript" */
902 args[1] = SHELL;
903 args[2] = INITSCRIPT;
904 args[3] = ch->id;
905 args[4] = ch->rlevel;
906 args[5] = "unknown";
907 for(f = 0; actions[f].name; f++) {
908 if (ch->action == actions[f].act) {
909 args[5] = actions[f].name;
910 break;
911 }
912 }
913 args[6] = proc;
914 args[7] = NULL;
915 } else if (strpbrk(proc, "~`!$^&*()=|\\{}[];\"'<>?")) {
916 /* See if we need to fire off a shell for this command */
917 /* Give command line to shell */
918 args[1] = SHELL;
919 args[2] = "-c";
920 strcpy(buf, "exec ");
921 strncat(buf, proc, sizeof(buf) - strlen(buf) - 1);
922 args[3] = buf;
923 args[4] = NULL;
924 } else {
925 /* Split up command line arguments */
926 buf[0] = 0;
927 strncat(buf, proc, sizeof(buf) - 1);
928 ptr = buf;
929 for(f = 1; f < 15; f++) {
930 /* Skip white space */
931 while(*ptr == ' ' || *ptr == '\t') ptr++;
932 args[f] = ptr;
933
934 /* May be trailing space.. */
935 if (*ptr == 0) break;
936
937 /* Skip this `word' */
938 while(*ptr && *ptr != ' ' && *ptr != '\t' && *ptr != '#')
939 ptr++;
940
941 /* If end-of-line, break */
942 if (*ptr == '#' || *ptr == 0) {
943 f++;
944 *ptr = 0;
945 break;
946 }
947 /* End word with \0 and continue */
948 *ptr++ = 0;
949 }
950 args[f] = NULL;
951 }
952 args[0] = args[1];
953 while(1) {
954 /*
955 * Block sigchild while forking.
956 */
957 sigemptyset(&nmask);
958 sigaddset(&nmask, SIGCHLD);
959 sigprocmask(SIG_BLOCK, &nmask, &omask);
960
961 if ((pid = fork()) == 0) {
962
963 close(0);
964 close(1);
965 close(2);
966 if (pipe_fd >= 0) close(pipe_fd);
967
968 sigprocmask(SIG_SETMASK, &omask, NULL);
969
90c78fcc
PR
970 /*
971 * Update utmp/wtmp file prior to starting
972 * any child. This MUST be done right here in
973 * the child process in order to prevent a race
974 * condition that occurs when the child
975 * process' time slice executes before the
976 * parent (can and does happen in a uniprocessor
977 * environment). If the child is a getty and
978 * the race condition happens, then init's utmp
979 * update will happen AFTER the getty runs
980 * and expects utmp to be updated already!
981 *
982 * Do NOT log if process field starts with '+'
983 * FIXME: that's for compatibility with *very*
984 * old getties - probably it can be taken out.
985 */
986 if (ch->action == RESPAWN && ch->process[0] != '+')
987 write_utmp_wtmp("", ch->id, getpid(), INIT_PROCESS, "");
988
a74aeac6
PR
989 /*
990 * In sysinit, boot, bootwait or single user mode:
991 * for any wait-type subprocess we _force_ the console
992 * to be its controlling tty.
993 */
994 if (strchr("*#sS", runlevel) && ch->flags & WAITING) {
995 /*
996 * We fork once extra. This is so that we can
997 * wait and change the process group and session
998 * of the console after exit of the leader.
999 */
1000 setsid();
1001 if ((f = console_open(O_RDWR|O_NOCTTY)) >= 0) {
1002 /* Take over controlling tty by force */
1003 (void)ioctl(f, TIOCSCTTY, 1);
1004 dup(f);
1005 dup(f);
1006 }
1007 SETSIG(sa, SIGCHLD, SIG_DFL, SA_RESTART);
1008 if ((pid = fork()) < 0) {
1009 initlog(L_VB, "cannot fork: %s",
1010 strerror(errno));
1011 exit(1);
1012 }
1013 if (pid > 0) {
1014 /*
1015 * Ignore keyboard signals etc.
1016 * Then wait for child to exit.
1017 */
1018 SETSIG(sa, SIGINT, SIG_IGN, SA_RESTART);
1019 SETSIG(sa, SIGTSTP, SIG_IGN, SA_RESTART);
1020 SETSIG(sa, SIGQUIT, SIG_IGN, SA_RESTART);
1021
1022 while ((rc = waitpid(pid, &st, 0)) != pid)
1023 if (rc < 0 && errno == ECHILD)
1024 break;
1025
1026 /*
1027 * Small optimization. See if stealing
1028 * controlling tty back is needed.
1029 */
1030 pgrp = tcgetpgrp(f);
1031 if (pgrp != getpid())
1032 exit(0);
1033
1034 /*
1035 * Steal controlling tty away. We do
1036 * this with a temporary process.
1037 */
1038 if ((pid = fork()) < 0) {
1039 initlog(L_VB, "cannot fork: %s",
1040 strerror(errno));
1041 exit(1);
1042 }
1043 if (pid == 0) {
1044 setsid();
1045 (void)ioctl(f, TIOCSCTTY, 1);
1046 exit(0);
1047 }
1048 while((rc = waitpid(pid, &st, 0)) != pid)
1049 if (rc < 0 && errno == ECHILD)
1050 break;
1051 exit(0);
1052 }
1053
1054 /* Set ioctl settings to default ones */
1055 console_stty();
1056
1057 } else {
1058 setsid();
1059 if ((f = console_open(O_RDWR|O_NOCTTY)) < 0) {
1060 initlog(L_VB, "open(%s): %s", console_dev,
1061 strerror(errno));
1062 f = open("/dev/null", O_RDWR);
1063 }
1064 dup(f);
1065 dup(f);
1066 }
1067
1068 /* Reset all the signals, set up environment */
1069 for(f = 1; f < NSIG; f++) SETSIG(sa, f, SIG_DFL, SA_RESTART);
1070 environ = init_buildenv(1);
1071
1072 /*
1073 * Execute prog. In case of ENOEXEC try again
1074 * as a shell script.
1075 */
1076 execvp(args[1], args + 1);
1077 if (errno == ENOEXEC) {
1078 args[1] = SHELL;
1079 args[2] = "-c";
1080 strcpy(buf, "exec ");
1081 strncat(buf, proc, sizeof(buf) - strlen(buf) - 1);
1082 args[3] = buf;
1083 args[4] = NULL;
1084 execvp(args[1], args + 1);
1085 }
1086 initlog(L_VB, "cannot execute \"%s\"", args[1]);
1087 exit(1);
1088 }
1089 *res = pid;
1090 sigprocmask(SIG_SETMASK, &omask, NULL);
1091
1092 INITDBG(L_VB, "Started id %s (pid %d)", ch->id, pid);
1093
1094 if (pid == -1) {
1095 initlog(L_VB, "cannot fork, retry..");
1096 do_sleep(5);
1097 continue;
1098 }
1099 return(pid);
1100 }
1101}
1102
1103/*
1104 * Start a child running!
1105 */
1106void startup(CHILD *ch)
1107{
1108 /*
1109 * See if it's disabled
1110 */
1111 if (ch->flags & FAILING) return;
1112
1113 switch(ch->action) {
1114
1115 case SYSINIT:
1116 case BOOTWAIT:
1117 case WAIT:
1118 case POWERWAIT:
1119 case POWERFAILNOW:
1120 case POWEROKWAIT:
1121 case CTRLALTDEL:
1122 if (!(ch->flags & XECUTED)) ch->flags |= WAITING;
1123 case KBREQUEST:
1124 case BOOT:
1125 case POWERFAIL:
1126 case ONCE:
1127 if (ch->flags & XECUTED) break;
1128 case ONDEMAND:
1129 case RESPAWN:
1130 ch->flags |= RUNNING;
90c78fcc 1131 (void)spawn(ch, &(ch->pid));
a74aeac6
PR
1132 break;
1133 }
1134}
1135
1136
1137/*
1138 * Read the inittab file.
1139 */
1140void read_inittab(void)
1141{
1142 FILE *fp; /* The INITTAB file */
1143 CHILD *ch, *old, *i; /* Pointers to CHILD structure */
1144 CHILD *head = NULL; /* Head of linked list */
1145#ifdef INITLVL
1146 struct stat st; /* To stat INITLVL */
1147#endif
1148 sigset_t nmask, omask; /* For blocking SIGCHLD. */
1149 char buf[256]; /* Line buffer */
1150 char err[64]; /* Error message. */
1151 char *id, *rlevel,
1152 *action, *process; /* Fields of a line */
1153 char *p;
1154 int lineNo = 0; /* Line number in INITTAB file */
1155 int actionNo; /* Decoded action field */
1156 int f; /* Counter */
1157 int round; /* round 0 for SIGTERM, 1 for SIGKILL */
1158 int foundOne = 0; /* No killing no sleep */
1159 int talk; /* Talk to the user */
1160 int done = 0; /* Ready yet? */
1161
1162#if DEBUG
1163 if (newFamily != NULL) {
1164 INITDBG(L_VB, "PANIC newFamily != NULL");
1165 exit(1);
1166 }
1167 INITDBG(L_VB, "Reading inittab");
1168#endif
1169
1170 /*
1171 * Open INITTAB and real line by line.
1172 */
1173 if ((fp = fopen(INITTAB, "r")) == NULL)
1174 initlog(L_VB, "No inittab file found");
1175
1176 while(!done) {
1177 /*
1178 * Add single user shell entry at the end.
1179 */
1180 if (fp == NULL || fgets(buf, sizeof(buf), fp) == NULL) {
1181 done = 1;
1182 /*
1183 * See if we have a single user entry.
1184 */
1185 for(old = newFamily; old; old = old->next)
1186 if (strpbrk(old->rlevel, "S")) break;
1187 if (old == NULL)
1188 snprintf(buf, sizeof(buf), "~~:S:wait:%s\n", SULOGIN);
1189 else
1190 continue;
1191 }
1192 lineNo++;
1193 /*
1194 * Skip comments and empty lines
1195 */
1196 for(p = buf; *p == ' ' || *p == '\t'; p++)
1197 ;
1198 if (*p == '#' || *p == '\n') continue;
1199
1200 /*
1201 * Decode the fields
1202 */
1203 id = strsep(&p, ":");
1204 rlevel = strsep(&p, ":");
1205 action = strsep(&p, ":");
1206 process = strsep(&p, "\n");
1207
1208 /*
1209 * Check if syntax is OK. Be very verbose here, to
1210 * avoid newbie postings on comp.os.linux.setup :)
1211 */
1212 err[0] = 0;
1213 if (!id || !*id) strcpy(err, "missing id field");
1214 if (!rlevel) strcpy(err, "missing runlevel field");
1215 if (!process) strcpy(err, "missing process field");
1216 if (!action || !*action)
1217 strcpy(err, "missing action field");
1218 if (id && strlen(id) > sizeof(utproto.ut_id))
1219 sprintf(err, "id field too long (max %d characters)",
1220 (int)sizeof(utproto.ut_id));
1221 if (rlevel && strlen(rlevel) > 11)
1222 strcpy(err, "rlevel field too long (max 11 characters)");
1223 if (process && strlen(process) > 127)
1224 strcpy(err, "process field too long");
1225 if (action && strlen(action) > 32)
1226 strcpy(err, "action field too long");
1227 if (err[0] != 0) {
1228 initlog(L_VB, "%s[%d]: %s", INITTAB, lineNo, err);
1229 INITDBG(L_VB, "%s:%s:%s:%s", id, rlevel, action, process);
1230 continue;
1231 }
1232
1233 /*
1234 * Decode the "action" field
1235 */
1236 actionNo = -1;
1237 for(f = 0; actions[f].name; f++)
1238 if (strcasecmp(action, actions[f].name) == 0) {
1239 actionNo = actions[f].act;
1240 break;
1241 }
1242 if (actionNo == -1) {
1243 initlog(L_VB, "%s[%d]: %s: unknown action field",
1244 INITTAB, lineNo, action);
1245 continue;
1246 }
1247
1248 /*
1249 * See if the id field is unique
1250 */
1251 for(old = newFamily; old; old = old->next) {
1252 if(strcmp(old->id, id) == 0 && strcmp(id, "~~")) {
1253 initlog(L_VB, "%s[%d]: duplicate ID field \"%s\"",
1254 INITTAB, lineNo, id);
1255 break;
1256 }
1257 }
1258 if (old) continue;
1259
1260 /*
1261 * Allocate a CHILD structure
1262 */
1263 ch = imalloc(sizeof(CHILD));
1264
1265 /*
1266 * And fill it in.
1267 */
1268 ch->action = actionNo;
1269 strncpy(ch->id, id, sizeof(utproto.ut_id) + 1); /* Hack for different libs. */
1270 strncpy(ch->process, process, sizeof(ch->process) - 1);
1271 if (rlevel[0]) {
192c4567 1272 for(f = 0; f < (int)sizeof(rlevel) - 1 && rlevel[f]; f++) {
a74aeac6
PR
1273 ch->rlevel[f] = rlevel[f];
1274 if (ch->rlevel[f] == 's') ch->rlevel[f] = 'S';
1275 }
1276 strncpy(ch->rlevel, rlevel, sizeof(ch->rlevel) - 1);
1277 } else {
1278 strcpy(ch->rlevel, "0123456789");
1279 if (ISPOWER(ch->action))
1280 strcpy(ch->rlevel, "S0123456789");
1281 }
1282 /*
1283 * We have the fake runlevel '#' for SYSINIT and
1284 * '*' for BOOT and BOOTWAIT.
1285 */
1286 if (ch->action == SYSINIT) strcpy(ch->rlevel, "#");
1287 if (ch->action == BOOT || ch->action == BOOTWAIT)
1288 strcpy(ch->rlevel, "*");
1289
1290 /*
1291 * Now add it to the linked list. Special for powerfail.
1292 */
1293 if (ISPOWER(ch->action)) {
1294
1295 /*
1296 * Disable by default
1297 */
1298 ch->flags |= XECUTED;
1299
1300 /*
1301 * Tricky: insert at the front of the list..
1302 */
1303 old = NULL;
1304 for(i = newFamily; i; i = i->next) {
1305 if (!ISPOWER(i->action)) break;
1306 old = i;
1307 }
1308 /*
1309 * Now add after entry "old"
1310 */
1311 if (old) {
1312 ch->next = i;
1313 old->next = ch;
1314 if (i == NULL) head = ch;
1315 } else {
1316 ch->next = newFamily;
1317 newFamily = ch;
1318 if (ch->next == NULL) head = ch;
1319 }
1320 } else {
1321 /*
1322 * Just add at end of the list
1323 */
1324 if (ch->action == KBREQUEST) ch->flags |= XECUTED;
1325 ch->next = NULL;
1326 if (head)
1327 head->next = ch;
1328 else
1329 newFamily = ch;
1330 head = ch;
1331 }
1332
1333 /*
1334 * Walk through the old list comparing id fields
1335 */
1336 for(old = family; old; old = old->next)
1337 if (strcmp(old->id, ch->id) == 0) {
1338 old->new = ch;
1339 break;
1340 }
1341 }
1342 /*
1343 * We're done.
1344 */
1345 if (fp) fclose(fp);
1346
1347 /*
1348 * Loop through the list of children, and see if they need to
1349 * be killed.
1350 */
1351
1352 INITDBG(L_VB, "Checking for children to kill");
1353 for(round = 0; round < 2; round++) {
1354 talk = 1;
1355 for(ch = family; ch; ch = ch->next) {
1356 ch->flags &= ~KILLME;
1357
1358 /*
1359 * Is this line deleted?
1360 */
1361 if (ch->new == NULL) ch->flags |= KILLME;
1362
1363 /*
1364 * If the entry has changed, kill it anyway. Note that
1365 * we do not check ch->process, only the "action" field.
1366 * This way, you can turn an entry "off" immediately, but
1367 * changes in the command line will only become effective
1368 * after the running version has exited.
1369 */
1370 if (ch->new && ch->action != ch->new->action) ch->flags |= KILLME;
1371
1372 /*
1373 * Only BOOT processes may live in all levels
1374 */
1375 if (ch->action != BOOT &&
1376 strchr(ch->rlevel, runlevel) == NULL) {
1377 /*
1378 * Ondemand procedures live always,
1379 * except in single user
1380 */
1381 if (runlevel == 'S' || !(ch->flags & DEMAND))
1382 ch->flags |= KILLME;
1383 }
1384
1385 /*
1386 * Now, if this process may live note so in the new list
1387 */
1388 if ((ch->flags & KILLME) == 0) {
1389 ch->new->flags = ch->flags;
1390 ch->new->pid = ch->pid;
1391 ch->new->exstat = ch->exstat;
1392 continue;
1393 }
1394
1395
1396 /*
1397 * Is this process still around?
1398 */
1399 if ((ch->flags & RUNNING) == 0) {
1400 ch->flags &= ~KILLME;
1401 continue;
1402 }
1403 INITDBG(L_VB, "Killing \"%s\"", ch->process);
1404 switch(round) {
1405 case 0: /* Send TERM signal */
1406 if (talk)
1407 initlog(L_CO,
1408 "Sending processes the TERM signal");
1409 kill(-(ch->pid), SIGTERM);
1410 foundOne = 1;
1411 break;
1412 case 1: /* Send KILL signal and collect status */
1413 if (talk)
1414 initlog(L_CO,
1415 "Sending processes the KILL signal");
1416 kill(-(ch->pid), SIGKILL);
1417 break;
1418 }
1419 talk = 0;
1420
1421 }
1422 /*
1423 * See if we have to wait 5 seconds
1424 */
1425 if (foundOne && round == 0) {
1426 /*
1427 * Yup, but check every second if we still have children.
1428 */
1429 for(f = 0; f < sltime; f++) {
1430 for(ch = family; ch; ch = ch->next) {
1431 if (!(ch->flags & KILLME)) continue;
1432 if ((ch->flags & RUNNING) && !(ch->flags & ZOMBIE))
1433 break;
1434 }
1435 if (ch == NULL) {
1436 /*
1437 * No running children, skip SIGKILL
1438 */
1439 round = 1;
1440 foundOne = 0; /* Skip the sleep below. */
1441 break;
1442 }
1443 do_sleep(1);
1444 }
1445 }
1446 }
1447
1448 /*
1449 * Now give all processes the chance to die and collect exit statuses.
1450 */
1451 if (foundOne) do_sleep(1);
1452 for(ch = family; ch; ch = ch->next)
1453 if (ch->flags & KILLME) {
1454 if (!(ch->flags & ZOMBIE))
1455 initlog(L_CO, "Pid %d [id %s] seems to hang", ch->pid,
1456 ch->id);
1457 else {
1458 INITDBG(L_VB, "Updating utmp for pid %d [id %s]",
1459 ch->pid, ch->id);
1460 ch->flags &= ~RUNNING;
1461 if (ch->process[0] != '+')
1462 write_utmp_wtmp("", ch->id, ch->pid, DEAD_PROCESS, NULL);
1463 }
1464 }
1465
1466 /*
1467 * Both rounds done; clean up the list.
1468 */
1469 sigemptyset(&nmask);
1470 sigaddset(&nmask, SIGCHLD);
1471 sigprocmask(SIG_BLOCK, &nmask, &omask);
1472 for(ch = family; ch; ch = old) {
1473 old = ch->next;
1474 free(ch);
1475 }
1476 family = newFamily;
1477 for(ch = family; ch; ch = ch->next) ch->new = NULL;
1478 newFamily = NULL;
1479 sigprocmask(SIG_SETMASK, &omask, NULL);
1480
1481#ifdef INITLVL
1482 /*
1483 * Dispose of INITLVL file.
1484 */
1485 if (lstat(INITLVL, &st) >= 0 && S_ISLNK(st.st_mode)) {
1486 /*
1487 * INITLVL is a symbolic link, so just truncate the file.
1488 */
1489 close(open(INITLVL, O_WRONLY|O_TRUNC));
1490 } else {
1491 /*
1492 * Delete INITLVL file.
1493 */
1494 unlink(INITLVL);
1495 }
1496#endif
1497#ifdef INITLVL2
1498 /*
1499 * Dispose of INITLVL2 file.
1500 */
1501 if (lstat(INITLVL2, &st) >= 0 && S_ISLNK(st.st_mode)) {
1502 /*
1503 * INITLVL2 is a symbolic link, so just truncate the file.
1504 */
1505 close(open(INITLVL2, O_WRONLY|O_TRUNC));
1506 } else {
1507 /*
1508 * Delete INITLVL2 file.
1509 */
1510 unlink(INITLVL2);
1511 }
1512#endif
1513}
1514
1515/*
1516 * Walk through the family list and start up children.
1517 * The entries that do not belong here at all are removed
1518 * from the list.
1519 */
1520void start_if_needed(void)
1521{
1522 CHILD *ch; /* Pointer to child */
1523 int delete; /* Delete this entry from list? */
1524
1525 INITDBG(L_VB, "Checking for children to start");
1526
1527 for(ch = family; ch; ch = ch->next) {
1528
1529#if DEBUG
1530 if (ch->rlevel[0] == 'C') {
1531 INITDBG(L_VB, "%s: flags %d", ch->process, ch->flags);
1532 }
1533#endif
1534
1535 /* Are we waiting for this process? Then quit here. */
1536 if (ch->flags & WAITING) break;
1537
1538 /* Already running? OK, don't touch it */
1539 if (ch->flags & RUNNING) continue;
1540
1541 /* See if we have to start it up */
1542 delete = 1;
1543 if (strchr(ch->rlevel, runlevel) ||
1544 ((ch->flags & DEMAND) && !strchr("#*Ss", runlevel))) {
1545 startup(ch);
1546 delete = 0;
1547 }
1548
1549 if (delete) {
1550 /* FIXME: is this OK? */
1551 ch->flags &= ~(RUNNING|WAITING);
1552 if (!ISPOWER(ch->action) && ch->action != KBREQUEST)
1553 ch->flags &= ~XECUTED;
1554 ch->pid = 0;
1555 } else
1556 /* Do we have to wait for this process? */
1557 if (ch->flags & WAITING) break;
1558 }
1559 /* Done. */
1560}
1561
1562/*
1563 * Ask the user on the console for a runlevel
1564 */
1565int ask_runlevel(void)
1566{
1567 const char prompt[] = "\nEnter runlevel: ";
1568 char buf[8];
1569 int lvl = -1;
1570 int fd;
1571
1572 console_stty();
1573 fd = console_open(O_RDWR|O_NOCTTY);
1574
1575 if (fd < 0) return('S');
1576
1577 while(!strchr("0123456789S", lvl)) {
1578 write(fd, prompt, sizeof(prompt) - 1);
1579 buf[0] = 0;
1580 read(fd, buf, sizeof(buf));
1581 if (buf[0] != 0 && (buf[1] == '\r' || buf[1] == '\n'))
1582 lvl = buf[0];
1583 if (islower(lvl)) lvl = toupper(lvl);
1584 }
1585 close(fd);
1586 return lvl;
1587}
1588
1589/*
1590 * Search the INITTAB file for the 'initdefault' field, with the default
1591 * runlevel. If this fails, ask the user to supply a runlevel.
1592 */
1593int get_init_default(void)
1594{
1595 CHILD *ch;
1596 int lvl = -1;
1597 char *p;
1598
1599 /*
1600 * Look for initdefault.
1601 */
1602 for(ch = family; ch; ch = ch->next)
1603 if (ch->action == INITDEFAULT) {
1604 p = ch->rlevel;
1605 while(*p) {
1606 if (*p > lvl) lvl = *p;
1607 p++;
1608 }
1609 break;
1610 }
1611 /*
1612 * See if level is valid
1613 */
1614 if (lvl > 0) {
1615 if (islower(lvl)) lvl = toupper(lvl);
1616 if (strchr("0123456789S", lvl) == NULL) {
1617 initlog(L_VB,
1618 "Initdefault level '%c' is invalid", lvl);
1619 lvl = 0;
1620 }
1621 }
1622 /*
1623 * Ask for runlevel on console if needed.
1624 */
1625 if (lvl <= 0) lvl = ask_runlevel();
1626
1627 /*
1628 * Log the fact that we have a runlevel now.
1629 */
1630 return lvl;
1631}
1632
1633
1634/*
1635 * We got signaled.
1636 *
1637 * Do actions for the new level. If we are compatible with
1638 * the "old" INITLVL and arg == 0, try to read the new
1639 * runlevel from that file first.
1640 */
1641int read_level(int arg)
1642{
1643 CHILD *ch; /* Walk through list */
1644 unsigned char foo = 'X'; /* Contents of INITLVL */
1645 int ok = 1;
1646#ifdef INITLVL
1647 FILE *fp;
1648 struct stat stt;
1649 int st;
1650#endif
1651
1652 if (arg) foo = arg;
1653
1654#ifdef INITLVL
1655 ok = 0;
1656
1657 if (arg == 0) {
1658 fp = NULL;
1659 if (stat(INITLVL, &stt) != 0 || stt.st_size != 0L)
1660 fp = fopen(INITLVL, "r");
1661#ifdef INITLVL2
1662 if (fp == NULL &&
1663 (stat(INITLVL2, &stt) != 0 || stt.st_size != 0L))
1664 fp = fopen(INITLVL2, "r");
1665#endif
1666 if (fp == NULL) {
1667 /* INITLVL file empty or not there - act as 'init q' */
1668 initlog(L_SY, "Re-reading inittab");
1669 return(runlevel);
1670 }
1671 ok = fscanf(fp, "%c %d", &foo, &st);
1672 fclose(fp);
1673 } else {
1674 /* We go to the new runlevel passed as an argument. */
1675 foo = arg;
1676 ok = 1;
1677 }
1678 if (ok == 2) sltime = st;
1679
1680#endif /* INITLVL */
1681
1682 if (islower(foo)) foo = toupper(foo);
1683 if (ok < 1 || ok > 2 || strchr("QS0123456789ABCU", foo) == NULL) {
1684 initlog(L_VB, "bad runlevel: %c", foo);
1685 return runlevel;
1686 }
1687
1688 /* Log this action */
1689 switch(foo) {
1690 case 'S':
1691 initlog(L_VB, "Going single user");
1692 break;
1693 case 'Q':
1694 initlog(L_SY, "Re-reading inittab");
1695 break;
1696 case 'A':
1697 case 'B':
1698 case 'C':
1699 initlog(L_SY,
1700 "Activating demand-procedures for '%c'", foo);
1701 break;
1702 case 'U':
1703 initlog(L_SY, "Trying to re-exec init");
1704 return 'U';
1705 default:
1706 initlog(L_VB, "Switching to runlevel: %c", foo);
1707 }
1708
1709 if (foo == 'Q') return runlevel;
1710
1711 /* Check if this is a runlevel a, b or c */
1712 if (strchr("ABC", foo)) {
1713 if (runlevel == 'S') return(runlevel);
1714
1715 /* Read inittab again first! */
1716 read_inittab();
1717
1718 /* Mark those special tasks */
1719 for(ch = family; ch; ch = ch->next)
1720 if (strchr(ch->rlevel, foo) != NULL ||
1721 strchr(ch->rlevel, tolower(foo)) != NULL) {
1722 ch->flags |= DEMAND;
1723 ch->flags &= ~XECUTED;
1724 INITDBG(L_VB,
1725 "Marking (%s) as ondemand, flags %d",
1726 ch->id, ch->flags);
1727 }
1728 return runlevel;
1729 }
1730
1731 /* Store both the old and the new runlevel. */
1732 write_utmp_wtmp("runlevel", "~~", foo + 256*runlevel, RUN_LVL, "~");
1733 thislevel = foo;
1734 prevlevel = runlevel;
1735 return foo;
1736}
1737
1738
1739/*
1740 * This procedure is called after every signal (SIGHUP, SIGALRM..)
1741 *
1742 * Only clear the 'failing' flag if the process is sleeping
1743 * longer than 5 minutes, or inittab was read again due
1744 * to user interaction.
1745 */
1746void fail_check(void)
1747{
1748 CHILD *ch; /* Pointer to child structure */
1749 time_t t; /* System time */
1750 time_t next_alarm = 0; /* When to set next alarm */
1751
1752 time(&t);
1753
1754 for(ch = family; ch; ch = ch->next) {
1755
1756 if (ch->flags & FAILING) {
1757 /* Can we free this sucker? */
1758 if (ch->tm + SLEEPTIME < t) {
1759 ch->flags &= ~FAILING;
1760 ch->count = 0;
1761 ch->tm = 0;
1762 } else {
1763 /* No, we'll look again later */
1764 if (next_alarm == 0 ||
1765 ch->tm + SLEEPTIME > next_alarm)
1766 next_alarm = ch->tm + SLEEPTIME;
1767 }
1768 }
1769 }
1770 if (next_alarm) {
1771 next_alarm -= t;
1772 if (next_alarm < 1) next_alarm = 1;
1773 alarm(next_alarm);
1774 }
1775}
1776
1777/* Set all 'Fail' timers to 0 */
1778void fail_cancel(void)
1779{
1780 CHILD *ch;
1781
1782 for(ch = family; ch; ch = ch->next) {
1783 ch->count = 0;
1784 ch->tm = 0;
1785 ch->flags &= ~FAILING;
1786 }
1787}
1788
1789/*
1790 * Start up powerfail entries.
1791 */
1792void do_power_fail(int pwrstat)
1793{
1794 CHILD *ch;
1795
1796 /*
1797 * Tell powerwait & powerfail entries to start up
1798 */
1799 for (ch = family; ch; ch = ch->next) {
1800 if (pwrstat == 'O') {
1801 /*
1802 * The power is OK again.
1803 */
1804 if (ch->action == POWEROKWAIT)
1805 ch->flags &= ~XECUTED;
1806 } else if (pwrstat == 'L') {
1807 /*
1808 * Low battery, shut down now.
1809 */
1810 if (ch->action == POWERFAILNOW)
1811 ch->flags &= ~XECUTED;
1812 } else {
1813 /*
1814 * Power is failing, shutdown imminent
1815 */
1816 if (ch->action == POWERFAIL || ch->action == POWERWAIT)
1817 ch->flags &= ~XECUTED;
1818 }
1819 }
1820}
1821
1822/*
1823 * Check for state-pipe presence
1824 */
1825int check_pipe(int fd)
1826{
1827 struct timeval t;
1828 fd_set s;
1829 char signature[8];
1830
1831 FD_ZERO(&s);
1832 FD_SET(fd, &s);
1833 t.tv_sec = t.tv_usec = 0;
1834
1835 if (select(fd+1, &s, NULL, NULL, &t) != 1)
1836 return 0;
1837 if (read(fd, signature, 8) != 8)
1838 return 0;
1839 return strncmp(Signature, signature, 8) == 0;
1840}
1841
1842/*
1843 * Make a state-pipe.
1844 */
1845int make_pipe(int fd)
1846{
1847 int fds[2];
1848
1849 pipe(fds);
1850 dup2(fds[0], fd);
1851 close(fds[0]);
1852 fcntl(fds[1], F_SETFD, 1);
1853 fcntl(fd, F_SETFD, 0);
1854 write(fds[1], Signature, 8);
1855
1856 return fds[1];
1857}
1858
1859/*
1860 * Attempt to re-exec.
1861 */
1862void re_exec(void)
1863{
1864 CHILD *ch;
1865 sigset_t mask, oldset;
1866 pid_t pid;
1867 char **env;
1868 int fd;
1869
1870 if (strchr("S0123456",runlevel) == NULL)
1871 return;
1872
1873 /*
1874 * Reset the alarm, and block all signals.
1875 */
1876 alarm(0);
1877 sigfillset(&mask);
1878 sigprocmask(SIG_BLOCK, &mask, &oldset);
1879
1880 /*
1881 * construct a pipe fd --> STATE_PIPE and write a signature
1882 */
1883 fd = make_pipe(STATE_PIPE);
1884
1885 /*
1886 * It's a backup day today, so I'm pissed off. Being a BOFH, however,
1887 * does have it's advantages...
1888 */
1889 fail_cancel();
1890 close(pipe_fd);
1891 pipe_fd = -1;
1892 DELSET(got_signals, SIGCHLD);
1893 DELSET(got_signals, SIGHUP);
1894 DELSET(got_signals, SIGUSR1);
1895
1896 /*
1897 * That should be cleaned.
1898 */
1899 for(ch = family; ch; ch = ch->next)
1900 if (ch->flags & ZOMBIE) {
1901 INITDBG(L_VB, "Child died, PID= %d", ch->pid);
1902 ch->flags &= ~(RUNNING|ZOMBIE|WAITING);
1903 if (ch->process[0] != '+')
1904 write_utmp_wtmp("", ch->id, ch->pid, DEAD_PROCESS, NULL);
1905 }
1906
1907 if ((pid = fork()) == 0) {
1908 /*
1909 * Child sends state information to the parent.
1910 */
1911 send_state(fd);
1912 exit(0);
1913 }
1914
1915 /*
1916 * The existing init process execs a new init binary.
1917 */
1918 env = init_buildenv(0);
1919 execle(myname, myname, "--init", NULL, env);
1920
1921 /*
1922 * We shouldn't be here, something failed.
1923 * Bitch, close the state pipe, unblock signals and return.
1924 */
1925 close(fd);
1926 close(STATE_PIPE);
1927 sigprocmask(SIG_SETMASK, &oldset, NULL);
1928 init_freeenv(env);
1929 initlog(L_CO, "Attempt to re-exec failed");
1930}
1931
1932
1933/*
1934 * We got a change runlevel request through the
1935 * init.fifo. Process it.
1936 */
1937void fifo_new_level(int level)
1938{
1939#if CHANGE_WAIT
1940 CHILD *ch;
1941#endif
1942 int oldlevel;
1943
1944 if (level == runlevel) return;
1945
1946#if CHANGE_WAIT
1947 /* Are we waiting for a child? */
1948 for(ch = family; ch; ch = ch->next)
1949 if (ch->flags & WAITING) break;
1950 if (ch == NULL)
1951#endif
1952 {
1953 /* We need to go into a new runlevel */
1954 oldlevel = runlevel;
1955 runlevel = read_level(level);
1956 if (runlevel == 'U') {
1957 runlevel = oldlevel;
1958 re_exec();
1959 } else {
1960 if (oldlevel != 'S' && runlevel == 'S') console_stty();
1961 if (runlevel == '6' || runlevel == '0' ||
1962 runlevel == '1') console_stty();
1963 read_inittab();
1964 fail_cancel();
1965 setproctitle("init [%c]", runlevel);
1966 }
1967 }
1968}
1969
1970
1971/*
1972 * Set/unset environment variables. The variables are
1973 * encoded as KEY=VAL\0KEY=VAL\0\0. With "=VAL" it means
1974 * setenv, without it means unsetenv.
1975 */
1976void initcmd_setenv(char *data, int size)
1977{
1978 char *env, *p, *e, *eq;
1979 int i, sz;
1980
1981 e = data + size;
1982
1983 while (*data && data < e) {
1984 eq = NULL;
1985 for (p = data; *p && p < e; p++)
1986 if (*p == '=') eq = p;
1987 if (*p) break;
1988 env = data;
1989 data = ++p;
1990
1991 sz = eq ? (eq - env) : (p - env);
1992
1993 /*initlog(L_SY, "init_setenv: %s, %s, %d", env, eq, sz);*/
1994
1995 /*
1996 * We only allow INIT_* to be set.
1997 */
1998 if (strncmp(env, "INIT_", 5) != 0)
1999 continue;
2000
2001 /* Free existing vars. */
2002 for (i = 0; i < NR_EXTRA_ENV; i++) {
2003 if (extra_env[i] == NULL) continue;
2004 if (!strncmp(extra_env[i], env, sz) &&
2005 extra_env[i][sz] == '=') {
2006 free(extra_env[i]);
2007 extra_env[i] = NULL;
2008 }
2009 }
2010
2011 /* Set new vars if needed. */
2012 if (eq == NULL) continue;
2013 for (i = 0; i < NR_EXTRA_ENV; i++) {
2014 if (extra_env[i] == NULL) {
2015 extra_env[i] = istrdup(env);
2016 break;
2017 }
2018 }
2019 }
2020}
2021
2022
2023/*
2024 * Read from the init FIFO. Processes like telnetd and rlogind can
2025 * ask us to create login processes on their behalf.
2026 *
2027 * FIXME: this needs to be finished. NOT that it is buggy, but we need
2028 * to add the telnetd/rlogind stuff so people can start using it.
2029 * Maybe move to using an AF_UNIX socket so we can use
2030 * the 2.2 kernel credential stuff to see who we're talking to.
2031 *
2032 */
2033void check_init_fifo(void)
2034{
2035 struct init_request request;
2036 struct timeval tv;
2037 struct stat st, st2;
2038 fd_set fds;
2039 int n;
2040 int quit = 0;
2041
2042 /*
2043 * First, try to create /dev/initctl if not present.
2044 */
2045 if (stat(INIT_FIFO, &st2) < 0 && errno == ENOENT)
2046 (void)mkfifo(INIT_FIFO, 0600);
2047
2048 /*
2049 * If /dev/initctl is open, stat the file to see if it
2050 * is still the _same_ inode.
2051 */
2052 if (pipe_fd >= 0) {
2053 fstat(pipe_fd, &st);
2054 if (stat(INIT_FIFO, &st2) < 0 ||
2055 st.st_dev != st2.st_dev ||
2056 st.st_ino != st2.st_ino) {
2057 close(pipe_fd);
2058 pipe_fd = -1;
2059 }
2060 }
2061
2062 /*
2063 * Now finally try to open /dev/initctl
2064 */
2065 if (pipe_fd < 0) {
2066 if ((pipe_fd = open(INIT_FIFO, O_RDWR|O_NONBLOCK)) >= 0) {
2067 fstat(pipe_fd, &st);
2068 if (!S_ISFIFO(st.st_mode)) {
2069 initlog(L_VB, "%s is not a fifo", INIT_FIFO);
2070 close(pipe_fd);
2071 pipe_fd = -1;
2072 }
2073 }
2074 if (pipe_fd >= 0) {
2075 /*
2076 * Don't use fd's 0, 1 or 2.
2077 */
2078 (void) dup2(pipe_fd, PIPE_FD);
2079 close(pipe_fd);
2080 pipe_fd = PIPE_FD;
2081
2082 /*
2083 * Return to caller - we'll be back later.
2084 */
2085 }
2086 }
2087
2088 /* Wait for data to appear, _if_ the pipe was opened. */
2089 if (pipe_fd >= 0) while(!quit) {
2090
2091 /* Do select, return on EINTR. */
2092 FD_ZERO(&fds);
2093 FD_SET(pipe_fd, &fds);
2094 tv.tv_sec = 5;
2095 tv.tv_usec = 0;
2096 n = select(pipe_fd + 1, &fds, NULL, NULL, &tv);
2097 if (n <= 0) {
2098 if (n == 0 || errno == EINTR) return;
2099 continue;
2100 }
2101
2102 /* Read the data, return on EINTR. */
2103 n = read(pipe_fd, &request, sizeof(request));
2104 if (n == 0) {
2105 /*
2106 * End of file. This can't happen under Linux (because
2107 * the pipe is opened O_RDWR - see select() in the
2108 * kernel) but you never know...
2109 */
2110 close(pipe_fd);
2111 pipe_fd = -1;
2112 return;
2113 }
2114 if (n <= 0) {
2115 if (errno == EINTR) return;
2116 initlog(L_VB, "error reading initrequest");
2117 continue;
2118 }
2119
2120 /*
2121 * This is a convenient point to also try to
2122 * find the console device or check if it changed.
2123 */
2124 console_init();
2125
2126 /*
2127 * Process request.
2128 */
2129 if (request.magic != INIT_MAGIC || n != sizeof(request)) {
2130 initlog(L_VB, "got bogus initrequest");
2131 continue;
2132 }
2133 switch(request.cmd) {
2134 case INIT_CMD_RUNLVL:
2135 sltime = request.sleeptime;
2136 fifo_new_level(request.runlevel);
2137 quit = 1;
2138 break;
2139 case INIT_CMD_POWERFAIL:
2140 sltime = request.sleeptime;
2141 do_power_fail('F');
2142 quit = 1;
2143 break;
2144 case INIT_CMD_POWERFAILNOW:
2145 sltime = request.sleeptime;
2146 do_power_fail('L');
2147 quit = 1;
2148 break;
2149 case INIT_CMD_POWEROK:
2150 sltime = request.sleeptime;
2151 do_power_fail('O');
2152 quit = 1;
2153 break;
2154 case INIT_CMD_SETENV:
2155 initcmd_setenv(request.i.data, sizeof(request.i.data));
2156 break;
a74aeac6
PR
2157 default:
2158 initlog(L_VB, "got unimplemented initrequest.");
2159 break;
2160 }
2161 }
2162
2163 /*
2164 * We come here if the pipe couldn't be opened.
2165 */
2166 if (pipe_fd < 0) pause();
2167
2168}
2169
2170
2171/*
2172 * This function is used in the transition
2173 * sysinit (-> single user) boot -> multi-user.
2174 */
2175void boot_transitions()
2176{
2177 CHILD *ch;
2178 static int newlevel = 0;
2179 static int warn = 1;
2180 int loglevel;
2181 int oldlevel;
2182
2183 /* Check if there is something to wait for! */
2184 for( ch = family; ch; ch = ch->next )
2185 if ((ch->flags & RUNNING) && ch->action != BOOT) break;
2186
2187 if (ch == NULL) {
2188 /* No processes left in this level, proceed to next level. */
2189 loglevel = -1;
2190 oldlevel = 'N';
2191 switch(runlevel) {
2192 case '#': /* SYSINIT -> BOOT */
2193 INITDBG(L_VB, "SYSINIT -> BOOT");
2194
2195 /* Write a boot record. */
2196 wrote_utmp_reboot = 0;
2197 wrote_wtmp_reboot = 0;
2198 write_utmp_wtmp("reboot", "~~", 0, BOOT_TIME, "~");
2199
2200 /* Get our run level */
2201 newlevel = dfl_level ? dfl_level : get_init_default();
2202 if (newlevel == 'S') {
2203 runlevel = newlevel;
2204 /* Not really 'S' but show anyway. */
2205 setproctitle("init [S]");
2206 } else
2207 runlevel = '*';
2208 break;
2209 case '*': /* BOOT -> NORMAL */
2210 INITDBG(L_VB, "BOOT -> NORMAL");
2211 if (runlevel != newlevel)
2212 loglevel = newlevel;
2213 runlevel = newlevel;
2214 did_boot = 1;
2215 warn = 1;
2216 break;
2217 case 'S': /* Ended SU mode */
2218 case 's':
2219 INITDBG(L_VB, "END SU MODE");
2220 newlevel = get_init_default();
2221 if (!did_boot && newlevel != 'S')
2222 runlevel = '*';
2223 else {
2224 if (runlevel != newlevel)
2225 loglevel = newlevel;
2226 runlevel = newlevel;
2227 oldlevel = 'S';
2228 }
2229 warn = 1;
2230 for(ch = family; ch; ch = ch->next)
2231 if (strcmp(ch->rlevel, "S") == 0)
2232 ch->flags &= ~(FAILING|WAITING|XECUTED);
2233 break;
2234 default:
2235 if (warn)
2236 initlog(L_VB,
2237 "no more processes left in this runlevel");
2238 warn = 0;
2239 loglevel = -1;
2240 if (got_signals == 0)
2241 check_init_fifo();
2242 break;
2243 }
2244 if (loglevel > 0) {
2245 initlog(L_VB, "Entering runlevel: %c", runlevel);
2246 write_utmp_wtmp("runlevel", "~~", runlevel + 256 * oldlevel, RUN_LVL, "~");
2247 thislevel = runlevel;
2248 prevlevel = oldlevel;
2249 setproctitle("init [%c]", runlevel);
2250 }
2251 }
2252}
2253
2254/*
2255 * Init got hit by a signal. See which signal it is,
2256 * and act accordingly.
2257 */
2258void process_signals()
2259{
2260 CHILD *ch;
2261 int pwrstat;
2262 int oldlevel;
2263 int fd;
2264 char c;
2265
2266 if (ISMEMBER(got_signals, SIGPWR)) {
2267 INITDBG(L_VB, "got SIGPWR");
2268 /* See _what_ kind of SIGPWR this is. */
2269 pwrstat = 0;
2270 if ((fd = open(PWRSTAT, O_RDONLY)) >= 0) {
2271 c = 0;
2272 read(fd, &c, 1);
2273 pwrstat = c;
2274 close(fd);
2275 unlink(PWRSTAT);
2276 }
2277 do_power_fail(pwrstat);
2278 DELSET(got_signals, SIGPWR);
2279 }
2280
2281 if (ISMEMBER(got_signals, SIGINT)) {
2282 INITDBG(L_VB, "got SIGINT");
2283 /* Tell ctrlaltdel entry to start up */
2284 for(ch = family; ch; ch = ch->next)
2285 if (ch->action == CTRLALTDEL)
2286 ch->flags &= ~XECUTED;
2287 DELSET(got_signals, SIGINT);
2288 }
2289
2290 if (ISMEMBER(got_signals, SIGWINCH)) {
2291 INITDBG(L_VB, "got SIGWINCH");
2292 /* Tell kbrequest entry to start up */
2293 for(ch = family; ch; ch = ch->next)
2294 if (ch->action == KBREQUEST)
2295 ch->flags &= ~XECUTED;
2296 DELSET(got_signals, SIGWINCH);
2297 }
2298
2299 if (ISMEMBER(got_signals, SIGALRM)) {
2300 INITDBG(L_VB, "got SIGALRM");
2301 /* The timer went off: check it out */
2302 DELSET(got_signals, SIGALRM);
2303 }
2304
2305 if (ISMEMBER(got_signals, SIGCHLD)) {
2306 INITDBG(L_VB, "got SIGCHLD");
2307 /* First set flag to 0 */
2308 DELSET(got_signals, SIGCHLD);
2309
2310 /* See which child this was */
2311 for(ch = family; ch; ch = ch->next)
2312 if (ch->flags & ZOMBIE) {
2313 INITDBG(L_VB, "Child died, PID= %d", ch->pid);
2314 ch->flags &= ~(RUNNING|ZOMBIE|WAITING);
2315 if (ch->process[0] != '+')
2316 write_utmp_wtmp("", ch->id, ch->pid, DEAD_PROCESS, NULL);
2317 }
2318
2319 }
2320
2321 if (ISMEMBER(got_signals, SIGHUP)) {
2322 INITDBG(L_VB, "got SIGHUP");
2323#if CHANGE_WAIT
2324 /* Are we waiting for a child? */
2325 for(ch = family; ch; ch = ch->next)
2326 if (ch->flags & WAITING) break;
2327 if (ch == NULL)
2328#endif
2329 {
2330 /* We need to go into a new runlevel */
2331 oldlevel = runlevel;
2332#ifdef INITLVL
2333 runlevel = read_level(0);
2334#endif
2335 if (runlevel == 'U') {
2336 runlevel = oldlevel;
2337 re_exec();
2338 } else {
2339 if (oldlevel != 'S' && runlevel == 'S') console_stty();
2340 if (runlevel == '6' || runlevel == '0' ||
2341 runlevel == '1') console_stty();
2342 read_inittab();
2343 fail_cancel();
2344 setproctitle("init [%c]", runlevel);
2345 DELSET(got_signals, SIGHUP);
2346 }
2347 }
2348 }
2349 if (ISMEMBER(got_signals, SIGUSR1)) {
2350 /*
2351 * SIGUSR1 means close and reopen /dev/initctl
2352 */
2353 INITDBG(L_VB, "got SIGUSR1");
2354 close(pipe_fd);
2355 pipe_fd = -1;
2356 DELSET(got_signals, SIGUSR1);
2357 }
2358}
2359
2360/*
2361 * The main loop
2362 */
2363int init_main()
2364{
2365 CHILD *ch;
2366 struct sigaction sa;
2367 sigset_t sgt;
2368 pid_t rc;
2369 int f, st;
2370
2371 if (!reload) {
2372
2373#if INITDEBUG
2374 /*
2375 * Fork so we can debug the init process.
2376 */
2377 if ((f = fork()) > 0) {
2378 static const char killmsg[] = "PRNT: init killed.\r\n";
2379 pid_t rc;
2380
2381 while((rc = wait(&st)) != f)
2382 if (rc < 0 && errno == ECHILD)
2383 break;
2384 write(1, killmsg, sizeof(killmsg) - 1);
2385 while(1) pause();
2386 }
2387#endif
2388
2389#ifdef __linux__
2390 /*
2391 * Tell the kernel to send us SIGINT when CTRL-ALT-DEL
2392 * is pressed, and that we want to handle keyboard signals.
2393 */
2394 init_reboot(BMAGIC_SOFT);
2395 if ((f = open(VT_MASTER, O_RDWR | O_NOCTTY)) >= 0) {
2396 (void) ioctl(f, KDSIGACCEPT, SIGWINCH);
2397 close(f);
2398 } else
2399 (void) ioctl(0, KDSIGACCEPT, SIGWINCH);
2400#endif
2401
2402 /*
2403 * Ignore all signals.
2404 */
2405 for(f = 1; f <= NSIG; f++)
2406 SETSIG(sa, f, SIG_IGN, SA_RESTART);
2407 }
2408
2409 SETSIG(sa, SIGALRM, signal_handler, 0);
2410 SETSIG(sa, SIGHUP, signal_handler, 0);
2411 SETSIG(sa, SIGINT, signal_handler, 0);
2412 SETSIG(sa, SIGCHLD, chld_handler, SA_RESTART);
2413 SETSIG(sa, SIGPWR, signal_handler, 0);
2414 SETSIG(sa, SIGWINCH, signal_handler, 0);
2415 SETSIG(sa, SIGUSR1, signal_handler, 0);
2416 SETSIG(sa, SIGSTOP, stop_handler, SA_RESTART);
2417 SETSIG(sa, SIGTSTP, stop_handler, SA_RESTART);
2418 SETSIG(sa, SIGCONT, cont_handler, SA_RESTART);
2419 SETSIG(sa, SIGSEGV, (void (*)(int))segv_handler, SA_RESTART);
2420
2421 console_init();
2422
2423 if (!reload) {
2424
2425 /* Close whatever files are open, and reset the console. */
2426 close(0);
2427 close(1);
2428 close(2);
2429 console_stty();
2430 setsid();
2431
2432 /*
2433 * Set default PATH variable.
2434 */
2435 setenv("PATH", PATH_DEFAULT, 1 /* Overwrite */);
2436
2437 /*
2438 * Initialize /var/run/utmp (only works if /var is on
2439 * root and mounted rw)
2440 */
2441 (void) close(open(UTMP_FILE, O_WRONLY|O_CREAT|O_TRUNC, 0644));
2442
2443 /*
2444 * Say hello to the world
2445 */
2446 initlog(L_CO, bootmsg, "booting");
2447
2448 /*
2449 * See if we have to start an emergency shell.
2450 */
2451 if (emerg_shell) {
2452 SETSIG(sa, SIGCHLD, SIG_DFL, SA_RESTART);
2453 if (spawn(&ch_emerg, &f) > 0) {
2454 while((rc = wait(&st)) != f)
2455 if (rc < 0 && errno == ECHILD)
2456 break;
2457 }
2458 SETSIG(sa, SIGCHLD, chld_handler, SA_RESTART);
2459 }
2460
2461 /*
2462 * Start normal boot procedure.
2463 */
2464 runlevel = '#';
2465 read_inittab();
2466
2467 } else {
2468 /*
2469 * Restart: unblock signals and let the show go on
2470 */
2471 initlog(L_CO, bootmsg, "reloading");
2472 sigfillset(&sgt);
2473 sigprocmask(SIG_UNBLOCK, &sgt, NULL);
2474
2475 /*
2476 * Set default PATH variable.
2477 */
2478 setenv("PATH", PATH_DEFAULT, 0 /* Don't overwrite */);
2479 }
2480 start_if_needed();
2481
2482 while(1) {
2483
2484 /* See if we need to make the boot transitions. */
2485 boot_transitions();
2486 INITDBG(L_VB, "init_main: waiting..");
2487
2488 /* Check if there are processes to be waited on. */
2489 for(ch = family; ch; ch = ch->next)
2490 if ((ch->flags & RUNNING) && ch->action != BOOT) break;
2491
2492#if CHANGE_WAIT
2493 /* Wait until we get hit by some signal. */
2494 while (ch != NULL && got_signals == 0) {
2495 if (ISMEMBER(got_signals, SIGHUP)) {
2496 /* See if there are processes to be waited on. */
2497 for(ch = family; ch; ch = ch->next)
2498 if (ch->flags & WAITING) break;
2499 }
2500 if (ch != NULL) check_init_fifo();
2501 }
2502#else /* CHANGE_WAIT */
2503 if (ch != NULL && got_signals == 0) check_init_fifo();
2504#endif /* CHANGE_WAIT */
2505
2506 /* Check the 'failing' flags */
2507 fail_check();
2508
2509 /* Process any signals. */
2510 process_signals();
2511
2512 /* See what we need to start up (again) */
2513 start_if_needed();
2514 }
2515 /*NOTREACHED*/
2516}
2517
2518/*
2519 * Tell the user about the syntax we expect.
2520 */
2521void usage(char *s)
2522{
2523 fprintf(stderr, "Usage: %s {-e VAR[=VAL] | [-t SECONDS] {0|1|2|3|4|5|6|S|s|Q|q|A|a|B|b|C|c|U|u}}\n", s);
2524 exit(1);
2525}
2526
2527int telinit(char *progname, int argc, char **argv)
2528{
2529#ifdef TELINIT_USES_INITLVL
2530 FILE *fp;
2531#endif
2532 struct init_request request;
2533 struct sigaction sa;
2534 int f, fd, l;
2535 char *env = NULL;
2536
2537 memset(&request, 0, sizeof(request));
2538 request.magic = INIT_MAGIC;
2539
2540 while ((f = getopt(argc, argv, "t:e:")) != EOF) switch(f) {
2541 case 't':
2542 sltime = atoi(optarg);
2543 break;
2544 case 'e':
2545 if (env == NULL)
2546 env = request.i.data;
2547 l = strlen(optarg);
2548 if (env + l + 2 > request.i.data + sizeof(request.i.data)) {
2549 fprintf(stderr, "%s: -e option data "
2550 "too large\n", progname);
2551 exit(1);
2552 }
2553 memcpy(env, optarg, l);
2554 env += l;
2555 *env++ = 0;
2556 break;
2557 default:
2558 usage(progname);
2559 break;
2560 }
2561
2562 if (env) *env++ = 0;
2563
2564 if (env) {
2565 if (argc != optind)
2566 usage(progname);
2567 request.cmd = INIT_CMD_SETENV;
2568 } else {
2569 if (argc - optind != 1 || strlen(argv[optind]) != 1)
2570 usage(progname);
2571 if (!strchr("0123456789SsQqAaBbCcUu", argv[optind][0]))
2572 usage(progname);
2573 request.cmd = INIT_CMD_RUNLVL;
2574 request.runlevel = env ? 0 : argv[optind][0];
2575 request.sleeptime = sltime;
2576 }
2577
2578 /* Open the fifo and write a command. */
2579 /* Make sure we don't hang on opening /dev/initctl */
2580 SETSIG(sa, SIGALRM, signal_handler, 0);
2581 alarm(3);
2582 if ((fd = open(INIT_FIFO, O_WRONLY)) >= 0 &&
2583 write(fd, &request, sizeof(request)) == sizeof(request)) {
2584 close(fd);
2585 alarm(0);
2586 return 0;
2587 }
2588
2589#ifdef TELINIT_USES_INITLVL
2590 if (request.cmd == INIT_CMD_RUNLVL) {
2591 /* Fallthrough to the old method. */
2592
2593 /* Now write the new runlevel. */
2594 if ((fp = fopen(INITLVL, "w")) == NULL) {
2595 fprintf(stderr, "%s: cannot create %s\n",
2596 progname, INITLVL);
2597 exit(1);
2598 }
2599 fprintf(fp, "%s %d", argv[optind], sltime);
2600 fclose(fp);
2601
2602 /* And tell init about the pending runlevel change. */
2603 if (kill(INITPID, SIGHUP) < 0) perror(progname);
2604
2605 return 0;
2606 }
2607#endif
2608
2609 fprintf(stderr, "%s: ", progname);
2610 if (ISMEMBER(got_signals, SIGALRM)) {
2611 fprintf(stderr, "timeout opening/writing control channel %s\n",
2612 INIT_FIFO);
2613 } else {
2614 perror(INIT_FIFO);
2615 }
2616 return 1;
2617}
2618
2619/*
2620 * Main entry for init and telinit.
2621 */
2622int main(int argc, char **argv)
2623{
2624 char *p;
2625 int f;
2626 int isinit;
e481cba6 2627#ifdef WITH_SELINUX
a74aeac6 2628 int enforce = 0;
e481cba6 2629#endif
a74aeac6
PR
2630
2631 /* Get my own name */
2632 if ((p = strrchr(argv[0], '/')) != NULL)
2633 p++;
2634 else
2635 p = argv[0];
2636 umask(022);
2637
2638 /* Quick check */
2639 if (geteuid() != 0) {
2640 fprintf(stderr, "%s: must be superuser.\n", p);
2641 exit(1);
2642 }
2643
2644 /*
2645 * Is this telinit or init ?
2646 */
2647 isinit = (getpid() == 1);
2648 for (f = 1; f < argc; f++) {
54cb4b75 2649 if (!strcmp(argv[f], "-i") || !strcmp(argv[f], "--init")) {
a74aeac6
PR
2650 isinit = 1;
2651 break;
54cb4b75 2652 }
a74aeac6
PR
2653 }
2654 if (!isinit) exit(telinit(p, argc, argv));
2655
2656 /*
2657 * Check for re-exec
2658 */
2659 if (check_pipe(STATE_PIPE)) {
2660
2661 receive_state(STATE_PIPE);
2662
2663 myname = istrdup(argv[0]);
2664 argv0 = argv[0];
2665 maxproclen = 0;
2666 for (f = 0; f < argc; f++)
2667 maxproclen += strlen(argv[f]) + 1;
2668 reload = 1;
2669 setproctitle("init [%c]",runlevel);
2670
2671 init_main();
2672 }
2673
2674 /* Check command line arguments */
2675 maxproclen = strlen(argv[0]) + 1;
2676 for(f = 1; f < argc; f++) {
2677 if (!strcmp(argv[f], "single") || !strcmp(argv[f], "-s"))
2678 dfl_level = 'S';
2679 else if (!strcmp(argv[f], "-a") || !strcmp(argv[f], "auto"))
2680 putenv("AUTOBOOT=YES");
2681 else if (!strcmp(argv[f], "-b") || !strcmp(argv[f],"emergency"))
2682 emerg_shell = 1;
2683 else if (!strcmp(argv[f], "-z")) {
2684 /* Ignore -z xxx */
2685 if (argv[f + 1]) f++;
2686 } else if (strchr("0123456789sS", argv[f][0])
2687 && strlen(argv[f]) == 1)
2688 dfl_level = argv[f][0];
2689 /* "init u" in the very beginning makes no sense */
2690 if (dfl_level == 's') dfl_level = 'S';
2691 maxproclen += strlen(argv[f]) + 1;
2692 }
2693
2694#ifdef WITH_SELINUX
2695 if (getenv("SELINUX_INIT") == NULL && !is_selinux_enabled()) {
2696 putenv("SELINUX_INIT=YES");
2697 if (selinux_init_load_policy(&enforce) == 0 ) {
2698 execv(myname, argv);
2699 } else {
2700 if (enforce > 0) {
2701 /* SELinux in enforcing mode but load_policy failed */
2702 /* At this point, we probably can't open /dev/console, so log() won't work */
2703 fprintf(stderr,"Unable to load SELinux Policy. Machine is in enforcing mode. Halting now.\n");
2704 exit(1);
2705 }
2706 }
2707 }
2708#endif
2709 /* Start booting. */
2710 argv0 = argv[0];
2711 argv[1] = NULL;
2712 setproctitle("init boot");
2713 init_main(dfl_level);
2714
2715 /*NOTREACHED*/
2716 return 0;
2717}