diff options
Diffstat (limited to 'procps')
-rw-r--r-- | procps/Kbuild | 1 | ||||
-rw-r--r-- | procps/kill.c | 95 |
2 files changed, 58 insertions, 38 deletions
diff --git a/procps/Kbuild b/procps/Kbuild index 6a9a86637..33f616fc2 100644 --- a/procps/Kbuild +++ b/procps/Kbuild | |||
@@ -7,6 +7,7 @@ | |||
7 | lib-y:= | 7 | lib-y:= |
8 | lib-$(CONFIG_FREE) += free.o | 8 | lib-$(CONFIG_FREE) += free.o |
9 | lib-$(CONFIG_KILL) += kill.o | 9 | lib-$(CONFIG_KILL) += kill.o |
10 | lib-$(CONFIG_ASH) += kill.o # used for built-in kill by ash | ||
10 | lib-$(CONFIG_PIDOF) += pidof.o | 11 | lib-$(CONFIG_PIDOF) += pidof.o |
11 | lib-$(CONFIG_PS) += ps.o | 12 | lib-$(CONFIG_PS) += ps.o |
12 | lib-$(CONFIG_RENICE) += renice.o | 13 | lib-$(CONFIG_RENICE) += renice.o |
diff --git a/procps/kill.c b/procps/kill.c index 9a6e93665..e2b029d20 100644 --- a/procps/kill.c +++ b/procps/kill.c | |||
@@ -10,16 +10,30 @@ | |||
10 | 10 | ||
11 | #include "busybox.h" | 11 | #include "busybox.h" |
12 | 12 | ||
13 | /* Note: kill_main is directly called from shell in order to implement | ||
14 | * kill built-in. Shell substitutes job ids with process groups first. | ||
15 | * | ||
16 | * This brings some complications: | ||
17 | * | ||
18 | * + we can't use xfunc here | ||
19 | * + we can't use applet_name | ||
20 | * + we can't use bb_show_usage | ||
21 | * (Above doesn't apply for killall[5] cases) | ||
22 | * | ||
23 | * kill %n gets translated into kill ' -<process group>' by shell (note space!) | ||
24 | * This is needed to avoid collision with kill -9 ... syntax | ||
25 | */ | ||
26 | |||
13 | int kill_main(int argc, char **argv); | 27 | int kill_main(int argc, char **argv); |
14 | int kill_main(int argc, char **argv) | 28 | int kill_main(int argc, char **argv) |
15 | { | 29 | { |
16 | char *arg; | 30 | char *arg; |
17 | pid_t pid; | 31 | pid_t pid; |
18 | int signo = SIGTERM, errors = 0, quiet = 0; | 32 | int signo = SIGTERM, errors = 0, quiet = 0; |
19 | const int killall = (ENABLE_KILLALL && applet_name[4] == 'a' | 33 | const int killall = (ENABLE_KILLALL && argv[0][4] == 'a' |
20 | && (!ENABLE_KILLALL5 || applet_name[7] != '5')); | 34 | && (!ENABLE_KILLALL5 || argv[0][7] != '5')); |
21 | const int killall5 = (ENABLE_KILLALL5 && applet_name[4] == 'a' | 35 | const int killall5 = (ENABLE_KILLALL5 && argv[0][4] == 'a' |
22 | && (!ENABLE_KILLALL || applet_name[7] == '5')); | 36 | && (!ENABLE_KILLALL || argv[0][7] == '5')); |
23 | 37 | ||
24 | /* Parse any options */ | 38 | /* Parse any options */ |
25 | argc--; | 39 | argc--; |
@@ -29,34 +43,38 @@ int kill_main(int argc, char **argv) | |||
29 | goto do_it_now; | 43 | goto do_it_now; |
30 | } | 44 | } |
31 | 45 | ||
32 | /* The -l option, which prints out signal names. */ | 46 | /* The -l option, which prints out signal names. |
47 | * Intended usage in shell: | ||
48 | * echo "Died of SIG`kill -l $?`" | ||
49 | * We try to mimic what kill from coreutils-6.8 does */ | ||
33 | if (arg[1] == 'l' && arg[2] == '\0') { | 50 | if (arg[1] == 'l' && arg[2] == '\0') { |
34 | const char *name; | ||
35 | if (argc == 1) { | 51 | if (argc == 1) { |
36 | /* Print the whole signal list */ | 52 | /* Print the whole signal list */ |
37 | int col = 0; | ||
38 | for (signo = 1; signo < 32; signo++) { | 53 | for (signo = 1; signo < 32; signo++) { |
39 | name = get_signame(signo); | 54 | puts(get_signame(signo)); |
40 | if (isdigit(name[0])) continue; | ||
41 | if (col > 66) { | ||
42 | puts(""); | ||
43 | col = 0; | ||
44 | } | ||
45 | col += printf("%2d) %-6s", signo, name); | ||
46 | } | 55 | } |
47 | puts(""); | ||
48 | } else { /* -l <sig list> */ | 56 | } else { /* -l <sig list> */ |
49 | while ((arg = *++argv)) { | 57 | while ((arg = *++argv)) { |
50 | if (isdigit(arg[0])) { | 58 | if (isdigit(arg[0])) { |
51 | signo = xatoi_u(arg); | 59 | signo = bb_strtou(arg, NULL, 10); |
52 | name = get_signame(signo); | 60 | if (errno) { |
61 | bb_error_msg("unknown signal '%s'", arg); | ||
62 | return EXIT_FAILURE; | ||
63 | } | ||
64 | /* Exitcodes >= 0x80 are to be treated | ||
65 | * as "killed by signal (exitcode & 0x7f)" */ | ||
66 | puts(get_signame(signo & 0x7f)); | ||
67 | /* TODO: 'bad' signal# - coreutils says: | ||
68 | * kill: 127: invalid signal | ||
69 | * we just print "127" instead */ | ||
53 | } else { | 70 | } else { |
54 | signo = get_signum(arg); | 71 | signo = get_signum(arg); |
55 | if (signo < 0) | 72 | if (signo < 0) { |
56 | bb_error_msg_and_die("unknown signal '%s'", arg); | 73 | bb_error_msg("unknown signal '%s'", arg); |
57 | name = get_signame(signo); | 74 | return EXIT_FAILURE; |
75 | } | ||
76 | printf("%d\n", signo); | ||
58 | } | 77 | } |
59 | printf("%2d) %s\n", signo, name); | ||
60 | } | 78 | } |
61 | } | 79 | } |
62 | /* If they specified -l, we are all done */ | 80 | /* If they specified -l, we are all done */ |
@@ -74,8 +92,10 @@ int kill_main(int argc, char **argv) | |||
74 | 92 | ||
75 | /* -SIG */ | 93 | /* -SIG */ |
76 | signo = get_signum(&arg[1]); | 94 | signo = get_signum(&arg[1]); |
77 | if (signo < 0) | 95 | if (signo < 0) { /* || signo > MAX_SIGNUM ? */ |
78 | bb_error_msg_and_die("bad signal name '%s'", &arg[1]); | 96 | bb_error_msg("bad signal name '%s'", &arg[1]); |
97 | return EXIT_FAILURE; | ||
98 | } | ||
79 | arg = *++argv; | 99 | arg = *++argv; |
80 | argc--; | 100 | argc--; |
81 | 101 | ||
@@ -85,10 +105,6 @@ do_it_now: | |||
85 | pid_t sid; | 105 | pid_t sid; |
86 | procps_status_t* p = NULL; | 106 | procps_status_t* p = NULL; |
87 | 107 | ||
88 | // Cannot happen anyway? We don't TERM ourself, we STOP | ||
89 | // /* kill(-1, sig) on Linux (at least 2.1.x) | ||
90 | // * might send signal to the calling process too */ | ||
91 | // signal(SIGTERM, SIG_IGN); | ||
92 | /* Now stop all processes */ | 108 | /* Now stop all processes */ |
93 | kill(-1, SIGSTOP); | 109 | kill(-1, SIGSTOP); |
94 | /* Find out our own session id */ | 110 | /* Find out our own session id */ |
@@ -104,9 +120,11 @@ do_it_now: | |||
104 | return 0; | 120 | return 0; |
105 | } | 121 | } |
106 | 122 | ||
107 | /* Pid or name required for kill/killall */ | 123 | /* Pid or name is required for kill/killall */ |
108 | if (argc < 1) | 124 | if (argc < 1) { |
109 | bb_show_usage(); | 125 | puts("You need to specify whom to kill"); |
126 | return EXIT_FAILURE; | ||
127 | } | ||
110 | 128 | ||
111 | if (killall) { | 129 | if (killall) { |
112 | /* Looks like they want to do a killall. Do that */ | 130 | /* Looks like they want to do a killall. Do that */ |
@@ -140,14 +158,15 @@ do_it_now: | |||
140 | 158 | ||
141 | /* Looks like they want to do a kill. Do that */ | 159 | /* Looks like they want to do a kill. Do that */ |
142 | while (arg) { | 160 | while (arg) { |
143 | /* Huh? | 161 | /* Support shell 'space' trick */ |
144 | if (!isdigit(arg[0]) && arg[0] != '-') | 162 | if (arg[0] == ' ') |
145 | bb_error_msg_and_die("bad pid '%s'", arg); | 163 | arg++; |
146 | */ | 164 | pid = bb_strtoi(arg, NULL, 10); |
147 | pid = xatou(arg); | 165 | if (errno) { |
148 | /* FIXME: better overflow check? */ | 166 | bb_error_msg("bad pid '%s'", arg); |
149 | if (kill(pid, signo) != 0) { | 167 | errors++; |
150 | bb_perror_msg("cannot kill pid %u", (unsigned)pid); | 168 | } else if (kill(pid, signo) != 0) { |
169 | bb_perror_msg("cannot kill pid %d", (int)pid); | ||
151 | errors++; | 170 | errors++; |
152 | } | 171 | } |
153 | arg = *++argv; | 172 | arg = *++argv; |