[BusyBox] another init.c complication

Tom Oehser tom at toms.net
Sat Apr 27 10:12:03 UTC 2002


Another complication turns out to be that init deletes actions
from the list, rather than marking them run, so the reload has
no way to know they aren't updates.  I think I'm going to just
start in on major butchery, here is what I had so far, which
behaves as expected as long as all the run-once things have
the same null ID as something (anything) that hangs around
(like a ctrl-alt-del action).  I think it really needs a
status field that changes to 'done' without deleting.

What I have so far:

--- ../../busybox-cvs-rb2/busybox/init/init.c	Fri Mar 29 00:59:44 2002
+++ init/init.c	Sat Apr 27 16:06:31 2002
@@ -1,5 +1,5 @@
 /* vi: set sw=4 ts=4: */
-/*
+/*
  * Mini init implementation for busybox
  *
  *
@@ -37,6 +37,7 @@
 #include <termios.h>
 #include <unistd.h>
 #include <limits.h>
+#include <sys/stat.h>
 #include <sys/fcntl.h>
 #include <sys/ioctl.h>
 #include <sys/mount.h>
@@ -153,10 +154,12 @@
 	char terminal[256];
 	struct init_action *next;
 	int action;
+	char id[3];
 };

 /* Static variables */
 static struct init_action *init_action_list = NULL;
+static char first_time = '1';
 static char *secondConsole = VC_2;
 static char *thirdConsole  = VC_3;
 static char *fourthConsole = VC_4;
@@ -499,6 +502,7 @@
 		signal(SIGINT,  SIG_DFL);
 		signal(SIGTERM, SIG_DFL);
 		signal(SIGHUP,  SIG_DFL);
+		signal(SIGURG,  SIG_DFL);
 		signal(SIGCONT, SIG_DFL);
 		signal(SIGSTOP, SIG_DFL);
 		signal(SIGTSTP, SIG_DFL);
@@ -718,6 +722,7 @@
 	/* first disable all our signals */
 	sigemptyset(&block_signals);
 	sigaddset(&block_signals, SIGHUP);
+	sigaddset(&block_signals, SIGURG);
 	sigaddset(&block_signals, SIGCHLD);
 	sigaddset(&block_signals, SIGUSR1);
 	sigaddset(&block_signals, SIGUSR2);
@@ -839,7 +844,7 @@

 #endif							/* ! DEBUG_INIT */

-static void new_init_action(int action, char *command, char *cons)
+static void new_init_action(int action, char *command, char *cons, char *id)
 {
 	struct init_action *new_action, *a;

@@ -856,6 +861,11 @@
 	if (strcmp(cons, "/dev/null") == 0 && (action & ASKFIRST))
 		return;

+	if (! first_time)
+		for (a = init_action_list; a && a->next; a = a->next)
+			if (!strcmp(a->id, id))
+				return;
+
 	new_action = calloc((size_t) (1), sizeof(struct init_action));
 	if (!new_action) {
 		message(LOG | CONSOLE, "\rMemory allocation failure\n");
@@ -873,6 +883,7 @@
 	new_action->action = action;
 	safe_strncpy(new_action->terminal, cons, 255);
 	new_action->pid = 0;
+	safe_strncpy(new_action->id, id, 255);
 //    message(LOG|CONSOLE, "command='%s' action='%d' terminal='%s'\n",
 //      new_action->command, new_action->action, new_action->terminal);
 }
@@ -906,42 +917,40 @@
 #ifdef CONFIG_FEATURE_USE_INITTAB
 	FILE *file;
 	char buf[256], lineAsRead[256], tmpConsole[256];
-	char *id, *runlev, *action, *command, *eol;
+	char *id, *runlev, *action, *command, *eol, *tty;
 	const struct init_action_type *a = actions;
 	int foundIt;
-
+	struct stat staat; // we really junk it and could use some other buffer

 	file = fopen(INITTAB, "r");
 	if (file == NULL) {
 		/* No inittab file -- set up some default behavior */
 #endif
 		/* Reboot on Ctrl-Alt-Del */
-		new_init_action(CTRLALTDEL, "/sbin/reboot", console);
+		new_init_action(CTRLALTDEL, "/sbin/reboot", console, "1");
 		/* Umount all filesystems on halt/reboot */
-		new_init_action(SHUTDOWN, "/bin/umount -a -r", console);
+		new_init_action(SHUTDOWN, "/bin/umount -a -r", console, "2");
 #if !defined(__UCLIBC__) || defined(__UCLIBC_HAS_MMU__)
 		/* Swapoff on halt/reboot */
-		new_init_action(SHUTDOWN, "/sbin/swapoff -a", console);
+		new_init_action(SHUTDOWN, "/sbin/swapoff -a", console, "3");
 #endif
 		/* Prepare to restart init when a HUP is received */
-		new_init_action(RESTART, "/sbin/init", console);
+		new_init_action(RESTART, "/sbin/init", console, "4");
 		/* Askfirst shell on tty1 */
-		new_init_action(ASKFIRST, LOGIN_SHELL, console);
+		new_init_action(ASKFIRST, LOGIN_SHELL, console, "5");
 		/* Askfirst shell on tty2 */
 		if (secondConsole != NULL)
-			new_init_action(ASKFIRST, LOGIN_SHELL, secondConsole);
+			new_init_action(ASKFIRST, LOGIN_SHELL, secondConsole, "6");
 		/* Askfirst shell on tty3 */
 		if (thirdConsole != NULL)
-			new_init_action(ASKFIRST, LOGIN_SHELL, thirdConsole);
+			new_init_action(ASKFIRST, LOGIN_SHELL, thirdConsole, "7");
 		/* Askfirst shell on tty4 */
 		if (fourthConsole != NULL)
-			new_init_action(ASKFIRST, LOGIN_SHELL, fourthConsole);
+			new_init_action(ASKFIRST, LOGIN_SHELL, fourthConsole, "8");
 		/* sysinit */
-		new_init_action(SYSINIT, INIT_SCRIPT, console);
-
-		return;
-#ifdef CONFIG_FEATURE_USE_INITTAB
+		new_init_action(SYSINIT, INIT_SCRIPT, console, "9");
 	}
+#ifdef CONFIG_FEATURE_USE_INITTAB

 	while (fgets(buf, 255, file) != NULL) {
 		foundIt = FALSE;
@@ -990,16 +999,31 @@
 			++command;
 		}

+		/* Separate the id from the tty */
+		if (*id == '\0') { // we got nothing
+			tty=id; // maybe hash or checksum the line for ID ?
+		} else {
+			tty=id; // default use as both
+// 	figure out whether our entry is the tty
+			strcpy(tmpConsole, "/dev/");
+			strncat(tmpConsole, tty, 200);
+			if (stat(tmpConsole,&staat)) { // treat as id only
+				tty=NULL;
+			} else {
+				// it can be both
+			}
+		}
+
 		/* Ok, now process it */
 		a = actions;
 		while (a->name != 0) {
 			if (strcmp(a->name, action) == 0) {
-				if (*id != '\0') {
+				if (*tty != '\0') {
 					strcpy(tmpConsole, "/dev/");
-					strncat(tmpConsole, id, 200);
-					id = tmpConsole;
+					strncat(tmpConsole, tty, 200);
+					tty = tmpConsole;
 				}
-				new_init_action(a->action, command, id);
+				new_init_action(a->action, command, tty, id);
 				foundIt = TRUE;
 			}
 			a++;
@@ -1011,11 +1035,16 @@
 			message(LOG | CONSOLE, "\rBad inittab entry: %s\n", lineAsRead);
 		}
 	}
-	return;
 #endif /* CONFIG_FEATURE_USE_INITTAB */
+	first_time = '\0';
+	return;
 }

-
+static void reload_signal(int sig)
+{
+	parse_inittab();
+	signal(SIGHUP,  reload_signal);
+}

 extern int init_main(int argc, char **argv)
 {
@@ -1023,6 +1052,18 @@
 	pid_t wpid;
 	int status;

+	if (argc > 1 && !strcmp(argv[1], "-r")) {
+		/* don't assume init's pid == 1 */
+		long *pid = find_pid_by_name("init");
+		if (!pid || *pid<=0) {
+			pid = find_pid_by_name("linuxrc");
+			if (!pid || *pid<=0)
+				error_msg_and_die("no process killed");
+		}
+		kill(*pid, SIGURG);
+		exit(0);
+	}
+
 	if (argc > 1 && !strcmp(argv[1], "-q")) {
 		/* don't assume init's pid == 1 */
 		long *pid = find_pid_by_name("init");
@@ -1047,7 +1088,8 @@
 	}
 	/* Set up sig handlers  -- be sure to
 	 * clear all of these in run() */
-	signal(SIGHUP,  exec_signal);
+	signal(SIGHUP,  reload_signal);
+	signal(SIGURG,  exec_signal);
 	signal(SIGUSR1, halt_signal);
 	signal(SIGUSR2, halt_signal);
 	signal(SIGINT,  ctrlaltdel_signal);
@@ -1090,13 +1132,13 @@
 					 !strcmp(argv[1], "-s") || !strcmp(argv[1], "1"))) {
 		/* Ask first then start a shell on tty2-4 */
 		if (secondConsole != NULL)
-			new_init_action(ASKFIRST, LOGIN_SHELL, secondConsole);
+			new_init_action(ASKFIRST, LOGIN_SHELL, secondConsole, "1");
 		if (thirdConsole != NULL)
-			new_init_action(ASKFIRST, LOGIN_SHELL, thirdConsole);
+			new_init_action(ASKFIRST, LOGIN_SHELL, thirdConsole, "2");
 		if (fourthConsole != NULL)
-			new_init_action(ASKFIRST, LOGIN_SHELL, fourthConsole);
+			new_init_action(ASKFIRST, LOGIN_SHELL, fourthConsole, "3");
 		/* Start a shell on tty1 */
-		new_init_action(RESPAWN, LOGIN_SHELL, console);
+		new_init_action(RESPAWN, LOGIN_SHELL, console, "4");
 	} else {
 		/* Not in single user mode -- see what inittab says */

@@ -1139,7 +1181,7 @@
 		sleep(1);

 		/* Wait for a child process to exit */
-		wpid = wait(&status);
+		wpid = waitpid(-1, &status, WNOHANG);
 		if (wpid > 0) {
 			/* Find out who died and clean up their corpse */
 			for (a = init_action_list; a; a = a->next) {




More information about the busybox mailing list