svn commit: trunk/busybox/init

vda at busybox.net vda at busybox.net
Tue Feb 19 02:57:08 UTC 2008


Author: vda
Date: 2008-02-18 18:57:07 -0800 (Mon, 18 Feb 2008)
New Revision: 21060

Log:
init: fix bug 1111: restart actions were not splitting words:

::restart:/sbin/rc restart
resulted in:
exec of '/sbin/rc restart' failed: No such file or directory



Modified:
   trunk/busybox/init/Config.in
   trunk/busybox/init/init.c


Changeset:
Modified: trunk/busybox/init/Config.in
===================================================================
--- trunk/busybox/init/Config.in	2008-02-19 01:10:20 UTC (rev 21059)
+++ trunk/busybox/init/Config.in	2008-02-19 02:57:07 UTC (rev 21060)
@@ -47,15 +47,18 @@
 	  wrong process!)
 
 config FEATURE_INIT_SCTTY
-	bool "Support running commands with a controlling-tty"
+	bool "Run commands with leading dash with controlling tty"
 	default n
 	depends on INIT
 	help
-	  If this option is enabled a command starting with hyphen (-)
-	  is run in its own session (setsid(2)) and possibly with a
-	  controlling tty (TIOCSCTTY).  This is not the traditional init
-	  behavour, but is often what you want in an embedded system where
-	  the console is only accessed during development or for maintenance.
+	  If this option is enabled, init will try to give a controlling
+	  tty to any command which has leading hyphen (often it's "-/bin/sh").
+	  More precisely, init will do "ioctl(STDIN_FILENO, TIOCSCTTY, 0)".
+	  If device attached to STDIN_FILENO can be a ctty but is not yet
+	  a ctty for other session, it will become this process' ctty.
+	  This is not the traditional init behavour, but is often what you want
+	  in an embedded system where the console is only accessed during
+	  development or for maintenance.
 	  NB: using cttyhack applet may work better.
 
 config FEATURE_INIT_SYSLOG

Modified: trunk/busybox/init/init.c
===================================================================
--- trunk/busybox/init/init.c	2008-02-19 01:10:20 UTC (rev 21059)
+++ trunk/busybox/init/init.c	2008-02-19 02:57:07 UTC (rev 21060)
@@ -14,7 +14,7 @@
 #include <paths.h>
 #include <sys/reboot.h>
 
-#define INIT_BUFFS_SIZE 256
+#define COMMAND_SIZE 256
 #define CONSOLE_NAME_SIZE 32
 #define MAXENV	16		/* Number of env. vars */
 
@@ -55,9 +55,9 @@
 struct init_action {
 	struct init_action *next;
 	pid_t pid;
-	uint8_t action;
+	uint8_t action_type;
 	char terminal[CONSOLE_NAME_SIZE];
-	char command[INIT_BUFFS_SIZE];
+	char command[COMMAND_SIZE];
 };
 
 /* Static variables */
@@ -294,14 +294,57 @@
 	set_sane_term();
 }
 
+/* wrapper around exec:
+ * takes string (max COMMAND_SIZE chars)
+ * runs [-]/bin/sh -c "exec ......." if '>' etc detected.
+ * otherwise splits words on whitespace and deals with leading dash.
+ */
+static void init_exec(const char *command)
+{
+	char *cmd[COMMAND_SIZE / 2];
+	char buf[COMMAND_SIZE + 6];  /* COMMAND_SIZE+strlen("exec ")+1 */
+	int dash = (command[0] == '-');
+
+	/* See if any special /bin/sh requiring characters are present */
+	if (strpbrk(command, "~`!$^&*()=|\\{}[];\"'<>?") != NULL) {
+		strcpy(buf, "exec ");
+		strcpy(buf + 5, command + dash); /* excluding "-" */
+		/* LIBBB_DEFAULT_LOGIN_SHELL has leading dash */
+		cmd[0] = (char*)(LIBBB_DEFAULT_LOGIN_SHELL + !dash);
+		cmd[1] = (char*)"-c";
+		cmd[2] = buf;
+		cmd[3] = NULL;
+	} else {
+		/* Convert command (char*) into cmd (char**, one word per string) */
+		char *word, *next;
+		int i = 0;
+		next = strcpy(buf, command); /* including "-" */
+		while ((word = strsep(&next, " \t")) != NULL) {
+			if (*word != '\0') { /* not two spaces/tabs together? */
+				cmd[i] = word;
+				i++;
+			}
+		}
+		cmd[i] = NULL;
+	}
+	/* If we saw leading "-", it is interactive shell.
+	 * Try harder to give it a controlling tty.
+	 * And skip "-" in actual exec call. */
+	if (dash) {
+		/* _Attempt_ to make stdin a controlling tty. */
+		if (ENABLE_FEATURE_INIT_SCTTY)
+			ioctl(STDIN_FILENO, TIOCSCTTY, 0 /*only try, don't steal*/);
+	}
+	BB_EXECVP(cmd[0] + dash, cmd);
+	message(L_LOG | L_CONSOLE, "Cannot run '%s': %s",
+			cmd[0], strerror(errno));
+	/* returns if execvp fails */
+}
+
 /* Used only by run_actions */
 static pid_t run(const struct init_action *a)
 {
-	int i;
 	pid_t pid;
-	char *s, *tmpCmd, *cmdpath;
-	char *cmd[INIT_BUFFS_SIZE];
-	char buf[INIT_BUFFS_SIZE + 6];	/* INIT_BUFFS_SIZE+strlen("exec ")+1 */
 	sigset_t nmask, omask;
 
 	/* Block sigchild while forking (why?) */
@@ -341,7 +384,7 @@
 #ifdef BUT_RUN_ACTIONS_ALREADY_DOES_WAITING
 	/* If the init Action requires us to wait, then force the
 	 * supplied terminal to be the controlling tty. */
-	if (a->action & (SYSINIT | WAIT | CTRLALTDEL | SHUTDOWN | RESTART)) {
+	if (a->action_type & (SYSINIT | WAIT | CTRLALTDEL | SHUTDOWN | RESTART)) {
 		/* Now fork off another process to just hang around */
 		pid = fork();
 		if (pid < 0) {
@@ -381,58 +424,7 @@
 		/* Child - fall though to actually execute things */
 	}
 #endif
-
-	/* See if any special /bin/sh requiring characters are present */
-	if (strpbrk(a->command, "~`!$^&*()=|\\{}[];\"'<>?") != NULL) {
-		cmd[0] = (char*)DEFAULT_SHELL;
-		cmd[1] = (char*)"-c";
-		cmd[2] = strcat(strcpy(buf, "exec "), a->command);
-		cmd[3] = NULL;
-	} else {
-		/* Convert command (char*) into cmd (char**, one word per string) */
-		strcpy(buf, a->command);
-		s = buf;
-		for (tmpCmd = buf, i = 0; (tmpCmd = strsep(&s, " \t")) != NULL;) {
-			if (*tmpCmd != '\0') {
-				cmd[i] = tmpCmd;
-				i++;
-			}
-		}
-		cmd[i] = NULL;
-	}
-
-	cmdpath = cmd[0];
-
-	/*
-	 * Interactive shells want to see a dash in argv[0].  This
-	 * typically is handled by login, argv will be setup this
-	 * way if a dash appears at the front of the command path
-	 * (like "-/bin/sh").
-	 */
-	if (*cmdpath == '-') {
-		/* skip over the dash */
-		++cmdpath;
-
-#ifdef WHY_WE_DO_THIS_SHELL_MUST_HANDLE_THIS_ITSELF
-		/* find the last component in the command pathname */
-		s = bb_get_last_path_component_nostrip(cmdpath);
-		/* make a new argv[0] */
-		cmd[0] = malloc(strlen(s) + 2);
-		if (cmd[0] == NULL) {
-			message(L_LOG | L_CONSOLE, bb_msg_memory_exhausted);
-			cmd[0] = cmdpath;
-		} else {
-			cmd[0][0] = '-';
-			strcpy(cmd[0] + 1, s);
-		}
-#endif
-
-		/* _Attempt_ to make stdin a controlling tty. */
-		if (ENABLE_FEATURE_INIT_SCTTY)
-			ioctl(0, TIOCSCTTY, 0 /*only try, don't steal*/);
-	}
-
-	if (a->action & ASKFIRST) {
+	if (a->action_type & ASKFIRST) {
 		static const char press_enter[] ALIGN1 =
 #ifdef CUSTOMIZED_BANNER
 #include CUSTOMIZED_BANNER
@@ -449,58 +441,54 @@
 		 */
 		messageD(L_LOG, "waiting for enter to start '%s'"
 					"(pid %d, tty '%s')\n",
-				  cmdpath, getpid(), a->terminal);
+				a->command, getpid(), a->terminal);
 		full_write(1, press_enter, sizeof(press_enter) - 1);
 		while (safe_read(0, &c, 1) == 1 && c != '\n')
 			continue;
 	}
 
-	/* Log the process name and args */
-	message(L_LOG, "starting pid %d, tty '%s': '%s'",
-			  getpid(), a->terminal, cmdpath);
-
 	if (ENABLE_FEATURE_INIT_COREDUMPS) {
 		struct stat sb;
 		if (stat(CORE_ENABLE_FLAG_FILE, &sb) == 0) {
 			struct rlimit limit;
-
 			limit.rlim_cur = RLIM_INFINITY;
 			limit.rlim_max = RLIM_INFINITY;
 			setrlimit(RLIMIT_CORE, &limit);
 		}
 	}
 
+	/* Log the process name and args */
+	message(L_LOG, "starting pid %d, tty '%s': '%s'",
+			  getpid(), a->terminal, a->command);
+
 	/* Now run it.  The new program will take over this PID,
 	 * so nothing further in init.c should be run. */
-	BB_EXECVP(cmdpath, cmd);
-
+	init_exec(a->command);
 	/* We're still here?  Some error happened. */
-	message(L_LOG | L_CONSOLE, "Cannot run '%s': %s",
-			cmdpath, strerror(errno));
 	_exit(-1);
 }
 
 /* Run all commands of a particular type */
-static void run_actions(int action)
+static void run_actions(int action_type)
 {
 	struct init_action *a, *tmp;
 
 	for (a = init_action_list; a; a = tmp) {
 		tmp = a->next;
-		if (a->action == action) {
+		if (a->action_type == action_type) {
 			// Pointless: run() will error out if open of device fails.
 			///* a->terminal of "" means "init's console" */
 			//if (a->terminal[0] && access(a->terminal, R_OK | W_OK)) {
 			//	//message(L_LOG | L_CONSOLE, "Device %s cannot be opened in RW mode", a->terminal /*, strerror(errno)*/);
 			//	delete_init_action(a);
 			//} else
-			if (a->action & (SYSINIT | WAIT | CTRLALTDEL | SHUTDOWN | RESTART)) {
+			if (a->action_type & (SYSINIT | WAIT | CTRLALTDEL | SHUTDOWN | RESTART)) {
 				waitfor(run(a));
 				delete_init_action(a);
-			} else if (a->action & ONCE) {
+			} else if (a->action_type & ONCE) {
 				run(a);
 				delete_init_action(a);
-			} else if (a->action & (RESPAWN | ASKFIRST)) {
+			} else if (a->action_type & (RESPAWN | ASKFIRST)) {
 				/* Only run stuff with pid==0.  If they have
 				 * a pid, that means it is still running */
 				if (a->pid == 0) {
@@ -593,12 +581,11 @@
  * else (no such action defined) do nothing */
 static void exec_restart_action(int sig ATTRIBUTE_UNUSED)
 {
-	struct init_action *a, *tmp;
+	struct init_action *a;
 	sigset_t unblock_signals;
 
-	for (a = init_action_list; a; a = tmp) {
-		tmp = a->next;
-		if (a->action & RESTART) {
+	for (a = init_action_list; a; a = a->next) {
+		if (a->action_type & RESTART) {
 			kill_all_processes();
 
 			/* unblock all signals (blocked in kill_all_processes()) */
@@ -620,10 +607,7 @@
 			open_stdio_to_tty(a->terminal, 0 /* - halt if open fails */);
 
 			messageD(L_CONSOLE | L_LOG, "Trying to re-exec %s", a->command);
-			BB_EXECLP(a->command, a->command, NULL);
-
-			message(L_CONSOLE | L_LOG, "Cannot run '%s': %s",
-					a->command, strerror(errno));
+			init_exec(a->command);
 			sleep(2);
 			init_reboot(RB_HALT_SYSTEM);
 			loop_forever();
@@ -654,12 +638,13 @@
 	got_cont = 1;
 }
 
-static void new_init_action(uint8_t action, const char *command, const char *cons)
+static void new_init_action(uint8_t action_type, const char *command, const char *cons)
 {
-	struct init_action *new_action, *a, *last;
+	struct init_action *a, *last;
 
-	if (strcmp(cons, bb_dev_null) == 0 && (action & ASKFIRST))
-		return;
+// Why?
+//	if (strcmp(cons, bb_dev_null) == 0 && (action & ASKFIRST))
+//		return;
 
 	/* Append to the end of the list */
 	for (a = last = init_action_list; a; a = a->next) {
@@ -668,23 +653,23 @@
 		if ((strcmp(a->command, command) == 0)
 		 && (strcmp(a->terminal, cons) == 0)
 		) {
-			a->action = action;
+			a->action_type = action_type;
 			return;
 		}
 		last = a;
 	}
 
-	new_action = xzalloc(sizeof(struct init_action));
+	a = xzalloc(sizeof(*a));
 	if (last) {
-		last->next = new_action;
+		last->next = a;
 	} else {
-		init_action_list = new_action;
+		init_action_list = a;
 	}
-	strcpy(new_action->command, command);
-	new_action->action = action;
-	strcpy(new_action->terminal, cons);
+	a->action_type = action_type;
+	safe_strncpy(a->command, command, sizeof(a->command));
+	safe_strncpy(a->terminal, cons, sizeof(a->terminal));
 	messageD(L_LOG | L_CONSOLE, "command='%s' action=%d tty='%s'\n",
-		new_action->command, new_action->action, new_action->terminal);
+		a->command, a->action_type, a->terminal);
 }
 
 static void delete_init_action(struct init_action *action)
@@ -714,7 +699,7 @@
 static void parse_inittab(void)
 {
 	FILE *file;
-	char buf[INIT_BUFFS_SIZE];
+	char buf[COMMAND_SIZE];
 
 	if (ENABLE_FEATURE_USE_INITTAB)
 		file = fopen(INITTAB, "r");
@@ -743,7 +728,7 @@
 		return;
 	}
 
-	while (fgets(buf, INIT_BUFFS_SIZE, file) != NULL) {
+	while (fgets(buf, COMMAND_SIZE, file) != NULL) {
 		static const char actions[] =
 			STR_SYSINIT    "sysinit\0"
 			STR_RESPAWN    "respawn\0"
@@ -810,7 +795,7 @@
 
 	/* disable old entrys */
 	for (a = init_action_list; a; a = a->next) {
-		a->action = ONCE;
+		a->action_type = ONCE;
 	}
 
 	parse_inittab();
@@ -819,7 +804,7 @@
 		/* Be nice and send SIGTERM first */
 		for (a = init_action_list; a; a = a->next) {
 			pid_t pid = a->pid;
-			if ((a->action & ONCE) && pid != 0) {
+			if ((a->action_type & ONCE) && pid != 0) {
 				kill(pid, SIGTERM);
 			}
 		}
@@ -828,7 +813,7 @@
 			sleep(CONFIG_FEATURE_KILL_DELAY);
 			for (a = init_action_list; a; a = a->next) {
 				pid_t pid = a->pid;
-				if ((a->action & ONCE) && pid != 0) {
+				if ((a->action_type & ONCE) && pid != 0) {
 					kill(pid, SIGKILL);
 				}
 			}
@@ -840,7 +825,7 @@
 	/* remove unused entrys */
 	for (a = init_action_list; a; a = tmp) {
 		tmp = a->next;
-		if ((a->action & (ONCE | SYSINIT | WAIT)) && a->pid == 0) {
+		if ((a->action_type & (ONCE | SYSINIT | WAIT)) && a->pid == 0) {
 			delete_init_action(a);
 		}
 	}
@@ -998,7 +983,7 @@
 					 * restarted by run_actions() */
 					a->pid = 0;
 					message(L_LOG, "process '%s' (pid %d) exited. "
-							"Scheduling it for restart.",
+							"Scheduling for restart.",
 							a->command, wpid);
 				}
 			}




More information about the busybox-cvs mailing list