Revert changes to coreutils kill.c...
..introduced by cc2c83fa5c and subsequent
cleanups. Instead, patch bash's builtin kill directly to handle the kill
by name functionality. Fixes #9687 and reintroduces the ability to kill
jobs.
This commit is contained in:
@@ -64,7 +64,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined (errno)
|
#if !defined (errno)
|
||||||
extern int errno;
|
extern int errno;
|
||||||
#endif /* !errno */
|
#endif /* !errno */
|
||||||
|
|
||||||
extern int indirection_level, subshell_environment;
|
extern int indirection_level, subshell_environment;
|
||||||
@@ -494,7 +494,7 @@ get_exitstat (list)
|
|||||||
list = list->next;
|
list = list->next;
|
||||||
|
|
||||||
if (list == 0)
|
if (list == 0)
|
||||||
return (last_command_exit_value);
|
return (last_command_exit_value);
|
||||||
|
|
||||||
arg = list->word->word;
|
arg = list->word->word;
|
||||||
if (arg == 0 || legal_number (arg, &sval) == 0)
|
if (arg == 0 || legal_number (arg, &sval) == 0)
|
||||||
@@ -760,7 +760,7 @@ display_signal_list (list, forcecols)
|
|||||||
list = list->next;
|
list = list->next;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#if defined (JOB_CONTROL) && defined(HAVE_KILL_BUILTIN)
|
#if defined (JOB_CONTROL)
|
||||||
/* POSIX.2 says that `kill -l signum' prints the signal name without
|
/* POSIX.2 says that `kill -l signum' prints the signal name without
|
||||||
the `SIG' prefix. */
|
the `SIG' prefix. */
|
||||||
printf ("%s\n", (this_shell_builtin == kill_builtin) ? name + 3 : name);
|
printf ("%s\n", (this_shell_builtin == kill_builtin) ? name + 3 : name);
|
||||||
@@ -771,10 +771,8 @@ display_signal_list (list, forcecols)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
dflags = DSIG_NOCASE;
|
dflags = DSIG_NOCASE;
|
||||||
#if defined(HAVE_KILL_BUILTIN)
|
|
||||||
if (posixly_correct == 0 || this_shell_builtin != kill_builtin)
|
if (posixly_correct == 0 || this_shell_builtin != kill_builtin)
|
||||||
dflags |= DSIG_SIGPREFIX;
|
dflags |= DSIG_SIGPREFIX;
|
||||||
#endif
|
|
||||||
signum = decode_signal (list->word->word, dflags);
|
signum = decode_signal (list->word->word, dflags);
|
||||||
if (signum == NO_SIG)
|
if (signum == NO_SIG)
|
||||||
{
|
{
|
||||||
@@ -869,7 +867,7 @@ find_special_builtin (name)
|
|||||||
current_builtin->function :
|
current_builtin->function :
|
||||||
(sh_builtin_func_t *)NULL);
|
(sh_builtin_func_t *)NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
shell_builtin_compare (sbp1, sbp2)
|
shell_builtin_compare (sbp1, sbp2)
|
||||||
struct builtin *sbp1, *sbp2;
|
struct builtin *sbp1, *sbp2;
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ $PRODUCES kill.c
|
|||||||
|
|
||||||
$BUILTIN kill
|
$BUILTIN kill
|
||||||
$FUNCTION kill_builtin
|
$FUNCTION kill_builtin
|
||||||
$DEPENDS_ON HAVE_KILL_BUILTIN
|
|
||||||
$SHORT_DOC kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l [sigspec]
|
$SHORT_DOC kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l [sigspec]
|
||||||
Send a signal to a job.
|
Send a signal to a job.
|
||||||
|
|
||||||
@@ -55,6 +54,8 @@ $END
|
|||||||
# include <unistd.h>
|
# include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <OS.h>
|
||||||
|
|
||||||
#include "../bashansi.h"
|
#include "../bashansi.h"
|
||||||
#include "../bashintl.h"
|
#include "../bashintl.h"
|
||||||
|
|
||||||
@@ -78,6 +79,46 @@ static void kill_error __P((pid_t, int));
|
|||||||
# define CONTINUE_OR_FAIL goto continue_killing
|
# define CONTINUE_OR_FAIL goto continue_killing
|
||||||
#endif /* CONTINUE_AFTER_KILL_ERROR */
|
#endif /* CONTINUE_AFTER_KILL_ERROR */
|
||||||
|
|
||||||
|
|
||||||
|
int kill_by_name(int signum, const char *name)
|
||||||
|
{
|
||||||
|
team_info teamInfo;
|
||||||
|
uint32 cookie = 0;
|
||||||
|
int status = EXECUTION_SUCCESS;
|
||||||
|
int found = 0;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* skip the path if any */
|
||||||
|
token = basename(args);
|
||||||
|
|
||||||
|
if (!strncmp(name, token, strlen(token))) {
|
||||||
|
found = 1;
|
||||||
|
/* name matched */
|
||||||
|
if (kill((pid_t)teamInfo.team, signum) != 0) {
|
||||||
|
kill_error (teamInfo.team, errno);
|
||||||
|
status = EXECUTION_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
builtin_error (_("(%s) - %s"), name, strerror(ESRCH));
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Here is the kill builtin. We only have it so that people can type
|
/* Here is the kill builtin. We only have it so that people can type
|
||||||
kill -KILL %1? No, if you fill up the process table this way you
|
kill -KILL %1? No, if you fill up the process table this way you
|
||||||
can still kill some. */
|
can still kill some. */
|
||||||
@@ -177,20 +218,27 @@ kill_builtin (list)
|
|||||||
word++;
|
word++;
|
||||||
|
|
||||||
/* Use the entire argument in case of minus sign presence. */
|
/* Use the entire argument in case of minus sign presence. */
|
||||||
if (*word && legal_number (list->word->word, &pid_value) && (pid_value == (pid_t)pid_value))
|
if (*word)
|
||||||
{
|
{
|
||||||
pid = (pid_t) pid_value;
|
if (legal_number (list->word->word, &pid_value)
|
||||||
|
&& (pid_value == (pid_t)pid_value))
|
||||||
|
{
|
||||||
|
pid = (pid_t) pid_value;
|
||||||
|
|
||||||
if (kill_pid (pid, sig, pid < -1) < 0)
|
if (kill_pid (pid, sig, pid < -1) < 0)
|
||||||
{
|
{
|
||||||
if (errno == EINVAL)
|
if (errno == EINVAL)
|
||||||
sh_invalidsig (sigspec);
|
sh_invalidsig (sigspec);
|
||||||
else
|
else
|
||||||
kill_error (pid, errno);
|
kill_error (pid, errno);
|
||||||
CONTINUE_OR_FAIL;
|
CONTINUE_OR_FAIL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
any_succeeded++;
|
any_succeeded++;
|
||||||
|
} else {
|
||||||
|
errno = kill_by_name(sig, word);
|
||||||
|
CONTINUE_OR_FAIL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#if defined (JOB_CONTROL)
|
#if defined (JOB_CONTROL)
|
||||||
else if (*list->word->word && *list->word->word != '%')
|
else if (*list->word->word && *list->word->word != '%')
|
||||||
|
|||||||
+23
-104
@@ -21,7 +21,6 @@
|
|||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <libgen.h>
|
|
||||||
|
|
||||||
#if HAVE_SYS_WAIT_H
|
#if HAVE_SYS_WAIT_H
|
||||||
# include <sys/wait.h>
|
# include <sys/wait.h>
|
||||||
@@ -37,7 +36,6 @@
|
|||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "sig2str.h"
|
#include "sig2str.h"
|
||||||
#include "operand2sig.h"
|
#include "operand2sig.h"
|
||||||
#include "OS.h"
|
|
||||||
|
|
||||||
/* The official name of this program (e.g., no `g' prefix). */
|
/* The official name of this program (e.g., no `g' prefix). */
|
||||||
#define PROGRAM_NAME "kill"
|
#define PROGRAM_NAME "kill"
|
||||||
@@ -87,7 +85,7 @@ usage (int status)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
printf (_("\
|
printf (_("\
|
||||||
Usage: %s [-s SIGNAL | -SIGNAL] <PID | PROCESS> ...\n\
|
Usage: %s [-s SIGNAL | -SIGNAL] PID...\n\
|
||||||
or: %s -l [SIGNAL]...\n\
|
or: %s -l [SIGNAL]...\n\
|
||||||
or: %s -t [SIGNAL]...\n\
|
or: %s -t [SIGNAL]...\n\
|
||||||
"),
|
"),
|
||||||
@@ -111,8 +109,6 @@ 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\
|
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\
|
or the exit status of a process terminated by a signal.\n\
|
||||||
PID is an integer; if negative it identifies a process group.\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);
|
"), stdout);
|
||||||
printf (USAGE_BUILTIN_WARNING, PROGRAM_NAME);
|
printf (USAGE_BUILTIN_WARNING, PROGRAM_NAME);
|
||||||
emit_ancillary_info ();
|
emit_ancillary_info ();
|
||||||
@@ -200,115 +196,38 @@ list_signals (bool table, char *const *argv)
|
|||||||
|
|
||||||
return status;
|
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;
|
|
||||||
int found = 0;
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* skip the path if any */
|
|
||||||
token = basename(args);
|
|
||||||
|
|
||||||
if (!strncmp(name, token, strlen(token))) {
|
|
||||||
found = 1;
|
|
||||||
/* name matched */
|
|
||||||
if (kill((pid_t)teamInfo.team, signum) != 0) {
|
|
||||||
error (0, errno, "%s", name);
|
|
||||||
status = EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!found)
|
|
||||||
error (0, ESRCH, "%s", name);
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Send signal SIGNUM to all the processes or process groups specified
|
/* Send signal SIGNUM to all the processes or process groups specified
|
||||||
by ARGV. Return a suitable exit status. */
|
by ARGV. Return a suitable exit status. */
|
||||||
|
|
||||||
static int
|
static int
|
||||||
send_signals (int signum, char *const *argv)
|
send_signals (int signum, char *const *argv)
|
||||||
{
|
{
|
||||||
int status = EXIT_SUCCESS;
|
int status = EXIT_SUCCESS;
|
||||||
char const *arg = *argv;
|
char const *arg = *argv;
|
||||||
pid_t pid;
|
|
||||||
|
|
||||||
do {
|
do
|
||||||
bool is_pid = is_number(arg, (intmax_t *) &pid);
|
{
|
||||||
if (is_pid) {
|
char *endp;
|
||||||
if (kill(pid, signum) != 0) {
|
intmax_t n = (errno = 0, strtoimax (arg, &endp, 10));
|
||||||
error (0, errno, "%s", arg);
|
pid_t pid = n;
|
||||||
status = EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
} else if (kill_by_name(signum, arg) != EXIT_SUCCESS)
|
|
||||||
status = EXIT_FAILURE;
|
|
||||||
|
|
||||||
} while ((arg = *++argv));
|
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));
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc, char **argv)
|
main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user