i-bash/builtins/kill.def

264 lines
6.1 KiB
Modula-2
Raw Normal View History

1996-08-26 18:22:31 +00:00
This file is kill.def, from which is created kill.c.
It implements the builtin "kill" in Bash.
Copyright (C) 1987-2010 Free Software Foundation, Inc.
1996-08-26 18:22:31 +00:00
This file is part of GNU Bash, the Bourne Again SHell.
2009-01-12 13:36:28 +00:00
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.
1996-08-26 18:22:31 +00:00
2009-01-12 13:36:28 +00:00
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.
1996-08-26 18:22:31 +00:00
2009-01-12 13:36:28 +00:00
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
1996-08-26 18:22:31 +00:00
$PRODUCES kill.c
$BUILTIN kill
$FUNCTION kill_builtin
2005-12-07 14:08:12 +00:00
$SHORT_DOC kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l [sigspec]
2009-01-12 13:36:28 +00:00
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.
1996-08-26 18:22:31 +00:00
$END
1996-12-23 17:02:34 +00:00
#include <config.h>
#include <stdio.h>
#include <errno.h>
#if defined (HAVE_UNISTD_H)
1998-04-17 19:52:44 +00:00
# ifdef _MINIX
# include <sys/types.h>
# endif
1996-12-23 17:02:34 +00:00
# include <unistd.h>
#endif
#include "../bashansi.h"
2004-07-27 13:29:18 +00:00
#include "../bashintl.h"
1996-08-26 18:22:31 +00:00
#include "../shell.h"
#include "../trap.h"
#include "../jobs.h"
#include "common.h"
1996-12-23 17:02:34 +00:00
/* Not all systems declare ERRNO in errno.h... and some systems #define it! */
#if !defined (errno)
extern int errno;
#endif /* !errno */
1996-08-26 18:22:31 +00:00
extern int posixly_correct;
2004-07-27 13:29:18 +00:00
static void kill_error __P((pid_t, int));
1996-08-26 18:22:31 +00:00
#if !defined (CONTINUE_AFTER_KILL_ERROR)
# define CONTINUE_OR_FAIL return (EXECUTION_FAILURE)
#else
# define CONTINUE_OR_FAIL goto continue_killing
#endif /* CONTINUE_AFTER_KILL_ERROR */
/* 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
can still kill some. */
int
kill_builtin (list)
WORD_LIST *list;
{
2004-07-27 13:29:18 +00:00
int sig, any_succeeded, listing, saw_signal, dflags;
1996-12-23 17:02:34 +00:00
char *sigspec, *word;
1996-08-26 18:22:31 +00:00
pid_t pid;
2002-07-17 14:10:11 +00:00
intmax_t pid_value;
1996-08-26 18:22:31 +00:00
1996-12-23 17:02:34 +00:00
if (list == 0)
1998-04-17 19:52:44 +00:00
{
builtin_usage ();
return (EXECUTION_FAILURE);
}
1996-08-26 18:22:31 +00:00
1996-12-23 17:02:34 +00:00
any_succeeded = listing = saw_signal = 0;
2002-07-17 14:10:11 +00:00
sig = SIGTERM;
1996-12-23 17:02:34 +00:00
sigspec = "TERM";
2004-07-27 13:29:18 +00:00
dflags = DSIG_NOCASE | ((posixly_correct == 0) ? DSIG_SIGPREFIX : 0);
1996-08-26 18:22:31 +00:00
/* Process options. */
while (list)
{
word = list->word->word;
if (ISOPTION (word, 'l'))
{
listing++;
list = list->next;
}
1996-12-23 17:02:34 +00:00
else if (ISOPTION (word, 's') || ISOPTION (word, 'n'))
1996-08-26 18:22:31 +00:00
{
list = list->next;
if (list)
{
sigspec = list->word->word;
1996-12-23 17:02:34 +00:00
if (sigspec[0] == '0' && sigspec[1] == '\0')
2002-07-17 14:10:11 +00:00
sig = 0;
1996-08-26 18:22:31 +00:00
else
2004-07-27 13:29:18 +00:00
sig = decode_signal (sigspec, dflags);
1996-08-26 18:22:31 +00:00
list = list->next;
saw_signal++;
1996-08-26 18:22:31 +00:00
}
else
{
2002-07-17 14:10:11 +00:00
sh_needarg (word);
1996-08-26 18:22:31 +00:00
return (EXECUTION_FAILURE);
}
}
else if (ISOPTION (word, '-'))
{
list = list->next;
break;
}
1996-12-23 17:02:34 +00:00
else if (ISOPTION (word, '?'))
{
builtin_usage ();
return (EXECUTION_SUCCESS);
}
1996-08-26 18:22:31 +00:00
/* 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). */
2011-11-21 20:51:19 -05:00
else if (*word == '-' && saw_signal == 0)
1996-08-26 18:22:31 +00:00
{
sigspec = word + 1;
2004-07-27 13:29:18 +00:00
sig = decode_signal (sigspec, dflags);
1996-08-26 18:22:31 +00:00
saw_signal++;
list = list->next;
}
else
break;
}
if (listing)
1996-12-23 17:02:34 +00:00
return (display_signal_list (list, 0));
1996-08-26 18:22:31 +00:00
/* OK, we are killing processes. */
2002-07-17 14:10:11 +00:00
if (sig == NO_SIG)
1996-08-26 18:22:31 +00:00
{
2002-07-17 14:10:11 +00:00
sh_invalidsig (sigspec);
1996-08-26 18:22:31 +00:00
return (EXECUTION_FAILURE);
}
1998-04-17 19:52:44 +00:00
if (list == 0)
{
builtin_usage ();
return (EXECUTION_FAILURE);
}
1996-08-26 18:22:31 +00:00
while (list)
{
word = list->word->word;
if (*word == '-')
word++;
2002-07-17 14:10:11 +00:00
/* 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))
1996-08-26 18:22:31 +00:00
{
2001-11-13 17:56:06 +00:00
pid = (pid_t) pid_value;
1996-08-26 18:22:31 +00:00
2005-12-07 14:08:12 +00:00
if (kill_pid (pid, sig, pid < -1) < 0)
2004-07-27 13:29:18 +00:00
{
if (errno == EINVAL)
sh_invalidsig (sigspec);
else
kill_error (pid, errno);
CONTINUE_OR_FAIL;
}
1996-08-26 18:22:31 +00:00
else
any_succeeded++;
}
2004-07-27 13:29:18 +00:00
#if defined (JOB_CONTROL)
1998-04-17 19:52:44 +00:00
else if (*list->word->word && *list->word->word != '%')
1996-08-26 18:22:31 +00:00
{
2004-07-27 13:29:18 +00:00
builtin_error (_("%s: arguments must be process or job IDs"), list->word->word);
1996-08-26 18:22:31 +00:00
CONTINUE_OR_FAIL;
}
2004-07-27 13:29:18 +00:00
else if (*word)
1996-08-26 18:22:31 +00:00
/* 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;
2005-12-07 14:08:12 +00:00
JOB *j;
1996-08-26 18:22:31 +00:00
BLOCK_CHILD (set, oset);
job = get_job_spec (list);
2005-12-07 14:08:12 +00:00
if (INVALID_JOB (job))
1996-08-26 18:22:31 +00:00
{
if (job != DUP_JOB)
2002-07-17 14:10:11 +00:00
sh_badjob (list->word->word);
1996-08-26 18:22:31 +00:00
UNBLOCK_CHILD (oset);
CONTINUE_OR_FAIL;
}
2005-12-07 14:08:12 +00:00
j = get_job_by_jid (job);
1996-08-26 18:22:31 +00:00
/* 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. */
2005-12-07 14:08:12 +00:00
pid = IS_JOBCONTROL (job) ? j->pgrp : j->pipe->pid;
1996-08-26 18:22:31 +00:00
UNBLOCK_CHILD (oset);
2002-07-17 14:10:11 +00:00
if (kill_pid (pid, sig, 1) < 0)
1996-08-26 18:22:31 +00:00
{
2001-11-13 17:56:06 +00:00
if (errno == EINVAL)
2002-07-17 14:10:11 +00:00
sh_invalidsig (sigspec);
2001-11-13 17:56:06 +00:00
else
2004-07-27 13:29:18 +00:00
kill_error (pid, errno);
1996-08-26 18:22:31 +00:00
CONTINUE_OR_FAIL;
}
else
any_succeeded++;
}
2004-07-27 13:29:18 +00:00
#endif /* !JOB_CONTROL */
1996-08-26 18:22:31 +00:00
else
{
2002-07-17 14:10:11 +00:00
sh_badpid (list->word->word);
1996-08-26 18:22:31 +00:00
CONTINUE_OR_FAIL;
}
continue_killing:
list = list->next;
}
1996-12-23 17:02:34 +00:00
return (any_succeeded ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
1996-08-26 18:22:31 +00:00
}
2004-07-27 13:29:18 +00:00
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);
}