This file is kill.def, from which is created kill.c.
It implements the builtin "kill" in Bash.
-Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
+Copyright (C) 1987-2010 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
-Bash is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 1, or (at your option) any later
-version.
+Bash is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
-Bash is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-for more details.
+Bash is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
-You should have received a copy of the GNU General Public License along
-with Bash; see the file COPYING. If not, write to the Free Software
-Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+You should have received a copy of the GNU General Public License
+along with Bash. If not, see <http://www.gnu.org/licenses/>.
$PRODUCES kill.c
$BUILTIN kill
$FUNCTION kill_builtin
-$DEPENDS_ON JOB_CONTROL
-$SHORT_DOC kill [-s sigspec | -n signum | -sigspec] [pid | job]... or kill -l [sigspec]
-Send the processes named by PID (or JOB) the signal SIGSPEC. If
-SIGSPEC is not present, then SIGTERM is assumed. An argument of `-l'
-lists the signal names; if arguments follow `-l' they are assumed to
-be signal numbers for which names should be listed. Kill is a shell
-builtin for two reasons: it allows job IDs to be used instead of
-process IDs, and, if you have reached the limit on processes that
-you can create, you don't have to start a process to kill another one.
+$SHORT_DOC kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l [sigspec]
+Send a signal to a job.
+
+Send the processes identified by PID or JOBSPEC the signal named by
+SIGSPEC or SIGNUM. If neither SIGSPEC nor SIGNUM is present, then
+SIGTERM is assumed.
+
+Options:
+ -s sig SIG is a signal name
+ -n sig SIG is a signal number
+ -l list the signal names; if arguments follow `-l' they are
+ assumed to be signal numbers for which names should be listed
+
+Kill is a shell builtin for two reasons: it allows job IDs to be used
+instead of process IDs, and allows processes to be killed if the limit
+on processes that you can create is reached.
+
+Exit Status:
+Returns success unless an invalid option is given or an error occurs.
$END
#include <config.h>
#include <stdio.h>
#include <errno.h>
#if defined (HAVE_UNISTD_H)
+# ifdef _MINIX
+# include <sys/types.h>
+# endif
# include <unistd.h>
#endif
#include "../bashansi.h"
+#include "../bashintl.h"
+
+#include <signal.h>
#include "../shell.h"
#include "../trap.h"
extern int errno;
#endif /* !errno */
-#if defined (JOB_CONTROL)
-extern int interactive;
-extern int job_control;
extern int posixly_correct;
+static void kill_error __P((pid_t, int));
+
#if !defined (CONTINUE_AFTER_KILL_ERROR)
# define CONTINUE_OR_FAIL return (EXECUTION_FAILURE)
#else
kill_builtin (list)
WORD_LIST *list;
{
- int signal, any_succeeded, listing, saw_signal;
+ int sig, any_succeeded, listing, saw_signal, dflags;
char *sigspec, *word;
pid_t pid;
+ intmax_t pid_value;
if (list == 0)
- return (EXECUTION_SUCCESS);
+ {
+ builtin_usage ();
+ return (EX_USAGE);
+ }
any_succeeded = listing = saw_signal = 0;
- signal = SIGTERM;
+ sig = SIGTERM;
sigspec = "TERM";
+ dflags = DSIG_NOCASE | ((posixly_correct == 0) ? DSIG_SIGPREFIX : 0);
/* Process options. */
while (list)
{
{
sigspec = list->word->word;
if (sigspec[0] == '0' && sigspec[1] == '\0')
- signal = 0;
+ sig = 0;
else
- signal = decode_signal (sigspec);
+ sig = decode_signal (sigspec, dflags);
list = list->next;
+ saw_signal++;
}
else
{
- builtin_error ("%s requires an argument", word);
+ sh_needarg (word);
return (EXECUTION_FAILURE);
}
}
else if (ISOPTION (word, '?'))
{
builtin_usage ();
- return (EXECUTION_SUCCESS);
+ return (EX_USAGE);
}
/* If this is a signal specification then process it. We only process
the first one seen; other arguments may signify process groups (e.g,
-num == process group num). */
- else if ((*word == '-') && !saw_signal)
+ else if (*word == '-' && saw_signal == 0)
{
sigspec = word + 1;
- signal = decode_signal (sigspec);
+ sig = decode_signal (sigspec, dflags);
saw_signal++;
list = list->next;
}
return (display_signal_list (list, 0));
/* OK, we are killing processes. */
- if (signal == NO_SIG)
+ if (sig == NO_SIG)
{
- builtin_error ("bad signal spec `%s'", sigspec);
+ sh_invalidsig (sigspec);
return (EXECUTION_FAILURE);
}
+ if (list == 0)
+ {
+ builtin_usage ();
+ return (EX_USAGE);
+ }
+
while (list)
{
word = list->word->word;
if (*word == '-')
word++;
- if (all_digits (word))
+ /* 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))
{
- /* Use the entire argument in case of minus sign presence. */
- pid = (pid_t) atoi (list->word->word);
+ pid = (pid_t) pid_value;
- if (kill_pid (pid, signal, 0) < 0)
- goto signal_error;
+ if (kill_pid (pid, sig, pid < -1) < 0)
+ {
+ if (errno == EINVAL)
+ sh_invalidsig (sigspec);
+ else
+ kill_error (pid, errno);
+ CONTINUE_OR_FAIL;
+ }
else
any_succeeded++;
}
- else if (*list->word->word != '%')
+#if defined (JOB_CONTROL)
+ else if (*list->word->word && *list->word->word != '%')
{
- builtin_error ("%s: no such pid", list->word->word);
+ builtin_error (_("%s: arguments must be process or job IDs"), list->word->word);
CONTINUE_OR_FAIL;
}
- else if (interactive || job_control)
+ else if (*word)
/* Posix.2 says you can kill without job control active (4.32.4) */
{ /* Must be a job spec. Check it out. */
int job;
sigset_t set, oset;
+ JOB *j;
BLOCK_CHILD (set, oset);
job = get_job_spec (list);
- if (job < 0 || job >= job_slots || !jobs[job])
+ if (INVALID_JOB (job))
{
if (job != DUP_JOB)
- builtin_error ("%s: no such job", list->word->word);
+ sh_badjob (list->word->word);
UNBLOCK_CHILD (oset);
CONTINUE_OR_FAIL;
}
+ j = get_job_by_jid (job);
/* Job spec used. Kill the process group. If the job was started
without job control, then its pgrp == shell_pgrp, so we have
to be careful. We take the pid of the first job in the pipeline
in that case. */
- pid = IS_JOBCONTROL (job) ? jobs[job]->pgrp : jobs[job]->pipe->pid;
+ pid = IS_JOBCONTROL (job) ? j->pgrp : j->pipe->pid;
UNBLOCK_CHILD (oset);
- if (kill_pid (pid, signal, 1) < 0)
+ if (kill_pid (pid, sig, 1) < 0)
{
- signal_error:
- if (errno == EPERM)
- builtin_error ("(%d) - Not owner", (int)pid);
- else if (errno == ESRCH)
- builtin_error ("(%d) - No such pid", (int)pid);
+ if (errno == EINVAL)
+ sh_invalidsig (sigspec);
else
- builtin_error ("Invalid signal %d", signal);
+ kill_error (pid, errno);
CONTINUE_OR_FAIL;
}
else
any_succeeded++;
}
+#endif /* !JOB_CONTROL */
else
{
- builtin_error ("`%s' is not a pid or valid job spec", list->word->word);
+ sh_badpid (list->word->word);
CONTINUE_OR_FAIL;
}
continue_killing:
return (any_succeeded ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
}
-#endif /* JOB_CONTROL */
+
+static void
+kill_error (pid, e)
+ pid_t pid;
+ int e;
+{
+ char *x;
+
+ x = strerror (e);
+ if (x == 0)
+ x = _("Unknown error");
+ builtin_error ("(%ld) - %s", (long)pid, x);
+}