Applied patch by Prasad Joshi to add kill by process name support. Thanks. Closed #1944.
This commit is contained in:
parent
103977d0a9
commit
cc2c83fa5c
@ -760,7 +760,7 @@ display_signal_list (list, forcecols)
|
||||
list = list->next;
|
||||
continue;
|
||||
}
|
||||
#if defined (JOB_CONTROL)
|
||||
#if defined (JOB_CONTROL) && defined(HAVE_KILL_BUILTIN)
|
||||
/* POSIX.2 says that `kill -l signum' prints the signal name without
|
||||
the `SIG' prefix. */
|
||||
printf ("%s\n", (this_shell_builtin == kill_builtin) ? name + 3 : name);
|
||||
@ -771,8 +771,10 @@ display_signal_list (list, forcecols)
|
||||
else
|
||||
{
|
||||
dflags = DSIG_NOCASE;
|
||||
#if defined(HAVE_KILL_BUILTIN)
|
||||
if (posixly_correct == 0 || this_shell_builtin != kill_builtin)
|
||||
dflags |= DSIG_SIGPREFIX;
|
||||
#endif
|
||||
signum = decode_signal (list->word->word, dflags);
|
||||
if (signum == NO_SIG)
|
||||
{
|
||||
|
@ -22,6 +22,7 @@ $PRODUCES kill.c
|
||||
|
||||
$BUILTIN kill
|
||||
$FUNCTION kill_builtin
|
||||
$DEPENDS_ON HAVE_KILL_BUILTIN
|
||||
$SHORT_DOC kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l [sigspec]
|
||||
Send a signal to a job.
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <getopt.h>
|
||||
#include <sys/types.h>
|
||||
#include <signal.h>
|
||||
#include <libgen.h>
|
||||
|
||||
#if HAVE_SYS_WAIT_H
|
||||
# include <sys/wait.h>
|
||||
@ -36,6 +37,7 @@
|
||||
#include "error.h"
|
||||
#include "sig2str.h"
|
||||
#include "operand2sig.h"
|
||||
#include "OS.h"
|
||||
|
||||
/* The official name of this program (e.g., no `g' prefix). */
|
||||
#define PROGRAM_NAME "kill"
|
||||
@ -85,7 +87,7 @@ usage (int status)
|
||||
else
|
||||
{
|
||||
printf (_("\
|
||||
Usage: %s [-s SIGNAL | -SIGNAL] PID...\n\
|
||||
Usage: %s [-s SIGNAL | -SIGNAL] <PID | PROCESS> ...\n\
|
||||
or: %s -l [SIGNAL]...\n\
|
||||
or: %s -t [SIGNAL]...\n\
|
||||
"),
|
||||
@ -109,6 +111,8 @@ Mandatory arguments to long options are mandatory for short options too.\n\
|
||||
SIGNAL may be a signal name like `HUP', or a signal number like `1',\n\
|
||||
or the exit status of a process terminated by a signal.\n\
|
||||
PID is an integer; if negative it identifies a process group.\n\
|
||||
PROCESS is name of the process to be killed. The signal will be sent \n\
|
||||
to all of the processes matching the given PROCESS name.\n\
|
||||
"), stdout);
|
||||
printf (USAGE_BUILTIN_WARNING, PROGRAM_NAME);
|
||||
emit_ancillary_info ();
|
||||
@ -196,38 +200,121 @@ list_signals (bool table, char *const *argv)
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Checks if passed string is a valid number
|
||||
*
|
||||
* Returns:
|
||||
* true: on valid number
|
||||
* The converted number is returned in NUM if it is not NULL
|
||||
*
|
||||
* false: on invalid number
|
||||
*
|
||||
*/
|
||||
bool is_number(const char *str, intmax_t *_number)
|
||||
{
|
||||
char *end;
|
||||
intmax_t number;
|
||||
|
||||
if (!str)
|
||||
return 0;
|
||||
|
||||
errno = 0;
|
||||
number = strtoimax(str, &end, 10);
|
||||
if (errno == ERANGE || str == end) {
|
||||
/* not a valid number */
|
||||
return false;
|
||||
}
|
||||
|
||||
/* skip all whitespace if there are any */
|
||||
while (*end == ' ' || *end == '\t')
|
||||
end++;
|
||||
|
||||
if (*end == '\0') {
|
||||
if (_number)
|
||||
*_number = number;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* kill the processes if they match given name
|
||||
*
|
||||
* Returns EXIT_SUCCESS signal was successfully sent to all matched processes,
|
||||
* otherwise EXIT_FAILURE is returned.
|
||||
*/
|
||||
int kill_by_name(int signum, const char *name)
|
||||
{
|
||||
team_info teamInfo;
|
||||
uint32 cookie = 0;
|
||||
int status = EXIT_SUCCESS;
|
||||
|
||||
while (get_next_team_info(&cookie, &teamInfo) >= B_OK) {
|
||||
char *token, *args;
|
||||
|
||||
args = teamInfo.args;
|
||||
token = strchr(args, ' ');
|
||||
if (token) {
|
||||
/* remove process argument */
|
||||
*token = 0;
|
||||
}
|
||||
|
||||
args = strdup(args);
|
||||
if (args == NULL) {
|
||||
error (0, errno, "%s", name);
|
||||
status = EXIT_FAILURE;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* skip the path if any */
|
||||
token = basename(args);
|
||||
|
||||
if (!strncmp(name, token, strlen(token))) {
|
||||
/* name matched */
|
||||
if (kill((pid_t)teamInfo.team, signum) != 0) {
|
||||
error (0, errno, "%s", name);
|
||||
status = EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
free(args);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/* Send signal SIGNUM to all the processes or process groups specified
|
||||
by ARGV. Return a suitable exit status. */
|
||||
|
||||
static int
|
||||
send_signals (int signum, char *const *argv)
|
||||
{
|
||||
int status = EXIT_SUCCESS;
|
||||
char const *arg = *argv;
|
||||
int status = EXIT_SUCCESS;
|
||||
char const *arg = *argv;
|
||||
pid_t pid;
|
||||
|
||||
do
|
||||
{
|
||||
char *endp;
|
||||
intmax_t n = (errno = 0, strtoimax (arg, &endp, 10));
|
||||
pid_t pid = n;
|
||||
do {
|
||||
bool is_pid = is_number(arg, (intmax_t *) &pid);
|
||||
if (is_pid) {
|
||||
if (kill(pid, signum) != 0) {
|
||||
error (0, errno, "%s", arg);
|
||||
status = EXIT_FAILURE;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (errno == ERANGE || pid != n || arg == endp || *endp)
|
||||
{
|
||||
error (0, 0, _("%s: invalid process id"), arg);
|
||||
status = EXIT_FAILURE;
|
||||
}
|
||||
else if (kill (pid, signum) != 0)
|
||||
{
|
||||
error (0, errno, "%s", arg);
|
||||
status = EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
while ((arg = *++argv));
|
||||
/* not a valid pid, kill by process name */
|
||||
if (kill_by_name(signum, arg) != EXIT_SUCCESS)
|
||||
status = EXIT_FAILURE;
|
||||
|
||||
return status;
|
||||
} while ((arg = *argv++));
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user