diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2017-01-08 17:19:38 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2017-01-08 17:19:38 +0100 |
commit | 1125d7d6801940a5218b74c8fd46f1eaa2e4de39 (patch) | |
tree | ec8b07c2799e6d538f0aaf63ab51497904580504 | |
parent | d5b5c2fa151d318fa96778d5871e23ede312e5fa (diff) | |
download | busybox-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.src | 5 | ||||
-rw-r--r-- | procps/Kbuild.src | 2 | ||||
-rw-r--r-- | procps/kill.c | 4 | ||||
-rw-r--r-- | shell/hush.c | 134 |
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 | |||
15 | lib-$(CONFIG_CRONTAB) += cat.o # crontab -l | 15 | lib-$(CONFIG_CRONTAB) += cat.o # crontab -l |
16 | lib-$(CONFIG_ADDUSER) += chown.o # used by adduser | 16 | lib-$(CONFIG_ADDUSER) += chown.o # used by adduser |
17 | lib-$(CONFIG_ADDGROUP) += chown.o # used by adduser | 17 | lib-$(CONFIG_ADDGROUP) += chown.o # used by adduser |
18 | lib-$(CONFIG_FTPD) += ls.o # used by ftpd | ||
19 | |||
18 | lib-$(CONFIG_ASH) += echo.o # used by ash | 20 | lib-$(CONFIG_ASH) += echo.o # used by ash |
19 | lib-$(CONFIG_SH_IS_ASH) += echo.o # used by ash | 21 | lib-$(CONFIG_SH_IS_ASH) += echo.o # used by ash |
20 | lib-$(CONFIG_BASH_IS_ASH) += echo.o # used by ash | 22 | lib-$(CONFIG_BASH_IS_ASH) += echo.o # used by ash |
21 | lib-$(CONFIG_HUSH) += echo.o # used by hush | 23 | lib-$(CONFIG_HUSH) += echo.o # used by hush |
22 | lib-$(CONFIG_SH_IS_HUSH) += echo.o # used by hush | 24 | lib-$(CONFIG_SH_IS_HUSH) += echo.o # used by hush |
23 | lib-$(CONFIG_BASH_IS_HUSH) += echo.o # used by hush | 25 | lib-$(CONFIG_BASH_IS_HUSH) += echo.o # used by hush |
24 | lib-$(CONFIG_FTPD) += ls.o # used by ftpd | 26 | |
25 | lib-$(CONFIG_ASH_BUILTIN_PRINTF) += printf.o | 27 | lib-$(CONFIG_ASH_BUILTIN_PRINTF) += printf.o |
28 | lib-$(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 | |||
11 | lib-$(CONFIG_ASH) += kill.o # used for built-in kill by ash | 11 | lib-$(CONFIG_ASH) += kill.o # used for built-in kill by ash |
12 | lib-$(CONFIG_SH_IS_ASH) += kill.o # used for built-in kill by ash | 12 | lib-$(CONFIG_SH_IS_ASH) += kill.o # used for built-in kill by ash |
13 | lib-$(CONFIG_BASH_IS_ASH) += kill.o # used for built-in kill by ash | 13 | lib-$(CONFIG_BASH_IS_ASH) += kill.o # used for built-in kill by ash |
14 | |||
15 | lib-$(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 |
861 | static int builtin_memleak(char **argv) FAST_FUNC; | 889 | static int builtin_memleak(char **argv) FAST_FUNC; |
862 | #endif | 890 | #endif |
863 | #if ENABLE_PRINTF | 891 | #if ENABLE_HUSH_PRINTF |
864 | static int builtin_printf(char **argv) FAST_FUNC; | 892 | static int builtin_printf(char **argv) FAST_FUNC; |
865 | #endif | 893 | #endif |
866 | static int builtin_pwd(char **argv) FAST_FUNC; | 894 | static int builtin_pwd(char **argv) FAST_FUNC; |
@@ -870,11 +898,18 @@ static int builtin_shift(char **argv) FAST_FUNC; | |||
870 | static int builtin_source(char **argv) FAST_FUNC; | 898 | static int builtin_source(char **argv) FAST_FUNC; |
871 | static int builtin_test(char **argv) FAST_FUNC; | 899 | static int builtin_test(char **argv) FAST_FUNC; |
872 | static int builtin_trap(char **argv) FAST_FUNC; | 900 | static int builtin_trap(char **argv) FAST_FUNC; |
901 | #if ENABLE_HUSH_TYPE | ||
873 | static int builtin_type(char **argv) FAST_FUNC; | 902 | static int builtin_type(char **argv) FAST_FUNC; |
903 | #endif | ||
874 | static int builtin_true(char **argv) FAST_FUNC; | 904 | static int builtin_true(char **argv) FAST_FUNC; |
875 | static int builtin_umask(char **argv) FAST_FUNC; | 905 | static int builtin_umask(char **argv) FAST_FUNC; |
876 | static int builtin_unset(char **argv) FAST_FUNC; | 906 | static int builtin_unset(char **argv) FAST_FUNC; |
907 | #if ENABLE_HUSH_KILL | ||
908 | static int builtin_kill(char **argv) FAST_FUNC; | ||
909 | #endif | ||
910 | #if ENABLE_HUSH_WAIT | ||
877 | static int builtin_wait(char **argv) FAST_FUNC; | 911 | static int builtin_wait(char **argv) FAST_FUNC; |
912 | #endif | ||
878 | #if ENABLE_HUSH_LOOPS | 913 | #if ENABLE_HUSH_LOOPS |
879 | static int builtin_break(char **argv) FAST_FUNC; | 914 | static int builtin_break(char **argv) FAST_FUNC; |
880 | static int builtin_continue(char **argv) FAST_FUNC; | 915 | static 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? */ |
957 | static const struct built_in_command bltins2[] = { | 999 | static 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 |
8693 | static int FAST_FUNC builtin_printf(char **argv) | 8735 | static 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 */ |
9231 | static int FAST_FUNC builtin_type(char **argv) | 9274 | static 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 |
9264 | static struct pipe *parse_jobspec(const char *str) | 9308 | static 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 | ||
9574 | static 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 |
9691 | static unsigned parse_numeric_argv1(char **argv, unsigned def, unsigned def_min) | 9817 | static unsigned parse_numeric_argv1(char **argv, unsigned def, unsigned def_min) |