Ticket #1944: 0001-Add-support-to-kill-processes-using-their-names.patch

File 0001-Add-support-to-kill-processes-using-their-names.patch, 6.5 KB (added by Prasad, 11 years ago)
  • src/bin/bash/builtins/common.c

    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)  
    760760          list = list->next;
    761761          continue;
    762762        }
    763 #if defined (JOB_CONTROL)
     763#if defined (JOB_CONTROL) && defined(HAVE_KILL_BUILTIN)
    764764      /* POSIX.2 says that `kill -l signum' prints the signal name without
    765765         the `SIG' prefix. */
    766766      printf ("%s\n", (this_shell_builtin == kill_builtin) ? name + 3 : name);
    display_signal_list (list, forcecols)  
    771771      else
    772772    {
    773773      dflags = DSIG_NOCASE;
     774#if defined(HAVE_KILL_BUILTIN)
    774775      if (posixly_correct == 0 || this_shell_builtin != kill_builtin)
    775776        dflags |= DSIG_SIGPREFIX;
     777#endif
    776778      signum = decode_signal (list->word->word, dflags);
    777779      if (signum == NO_SIG)
    778780        {
  • src/bin/bash/builtins/kill.def

    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  
    2222
    2323$BUILTIN kill
    2424$FUNCTION kill_builtin
     25$DEPENDS_ON HAVE_KILL_BUILTIN
    2526$SHORT_DOC kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l [sigspec]
    2627Send a signal to a job.
    2728
  • src/bin/coreutils/src/kill.c

    diff --git a/src/bin/coreutils/src/kill.c b/src/bin/coreutils/src/kill.c
    index dab4fa8..186a63b 100644
    a b  
    2121#include <getopt.h>
    2222#include <sys/types.h>
    2323#include <signal.h>
     24#include <libgen.h>
    2425
    2526#if HAVE_SYS_WAIT_H
    2627# include <sys/wait.h>
     
    3637#include "error.h"
    3738#include "sig2str.h"
    3839#include "operand2sig.h"
     40#include "OS.h"
    3941
    4042/* The official name of this program (e.g., no `g' prefix).  */
    4143#define PROGRAM_NAME "kill"
    usage (int status)  
    8587  else
    8688    {
    8789      printf (_("\
    88 Usage: %s [-s SIGNAL | -SIGNAL] PID...\n\
     90Usage: %s [-s SIGNAL | -SIGNAL] <PID | PROCESS> ...\n\
    8991  or:  %s -l [SIGNAL]...\n\
    9092  or:  %s -t [SIGNAL]...\n\
    9193"),
    Mandatory arguments to long options are mandatory for short options too.\n\  
    109111SIGNAL may be a signal name like `HUP', or a signal number like `1',\n\
    110112or the exit status of a process terminated by a signal.\n\
    111113PID is an integer; if negative it identifies a process group.\n\
     114PROCESS is name of the process to be killed. The signal will be sent \n\
     115to all of the processes matching the given PROCESS name.\n\
    112116"), stdout);
    113117      printf (USAGE_BUILTIN_WARNING, PROGRAM_NAME);
    114118      emit_ancillary_info ();
    list_signals (bool table, char *const *argv)  
    196200
    197201  return status;
    198202}
    199 
    200203
     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 */
     216bool 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 */
     250int 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
    201292/* Send signal SIGNUM to all the processes or process groups specified
    202293   by ARGV.  Return a suitable exit status.  */
    203294
    204295static int
    205296send_signals (int signum, char *const *argv)
    206297{
    207   int status = EXIT_SUCCESS;
    208   char const *arg = *argv;
     298    int status = EXIT_SUCCESS;
     299    char const *arg = *argv;
     300    pid_t pid;
    209301
    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        }
    228311
    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;
    230319}
    231 
    232320
     321
     322
    233323int