From 4b13043dcb4ec84a7b2a693db0a6a8f88cbc84b9 Mon Sep 17 00:00:00 2001
From: Prasad Joshi <prasadjoshi.linux@gmail.com>
Date: Sat, 27 Oct 2012 09:59:37 +0530
Subject: [PATCH] Add support to kill processes using their names
BeOS R5 supported sending a signal to processes (kill) using their
name. Haiku has two different kill utilities, one that is built into
the shell and the other which comes with the coreutils. The builtin
kill command does not have an executable and it is part of the shell.
The other kill command is present at location /bin/kill.
The shell keeps track of the all of the jobs ran on the terminal. The
builtin in kill command is designed to work only with the shell jobs
and never does it goes through all the processes running on the machine.
Therefore, it would be unwise to modify the source of the builtin kill
command to traverse the list of all processes looking for specific
process to kill.
The patch disables the builtin kill command and adds support for
process names in the coreutils kill utility.
---
src/bin/bash/builtins/common.c | 4 +-
src/bin/bash/builtins/kill.def | 1 +
src/bin/coreutils/src/kill.c | 138 +++++++++++++++++++++++++++++++++-------
3 files changed, 118 insertions(+), 25 deletions(-)
diff --git a/src/bin/bash/builtins/common.c b/src/bin/bash/builtins/common.c
index 6ba641b..2c75b84 100644
a
|
b
|
display_signal_list (list, forcecols)
|
760 | 760 | list = list->next; |
761 | 761 | continue; |
762 | 762 | } |
763 | | #if defined (JOB_CONTROL) |
| 763 | #if defined (JOB_CONTROL) && defined(HAVE_KILL_BUILTIN) |
764 | 764 | /* POSIX.2 says that `kill -l signum' prints the signal name without |
765 | 765 | the `SIG' prefix. */ |
766 | 766 | printf ("%s\n", (this_shell_builtin == kill_builtin) ? name + 3 : name); |
… |
… |
display_signal_list (list, forcecols)
|
771 | 771 | else |
772 | 772 | { |
773 | 773 | dflags = DSIG_NOCASE; |
| 774 | #if defined(HAVE_KILL_BUILTIN) |
774 | 775 | if (posixly_correct == 0 || this_shell_builtin != kill_builtin) |
775 | 776 | dflags |= DSIG_SIGPREFIX; |
| 777 | #endif |
776 | 778 | signum = decode_signal (list->word->word, dflags); |
777 | 779 | if (signum == NO_SIG) |
778 | 780 | { |
diff --git a/src/bin/bash/builtins/kill.def b/src/bin/bash/builtins/kill.def
index 734da25..4cff928 100644
a
|
b
|
$PRODUCES kill.c
|
22 | 22 | |
23 | 23 | $BUILTIN kill |
24 | 24 | $FUNCTION kill_builtin |
| 25 | $DEPENDS_ON HAVE_KILL_BUILTIN |
25 | 26 | $SHORT_DOC kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l [sigspec] |
26 | 27 | Send a signal to a job. |
27 | 28 | |
diff --git a/src/bin/coreutils/src/kill.c b/src/bin/coreutils/src/kill.c
index dab4fa8..186a63b 100644
a
|
b
|
|
21 | 21 | #include <getopt.h> |
22 | 22 | #include <sys/types.h> |
23 | 23 | #include <signal.h> |
| 24 | #include <libgen.h> |
24 | 25 | |
25 | 26 | #if HAVE_SYS_WAIT_H |
26 | 27 | # include <sys/wait.h> |
… |
… |
|
36 | 37 | #include "error.h" |
37 | 38 | #include "sig2str.h" |
38 | 39 | #include "operand2sig.h" |
| 40 | #include "OS.h" |
39 | 41 | |
40 | 42 | /* The official name of this program (e.g., no `g' prefix). */ |
41 | 43 | #define PROGRAM_NAME "kill" |
… |
… |
usage (int status)
|
85 | 87 | else |
86 | 88 | { |
87 | 89 | printf (_("\ |
88 | | Usage: %s [-s SIGNAL | -SIGNAL] PID...\n\ |
| 90 | Usage: %s [-s SIGNAL | -SIGNAL] <PID | PROCESS> ...\n\ |
89 | 91 | or: %s -l [SIGNAL]...\n\ |
90 | 92 | or: %s -t [SIGNAL]...\n\ |
91 | 93 | "), |
… |
… |
Mandatory arguments to long options are mandatory for short options too.\n\
|
109 | 111 | SIGNAL may be a signal name like `HUP', or a signal number like `1',\n\ |
110 | 112 | or the exit status of a process terminated by a signal.\n\ |
111 | 113 | PID is an integer; if negative it identifies a process group.\n\ |
| 114 | PROCESS is name of the process to be killed. The signal will be sent \n\ |
| 115 | to all of the processes matching the given PROCESS name.\n\ |
112 | 116 | "), stdout); |
113 | 117 | printf (USAGE_BUILTIN_WARNING, PROGRAM_NAME); |
114 | 118 | emit_ancillary_info (); |
… |
… |
list_signals (bool table, char *const *argv)
|
196 | 200 | |
197 | 201 | return status; |
198 | 202 | } |
199 | | |
200 | 203 | |
| 204 | |
| 205 | |
| 206 | /* |
| 207 | * Checks if passed string is a valid number |
| 208 | * |
| 209 | * Returns: |
| 210 | * true: on valid number |
| 211 | * The converted number is returned in NUM if it is not NULL |
| 212 | * |
| 213 | * false: on invalid number |
| 214 | * |
| 215 | */ |
| 216 | bool is_number(const char *str, intmax_t *num) |
| 217 | { |
| 218 | char *e; |
| 219 | intmax_t n; |
| 220 | |
| 221 | if (!str) |
| 222 | return 0; |
| 223 | |
| 224 | errno = 0; |
| 225 | n = strtoimax(str, &e, 10); |
| 226 | if (errno == ERANGE || str == e) { |
| 227 | /* not a valid number */ |
| 228 | return false; |
| 229 | } |
| 230 | |
| 231 | /* skip all whitespace if there are any */ |
| 232 | while (*e == ' ' || *e == '\t') |
| 233 | e++; |
| 234 | |
| 235 | if (*e == '\0') { |
| 236 | if (num) |
| 237 | *num = n; |
| 238 | return true; |
| 239 | } |
| 240 | return false; |
| 241 | } |
| 242 | |
| 243 | |
| 244 | /* |
| 245 | * kill the processes if they match given name |
| 246 | * |
| 247 | * Returns EXIT_SUCCESS signal was successfully sent to all matched processes, |
| 248 | * otherwise EXIT_FAILURE is returned. |
| 249 | */ |
| 250 | int kill_by_name(int signum, const char *name) |
| 251 | { |
| 252 | team_info tm; |
| 253 | uint32 tc = 0; |
| 254 | int status = EXIT_SUCCESS; |
| 255 | |
| 256 | while (get_next_team_info(&tc, &tm) >= B_OK) { |
| 257 | char *p, *q; |
| 258 | int l; |
| 259 | |
| 260 | q = tm.args; |
| 261 | p = strchr(q, ' '); |
| 262 | if (p) { |
| 263 | /* remove process argument */ |
| 264 | *p = 0; |
| 265 | } |
| 266 | |
| 267 | /* skip the path if any */ |
| 268 | p = strdup(q); |
| 269 | if (!p) { |
| 270 | error (0, errno, "%s", name); |
| 271 | status = EXIT_FAILURE; |
| 272 | } |
| 273 | |
| 274 | q = basename(p); |
| 275 | |
| 276 | if (!strncmp(name, q, strlen(q))) { |
| 277 | /* name matched */ |
| 278 | pid_t pid = tm.team; |
| 279 | if (kill(pid, signum) != 0) { |
| 280 | error (0, errno, "%s", name); |
| 281 | free(p); |
| 282 | status = EXIT_FAILURE; |
| 283 | } |
| 284 | } |
| 285 | |
| 286 | free(p); |
| 287 | } |
| 288 | return status; |
| 289 | } |
| 290 | |
| 291 | |
201 | 292 | /* Send signal SIGNUM to all the processes or process groups specified |
202 | 293 | by ARGV. Return a suitable exit status. */ |
203 | 294 | |
204 | 295 | static int |
205 | 296 | send_signals (int signum, char *const *argv) |
206 | 297 | { |
207 | | int status = EXIT_SUCCESS; |
208 | | char const *arg = *argv; |
| 298 | int status = EXIT_SUCCESS; |
| 299 | char const *arg = *argv; |
| 300 | pid_t pid; |
209 | 301 | |
210 | | do |
211 | | { |
212 | | char *endp; |
213 | | intmax_t n = (errno = 0, strtoimax (arg, &endp, 10)); |
214 | | pid_t pid = n; |
215 | | |
216 | | if (errno == ERANGE || pid != n || arg == endp || *endp) |
217 | | { |
218 | | error (0, 0, _("%s: invalid process id"), arg); |
219 | | status = EXIT_FAILURE; |
220 | | } |
221 | | else if (kill (pid, signum) != 0) |
222 | | { |
223 | | error (0, errno, "%s", arg); |
224 | | status = EXIT_FAILURE; |
225 | | } |
226 | | } |
227 | | while ((arg = *++argv)); |
| 302 | do { |
| 303 | bool is_pid = is_number(arg, (intmax_t *) &pid); |
| 304 | if (is_pid) { |
| 305 | if (kill(pid, signum) != 0) { |
| 306 | error (0, errno, "%s", arg); |
| 307 | status = EXIT_FAILURE; |
| 308 | } |
| 309 | continue; |
| 310 | } |
228 | 311 | |
229 | | return status; |
| 312 | /* not a valid pid, kill by process name */ |
| 313 | if (kill_by_name(signum, arg) != EXIT_SUCCESS) |
| 314 | status = EXIT_FAILURE; |
| 315 | |
| 316 | } while ((arg = *argv++)); |
| 317 | |
| 318 | return status; |
230 | 319 | } |
231 | | |
232 | 320 | |
| 321 | |
| 322 | |
233 | 323 | int |