svn commit: trunk/busybox: applets docs init shell

vda at busybox.net vda at busybox.net
Mon Dec 10 07:06:10 UTC 2007


Author: vda
Date: 2007-12-09 23:06:04 -0800 (Sun, 09 Dec 2007)
New Revision: 20635

Log:
init: remove superfluous forks and messing up with argv[0]
cttyhack: add stealing of ctty



Modified:
   trunk/busybox/applets/Kbuild
   trunk/busybox/docs/ctty.htm
   trunk/busybox/init/Config.in
   trunk/busybox/init/init.c
   trunk/busybox/shell/cttyhack.c


Changeset:
Modified: trunk/busybox/applets/Kbuild
===================================================================
--- trunk/busybox/applets/Kbuild	2007-12-10 07:03:38 UTC (rev 20634)
+++ trunk/busybox/applets/Kbuild	2007-12-10 07:06:04 UTC (rev 20635)
@@ -18,7 +18,8 @@
 
 applets/applets.o: include/usage_compressed.h include/applet_tables.h
 
-applets/usage:     .config $(srctree)/applets/usage_compressed
+applets/usage:         .config $(srctree)/applets/usage_compressed
+applets/applet_tables: .config
 
 quiet_cmd_gen_usage_compressed = GEN     include/usage_compressed.h
       cmd_gen_usage_compressed = $(srctree)/applets/usage_compressed include/usage_compressed.h applets

Modified: trunk/busybox/docs/ctty.htm
===================================================================
--- trunk/busybox/docs/ctty.htm	2007-12-10 07:03:38 UTC (rev 20634)
+++ trunk/busybox/docs/ctty.htm	2007-12-10 07:06:04 UTC (rev 20635)
@@ -365,7 +365,7 @@
 becomes its controlling tty.
 </p><p>The BSD approach is that one has to explicitly call
 </p><blockquote>
-<pre>ioctl(fd, TIOCSCTTY, ...);
+<pre>ioctl(fd, TIOCSCTTY, 0/1);
 </pre>
 </blockquote>
 
@@ -378,6 +378,8 @@
 (iii) maybe the tty should not already control some other session;
 if it does it is an error if we aren't root, or we steal the tty
 if we are all-powerful.
+[vda: correction: third parameter controls this: if 1, we steal tty from
+any such session, if 0, we don't steal]
 </p><p>Opening some terminal will give us a controlling tty,
 provided that (i) the current process is a session leader, and
 (ii) it does not yet have a controlling tty, and

Modified: trunk/busybox/init/Config.in
===================================================================
--- trunk/busybox/init/Config.in	2007-12-10 07:03:38 UTC (rev 20634)
+++ trunk/busybox/init/Config.in	2007-12-10 07:06:04 UTC (rev 20635)
@@ -37,6 +37,7 @@
 	  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.
+	  NB: using cttyhack applet may work better.
 
 config FEATURE_INIT_SYSLOG
 	bool "Enable init to write to syslog"

Modified: trunk/busybox/init/init.c
===================================================================
--- trunk/busybox/init/init.c	2007-12-10 07:03:38 UTC (rev 20634)
+++ trunk/busybox/init/init.c	2007-12-10 07:06:04 UTC (rev 20635)
@@ -47,31 +47,22 @@
 #define SHUTDOWN    0x040
 #define RESTART     0x080
 
-/* A mapping between "inittab" action name strings and action type codes. */
-struct init_action_type {
-	const char *name;
-	int action;
-};
+#define STR_SYSINIT     "\x01"
+#define STR_RESPAWN     "\x02"
+#define STR_ASKFIRST    "\x04"
+#define STR_WAIT        "\x08"
+#define STR_ONCE        "\x10"
+#define STR_CTRLALTDEL  "\x20"
+#define STR_SHUTDOWN    "\x40"
+#define STR_RESTART     "\x80"
 
-static const struct init_action_type actions[] = {
-	{"sysinit", SYSINIT},
-	{"respawn", RESPAWN},
-	{"askfirst", ASKFIRST},
-	{"wait", WAIT},
-	{"once", ONCE},
-	{"ctrlaltdel", CTRLALTDEL},
-	{"shutdown", SHUTDOWN},
-	{"restart", RESTART},
-	{0, 0}
-};
-
 /* Set up a linked list of init_actions, to be read from inittab */
 struct init_action {
 	struct init_action *next;
-	int action;
 	pid_t pid;
-	char command[INIT_BUFFS_SIZE];
+	uint8_t action;
 	char terminal[CONSOLE_NAME_SIZE];
+	char command[INIT_BUFFS_SIZE];
 };
 
 /* Static variables */
@@ -113,7 +104,7 @@
 
 /* Function prototypes */
 static void delete_init_action(struct init_action *a);
-static int waitfor(const struct init_action *a, pid_t pid);
+static int waitfor(pid_t pid);
 #if !ENABLE_DEBUG_INIT
 static void shutdown_signal(int sig);
 #endif
@@ -193,43 +184,6 @@
 	}
 }
 
-/* Set terminal settings to reasonable defaults */
-static void set_sane_term(void)
-{
-	struct termios tty;
-
-	tcgetattr(STDIN_FILENO, &tty);
-
-	/* set control chars */
-	tty.c_cc[VINTR] = 3;	/* C-c */
-	tty.c_cc[VQUIT] = 28;	/* C-\ */
-	tty.c_cc[VERASE] = 127;	/* C-? */
-	tty.c_cc[VKILL] = 21;	/* C-u */
-	tty.c_cc[VEOF] = 4;	/* C-d */
-	tty.c_cc[VSTART] = 17;	/* C-q */
-	tty.c_cc[VSTOP] = 19;	/* C-s */
-	tty.c_cc[VSUSP] = 26;	/* C-z */
-
-	/* use line dicipline 0 */
-	tty.c_line = 0;
-
-	/* Make it be sane */
-	tty.c_cflag &= CBAUD | CBAUDEX | CSIZE | CSTOPB | PARENB | PARODD;
-	tty.c_cflag |= CREAD | HUPCL | CLOCAL;
-
-	/* input modes */
-	tty.c_iflag = ICRNL | IXON | IXOFF;
-
-	/* output modes */
-	tty.c_oflag = OPOST | ONLCR;
-
-	/* local modes */
-	tty.c_lflag =
-		ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOKE | IEXTEN;
-
-	tcsetattr(STDIN_FILENO, TCSANOW, &tty);
-}
-
 /* From <linux/serial.h> */
 struct serial_struct {
 	int	type;
@@ -277,7 +231,7 @@
 
 	s = getenv("TERM");
 	if (ioctl(0, TIOCGSERIAL, &sr) == 0) {
-		/* Force the TERM setting to vt102 for serial console --
+		/* Force the TERM setting to vt102 for serial console
 		 * if TERM is set to linux (the default) */
 		if (!s || strcmp(s, "linux") == 0)
 			putenv((char*)"TERM=vt102");
@@ -288,14 +242,41 @@
 		putenv((char*)"TERM=linux");
 }
 
-static void fixup_argv(char **argv)
+/* Set terminal settings to reasonable defaults */
+static void set_sane_term(void)
 {
-	/* Fix up argv[0] to be certain we claim to be init */
-	strncpy(argv[0], "init", strlen(argv[0]));
+	struct termios tty;
 
-	/* Wipe argv[1]-argv[N] so they don't clutter the ps listing */
-	while (*++argv)
-		memset(*argv, 0, strlen(*argv));
+	tcgetattr(STDIN_FILENO, &tty);
+
+	/* set control chars */
+	tty.c_cc[VINTR] = 3;	/* C-c */
+	tty.c_cc[VQUIT] = 28;	/* C-\ */
+	tty.c_cc[VERASE] = 127;	/* C-? */
+	tty.c_cc[VKILL] = 21;	/* C-u */
+	tty.c_cc[VEOF] = 4;	/* C-d */
+	tty.c_cc[VSTART] = 17;	/* C-q */
+	tty.c_cc[VSTOP] = 19;	/* C-s */
+	tty.c_cc[VSUSP] = 26;	/* C-z */
+
+	/* use line dicipline 0 */
+	tty.c_line = 0;
+
+	/* Make it be sane */
+	tty.c_cflag &= CBAUD | CBAUDEX | CSIZE | CSTOPB | PARENB | PARODD;
+	tty.c_cflag |= CREAD | HUPCL | CLOCAL;
+
+	/* input modes */
+	tty.c_iflag = ICRNL | IXON | IXOFF;
+
+	/* output modes */
+	tty.c_oflag = OPOST | ONLCR;
+
+	/* local modes */
+	tty.c_lflag =
+		ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOKE | IEXTEN;
+
+	tcsetattr(STDIN_FILENO, TCSANOW, &tty);
 }
 
 /* Open the new terminal device */
@@ -324,6 +305,7 @@
 	set_sane_term();
 }
 
+/* Used only by run_actions */
 static pid_t run(const struct init_action *a)
 {
 	int i;
@@ -333,16 +315,20 @@
 	char buf[INIT_BUFFS_SIZE + 6];	/* INIT_BUFFS_SIZE+strlen("exec ")+1 */
 	sigset_t nmask, omask;
 
-	/* Block sigchild while forking.  */
+	/* Block sigchild while forking (why?) */
 	sigemptyset(&nmask);
 	sigaddset(&nmask, SIGCHLD);
 	sigprocmask(SIG_BLOCK, &nmask, &omask);
 	pid = fork();
 	sigprocmask(SIG_SETMASK, &omask, NULL);
 
+	if (pid < 0)
+		message(L_LOG | L_CONSOLE, "Can't fork");
 	if (pid)
 		return pid;
 
+	/* Child */
+
 	/* Reset signal handlers that were set by the parent process */
 	signal(SIGUSR1, SIG_DFL);
 	signal(SIGUSR2, SIG_DFL);
@@ -359,8 +345,9 @@
 	setsid();
 
 	/* Open the new terminal device */
-	open_stdio_to_tty(a->terminal, 1);
+	open_stdio_to_tty(a->terminal, 1 /* - exit if open fails*/);
 
+#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)) {
@@ -373,13 +360,13 @@
 		}
 
 		if (pid > 0) {
-			/* We are the parent -- wait till the child is done */
+			/* Parent - wait till the child is done */
 			signal(SIGINT, SIG_IGN);
 			signal(SIGTSTP, SIG_IGN);
 			signal(SIGQUIT, SIG_IGN);
 			signal(SIGCHLD, SIG_DFL);
 
-			waitfor(NULL, pid);
+			waitfor(pid);
 			/* See if stealing the controlling tty back is necessary */
 			if (tcgetpgrp(0) != getpid())
 				_exit(0);
@@ -395,12 +382,13 @@
 				ioctl(0, TIOCSCTTY, 1);
 				_exit(0);
 			}
-			waitfor(NULL, pid);
+			waitfor(pid);
 			_exit(0);
 		}
 
-		/* Now fall though to actually execute things */
+		/* Child - fall though to actually execute things */
 	}
+#endif
 
 	/* See if any special /bin/sh requiring characters are present */
 	if (strpbrk(a->command, "~`!$^&*()=|\\{}[];\"'<>?") != NULL) {
@@ -433,9 +421,9 @@
 		/* 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) {
@@ -445,16 +433,16 @@
 			cmd[0][0] = '-';
 			strcpy(cmd[0] + 1, s);
 		}
+#endif
+
 #if ENABLE_FEATURE_INIT_SCTTY
 		/* Establish this process as session leader and
-		 * (attempt) to make the tty (if any) a controlling tty.
+		 * _attempt_ to make stdin a controlling tty.
 		 */
-		setsid();
-		ioctl(0, TIOCSCTTY, 0 /*don't steal it*/);
+		ioctl(0, TIOCSCTTY, 0 /*only try, don't steal*/);
 #endif
 	}
 
-#if !defined(__UCLIBC__) || defined(__ARCH_HAS_MMU__)
 	if (a->action & ASKFIRST) {
 		static const char press_enter[] ALIGN1 =
 #ifdef CUSTOMIZED_BANNER
@@ -474,10 +462,10 @@
 					"(pid %d, tty '%s')\n",
 				  cmdpath, getpid(), a->terminal);
 		full_write(1, press_enter, sizeof(press_enter) - 1);
-		while (read(0, &c, 1) == 1 && c != '\n')
-			;
+		while (safe_read(0, &c, 1) == 1 && c != '\n')
+			continue;
 	}
-#endif
+
 	/* Log the process name and args */
 	message(L_LOG, "starting pid %d, tty '%s': '%s'",
 			  getpid(), a->terminal, cmdpath);
@@ -504,22 +492,15 @@
 	_exit(-1);
 }
 
-static int waitfor(const struct init_action *a, pid_t pid)
+static int waitfor(pid_t runpid)
 {
-	int runpid;
 	int status, wpid;
 
-	runpid = (NULL == a)? pid : run(a);
 	while (1) {
 		wpid = waitpid(runpid, &status, 0);
-		if (wpid == runpid)
-			break;
-		if (wpid == -1 && errno == ECHILD) {
-			/* we missed its termination */
-			break;
-		}
-		/* FIXME other errors should maybe trigger an error, but allow
-		 * the program to continue */
+		if (wpid == -1 && errno == EINTR)
+			continue;
+		break;
 	}
 	return wpid;
 }
@@ -534,9 +515,10 @@
 		if (a->action == action) {
 			/* 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)) {
-				waitfor(a, 0);
+				waitfor(run(a));
 				delete_init_action(a);
 			} else if (a->action & ONCE) {
 				run(a);
@@ -607,6 +589,29 @@
 	sleep(1);
 }
 
+static void shutdown_signal(int sig)
+{
+	const char *m;
+	int rb;
+
+	shutdown_system();
+
+	m = "halt";
+	rb = RB_HALT_SYSTEM;
+	if (sig == SIGTERM) {
+		m = "reboot";
+		rb = RB_AUTOBOOT;
+	} else if (sig == SIGUSR2) {
+		m = "poweroff";
+		rb = RB_POWER_OFF;
+	}
+	message(L_CONSOLE | L_LOG, "Requesting system %s", m);
+	/* allow time for last message to reach serial console */
+	sleep(2);
+	init_reboot(rb);
+	loop_forever();
+}
+
 static void exec_signal(int sig ATTRIBUTE_UNUSED)
 {
 	struct init_action *a, *tmp;
@@ -632,7 +637,7 @@
 			sigprocmask(SIG_UNBLOCK, &unblock_signals, NULL);
 
 			/* Open the new terminal device */
-			open_stdio_to_tty(a->terminal, 0);
+			open_stdio_to_tty(a->terminal, 0 /* - shutdown_signal(SIGUSR1) [halt] if open fails */);
 
 			messageD(L_CONSOLE | L_LOG, "Trying to re-exec %s", a->command);
 			BB_EXECLP(a->command, a->command, NULL);
@@ -646,29 +651,6 @@
 	}
 }
 
-static void shutdown_signal(int sig)
-{
-	const char *m;
-	int rb;
-
-	shutdown_system();
-
-	m = "halt";
-	rb = RB_HALT_SYSTEM;
-	if (sig == SIGTERM) {
-		m = "reboot";
-		rb = RB_AUTOBOOT;
-	} else if (sig == SIGUSR2) {
-		m = "poweroff";
-		rb = RB_POWER_OFF;
-	}
-	message(L_CONSOLE | L_LOG, "Requesting system %s", m);
-	/* allow time for last message to reach serial console */
-	sleep(2);
-	init_reboot(rb);
-	loop_forever();
-}
-
 static void ctrlaltdel_signal(int sig ATTRIBUTE_UNUSED)
 {
 	run_actions(CTRLALTDEL);
@@ -682,7 +664,7 @@
 	got_cont = 0;
 	while (!got_cont)
 		pause();
-	got_cont = 0;
+
 	errno = saved_errno;
 }
 
@@ -694,7 +676,7 @@
 
 #endif	/* !ENABLE_DEBUG_INIT */
 
-static void new_init_action(int action, const char *command, const char *cons)
+static void new_init_action(uint8_t action, const char *command, const char *cons)
 {
 	struct init_action *new_action, *a, *last;
 
@@ -754,11 +736,21 @@
 static void parse_inittab(void)
 {
 #if ENABLE_FEATURE_USE_INITTAB
+	static const char actions[] =
+		STR_SYSINIT    "sysinit\0"
+		STR_RESPAWN    "respawn\0"
+		STR_ASKFIRST   "askfirst\0"
+		STR_WAIT       "wait\0"
+		STR_ONCE       "once\0"
+		STR_CTRLALTDEL "ctrlaltdel\0"
+		STR_SHUTDOWN   "shutdown\0"
+		STR_RESTART    "restart\0"
+	;
+
 	FILE *file;
 	char buf[INIT_BUFFS_SIZE], lineAsRead[INIT_BUFFS_SIZE];
 	char tmpConsole[CONSOLE_NAME_SIZE];
 	char *id, *runlev, *action, *command, *eol;
-	const struct init_action_type *a = actions;
 
 	file = fopen(INITTAB, "r");
 	if (file == NULL) {
@@ -769,7 +761,8 @@
 		/* Umount all filesystems on halt/reboot */
 		new_init_action(SHUTDOWN, "umount -a -r", "");
 		/* Swapoff on halt/reboot */
-		if (ENABLE_SWAPONOFF) new_init_action(SHUTDOWN, "swapoff -a", "");
+		if (ENABLE_SWAPONOFF)
+			new_init_action(SHUTDOWN, "swapoff -a", "");
 		/* Prepare to restart init when a HUP is received */
 		new_init_action(RESTART, "init", "");
 		/* Askfirst shell on tty1-4 */
@@ -785,6 +778,8 @@
 	}
 
 	while (fgets(buf, INIT_BUFFS_SIZE, file) != NULL) {
+		const char *a;
+
 		/* Skip leading spaces */
 		for (id = buf; *id == ' ' || *id == '\t'; id++);
 
@@ -832,8 +827,8 @@
 		}
 
 		/* Ok, now process it */
-		for (a = actions; a->name != 0; a++) {
-			if (strcmp(a->name, action) == 0) {
+		for (a = actions; a[0]; a += strlen(a) + 1) {
+			if (strcmp(a + 1, action) == 0) {
 				if (*id != '\0') {
 					if (strncmp(id, "/dev/", 5) == 0)
 						id += 5;
@@ -842,11 +837,11 @@
 						sizeof(tmpConsole) - 5);
 					id = tmpConsole;
 				}
-				new_init_action(a->action, command, id);
+				new_init_action((uint8_t)a[0], command, id);
 				break;
 			}
 		}
-		if (a->name == 0) {
+		if (!a[0]) {
 			/* Choke on an unknown action */
 			message(L_LOG | L_CONSOLE, "Bad inittab entry: %s", lineAsRead);
 		}
@@ -981,8 +976,11 @@
 	}
 #endif /* CONFIG_SELINUX */
 
-	/* Make the command line just say "init"  -- thats all, nothing else */
-	fixup_argv(argv);
+	/* 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)
+		memset(*argv, 0, strlen(*argv));
 
 	/* Now run everything that needs to be run */
 

Modified: trunk/busybox/shell/cttyhack.c
===================================================================
--- trunk/busybox/shell/cttyhack.c	2007-12-10 07:03:38 UTC (rev 20634)
+++ trunk/busybox/shell/cttyhack.c	2007-12-10 07:06:04 UTC (rev 20635)
@@ -1,16 +1,18 @@
-/* This code is adapted from busybox project
+/* vi: set sw=4 ts=4: */
+/*
+ * Licensed under GPLv2
  *
- * Licensed under GPLv2
+ * Copyright (c) 2007 Denys Vlasenko <vda.linux at googlemail.com>
  */
 #include "libbb.h"
 
 /* From <linux/vt.h> */
 struct vt_stat {
-	unsigned short v_active;	/* active vt */
-	unsigned short v_signal;	/* signal to send */
-	unsigned short v_state;	/* vt bitmask */
+	unsigned short v_active;        /* active vt */
+	unsigned short v_signal;        /* signal to send */
+	unsigned short v_state;         /* vt bitmask */
 };
-enum { VT_GETSTATE = 0x5603 };	/* get global vt state info */
+enum { VT_GETSTATE = 0x5603 }; /* get global vt state info */
 
 /* From <linux/serial.h> */
 struct serial_struct {
@@ -26,8 +28,8 @@
 	char	io_type;
 	char	reserved_char[1];
 	int	hub6;
-	unsigned short	closing_wait; /* time to wait before closing */
-	unsigned short	closing_wait2; /* no longer used... */
+	unsigned short	closing_wait;   /* time to wait before closing */
+	unsigned short	closing_wait2;  /* no longer used... */
 	unsigned char	*iomem_base;
 	unsigned short	iomem_reg_shift;
 	unsigned int	port_high;
@@ -66,8 +68,10 @@
 		dup2(fd, 1);
 		dup2(fd, 2);
 		while (fd > 2) close(fd--);
+		/* Some other session may have it as ctty. Steal it from them */
+		ioctl(0, TIOCSCTTY, 1)
 	}
 
-	execvp(argv[0], argv);
+	BB_EXECVP(argv[0], argv);
 	bb_perror_msg_and_die("cannot exec '%s'", argv[0]);
 }




More information about the busybox-cvs mailing list