aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2017-01-08 17:19:38 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2017-01-08 17:19:38 +0100
commit1125d7d6801940a5218b74c8fd46f1eaa2e4de39 (patch)
treeec8b07c2799e6d538f0aaf63ab51497904580504
parentd5b5c2fa151d318fa96778d5871e23ede312e5fa (diff)
downloadbusybox-w32-1125d7d6801940a5218b74c8fd46f1eaa2e4de39.tar.gz
busybox-w32-1125d7d6801940a5218b74c8fd46f1eaa2e4de39.tar.bz2
busybox-w32-1125d7d6801940a5218b74c8fd46f1eaa2e4de39.zip
hush: kill builtin and kill %jobspec support
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@googlemail.com>
-rw-r--r--coreutils/Kbuild.src5
-rw-r--r--procps/Kbuild.src2
-rw-r--r--procps/kill.c4
-rw-r--r--shell/hush.c134
4 files changed, 138 insertions, 7 deletions
diff --git a/coreutils/Kbuild.src b/coreutils/Kbuild.src
index d9a448781..9ac6b9e78 100644
--- a/coreutils/Kbuild.src
+++ b/coreutils/Kbuild.src
@@ -15,11 +15,14 @@ lib-$(CONFIG_LESS) += cat.o # less too
15lib-$(CONFIG_CRONTAB) += cat.o # crontab -l 15lib-$(CONFIG_CRONTAB) += cat.o # crontab -l
16lib-$(CONFIG_ADDUSER) += chown.o # used by adduser 16lib-$(CONFIG_ADDUSER) += chown.o # used by adduser
17lib-$(CONFIG_ADDGROUP) += chown.o # used by adduser 17lib-$(CONFIG_ADDGROUP) += chown.o # used by adduser
18lib-$(CONFIG_FTPD) += ls.o # used by ftpd
19
18lib-$(CONFIG_ASH) += echo.o # used by ash 20lib-$(CONFIG_ASH) += echo.o # used by ash
19lib-$(CONFIG_SH_IS_ASH) += echo.o # used by ash 21lib-$(CONFIG_SH_IS_ASH) += echo.o # used by ash
20lib-$(CONFIG_BASH_IS_ASH) += echo.o # used by ash 22lib-$(CONFIG_BASH_IS_ASH) += echo.o # used by ash
21lib-$(CONFIG_HUSH) += echo.o # used by hush 23lib-$(CONFIG_HUSH) += echo.o # used by hush
22lib-$(CONFIG_SH_IS_HUSH) += echo.o # used by hush 24lib-$(CONFIG_SH_IS_HUSH) += echo.o # used by hush
23lib-$(CONFIG_BASH_IS_HUSH) += echo.o # used by hush 25lib-$(CONFIG_BASH_IS_HUSH) += echo.o # used by hush
24lib-$(CONFIG_FTPD) += ls.o # used by ftpd 26
25lib-$(CONFIG_ASH_BUILTIN_PRINTF) += printf.o 27lib-$(CONFIG_ASH_BUILTIN_PRINTF) += printf.o
28lib-$(CONFIG_HUSH_PRINTF) += printf.o
diff --git a/procps/Kbuild.src b/procps/Kbuild.src
index e7adc7340..82f37f0df 100644
--- a/procps/Kbuild.src
+++ b/procps/Kbuild.src
@@ -11,3 +11,5 @@ INSERT
11lib-$(CONFIG_ASH) += kill.o # used for built-in kill by ash 11lib-$(CONFIG_ASH) += kill.o # used for built-in kill by ash
12lib-$(CONFIG_SH_IS_ASH) += kill.o # used for built-in kill by ash 12lib-$(CONFIG_SH_IS_ASH) += kill.o # used for built-in kill by ash
13lib-$(CONFIG_BASH_IS_ASH) += kill.o # used for built-in kill by ash 13lib-$(CONFIG_BASH_IS_ASH) += kill.o # used for built-in kill by ash
14
15lib-$(CONFIG_HUSH_KILL) += kill.o # used for built-in kill by hush
diff --git a/procps/kill.c b/procps/kill.c
index 36cd22f37..579c8e53c 100644
--- a/procps/kill.c
+++ b/procps/kill.c
@@ -285,8 +285,8 @@ int kill_main(int argc UNUSED_PARAM, char **argv)
285 285
286 /* Looks like they want to do a kill. Do that */ 286 /* Looks like they want to do a kill. Do that */
287 while (arg) { 287 while (arg) {
288#if ENABLE_ASH || ENABLE_SH_IS_ASH || ENABLE_BASH_IS_ASH \ 288#if ENABLE_ASH || ENABLE_SH_IS_ASH || ENABLE_BASH_IS_ASH \
289 || ENABLE_HUSH || ENABLE_SH_IS_HUSH || ENABLE_BASH_IS_HUSH 289 || ENABLE_HUSH_KILL
290 /* 290 /*
291 * We need to support shell's "hack formats" of 291 * We need to support shell's "hack formats" of
292 * " -PRGP_ID" (yes, with a leading space) 292 * " -PRGP_ID" (yes, with a leading space)
diff --git a/shell/hush.c b/shell/hush.c
index 58132ef17..9aafb4d25 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -44,12 +44,12 @@
44 * special variables (done: PWD, PPID, RANDOM) 44 * special variables (done: PWD, PPID, RANDOM)
45 * tilde expansion 45 * tilde expansion
46 * aliases 46 * aliases
47 * kill %jobspec
48 * follow IFS rules more precisely, including update semantics 47 * follow IFS rules more precisely, including update semantics
49 * builtins mandated by standards we don't support: 48 * builtins mandated by standards we don't support:
50 * [un]alias, command, fc, getopts, newgrp, readonly, times 49 * [un]alias, command, fc, getopts, newgrp, readonly, times
51 * make complex ${var%...} constructs support optional 50 * make complex ${var%...} constructs support optional
52 * make here documents optional 51 * make here documents optional
52 * make trap, read, ulimit builtins optional
53 * 53 *
54 * Bash compat TODO: 54 * Bash compat TODO:
55 * redirection of stdout+stderr: &> and >& 55 * redirection of stdout+stderr: &> and >&
@@ -117,6 +117,34 @@
117//config: help 117//config: help
118//config: Enable help builtin in hush. Code size + ~1 kbyte. 118//config: Enable help builtin in hush. Code size + ~1 kbyte.
119//config: 119//config:
120//config:config HUSH_PRINTF
121//config: bool "printf builtin"
122//config: default y
123//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
124//config: help
125//config: Enable printf builtin in hush.
126//config:
127//config:config HUSH_KILL
128//config: bool "kill builtin (for kill %jobspec)"
129//config: default y
130//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
131//config: help
132//config: Enable kill builtin in hush.
133//config:
134//config:config HUSH_WAIT
135//config: bool "wait builtin"
136//config: default y
137//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
138//config: help
139//config: Enable wait builtin in hush.
140//config:
141//config:config HUSH_TYPE
142//config: bool "type builtin"
143//config: default y
144//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
145//config: help
146//config: Enable type builtin in hush.
147//config:
120//config:config HUSH_INTERACTIVE 148//config:config HUSH_INTERACTIVE
121//config: bool "Interactive mode" 149//config: bool "Interactive mode"
122//config: default y 150//config: default y
@@ -860,7 +888,7 @@ static int builtin_local(char **argv) FAST_FUNC;
860#if HUSH_DEBUG 888#if HUSH_DEBUG
861static int builtin_memleak(char **argv) FAST_FUNC; 889static int builtin_memleak(char **argv) FAST_FUNC;
862#endif 890#endif
863#if ENABLE_PRINTF 891#if ENABLE_HUSH_PRINTF
864static int builtin_printf(char **argv) FAST_FUNC; 892static int builtin_printf(char **argv) FAST_FUNC;
865#endif 893#endif
866static int builtin_pwd(char **argv) FAST_FUNC; 894static int builtin_pwd(char **argv) FAST_FUNC;
@@ -870,11 +898,18 @@ static int builtin_shift(char **argv) FAST_FUNC;
870static int builtin_source(char **argv) FAST_FUNC; 898static int builtin_source(char **argv) FAST_FUNC;
871static int builtin_test(char **argv) FAST_FUNC; 899static int builtin_test(char **argv) FAST_FUNC;
872static int builtin_trap(char **argv) FAST_FUNC; 900static int builtin_trap(char **argv) FAST_FUNC;
901#if ENABLE_HUSH_TYPE
873static int builtin_type(char **argv) FAST_FUNC; 902static int builtin_type(char **argv) FAST_FUNC;
903#endif
874static int builtin_true(char **argv) FAST_FUNC; 904static int builtin_true(char **argv) FAST_FUNC;
875static int builtin_umask(char **argv) FAST_FUNC; 905static int builtin_umask(char **argv) FAST_FUNC;
876static int builtin_unset(char **argv) FAST_FUNC; 906static int builtin_unset(char **argv) FAST_FUNC;
907#if ENABLE_HUSH_KILL
908static int builtin_kill(char **argv) FAST_FUNC;
909#endif
910#if ENABLE_HUSH_WAIT
877static int builtin_wait(char **argv) FAST_FUNC; 911static int builtin_wait(char **argv) FAST_FUNC;
912#endif
878#if ENABLE_HUSH_LOOPS 913#if ENABLE_HUSH_LOOPS
879static int builtin_break(char **argv) FAST_FUNC; 914static int builtin_break(char **argv) FAST_FUNC;
880static int builtin_continue(char **argv) FAST_FUNC; 915static int builtin_continue(char **argv) FAST_FUNC;
@@ -929,6 +964,9 @@ static const struct built_in_command bltins1[] = {
929#if ENABLE_HUSH_JOB 964#if ENABLE_HUSH_JOB
930 BLTIN("jobs" , builtin_jobs , "List jobs"), 965 BLTIN("jobs" , builtin_jobs , "List jobs"),
931#endif 966#endif
967#if ENABLE_HUSH_KILL
968 BLTIN("kill" , builtin_kill , "Send signals to processes"),
969#endif
932#if ENABLE_HUSH_LOCAL 970#if ENABLE_HUSH_LOCAL
933 BLTIN("local" , builtin_local , "Set local variables"), 971 BLTIN("local" , builtin_local , "Set local variables"),
934#endif 972#endif
@@ -946,18 +984,22 @@ static const struct built_in_command bltins1[] = {
946#endif 984#endif
947 BLTIN("trap" , builtin_trap , "Trap signals"), 985 BLTIN("trap" , builtin_trap , "Trap signals"),
948 BLTIN("true" , builtin_true , NULL), 986 BLTIN("true" , builtin_true , NULL),
987#if ENABLE_HUSH_TYPE
949 BLTIN("type" , builtin_type , "Show command type"), 988 BLTIN("type" , builtin_type , "Show command type"),
989#endif
950 BLTIN("ulimit" , shell_builtin_ulimit , "Control resource limits"), 990 BLTIN("ulimit" , shell_builtin_ulimit , "Control resource limits"),
951 BLTIN("umask" , builtin_umask , "Set file creation mask"), 991 BLTIN("umask" , builtin_umask , "Set file creation mask"),
952 BLTIN("unset" , builtin_unset , "Unset variables"), 992 BLTIN("unset" , builtin_unset , "Unset variables"),
993#if ENABLE_HUSH_WAIT
953 BLTIN("wait" , builtin_wait , "Wait for process"), 994 BLTIN("wait" , builtin_wait , "Wait for process"),
995#endif
954}; 996};
955/* For now, echo and test are unconditionally enabled. 997/* For now, echo and test are unconditionally enabled.
956 * Maybe make it configurable? */ 998 * Maybe make it configurable? */
957static const struct built_in_command bltins2[] = { 999static const struct built_in_command bltins2[] = {
958 BLTIN("[" , builtin_test , NULL), 1000 BLTIN("[" , builtin_test , NULL),
959 BLTIN("echo" , builtin_echo , NULL), 1001 BLTIN("echo" , builtin_echo , NULL),
960#if ENABLE_PRINTF 1002#if ENABLE_HUSH_PRINTF
961 BLTIN("printf" , builtin_printf , NULL), 1003 BLTIN("printf" , builtin_printf , NULL),
962#endif 1004#endif
963 BLTIN("pwd" , builtin_pwd , NULL), 1005 BLTIN("pwd" , builtin_pwd , NULL),
@@ -8689,7 +8731,7 @@ static int FAST_FUNC builtin_echo(char **argv)
8689 return run_applet_main(argv, echo_main); 8731 return run_applet_main(argv, echo_main);
8690} 8732}
8691 8733
8692#if ENABLE_PRINTF 8734#if ENABLE_HUSH_PRINTF
8693static int FAST_FUNC builtin_printf(char **argv) 8735static int FAST_FUNC builtin_printf(char **argv)
8694{ 8736{
8695 return run_applet_main(argv, printf_main); 8737 return run_applet_main(argv, printf_main);
@@ -9227,6 +9269,7 @@ static int FAST_FUNC builtin_trap(char **argv)
9227 goto process_sig_list; 9269 goto process_sig_list;
9228} 9270}
9229 9271
9272#if ENABLE_HUSH_TYPE
9230/* http://www.opengroup.org/onlinepubs/9699919799/utilities/type.html */ 9273/* http://www.opengroup.org/onlinepubs/9699919799/utilities/type.html */
9231static int FAST_FUNC builtin_type(char **argv) 9274static int FAST_FUNC builtin_type(char **argv)
9232{ 9275{
@@ -9259,6 +9302,7 @@ static int FAST_FUNC builtin_type(char **argv)
9259 9302
9260 return ret; 9303 return ret;
9261} 9304}
9305#endif
9262 9306
9263#if ENABLE_HUSH_JOB 9307#if ENABLE_HUSH_JOB
9264static struct pipe *parse_jobspec(const char *str) 9308static struct pipe *parse_jobspec(const char *str)
@@ -9526,6 +9570,87 @@ static int FAST_FUNC builtin_umask(char **argv)
9526 return !rc; /* rc != 0 - success */ 9570 return !rc; /* rc != 0 - success */
9527} 9571}
9528 9572
9573#if ENABLE_HUSH_KILL
9574static int FAST_FUNC builtin_kill(char **argv)
9575{
9576 int ret = 0;
9577
9578 argv = skip_dash_dash(argv);
9579 if (argv[0] && strcmp(argv[0], "-l") != 0) {
9580 int i = 0;
9581
9582 do {
9583 struct pipe *pi;
9584 char *dst;
9585 int j, n;
9586
9587 if (argv[i][0] != '%')
9588 continue;
9589 /*
9590 * "kill %N" - job kill
9591 * Converting to pgrp / pid kill
9592 */
9593 pi = parse_jobspec(argv[i]);
9594 if (!pi) {
9595 /* Eat bad jobspec */
9596 j = i;
9597 do {
9598 j++;
9599 argv[j - 1] = argv[j];
9600 } while (argv[j]);
9601 ret = 1;
9602 i--;
9603 continue;
9604 }
9605 /*
9606 * In jobs started under job control, we signal
9607 * entire process group by kill -PGRP_ID.
9608 * This happens, f.e., in interactive shell.
9609 *
9610 * Otherwise, we signal each child via
9611 * kill PID1 PID2 PID3.
9612 * Testcases:
9613 * sh -c 'sleep 1|sleep 1 & kill %1'
9614 * sh -c 'true|sleep 2 & sleep 1; kill %1'
9615 * sh -c 'true|sleep 1 & sleep 2; kill %1'
9616 */
9617 n = pi->num_cmds;
9618 if (ENABLE_HUSH_JOB && G_interactive_fd)
9619 n = 1;
9620 dst = alloca(n * sizeof(int)*4);
9621 argv[i] = dst;
9622#if ENABLE_HUSH_JOB
9623 if (G_interactive_fd)
9624 dst += sprintf(dst, " -%u", (int)pi->pgrp);
9625 else
9626#endif
9627 for (j = 0; j < n; j++) {
9628 struct command *cmd = &pi->cmds[j];
9629 /* Skip exited members of the job */
9630 if (cmd->pid == 0)
9631 continue;
9632 /*
9633 * kill_main has matching code to expect
9634 * leading space. Needed to not confuse
9635 * negative pids with "kill -SIGNAL_NO" syntax
9636 */
9637 dst += sprintf(dst, " %u", (int)cmd->pid);
9638 }
9639 *dst = '\0';
9640 } while (argv[++i]);
9641 }
9642
9643 if (argv[0] || ret == 0) {
9644 argv--;
9645 argv[0] = (char*)"kill"; /* why? think about "kill -- PID" */
9646 /* kill_main also handles "killall" etc, so it does look at argv[0]! */
9647 ret = run_applet_main(argv, kill_main);
9648 }
9649 return ret;
9650}
9651#endif
9652
9653#if ENABLE_HUSH_WAIT
9529/* http://www.opengroup.org/onlinepubs/9699919799/utilities/wait.html */ 9654/* http://www.opengroup.org/onlinepubs/9699919799/utilities/wait.html */
9530#if !ENABLE_HUSH_JOB 9655#if !ENABLE_HUSH_JOB
9531# define wait_for_child_or_signal(pipe,pid) wait_for_child_or_signal(pid) 9656# 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)
9686 9811
9687 return ret; 9812 return ret;
9688} 9813}
9814#endif
9689 9815
9690#if ENABLE_HUSH_LOOPS || ENABLE_HUSH_FUNCTIONS 9816#if ENABLE_HUSH_LOOPS || ENABLE_HUSH_FUNCTIONS
9691static unsigned parse_numeric_argv1(char **argv, unsigned def, unsigned def_min) 9817static unsigned parse_numeric_argv1(char **argv, unsigned def, unsigned def_min)