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 /shell | |
| 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>
Diffstat (limited to 'shell')
| -rw-r--r-- | shell/hush.c | 134 |
1 files changed, 130 insertions, 4 deletions
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) |
