summaryrefslogtreecommitdiff
path: root/builtins/kill.def
diff options
context:
space:
mode:
Diffstat (limited to 'builtins/kill.def')
-rw-r--r--builtins/kill.def281
1 files changed, 281 insertions, 0 deletions
diff --git a/builtins/kill.def b/builtins/kill.def
new file mode 100644
index 00000000..53d5c8fa
--- /dev/null
+++ b/builtins/kill.def
@@ -0,0 +1,281 @@
+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.
+
+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 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.
+
+$PRODUCES kill.c
+
+$BUILTIN kill
+$FUNCTION kill_builtin
+$DEPENDS_ON JOB_CONTROL
+$SHORT_DOC kill [-s sigspec | -sigspec] [pid | job]... | -l [signum]
+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.
+$END
+
+/* Not all systems declare ERRNO in errno.h... and some systems #define it! */
+#if !defined (errno)
+extern int errno;
+#endif /* !errno */
+
+#include "../bashtypes.h"
+#include "../shell.h"
+#include "../trap.h"
+#include "../jobs.h"
+#include "common.h"
+#include <errno.h>
+
+#if defined (JOB_CONTROL)
+extern int interactive;
+extern int posixly_correct;
+
+#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;
+{
+ int signal = SIGTERM;
+ int any_succeeded = 0, listing = 0, saw_signal = 0;
+ char *sigspec = "TERM", *word;
+ pid_t pid;
+
+ if (!list)
+ return (EXECUTION_SUCCESS);
+
+ /* Process options. */
+ while (list)
+ {
+ word = list->word->word;
+
+ if (ISOPTION (word, 'l'))
+ {
+ listing++;
+ list = list->next;
+ }
+ else if (ISOPTION (word, 's'))
+ {
+ list = list->next;
+ if (list)
+ {
+ sigspec = list->word->word;
+ if (sigspec[0] == '0' && !sigspec[1])
+ signal = 0;
+ else
+ signal = decode_signal (sigspec);
+ list = list->next;
+ }
+ else
+ {
+ builtin_error ("-s requires an argument");
+ return (EXECUTION_FAILURE);
+ }
+ }
+ else if (ISOPTION (word, '-'))
+ {
+ list = list->next;
+ break;
+ }
+ /* 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)
+ {
+ sigspec = word + 1;
+ signal = decode_signal (sigspec);
+ saw_signal++;
+ list = list->next;
+ }
+ else
+ break;
+ }
+
+ if (listing)
+ {
+ if (!list)
+ {
+ register int i;
+ register int column = 0;
+ char *name;
+
+ for (i = 1; i < NSIG; i++)
+ {
+ name = signal_name (i);
+ if (STREQN (name, "SIGJUNK", 7) || STREQN (name, "Unknown", 7))
+ continue;
+
+ if (posixly_correct)
+ printf ("%s%s", name, (i == NSIG - 1) ? "" : " ");
+ else
+ {
+ printf ("%2d) %s", i, name);
+
+ if (++column < 4)
+ printf ("\t");
+ else
+ {
+ printf ("\n");
+ column = 0;
+ }
+ }
+ }
+
+ if (posixly_correct || column != 0)
+ printf ("\n");
+ }
+ else
+ {
+ /* List individual signal names. */
+ while (list)
+ {
+ int signum;
+ char *name;
+
+ if ((sscanf (list->word->word, "%d", &signum) != 1) ||
+ (signum <= 0))
+ {
+ list_error:
+ builtin_error ("bad signal number: %s", list->word->word);
+ list = list->next;
+ continue;
+ }
+
+ /* This is specified by Posix.2 so that exit statuses can be
+ mapped into signal numbers. */
+ if (signum > 128)
+ signum -= 128;
+
+ if (signum >= NSIG)
+ goto list_error;
+
+ name = signal_name (signum);
+ if (STREQN (name, "SIGJUNK", 7) || STREQN (name, "Unknown", 7))
+ {
+ list = list->next;
+ continue;
+ }
+ printf ("%s\n", name);
+ list = list->next;
+ }
+ }
+ return (EXECUTION_SUCCESS);
+ }
+
+ /* OK, we are killing processes. */
+ if (signal == NO_SIG)
+ {
+ builtin_error ("bad signal spec `%s'", sigspec);
+ return (EXECUTION_FAILURE);
+ }
+
+ while (list)
+ {
+ word = list->word->word;
+
+ if (*word == '-')
+ word++;
+
+ if (all_digits (word))
+ {
+ /* Use the entire argument in case of minus sign presence. */
+ pid = (pid_t) atoi (list->word->word);
+
+ if (kill_pid (pid, signal, 0) < 0)
+ goto signal_error;
+ else
+ any_succeeded++;
+ }
+ else if (*list->word->word != '%')
+ {
+ builtin_error ("No such pid %s", list->word->word);
+ CONTINUE_OR_FAIL;
+ }
+#if 1
+ else if (interactive)
+ /* Posix.2 says you can kill without job control active (4.32.4) */
+#else
+ else if (job_control) /* can't kill jobs if not using job control */
+#endif
+ { /* Must be a job spec. Check it out. */
+ int job;
+ sigset_t set, oset;
+
+ BLOCK_CHILD (set, oset);
+ job = get_job_spec (list);
+
+ if (job < 0 || job >= job_slots || !jobs[job])
+ {
+ if (job != DUP_JOB)
+ builtin_error ("No such job %s", list->word->word);
+ UNBLOCK_CHILD (oset);
+ CONTINUE_OR_FAIL;
+ }
+
+ /* 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. */
+ if (jobs[job]->flags & J_JOBCONTROL)
+ pid = jobs[job]->pgrp;
+ else
+ pid = jobs[job]->pipe->pid;
+
+ UNBLOCK_CHILD (oset);
+
+ if (kill_pid (pid, signal, 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);
+ else
+ builtin_error ("Invalid signal %d", signal);
+ CONTINUE_OR_FAIL;
+ }
+ else
+ any_succeeded++;
+ }
+ else
+ {
+ builtin_error ("bad process specification `%s'", list->word->word);
+ CONTINUE_OR_FAIL;
+ }
+ continue_killing:
+ list = list->next;
+ }
+
+ if (any_succeeded)
+ return (EXECUTION_SUCCESS);
+ else
+ return (EXECUTION_FAILURE);
+}
+#endif /* JOB_CONTROL */