1303 files changed, 32187 insertions, 57138 deletions
diff --git a/init/init.c b/init/init.c index d29328c..055f2b4 100644 --- a/init/init.c +++ b/init/init.c @@ -16,10 +16,21 @@ //config: help //config: init is the first program run when the system boots. //config: +//config:config LINUXRC +//config: bool "Support running init from within an initrd (not initramfs)" +//config: default y +//config: select FEATURE_SYSLOG +//config: help +//config: Legacy support for running init under the old-style initrd. Allows +//config: the name linuxrc to act as init, and it doesn't assume init is PID 1. +//config: +//config: This does not apply to initramfs, which runs /init as PID 1 and +//config: requires no special support. +//config: //config:config FEATURE_USE_INITTAB //config: bool "Support reading an inittab file" //config: default y -//config: depends on INIT +//config: depends on INIT || LINUXRC //config: help //config: Allow init to read an inittab file when the system boot. //config: @@ -46,7 +57,7 @@ //config:config FEATURE_INIT_SCTTY //config: bool "Run commands with leading dash with controlling tty" //config: default y -//config: depends on INIT +//config: depends on INIT || LINUXRC //config: help //config: If this option is enabled, init will try to give a controlling //config: tty to any command which has leading hyphen (often it's "-/bin/sh"). @@ -61,40 +72,29 @@ //config:config FEATURE_INIT_SYSLOG //config: bool "Enable init to write to syslog" //config: default y -//config: depends on INIT +//config: depends on INIT || LINUXRC //config: //config:config FEATURE_EXTRA_QUIET //config: bool "Be _extra_ quiet on boot" //config: default y -//config: depends on INIT +//config: depends on INIT || LINUXRC //config: help //config: Prevent init from logging some messages to the console during boot. //config: //config:config FEATURE_INIT_COREDUMPS //config: bool "Support dumping core for child processes (debugging only)" -//config: default y -//config: depends on INIT +//config: default n # not Y because this is a debug option +//config: depends on INIT || LINUXRC //config: help //config: If this option is enabled and the file /.init_enable_core //config: exists, then init will call setrlimit() to allow unlimited //config: core file sizes. If this option is disabled, processes //config: will not generate any core files. //config: -//config:config FEATURE_INITRD -//config: bool "Support running init from within an initrd (not initramfs)" -//config: default y -//config: depends on INIT -//config: help -//config: Legacy support for running init under the old-style initrd. Allows -//config: the name linuxrc to act as init, and it doesn't assume init is PID 1. -//config: -//config: This does not apply to initramfs, which runs /init as PID 1 and -//config: requires no special support. -//config: //config:config INIT_TERMINAL_TYPE //config: string "Initial terminal type" //config: default "linux" -//config: depends on INIT +//config: depends on INIT || LINUXRC //config: help //config: This is the initial value set by init for the TERM environment //config: variable. This variable is used by programs which make use of @@ -102,17 +102,32 @@ //config: //config: Note that on Linux, init attempts to detect serial terminal and //config: sets TERM to "vt102" if one is found. +//config: +//config:config FEATURE_INIT_MODIFY_CMDLINE +//config: bool "Modify the command-line to \"init\"" +//config: default y +//config: depends on INIT || LINUXRC +//config: help +//config: When launched as PID 1 and after parsing its arguments, init +//config: wipes all the arguments but argv[0] and rewrites argv[0] to +//config: contain only "init", so that its command-line appears solely as +//config: "init" in tools such as ps. +//config: If this option is set to Y, init will keep its original behavior, +//config: otherwise, all the arguments including argv[0] will be preserved, +//config: be they parsed or ignored by init. +//config: The original command-line used to launch init can then be +//config: retrieved in /proc/1/cmdline on Linux, for example. //applet:IF_INIT(APPLET(init, BB_DIR_SBIN, BB_SUID_DROP)) -//applet:IF_FEATURE_INITRD(APPLET_ODDNAME(linuxrc, init, BB_DIR_ROOT, BB_SUID_DROP, linuxrc)) +//applet:IF_LINUXRC(APPLET_ODDNAME(linuxrc, init, BB_DIR_ROOT, BB_SUID_DROP, linuxrc)) //kbuild:lib-$(CONFIG_INIT) += init.o +//kbuild:lib-$(CONFIG_LINUXRC) += init.o #define DEBUG_SEGV_HANDLER 0 #include "libbb.h" #include <syslog.h> -#include <paths.h> #include <sys/resource.h> #ifdef __linux__ # include <linux/vt.h> @@ -282,6 +297,11 @@ static void console_init(void) s = getenv("CONSOLE"); if (!s) s = getenv("console"); +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) + /* BSD people say their kernels do not open fd 0,1,2; they need this: */ + if (!s) + s = (char*)"/dev/console"; +#endif if (s) { int fd = open(s, O_RDWR | O_NONBLOCK | O_NOCTTY); if (fd >= 0) { @@ -538,11 +558,7 @@ static struct init_action *mark_terminated(pid_t pid) struct init_action *a; if (pid > 0) { - update_utmp(pid, DEAD_PROCESS, - /*tty_name:*/ NULL, - /*username:*/ NULL, - /*hostname:*/ NULL - ); + update_utmp_DEAD_PROCESS(pid); for (a = init_action_list; a; a = a->next) { if (a->pid == pid) { a->pid = 0; @@ -822,7 +838,7 @@ static void halt_reboot_pwoff(int sig) /* Handler for QUIT - exec "restart" action, * else (no such action defined) do nothing */ -static void restart_handler(int sig UNUSED_PARAM) +static void exec_restart_action(void) { struct init_action *a; @@ -975,6 +991,20 @@ static int check_delayed_sigs(void) #endif if (sig == SIGINT) run_actions(CTRLALTDEL); + if (sig == SIGQUIT) { + exec_restart_action(); + /* returns only if no restart action defined */ + } + if ((1 << sig) & (0 +#ifdef SIGPWR + + (1 << SIGPWR) +#endif + + (1 << SIGUSR1) + + (1 << SIGUSR2) + + (1 << SIGTERM) + )) { + halt_reboot_pwoff(sig); + } } } @@ -1005,6 +1035,11 @@ void handle_sigsegv(int sig, siginfo_t *info, void *ucontext) } #endif +static void sleep_much(void) +{ + sleep(30 * 24*60*60); +} + int init_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int init_main(int argc UNUSED_PARAM, char **argv) { @@ -1028,7 +1063,7 @@ int init_main(int argc UNUSED_PARAM, char **argv) if (!DEBUG_INIT) { /* Expect to be invoked as init with PID=1 or be invoked as linuxrc */ if (getpid() != 1 - && (!ENABLE_FEATURE_INITRD || applet_name[0] != 'l') /* not linuxrc? */ + && (!ENABLE_LINUXRC || applet_name[0] != 'l') /* not linuxrc? */ ) { bb_error_msg_and_die("must be run as PID 1"); } @@ -1041,12 +1076,12 @@ int init_main(int argc UNUSED_PARAM, char **argv) /* If, say, xmalloc would ever die, we don't want to oops kernel * by exiting. - * NB: we set die_sleep *after* PID 1 check and bb_show_usage. + * NB: we set die_func *after* PID 1 check and bb_show_usage. * Otherwise, for example, "init u" ("please rexec yourself" * command for sysvinit) will show help text (which isn't too bad), * *and sleep forever* (which is bad!) */ - die_sleep = 30 * 24*60*60; + die_func = sleep_much; /* Figure out where the default console should be */ console_init(); @@ -1070,7 +1105,7 @@ int init_main(int argc UNUSED_PARAM, char **argv) #if 0 /* It's 2013, does anyone really still depend on this? */ -/* If you do, consider adding swapon to sysinot actions then! */ +/* If you do, consider adding swapon to sysinit actions then! */ /* struct sysinfo is linux-specific */ # ifdef __linux__ /* Make sure there is enough memory to do something useful. */ @@ -1108,7 +1143,7 @@ int init_main(int argc UNUSED_PARAM, char **argv) parse_inittab(); } -#if ENABLE_SELINUX +/*#if ENABLE_SELINUX if (getenv("SELINUX_INIT") == NULL) { int enforce = 0; @@ -1116,32 +1151,25 @@ int init_main(int argc UNUSED_PARAM, char **argv) if (selinux_init_load_policy(&enforce) == 0) { BB_EXECVP(argv[0], argv); } else if (enforce > 0) { - /* SELinux in enforcing mode but load_policy failed */ message(L_CONSOLE, "can't load SELinux Policy. " "Machine is in enforcing mode. Halting now."); return EXIT_FAILURE; } } -#endif - - /* Make the command line just say "init" - thats all, nothing else */ - strncpy(argv[0], "init", strlen(argv[0])); - /* Wipe argv[1]-argv[N] so they don't clutter the ps listing */ - while (*++argv) - nuke_str(*argv); +#endif*/ + + if (ENABLE_FEATURE_INIT_MODIFY_CMDLINE) { + /* Make the command line just say "init" - that's all, nothing else */ + strncpy(argv[0], "init", strlen(argv[0])); + /* Wipe argv[1]-argv[N] so they don't clutter the ps listing */ + while (*++argv) + nuke_str(*argv); + } /* Set up signal handlers */ if (!DEBUG_INIT) { struct sigaction sa; - bb_signals(0 - + (1 << SIGPWR) /* halt */ - + (1 << SIGUSR1) /* halt */ - + (1 << SIGTERM) /* reboot */ - + (1 << SIGUSR2) /* poweroff */ - , halt_reboot_pwoff); - signal(SIGQUIT, restart_handler); /* re-exec another init */ - /* Stop handler must allow only SIGCONT inside itself */ memset(&sa, 0, sizeof(sa)); sigfillset(&sa.sa_mask); @@ -1156,18 +1184,24 @@ int init_main(int argc UNUSED_PARAM, char **argv) */ sigaction_set(SIGSTOP, &sa); /* pause */ - /* SIGINT (Ctrl-Alt-Del) must interrupt wait(), + /* These signals must interrupt wait(), * setting handler without SA_RESTART flag. */ - bb_signals_recursive_norestart((1 << SIGINT), record_signo); + bb_signals_recursive_norestart(0 + + (1 << SIGINT) /* Ctrl-Alt-Del */ + + (1 << SIGQUIT) /* re-exec another init */ +#ifdef SIGPWR + + (1 << SIGPWR) /* halt */ +#endif + + (1 << SIGUSR1) /* halt */ + + (1 << SIGTERM) /* reboot */ + + (1 << SIGUSR2) /* poweroff */ +#if ENABLE_FEATURE_USE_INITTAB + + (1 << SIGHUP) /* reread /etc/inittab */ +#endif + , record_signo); } - /* Set up "reread /etc/inittab" handler. - * Handler is set up without SA_RESTART, it will interrupt syscalls. - */ - if (!DEBUG_INIT && ENABLE_FEATURE_USE_INITTAB) - bb_signals_recursive_norestart((1 << SIGHUP), record_signo); - /* Now run everything that needs to be run */ /* First run the sysinit command */ run_actions(SYSINIT); |