* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
-//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))
-
-//kbuild:lib-$(CONFIG_INIT) += init.o
-
//config:config INIT
//config: bool "init"
//config: default y
//config: Note that on Linux, init attempts to detect serial terminal and
//config: sets TERM to "vt102" if one is found.
+//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))
+
+//kbuild:lib-$(CONFIG_INIT) += init.o
+
#define DEBUG_SEGV_HANDLER 0
#include "libbb.h"
msg[0] = '\r';
va_start(arguments, fmt);
l = 1 + vsnprintf(msg + 1, sizeof(msg) - 2, fmt, arguments);
- if (l > sizeof(msg) - 1)
- l = sizeof(msg) - 1;
+ if (l > sizeof(msg) - 2)
+ l = sizeof(msg) - 2;
va_end(arguments);
#if ENABLE_FEATURE_INIT_SYSLOG
a->action_type = action_type;
strcpy(a->command, command);
safe_strncpy(a->terminal, cons, sizeof(a->terminal));
- dbg_message(L_LOG | L_CONSOLE, "command='%s' action=%d tty='%s'\n",
+ dbg_message(L_LOG | L_CONSOLE, "command='%s' action=%x tty='%s'\n",
a->command, a->action_type, a->terminal);
}
* and only one will be remembered and acted upon.
*/
-/* The SIGUSR[12]/SIGTERM handler */
+/* The SIGPWR/SIGUSR[12]/SIGTERM handler */
static void halt_reboot_pwoff(int sig) NORETURN;
static void halt_reboot_pwoff(int sig)
{
/* Remove stale entries and SYSINIT entries.
* We never rerun SYSINIT entries anyway,
- * removing them too saves a few bytes */
+ * removing them too saves a few bytes
+ */
nextp = &init_action_list;
while ((a = *nextp) != NULL) {
- if ((a->action_type & ~SYSINIT) == 0) {
+ /*
+ * Why pid == 0 check?
+ * Process can be removed from inittab and added *later*.
+ * If we delete its entry but process still runs,
+ * duplicate is spawned when the entry is re-added.
+ */
+ if ((a->action_type & ~SYSINIT) == 0 && a->pid == 0) {
*nextp = a->next;
free(a);
} else {
/* NOTE that if CONFIG_FEATURE_USE_INITTAB is NOT defined,
* then parse_inittab() simply adds in some default
- * actions(i.e., INIT_SCRIPT and a pair
- * of "askfirst" shells */
+ * actions (i.e., INIT_SCRIPT and a pair
+ * of "askfirst" shells) */
parse_inittab();
}
strncpy(argv[0], "init", strlen(argv[0]));
/* Wipe argv[1]-argv[N] so they don't clutter the ps listing */
while (*++argv)
- memset(*argv, 0, strlen(*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 */
//usage:#define init_trivial_usage
//usage: ""
//usage:#define init_full_usage "\n\n"
-//usage: "Init is the parent of all processes"
+//usage: "Init is the first process started during boot. It never exits."
+//usage: IF_FEATURE_USE_INITTAB(
+//usage: "\n""It (re)spawns children according to /etc/inittab."
+//usage: )
+//usage: IF_NOT_FEATURE_USE_INITTAB(
+//usage: "\n""This version of init doesn't use /etc/inittab,"
+//usage: "\n""has fixed set of processed to run."
+//usage: )
//usage:
//usage:#define init_notes_usage
//usage: "This version of init is designed to be run only by the kernel.\n"