[git commit] hush: kill builtin and kill %jobspec support

Denys Vlasenko vda.linux at googlemail.com
Sun Jan 8 16:19:38 UTC 2017


commit: https://git.busybox.net/busybox/commit/?id=1125d7d6801940a5218b74c8fd46f1eaa2e4de39
branch: https://git.busybox.net/busybox/commit/?id=refs/heads/master

Also made it and printf, type and wait builtins optional.

function                                             old     new   delta
builtin_kill                                           -     323    +323
bltins1                                              336     348     +12
builtin_type                                         114     116      +2
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 2/0 up/down: 337/0)             Total: 337 bytes

Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 coreutils/Kbuild.src |   5 +-
 procps/Kbuild.src    |   2 +
 procps/kill.c        |   4 +-
 shell/hush.c         | 134 +++++++++++++++++++++++++++++++++++++++++++++++++--
 4 files changed, 138 insertions(+), 7 deletions(-)

diff --git a/coreutils/Kbuild.src b/coreutils/Kbuild.src
index d9a4487..9ac6b9e 100644
--- a/coreutils/Kbuild.src
+++ b/coreutils/Kbuild.src
@@ -15,11 +15,14 @@ lib-$(CONFIG_LESS)          += cat.o   # less too
 lib-$(CONFIG_CRONTAB)       += cat.o   # crontab -l
 lib-$(CONFIG_ADDUSER)       += chown.o # used by adduser
 lib-$(CONFIG_ADDGROUP)      += chown.o # used by adduser
+lib-$(CONFIG_FTPD)          += ls.o    # used by ftpd
+
 lib-$(CONFIG_ASH)           += echo.o  # used by ash
 lib-$(CONFIG_SH_IS_ASH)     += echo.o  # used by ash
 lib-$(CONFIG_BASH_IS_ASH)   += echo.o  # used by ash
 lib-$(CONFIG_HUSH)          += echo.o  # used by hush
 lib-$(CONFIG_SH_IS_HUSH)    += echo.o  # used by hush
 lib-$(CONFIG_BASH_IS_HUSH)  += echo.o  # used by hush
-lib-$(CONFIG_FTPD)          += ls.o    # used by ftpd
+
 lib-$(CONFIG_ASH_BUILTIN_PRINTF) += printf.o
+lib-$(CONFIG_HUSH_PRINTF) += printf.o
diff --git a/procps/Kbuild.src b/procps/Kbuild.src
index e7adc73..82f37f0 100644
--- a/procps/Kbuild.src
+++ b/procps/Kbuild.src
@@ -11,3 +11,5 @@ INSERT
 lib-$(CONFIG_ASH) += kill.o  # used for built-in kill by ash
 lib-$(CONFIG_SH_IS_ASH) += kill.o  # used for built-in kill by ash
 lib-$(CONFIG_BASH_IS_ASH) += kill.o  # used for built-in kill by ash
+
+lib-$(CONFIG_HUSH_KILL) += kill.o  # used for built-in kill by hush
diff --git a/procps/kill.c b/procps/kill.c
index 36cd22f..579c8e5 100644
--- a/procps/kill.c
+++ b/procps/kill.c
@@ -285,8 +285,8 @@ int kill_main(int argc UNUSED_PARAM, char **argv)
 
 	/* Looks like they want to do a kill. Do that */
 	while (arg) {
-#if ENABLE_ASH  || ENABLE_SH_IS_ASH  || ENABLE_BASH_IS_ASH \
- || ENABLE_HUSH || ENABLE_SH_IS_HUSH || ENABLE_BASH_IS_HUSH
+#if ENABLE_ASH || ENABLE_SH_IS_ASH || ENABLE_BASH_IS_ASH \
+ || ENABLE_HUSH_KILL
 		/*
 		 * We need to support shell's "hack formats" of
 		 * " -PRGP_ID" (yes, with a leading space)
diff --git a/shell/hush.c b/shell/hush.c
index 58132ef..9aafb4d 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -44,12 +44,12 @@
  *      special variables (done: PWD, PPID, RANDOM)
  *      tilde expansion
  *      aliases
- *      kill %jobspec
  *      follow IFS rules more precisely, including update semantics
  *      builtins mandated by standards we don't support:
  *          [un]alias, command, fc, getopts, newgrp, readonly, times
  *      make complex ${var%...} constructs support optional
  *      make here documents optional
+ *      make trap, read, ulimit builtins optional
  *
  * Bash compat TODO:
  *      redirection of stdout+stderr: &> and >&
@@ -117,6 +117,34 @@
 //config:	help
 //config:	  Enable help builtin in hush. Code size + ~1 kbyte.
 //config:
+//config:config HUSH_PRINTF
+//config:	bool "printf builtin"
+//config:	default y
+//config:	depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
+//config:	help
+//config:	  Enable printf builtin in hush.
+//config:
+//config:config HUSH_KILL
+//config:	bool "kill builtin (for kill %jobspec)"
+//config:	default y
+//config:	depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
+//config:	help
+//config:	  Enable kill builtin in hush.
+//config:
+//config:config HUSH_WAIT
+//config:	bool "wait builtin"
+//config:	default y
+//config:	depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
+//config:	help
+//config:	  Enable wait builtin in hush.
+//config:
+//config:config HUSH_TYPE
+//config:	bool "type builtin"
+//config:	default y
+//config:	depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
+//config:	help
+//config:	  Enable type builtin in hush.
+//config:
 //config:config HUSH_INTERACTIVE
 //config:	bool "Interactive mode"
 //config:	default y
@@ -860,7 +888,7 @@ static int builtin_local(char **argv) FAST_FUNC;
 #if HUSH_DEBUG
 static int builtin_memleak(char **argv) FAST_FUNC;
 #endif
-#if ENABLE_PRINTF
+#if ENABLE_HUSH_PRINTF
 static int builtin_printf(char **argv) FAST_FUNC;
 #endif
 static int builtin_pwd(char **argv) FAST_FUNC;
@@ -870,11 +898,18 @@ static int builtin_shift(char **argv) FAST_FUNC;
 static int builtin_source(char **argv) FAST_FUNC;
 static int builtin_test(char **argv) FAST_FUNC;
 static int builtin_trap(char **argv) FAST_FUNC;
+#if ENABLE_HUSH_TYPE
 static int builtin_type(char **argv) FAST_FUNC;
+#endif
 static int builtin_true(char **argv) FAST_FUNC;
 static int builtin_umask(char **argv) FAST_FUNC;
 static int builtin_unset(char **argv) FAST_FUNC;
+#if ENABLE_HUSH_KILL
+static int builtin_kill(char **argv) FAST_FUNC;
+#endif
+#if ENABLE_HUSH_WAIT
 static int builtin_wait(char **argv) FAST_FUNC;
+#endif
 #if ENABLE_HUSH_LOOPS
 static int builtin_break(char **argv) FAST_FUNC;
 static int builtin_continue(char **argv) FAST_FUNC;
@@ -929,6 +964,9 @@ static const struct built_in_command bltins1[] = {
 #if ENABLE_HUSH_JOB
 	BLTIN("jobs"     , builtin_jobs    , "List jobs"),
 #endif
+#if ENABLE_HUSH_KILL
+	BLTIN("kill"     , builtin_kill    , "Send signals to processes"),
+#endif
 #if ENABLE_HUSH_LOCAL
 	BLTIN("local"    , builtin_local   , "Set local variables"),
 #endif
@@ -946,18 +984,22 @@ static const struct built_in_command bltins1[] = {
 #endif
 	BLTIN("trap"     , builtin_trap    , "Trap signals"),
 	BLTIN("true"     , builtin_true    , NULL),
+#if ENABLE_HUSH_TYPE
 	BLTIN("type"     , builtin_type    , "Show command type"),
+#endif
 	BLTIN("ulimit"   , shell_builtin_ulimit  , "Control resource limits"),
 	BLTIN("umask"    , builtin_umask   , "Set file creation mask"),
 	BLTIN("unset"    , builtin_unset   , "Unset variables"),
+#if ENABLE_HUSH_WAIT
 	BLTIN("wait"     , builtin_wait    , "Wait for process"),
+#endif
 };
 /* For now, echo and test are unconditionally enabled.
  * Maybe make it configurable? */
 static const struct built_in_command bltins2[] = {
 	BLTIN("["        , builtin_test    , NULL),
 	BLTIN("echo"     , builtin_echo    , NULL),
-#if ENABLE_PRINTF
+#if ENABLE_HUSH_PRINTF
 	BLTIN("printf"   , builtin_printf  , NULL),
 #endif
 	BLTIN("pwd"      , builtin_pwd     , NULL),
@@ -8689,7 +8731,7 @@ static int FAST_FUNC builtin_echo(char **argv)
 	return run_applet_main(argv, echo_main);
 }
 
-#if ENABLE_PRINTF
+#if ENABLE_HUSH_PRINTF
 static int FAST_FUNC builtin_printf(char **argv)
 {
 	return run_applet_main(argv, printf_main);
@@ -9227,6 +9269,7 @@ static int FAST_FUNC builtin_trap(char **argv)
 	goto process_sig_list;
 }
 
+#if ENABLE_HUSH_TYPE
 /* http://www.opengroup.org/onlinepubs/9699919799/utilities/type.html */
 static int FAST_FUNC builtin_type(char **argv)
 {
@@ -9259,6 +9302,7 @@ static int FAST_FUNC builtin_type(char **argv)
 
 	return ret;
 }
+#endif
 
 #if ENABLE_HUSH_JOB
 static struct pipe *parse_jobspec(const char *str)
@@ -9526,6 +9570,87 @@ static int FAST_FUNC builtin_umask(char **argv)
 	return !rc; /* rc != 0 - success */
 }
 
+#if ENABLE_HUSH_KILL
+static int FAST_FUNC builtin_kill(char **argv)
+{
+	int ret = 0;
+
+	argv = skip_dash_dash(argv);
+	if (argv[0] && strcmp(argv[0], "-l") != 0) {
+		int i = 0;
+
+		do {
+			struct pipe *pi;
+			char *dst;
+			int j, n;
+
+			if (argv[i][0] != '%')
+				continue;
+			/*
+			 * "kill %N" - job kill
+			 * Converting to pgrp / pid kill
+			 */
+			pi = parse_jobspec(argv[i]);
+			if (!pi) {
+				/* Eat bad jobspec */
+				j = i;
+				do {
+					j++;
+					argv[j - 1] = argv[j];
+				} while (argv[j]);
+				ret = 1;
+				i--;
+				continue;
+			}
+			/*
+			 * In jobs started under job control, we signal
+			 * entire process group by kill -PGRP_ID.
+			 * This happens, f.e., in interactive shell.
+			 *
+			 * Otherwise, we signal each child via
+			 * kill PID1 PID2 PID3.
+			 * Testcases:
+			 * sh -c 'sleep 1|sleep 1 & kill %1'
+			 * sh -c 'true|sleep 2 & sleep 1; kill %1'
+			 * sh -c 'true|sleep 1 & sleep 2; kill %1'
+			 */
+			n = pi->num_cmds;
+			if (ENABLE_HUSH_JOB && G_interactive_fd)
+				n = 1;
+			dst = alloca(n * sizeof(int)*4);
+			argv[i] = dst;
+#if ENABLE_HUSH_JOB
+			if (G_interactive_fd)
+				dst += sprintf(dst, " -%u", (int)pi->pgrp);
+			else
+#endif
+			for (j = 0; j < n; j++) {
+				struct command *cmd = &pi->cmds[j];
+				/* Skip exited members of the job */
+				if (cmd->pid == 0)
+					continue;
+				/*
+				 * kill_main has matching code to expect
+				 * leading space. Needed to not confuse
+				 * negative pids with "kill -SIGNAL_NO" syntax
+				 */
+				dst += sprintf(dst, " %u", (int)cmd->pid);
+			}
+			*dst = '\0';
+		} while (argv[++i]);
+	}
+
+	if (argv[0] || ret == 0) {
+		argv--;
+		argv[0] = (char*)"kill"; /* why? think about "kill -- PID" */
+		/* kill_main also handles "killall" etc, so it does look at argv[0]! */
+		ret = run_applet_main(argv, kill_main);
+	}
+	return ret;
+}
+#endif
+
+#if ENABLE_HUSH_WAIT
 /* http://www.opengroup.org/onlinepubs/9699919799/utilities/wait.html */
 #if !ENABLE_HUSH_JOB
 # define wait_for_child_or_signal(pipe,pid) wait_for_child_or_signal(pid)
@@ -9686,6 +9811,7 @@ static int FAST_FUNC builtin_wait(char **argv)
 
 	return ret;
 }
+#endif
 
 #if ENABLE_HUSH_LOOPS || ENABLE_HUSH_FUNCTIONS
 static unsigned parse_numeric_argv1(char **argv, unsigned def, unsigned def_min)


More information about the busybox-cvs mailing list