[prev in list] [next in list] [prev in thread] [next in thread] 

List:       busybox
Subject:    [BusyBox] another init.c complication
From:       Tom Oehser <tom () toms ! net>
Date:       2002-04-27 10:12:03
[Download RAW message or body]

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) {


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic