add -fvisibility=hidden to CC flags, mark XXX_main functions
[oweals/busybox.git] / init / init.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * Mini init implementation for busybox
4  *
5  * Copyright (C) 1995, 1996 by Bruce Perens <bruce@pixar.com>.
6  * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
7  * Adjusted by so many folks, it's impossible to keep track.
8  *
9  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
10  */
11
12 #include "libbb.h"
13 #include <paths.h>
14 //#include <signal.h>
15 //#include <sys/ioctl.h>
16 //#include <sys/wait.h>
17 #include <sys/reboot.h>
18
19 #if ENABLE_FEATURE_INIT_SYSLOG
20 # include <sys/syslog.h>
21 #endif
22
23 #define INIT_BUFFS_SIZE 256
24 #define CONSOLE_NAME_SIZE 32
25 #define MAXENV  16              /* Number of env. vars */
26
27 #if ENABLE_FEATURE_INIT_COREDUMPS
28 /*
29  * When a file named CORE_ENABLE_FLAG_FILE exists, setrlimit is called
30  * before processes are spawned to set core file size as unlimited.
31  * This is for debugging only.  Don't use this is production, unless
32  * you want core dumps lying about....
33  */
34 #define CORE_ENABLE_FLAG_FILE "/.init_enable_core"
35 #include <sys/resource.h>
36 #endif
37
38 #define INITTAB      "/etc/inittab"     /* inittab file location */
39 #ifndef INIT_SCRIPT
40 #define INIT_SCRIPT  "/etc/init.d/rcS"  /* Default sysinit script. */
41 #endif
42
43 /* Allowed init action types */
44 #define SYSINIT     0x001
45 #define RESPAWN     0x002
46 #define ASKFIRST    0x004
47 #define WAIT        0x008
48 #define ONCE        0x010
49 #define CTRLALTDEL  0x020
50 #define SHUTDOWN    0x040
51 #define RESTART     0x080
52
53 /* A mapping between "inittab" action name strings and action type codes. */
54 struct init_action_type {
55         const char *name;
56         int action;
57 };
58
59 static const struct init_action_type actions[] = {
60         {"sysinit", SYSINIT},
61         {"respawn", RESPAWN},
62         {"askfirst", ASKFIRST},
63         {"wait", WAIT},
64         {"once", ONCE},
65         {"ctrlaltdel", CTRLALTDEL},
66         {"shutdown", SHUTDOWN},
67         {"restart", RESTART},
68         {0, 0}
69 };
70
71 /* Set up a linked list of init_actions, to be read from inittab */
72 struct init_action {
73         struct init_action *next;
74         int action;
75         pid_t pid;
76         char command[INIT_BUFFS_SIZE];
77         char terminal[CONSOLE_NAME_SIZE];
78 };
79
80 /* Static variables */
81 static struct init_action *init_action_list = NULL;
82
83 #if !ENABLE_FEATURE_INIT_SYSLOG
84 static const char *log_console = VC_5;
85 #endif
86 #if !ENABLE_DEBUG_INIT
87 static sig_atomic_t got_cont = 0;
88 #endif
89
90 enum {
91         L_LOG = 0x1,
92         L_CONSOLE = 0x2,
93
94 #if ENABLE_FEATURE_EXTRA_QUIET
95         MAYBE_CONSOLE = 0x0,
96 #else
97         MAYBE_CONSOLE = L_CONSOLE,
98 #endif
99
100 #ifndef RB_HALT_SYSTEM
101         RB_HALT_SYSTEM = 0xcdef0123, /* FIXME: this overflows enum */
102         RB_ENABLE_CAD = 0x89abcdef,
103         RB_DISABLE_CAD = 0,
104         RB_POWER_OFF = 0x4321fedc,
105         RB_AUTOBOOT = 0x01234567,
106 #endif
107 };
108
109 static const char *const environment[] = {
110         "HOME=/",
111         bb_PATH_root_path,
112         "SHELL=/bin/sh",
113         "USER=root",
114         NULL
115 };
116
117 /* Function prototypes */
118 static void delete_init_action(struct init_action *a);
119 static int waitfor(const struct init_action *a, pid_t pid);
120 #if !ENABLE_DEBUG_INIT
121 static void shutdown_signal(int sig);
122 #endif
123
124 #if !ENABLE_DEBUG_INIT
125 static void loop_forever(void)
126 {
127         while (1)
128                 sleep(1);
129 }
130 #endif
131
132 /* Print a message to the specified device.
133  * Device may be bitwise-or'd from L_LOG | L_CONSOLE */
134 #if ENABLE_DEBUG_INIT
135 #define messageD message
136 #else
137 #define messageD(...)  do {} while (0)
138 #endif
139 static void message(int device, const char *fmt, ...)
140         __attribute__ ((format(printf, 2, 3)));
141 static void message(int device, const char *fmt, ...)
142 {
143 #if !ENABLE_FEATURE_INIT_SYSLOG
144         static int log_fd = -1;
145 #endif
146
147         va_list arguments;
148         int l;
149         char msg[128];
150
151         msg[0] = '\r';
152         va_start(arguments, fmt);
153         vsnprintf(msg + 1, sizeof(msg) - 2, fmt, arguments);
154         va_end(arguments);
155         msg[sizeof(msg) - 2] = '\0';
156         l = strlen(msg);
157
158 #if ENABLE_FEATURE_INIT_SYSLOG
159         /* Log the message to syslogd */
160         if (device & L_LOG) {
161                 /* don't out "\r" */
162                 openlog(applet_name, 0, LOG_DAEMON);
163                 syslog(LOG_INFO, "init: %s", msg + 1);
164                 closelog();
165         }
166         msg[l++] = '\n';
167         msg[l] = '\0';
168 #else
169         msg[l++] = '\n';
170         msg[l] = '\0';
171         /* Take full control of the log tty, and never close it.
172          * It's mine, all mine!  Muhahahaha! */
173         if (log_fd < 0) {
174                 if (!log_console) {
175                         log_fd = 2;
176                 } else {
177                         log_fd = device_open(log_console, O_WRONLY | O_NONBLOCK | O_NOCTTY);
178                         if (log_fd < 0) {
179                                 bb_error_msg("can't log to %s", log_console);
180                                 device = L_CONSOLE;
181                         } else {
182                                 close_on_exec_on(log_fd);
183                         }
184                 }
185         }
186         if (device & L_LOG) {
187                 full_write(log_fd, msg, l);
188                 if (log_fd == 2)
189                         return; /* don't print dup messages */
190         }
191 #endif
192
193         if (device & L_CONSOLE) {
194                 /* Send console messages to console so people will see them. */
195                 full_write(2, msg, l);
196         }
197 }
198
199 /* Set terminal settings to reasonable defaults */
200 static void set_sane_term(void)
201 {
202         struct termios tty;
203
204         tcgetattr(STDIN_FILENO, &tty);
205
206         /* set control chars */
207         tty.c_cc[VINTR] = 3;    /* C-c */
208         tty.c_cc[VQUIT] = 28;   /* C-\ */
209         tty.c_cc[VERASE] = 127; /* C-? */
210         tty.c_cc[VKILL] = 21;   /* C-u */
211         tty.c_cc[VEOF] = 4;     /* C-d */
212         tty.c_cc[VSTART] = 17;  /* C-q */
213         tty.c_cc[VSTOP] = 19;   /* C-s */
214         tty.c_cc[VSUSP] = 26;   /* C-z */
215
216         /* use line dicipline 0 */
217         tty.c_line = 0;
218
219         /* Make it be sane */
220         tty.c_cflag &= CBAUD | CBAUDEX | CSIZE | CSTOPB | PARENB | PARODD;
221         tty.c_cflag |= CREAD | HUPCL | CLOCAL;
222
223         /* input modes */
224         tty.c_iflag = ICRNL | IXON | IXOFF;
225
226         /* output modes */
227         tty.c_oflag = OPOST | ONLCR;
228
229         /* local modes */
230         tty.c_lflag =
231                 ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOKE | IEXTEN;
232
233         tcsetattr(STDIN_FILENO, TCSANOW, &tty);
234 }
235
236 /* From <linux/serial.h> */
237 struct serial_struct {
238         int     type;
239         int     line;
240         unsigned int    port;
241         int     irq;
242         int     flags;
243         int     xmit_fifo_size;
244         int     custom_divisor;
245         int     baud_base;
246         unsigned short  close_delay;
247         char    io_type;
248         char    reserved_char[1];
249         int     hub6;
250         unsigned short  closing_wait; /* time to wait before closing */
251         unsigned short  closing_wait2; /* no longer used... */
252         unsigned char   *iomem_base;
253         unsigned short  iomem_reg_shift;
254         unsigned int    port_high;
255         unsigned long   iomap_base;     /* cookie passed into ioremap */
256         int     reserved[1];
257         /* Paranoia (imagine 64bit kernel overwriting 32bit userspace stack) */
258         uint32_t bbox_reserved[16];
259 };
260 static void console_init(void)
261 {
262         struct serial_struct sr;
263         char *s;
264
265         s = getenv("CONSOLE");
266         if (!s) s = getenv("console");
267         if (s) {
268                 int fd = open(s, O_RDWR | O_NONBLOCK | O_NOCTTY);
269                 if (fd >= 0) {
270                         dup2(fd, 0);
271                         dup2(fd, 1);
272                         dup2(fd, 2);
273                         while (fd > 2) close(fd--);
274                 }
275                 messageD(L_LOG, "console='%s'", s);
276         } else {
277                 /* Make sure fd 0,1,2 are not closed */
278                 bb_sanitize_stdio();
279         }
280
281         s = getenv("TERM");
282         if (ioctl(0, TIOCGSERIAL, &sr) == 0) {
283                 /* Force the TERM setting to vt102 for serial console --
284                  * if TERM is set to linux (the default) */
285                 if (!s || strcmp(s, "linux") == 0)
286                         putenv((char*)"TERM=vt102");
287 #if !ENABLE_FEATURE_INIT_SYSLOG
288                 log_console = NULL;
289 #endif
290         } else if (!s)
291                 putenv((char*)"TERM=linux");
292 }
293
294 static void fixup_argv(char **argv)
295 {
296         /* Fix up argv[0] to be certain we claim to be init */
297         strncpy(argv[0], "init", strlen(argv[0]));
298
299         /* Wipe argv[1]-argv[N] so they don't clutter the ps listing */
300         while (*++argv)
301                 memset(*argv, 0, strlen(*argv));
302 }
303
304 /* Open the new terminal device */
305 static void open_stdio_to_tty(const char* tty_name, int fail)
306 {
307         /* empty tty_name means "use init's tty", else... */
308         if (tty_name[0]) {
309                 int fd = device_open(tty_name, O_RDWR);
310                 if (fd < 0) {
311                         message(L_LOG | L_CONSOLE, "Can't open %s: %s",
312                                 tty_name, strerror(errno));
313                         if (fail)
314                                 _exit(1);
315 #if !ENABLE_DEBUG_INIT
316                         shutdown_signal(SIGUSR1);
317 #else
318                         _exit(2);
319 #endif
320                 } else {
321                         dup2(fd, 0);
322                         dup2(fd, 1);
323                         dup2(fd, 2);
324                         if (fd > 2) close(fd);
325                 }
326         }
327         set_sane_term();
328 }
329
330 static pid_t run(const struct init_action *a)
331 {
332         int i;
333         pid_t pid;
334         char *s, *tmpCmd, *cmdpath;
335         char *cmd[INIT_BUFFS_SIZE];
336         char buf[INIT_BUFFS_SIZE + 6];  /* INIT_BUFFS_SIZE+strlen("exec ")+1 */
337         sigset_t nmask, omask;
338
339         /* Block sigchild while forking.  */
340         sigemptyset(&nmask);
341         sigaddset(&nmask, SIGCHLD);
342         sigprocmask(SIG_BLOCK, &nmask, &omask);
343         pid = fork();
344         sigprocmask(SIG_SETMASK, &omask, NULL);
345
346         if (pid)
347                 return pid;
348
349         /* Reset signal handlers that were set by the parent process */
350         signal(SIGUSR1, SIG_DFL);
351         signal(SIGUSR2, SIG_DFL);
352         signal(SIGINT, SIG_DFL);
353         signal(SIGTERM, SIG_DFL);
354         signal(SIGHUP, SIG_DFL);
355         signal(SIGQUIT, SIG_DFL);
356         signal(SIGCONT, SIG_DFL);
357         signal(SIGSTOP, SIG_DFL);
358         signal(SIGTSTP, SIG_DFL);
359
360         /* Create a new session and make ourself the process
361          * group leader */
362         setsid();
363
364         /* Open the new terminal device */
365         open_stdio_to_tty(a->terminal, 1);
366
367         /* If the init Action requires us to wait, then force the
368          * supplied terminal to be the controlling tty. */
369         if (a->action & (SYSINIT | WAIT | CTRLALTDEL | SHUTDOWN | RESTART)) {
370
371                 /* Now fork off another process to just hang around */
372                 if ((pid = fork()) < 0) {
373                         message(L_LOG | L_CONSOLE, "Can't fork");
374                         _exit(1);
375                 }
376
377                 if (pid > 0) {
378
379                         /* We are the parent -- wait till the child is done */
380                         signal(SIGINT, SIG_IGN);
381                         signal(SIGTSTP, SIG_IGN);
382                         signal(SIGQUIT, SIG_IGN);
383                         signal(SIGCHLD, SIG_DFL);
384
385                         waitfor(NULL, pid);
386                         /* See if stealing the controlling tty back is necessary */
387                         if (tcgetpgrp(0) != getpid())
388                                 _exit(0);
389
390                         /* Use a temporary process to steal the controlling tty. */
391                         if ((pid = fork()) < 0) {
392                                 message(L_LOG | L_CONSOLE, "Can't fork");
393                                 _exit(1);
394                         }
395                         if (pid == 0) {
396                                 setsid();
397                                 ioctl(0, TIOCSCTTY, 1);
398                                 _exit(0);
399                         }
400                         waitfor(NULL, pid);
401                         _exit(0);
402                 }
403
404                 /* Now fall though to actually execute things */
405         }
406
407         /* See if any special /bin/sh requiring characters are present */
408         if (strpbrk(a->command, "~`!$^&*()=|\\{}[];\"'<>?") != NULL) {
409                 cmd[0] = (char*)DEFAULT_SHELL;
410                 cmd[1] = (char*)"-c";
411                 cmd[2] = strcat(strcpy(buf, "exec "), a->command);
412                 cmd[3] = NULL;
413         } else {
414                 /* Convert command (char*) into cmd (char**, one word per string) */
415                 strcpy(buf, a->command);
416                 s = buf;
417                 for (tmpCmd = buf, i = 0; (tmpCmd = strsep(&s, " \t")) != NULL;) {
418                         if (*tmpCmd != '\0') {
419                                 cmd[i] = tmpCmd;
420                                 i++;
421                         }
422                 }
423                 cmd[i] = NULL;
424         }
425
426         cmdpath = cmd[0];
427
428         /*
429          * Interactive shells want to see a dash in argv[0].  This
430          * typically is handled by login, argv will be setup this
431          * way if a dash appears at the front of the command path
432          * (like "-/bin/sh").
433          */
434         if (*cmdpath == '-') {
435                 /* skip over the dash */
436                 ++cmdpath;
437
438                 /* find the last component in the command pathname */
439                 s = bb_get_last_path_component_nostrip(cmdpath);
440
441                 /* make a new argv[0] */
442                 cmd[0] = malloc(strlen(s) + 2);
443                 if (cmd[0] == NULL) {
444                         message(L_LOG | L_CONSOLE, bb_msg_memory_exhausted);
445                         cmd[0] = cmdpath;
446                 } else {
447                         cmd[0][0] = '-';
448                         strcpy(cmd[0] + 1, s);
449                 }
450 #if ENABLE_FEATURE_INIT_SCTTY
451                 /* Establish this process as session leader and
452                  * (attempt) to make the tty (if any) a controlling tty.
453                  */
454                 setsid();
455                 ioctl(0, TIOCSCTTY, 0 /*don't steal it*/);
456 #endif
457         }
458
459 #if !defined(__UCLIBC__) || defined(__ARCH_HAS_MMU__)
460         if (a->action & ASKFIRST) {
461                 static const char press_enter[] ALIGN1 =
462 #ifdef CUSTOMIZED_BANNER
463 #include CUSTOMIZED_BANNER
464 #endif
465                         "\nPlease press Enter to activate this console. ";
466                 char c;
467                 /*
468                  * Save memory by not exec-ing anything large (like a shell)
469                  * before the user wants it. This is critical if swap is not
470                  * enabled and the system has low memory. Generally this will
471                  * be run on the second virtual console, and the first will
472                  * be allowed to start a shell or whatever an init script
473                  * specifies.
474                  */
475                 messageD(L_LOG, "waiting for enter to start '%s'"
476                                         "(pid %d, tty '%s')\n",
477                                   cmdpath, getpid(), a->terminal);
478                 full_write(1, press_enter, sizeof(press_enter) - 1);
479                 while (read(0, &c, 1) == 1 && c != '\n')
480                         ;
481         }
482 #endif
483         /* Log the process name and args */
484         message(L_LOG, "starting pid %d, tty '%s': '%s'",
485                           getpid(), a->terminal, cmdpath);
486
487 #if ENABLE_FEATURE_INIT_COREDUMPS
488         {
489                 struct stat sb;
490                 if (stat(CORE_ENABLE_FLAG_FILE, &sb) == 0) {
491                         struct rlimit limit;
492
493                         limit.rlim_cur = RLIM_INFINITY;
494                         limit.rlim_max = RLIM_INFINITY;
495                         setrlimit(RLIMIT_CORE, &limit);
496                 }
497         }
498 #endif
499         /* Now run it.  The new program will take over this PID,
500          * so nothing further in init.c should be run. */
501         BB_EXECVP(cmdpath, cmd);
502
503         /* We're still here?  Some error happened. */
504         message(L_LOG | L_CONSOLE, "Cannot run '%s': %s",
505                         cmdpath, strerror(errno));
506         _exit(-1);
507 }
508
509 static int waitfor(const struct init_action *a, pid_t pid)
510 {
511         int runpid;
512         int status, wpid;
513
514         runpid = (NULL == a)? pid : run(a);
515         while (1) {
516                 wpid = waitpid(runpid, &status, 0);
517                 if (wpid == runpid)
518                         break;
519                 if (wpid == -1 && errno == ECHILD) {
520                         /* we missed its termination */
521                         break;
522                 }
523                 /* FIXME other errors should maybe trigger an error, but allow
524                  * the program to continue */
525         }
526         return wpid;
527 }
528
529 /* Run all commands of a particular type */
530 static void run_actions(int action)
531 {
532         struct init_action *a, *tmp;
533
534         for (a = init_action_list; a; a = tmp) {
535                 tmp = a->next;
536                 if (a->action == action) {
537                         /* a->terminal of "" means "init's console" */
538                         if (a->terminal[0] && access(a->terminal, R_OK | W_OK)) {
539                                 delete_init_action(a);
540                         } else if (a->action & (SYSINIT | WAIT | CTRLALTDEL | SHUTDOWN | RESTART)) {
541                                 waitfor(a, 0);
542                                 delete_init_action(a);
543                         } else if (a->action & ONCE) {
544                                 run(a);
545                                 delete_init_action(a);
546                         } else if (a->action & (RESPAWN | ASKFIRST)) {
547                                 /* Only run stuff with pid==0.  If they have
548                                  * a pid, that means it is still running */
549                                 if (a->pid == 0) {
550                                         a->pid = run(a);
551                                 }
552                         }
553                 }
554         }
555 }
556
557 #if !ENABLE_DEBUG_INIT
558 static void init_reboot(unsigned long magic)
559 {
560         pid_t pid;
561         /* We have to fork here, since the kernel calls do_exit(0) in
562          * linux/kernel/sys.c, which can cause the machine to panic when
563          * the init process is killed.... */
564         pid = vfork();
565         if (pid == 0) { /* child */
566                 reboot(magic);
567                 _exit(0);
568         }
569         waitpid(pid, NULL, 0);
570 }
571
572 static void shutdown_system(void)
573 {
574         sigset_t block_signals;
575
576         /* run everything to be run at "shutdown".  This is done _prior_
577          * to killing everything, in case people wish to use scripts to
578          * shut things down gracefully... */
579         run_actions(SHUTDOWN);
580
581         /* first disable all our signals */
582         sigemptyset(&block_signals);
583         sigaddset(&block_signals, SIGHUP);
584         sigaddset(&block_signals, SIGQUIT);
585         sigaddset(&block_signals, SIGCHLD);
586         sigaddset(&block_signals, SIGUSR1);
587         sigaddset(&block_signals, SIGUSR2);
588         sigaddset(&block_signals, SIGINT);
589         sigaddset(&block_signals, SIGTERM);
590         sigaddset(&block_signals, SIGCONT);
591         sigaddset(&block_signals, SIGSTOP);
592         sigaddset(&block_signals, SIGTSTP);
593         sigprocmask(SIG_BLOCK, &block_signals, NULL);
594
595         message(L_CONSOLE | L_LOG, "The system is going down NOW!");
596
597         /* Allow Ctrl-Alt-Del to reboot system. */
598         init_reboot(RB_ENABLE_CAD);
599
600         /* Send signals to every process _except_ pid 1 */
601         message(L_CONSOLE | L_LOG, "Sending SIG%s to all processes", "TERM");
602         kill(-1, SIGTERM);
603         sync();
604         sleep(1);
605
606         message(L_CONSOLE | L_LOG, "Sending SIG%s to all processes", "KILL");
607         kill(-1, SIGKILL);
608         sync();
609         sleep(1);
610 }
611
612 static void exec_signal(int sig ATTRIBUTE_UNUSED)
613 {
614         struct init_action *a, *tmp;
615         sigset_t unblock_signals;
616
617         for (a = init_action_list; a; a = tmp) {
618                 tmp = a->next;
619                 if (a->action & RESTART) {
620                         shutdown_system();
621
622                         /* unblock all signals, blocked in shutdown_system() */
623                         sigemptyset(&unblock_signals);
624                         sigaddset(&unblock_signals, SIGHUP);
625                         sigaddset(&unblock_signals, SIGQUIT);
626                         sigaddset(&unblock_signals, SIGCHLD);
627                         sigaddset(&unblock_signals, SIGUSR1);
628                         sigaddset(&unblock_signals, SIGUSR2);
629                         sigaddset(&unblock_signals, SIGINT);
630                         sigaddset(&unblock_signals, SIGTERM);
631                         sigaddset(&unblock_signals, SIGCONT);
632                         sigaddset(&unblock_signals, SIGSTOP);
633                         sigaddset(&unblock_signals, SIGTSTP);
634                         sigprocmask(SIG_UNBLOCK, &unblock_signals, NULL);
635
636                         /* Open the new terminal device */
637                         open_stdio_to_tty(a->terminal, 0);
638
639                         messageD(L_CONSOLE | L_LOG, "Trying to re-exec %s", a->command);
640                         BB_EXECLP(a->command, a->command, NULL);
641
642                         message(L_CONSOLE | L_LOG, "Cannot run '%s': %s",
643                                         a->command, strerror(errno));
644                         sleep(2);
645                         init_reboot(RB_HALT_SYSTEM);
646                         loop_forever();
647                 }
648         }
649 }
650
651 static void shutdown_signal(int sig)
652 {
653         const char *m;
654         int rb;
655
656         shutdown_system();
657
658         m = "halt";
659         rb = RB_HALT_SYSTEM;
660         if (sig == SIGTERM) {
661                 m = "reboot";
662                 rb = RB_AUTOBOOT;
663         } else if (sig == SIGUSR2) {
664                 m = "poweroff";
665                 rb = RB_POWER_OFF;
666         }
667         message(L_CONSOLE | L_LOG, "Requesting system %s", m);
668         /* allow time for last message to reach serial console */
669         sleep(2);
670         init_reboot(rb);
671         loop_forever();
672 }
673
674 static void ctrlaltdel_signal(int sig ATTRIBUTE_UNUSED)
675 {
676         run_actions(CTRLALTDEL);
677 }
678
679 /* The SIGSTOP & SIGTSTP handler */
680 static void stop_handler(int sig ATTRIBUTE_UNUSED)
681 {
682         int saved_errno = errno;
683
684         got_cont = 0;
685         while (!got_cont)
686                 pause();
687         got_cont = 0;
688         errno = saved_errno;
689 }
690
691 /* The SIGCONT handler */
692 static void cont_handler(int sig ATTRIBUTE_UNUSED)
693 {
694         got_cont = 1;
695 }
696
697 #endif  /* !ENABLE_DEBUG_INIT */
698
699 static void new_init_action(int action, const char *command, const char *cons)
700 {
701         struct init_action *new_action, *a, *last;
702
703         if (strcmp(cons, bb_dev_null) == 0 && (action & ASKFIRST))
704                 return;
705
706         /* Append to the end of the list */
707         for (a = last = init_action_list; a; a = a->next) {
708                 /* don't enter action if it's already in the list,
709                  * but do overwrite existing actions */
710                 if ((strcmp(a->command, command) == 0)
711                  && (strcmp(a->terminal, cons) == 0)
712                 ) {
713                         a->action = action;
714                         return;
715                 }
716                 last = a;
717         }
718
719         new_action = xzalloc(sizeof(struct init_action));
720         if (last) {
721                 last->next = new_action;
722         } else {
723                 init_action_list = new_action;
724         }
725         strcpy(new_action->command, command);
726         new_action->action = action;
727         strcpy(new_action->terminal, cons);
728         messageD(L_LOG | L_CONSOLE, "command='%s' action=%d tty='%s'\n",
729                 new_action->command, new_action->action, new_action->terminal);
730 }
731
732 static void delete_init_action(struct init_action *action)
733 {
734         struct init_action *a, *b = NULL;
735
736         for (a = init_action_list; a; b = a, a = a->next) {
737                 if (a == action) {
738                         if (b == NULL) {
739                                 init_action_list = a->next;
740                         } else {
741                                 b->next = a->next;
742                         }
743                         free(a);
744                         break;
745                 }
746         }
747 }
748
749 /* NOTE that if CONFIG_FEATURE_USE_INITTAB is NOT defined,
750  * then parse_inittab() simply adds in some default
751  * actions(i.e., runs INIT_SCRIPT and then starts a pair
752  * of "askfirst" shells).  If CONFIG_FEATURE_USE_INITTAB
753  * _is_ defined, but /etc/inittab is missing, this
754  * results in the same set of default behaviors.
755  */
756 static void parse_inittab(void)
757 {
758 #if ENABLE_FEATURE_USE_INITTAB
759         FILE *file;
760         char buf[INIT_BUFFS_SIZE], lineAsRead[INIT_BUFFS_SIZE];
761         char tmpConsole[CONSOLE_NAME_SIZE];
762         char *id, *runlev, *action, *command, *eol;
763         const struct init_action_type *a = actions;
764
765         file = fopen(INITTAB, "r");
766         if (file == NULL) {
767                 /* No inittab file -- set up some default behavior */
768 #endif
769                 /* Reboot on Ctrl-Alt-Del */
770                 new_init_action(CTRLALTDEL, "reboot", "");
771                 /* Umount all filesystems on halt/reboot */
772                 new_init_action(SHUTDOWN, "umount -a -r", "");
773                 /* Swapoff on halt/reboot */
774                 if (ENABLE_SWAPONOFF) new_init_action(SHUTDOWN, "swapoff -a", "");
775                 /* Prepare to restart init when a HUP is received */
776                 new_init_action(RESTART, "init", "");
777                 /* Askfirst shell on tty1-4 */
778                 new_init_action(ASKFIRST, bb_default_login_shell, "");
779                 new_init_action(ASKFIRST, bb_default_login_shell, VC_2);
780                 new_init_action(ASKFIRST, bb_default_login_shell, VC_3);
781                 new_init_action(ASKFIRST, bb_default_login_shell, VC_4);
782                 /* sysinit */
783                 new_init_action(SYSINIT, INIT_SCRIPT, "");
784
785                 return;
786 #if ENABLE_FEATURE_USE_INITTAB
787         }
788
789         while (fgets(buf, INIT_BUFFS_SIZE, file) != NULL) {
790                 /* Skip leading spaces */
791                 for (id = buf; *id == ' ' || *id == '\t'; id++);
792
793                 /* Skip the line if it's a comment */
794                 if (*id == '#' || *id == '\n')
795                         continue;
796
797                 /* Trim the trailing \n */
798                 //XXX: chomp() ?
799                 eol = strrchr(id, '\n');
800                 if (eol != NULL)
801                         *eol = '\0';
802
803                 /* Keep a copy around for posterity's sake (and error msgs) */
804                 strcpy(lineAsRead, buf);
805
806                 /* Separate the ID field from the runlevels */
807                 runlev = strchr(id, ':');
808                 if (runlev == NULL || *(runlev + 1) == '\0') {
809                         message(L_LOG | L_CONSOLE, "Bad inittab entry: %s", lineAsRead);
810                         continue;
811                 } else {
812                         *runlev = '\0';
813                         ++runlev;
814                 }
815
816                 /* Separate the runlevels from the action */
817                 action = strchr(runlev, ':');
818                 if (action == NULL || *(action + 1) == '\0') {
819                         message(L_LOG | L_CONSOLE, "Bad inittab entry: %s", lineAsRead);
820                         continue;
821                 } else {
822                         *action = '\0';
823                         ++action;
824                 }
825
826                 /* Separate the action from the command */
827                 command = strchr(action, ':');
828                 if (command == NULL || *(command + 1) == '\0') {
829                         message(L_LOG | L_CONSOLE, "Bad inittab entry: %s", lineAsRead);
830                         continue;
831                 } else {
832                         *command = '\0';
833                         ++command;
834                 }
835
836                 /* Ok, now process it */
837                 for (a = actions; a->name != 0; a++) {
838                         if (strcmp(a->name, action) == 0) {
839                                 if (*id != '\0') {
840                                         if (strncmp(id, "/dev/", 5) == 0)
841                                                 id += 5;
842                                         strcpy(tmpConsole, "/dev/");
843                                         safe_strncpy(tmpConsole + 5, id,
844                                                 sizeof(tmpConsole) - 5);
845                                         id = tmpConsole;
846                                 }
847                                 new_init_action(a->action, command, id);
848                                 break;
849                         }
850                 }
851                 if (a->name == 0) {
852                         /* Choke on an unknown action */
853                         message(L_LOG | L_CONSOLE, "Bad inittab entry: %s", lineAsRead);
854                 }
855         }
856         fclose(file);
857 #endif /* FEATURE_USE_INITTAB */
858 }
859
860 #if ENABLE_FEATURE_USE_INITTAB
861 static void reload_signal(int sig ATTRIBUTE_UNUSED)
862 {
863         struct init_action *a, *tmp;
864
865         message(L_LOG, "reloading /etc/inittab");
866
867         /* disable old entrys */
868         for (a = init_action_list; a; a = a->next ) {
869                 a->action = ONCE;
870         }
871
872         parse_inittab();
873
874         /* remove unused entrys */
875         for (a = init_action_list; a; a = tmp) {
876                 tmp = a->next;
877                 if ((a->action & (ONCE | SYSINIT | WAIT)) && a->pid == 0) {
878                         delete_init_action(a);
879                 }
880         }
881         run_actions(RESPAWN);
882 }
883 #endif  /* FEATURE_USE_INITTAB */
884
885 int init_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
886 int init_main(int argc, char **argv)
887 {
888         struct init_action *a;
889         pid_t wpid;
890
891         die_sleep = 30 * 24*60*60; /* if xmalloc will ever die... */
892
893         if (argc > 1 && !strcmp(argv[1], "-q")) {
894                 return kill(1, SIGHUP);
895         }
896 #if !ENABLE_DEBUG_INIT
897         /* Expect to be invoked as init with PID=1 or be invoked as linuxrc */
898         if (getpid() != 1
899          && (!ENABLE_FEATURE_INITRD || !strstr(applet_name, "linuxrc"))
900         ) {
901                 bb_show_usage();
902         }
903         /* Set up sig handlers  -- be sure to
904          * clear all of these in run() */
905         signal(SIGHUP, exec_signal);
906         signal(SIGQUIT, exec_signal);
907         signal(SIGUSR1, shutdown_signal);
908         signal(SIGUSR2, shutdown_signal);
909         signal(SIGINT, ctrlaltdel_signal);
910         signal(SIGTERM, shutdown_signal);
911         signal(SIGCONT, cont_handler);
912         signal(SIGSTOP, stop_handler);
913         signal(SIGTSTP, stop_handler);
914
915         /* Turn off rebooting via CTL-ALT-DEL -- we get a
916          * SIGINT on CAD so we can shut things down gracefully... */
917         init_reboot(RB_DISABLE_CAD);
918 #endif
919
920
921         /* Figure out where the default console should be */
922         console_init();
923         set_sane_term();
924         chdir("/");
925         setsid();
926         {
927                 const char *const *e;
928                 /* Make sure environs is set to something sane */
929                 for (e = environment; *e; e++)
930                         putenv((char *) *e);
931         }
932
933         if (argc > 1) setenv("RUNLEVEL", argv[1], 1);
934
935         /* Hello world */
936         message(MAYBE_CONSOLE | L_LOG, "init started: %s", bb_banner);
937
938         /* Make sure there is enough memory to do something useful. */
939         if (ENABLE_SWAPONOFF) {
940                 struct sysinfo info;
941
942                 if (!sysinfo(&info) &&
943                         (info.mem_unit ? : 1) * (long long)info.totalram < 1024*1024)
944                 {
945                         message(L_CONSOLE, "Low memory, forcing swapon");
946                         /* swapon -a requires /proc typically */
947                         new_init_action(SYSINIT, "mount -t proc proc /proc", "");
948                         /* Try to turn on swap */
949                         new_init_action(SYSINIT, "swapon -a", "");
950                         run_actions(SYSINIT);   /* wait and removing */
951                 }
952         }
953
954         /* Check if we are supposed to be in single user mode */
955         if (argc > 1
956          && (!strcmp(argv[1], "single") || !strcmp(argv[1], "-s") || LONE_CHAR(argv[1], '1'))
957         ) {
958                 /* Start a shell on console */
959                 new_init_action(RESPAWN, bb_default_login_shell, "");
960         } else {
961                 /* Not in single user mode -- see what inittab says */
962
963                 /* NOTE that if CONFIG_FEATURE_USE_INITTAB is NOT defined,
964                  * then parse_inittab() simply adds in some default
965                  * actions(i.e., runs INIT_SCRIPT and then starts a pair
966                  * of "askfirst" shells */
967                 parse_inittab();
968         }
969
970 #if ENABLE_SELINUX
971         if (getenv("SELINUX_INIT") == NULL) {
972                 int enforce = 0;
973
974                 putenv((char*)"SELINUX_INIT=YES");
975                 if (selinux_init_load_policy(&enforce) == 0) {
976                         BB_EXECVP(argv[0], argv);
977                 } else if (enforce > 0) {
978                         /* SELinux in enforcing mode but load_policy failed */
979                         /* At this point, we probably can't open /dev/console, so log() won't work */
980                         message(L_CONSOLE, "Cannot load SELinux Policy. "
981                                 "Machine is in enforcing mode. Halting now.");
982                         exit(1);
983                 }
984         }
985 #endif /* CONFIG_SELINUX */
986
987         /* Make the command line just say "init"  -- thats all, nothing else */
988         fixup_argv(argv);
989
990         /* Now run everything that needs to be run */
991
992         /* First run the sysinit command */
993         run_actions(SYSINIT);
994
995         /* Next run anything that wants to block */
996         run_actions(WAIT);
997
998         /* Next run anything to be run only once */
999         run_actions(ONCE);
1000
1001 #if ENABLE_FEATURE_USE_INITTAB
1002         /* Redefine SIGHUP to reread /etc/inittab */
1003         signal(SIGHUP, reload_signal);
1004 #else
1005         signal(SIGHUP, SIG_IGN);
1006 #endif /* FEATURE_USE_INITTAB */
1007
1008         /* Now run the looping stuff for the rest of forever */
1009         while (1) {
1010                 /* run the respawn stuff */
1011                 run_actions(RESPAWN);
1012
1013                 /* run the askfirst stuff */
1014                 run_actions(ASKFIRST);
1015
1016                 /* Don't consume all CPU time -- sleep a bit */
1017                 sleep(1);
1018
1019                 /* Wait for a child process to exit */
1020                 wpid = wait(NULL);
1021                 while (wpid > 0) {
1022                         /* Find out who died and clean up their corpse */
1023                         for (a = init_action_list; a; a = a->next) {
1024                                 if (a->pid == wpid) {
1025                                         /* Set the pid to 0 so that the process gets
1026                                          * restarted by run_actions() */
1027                                         a->pid = 0;
1028                                         message(L_LOG, "process '%s' (pid %d) exited. "
1029                                                         "Scheduling it for restart.",
1030                                                         a->command, wpid);
1031                                 }
1032                         }
1033                         /* see if anyone else is waiting to be reaped */
1034                         wpid = waitpid(-1, NULL, WNOHANG);
1035                 }
1036         }
1037 }