1This file is kill.def, from which is created kill.c.
2It implements the builtin "kill" in Bash.
3
4Copyright (C) 1987-2009 Free Software Foundation, Inc.
5
6This file is part of GNU Bash, the Bourne Again SHell.
7
8Bash is free software: you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation, either version 3 of the License, or
11(at your option) any later version.
12
13Bash is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along with Bash.  If not, see <http://www.gnu.org/licenses/>.
20
21$PRODUCES kill.c
22
23$BUILTIN kill
24$FUNCTION kill_builtin
25$SHORT_DOC kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l [sigspec]
26Send a signal to a job.
27
28Send the processes identified by PID or JOBSPEC the signal named by
29SIGSPEC or SIGNUM.  If neither SIGSPEC nor SIGNUM is present, then
30SIGTERM is assumed.
31
32Options:
33  -s sig	SIG is a signal name
34  -n sig	SIG is a signal number
35  -l	list the signal names; if arguments follow `-l' they are
36	assumed to be signal numbers for which names should be listed
37
38Kill is a shell builtin for two reasons: it allows job IDs to be used
39instead of process IDs, and allows processes to be killed if the limit
40on processes that you can create is reached.
41
42Exit Status:
43Returns success unless an invalid option is given or an error occurs.
44$END
45
46#include <config.h>
47
48#include <stdio.h>
49#include <errno.h>
50#if defined (HAVE_UNISTD_H)
51#  ifdef _MINIX
52#    include <sys/types.h>
53#  endif
54#  include <unistd.h>
55#endif
56
57#include "../bashansi.h"
58#include "../bashintl.h"
59
60#include "../shell.h"
61#include "../trap.h"
62#include "../jobs.h"
63#include "common.h"
64
65/* Not all systems declare ERRNO in errno.h... and some systems #define it! */
66#if !defined (errno)
67extern int errno;
68#endif /* !errno */
69
70extern int posixly_correct;
71
72static void kill_error __P((pid_t, int));
73
74#if !defined (CONTINUE_AFTER_KILL_ERROR)
75#  define CONTINUE_OR_FAIL return (EXECUTION_FAILURE)
76#else
77#  define CONTINUE_OR_FAIL goto continue_killing
78#endif /* CONTINUE_AFTER_KILL_ERROR */
79
80/* Here is the kill builtin.  We only have it so that people can type
81   kill -KILL %1?  No, if you fill up the process table this way you
82   can still kill some. */
83int
84kill_builtin (list)
85     WORD_LIST *list;
86{
87  int sig, any_succeeded, listing, saw_signal, dflags;
88  char *sigspec, *word;
89  pid_t pid;
90  intmax_t pid_value;
91
92  if (list == 0)
93    {
94      builtin_usage ();
95      return (EXECUTION_FAILURE);
96    }
97
98  any_succeeded = listing = saw_signal = 0;
99  sig = SIGTERM;
100  sigspec = "TERM";
101
102  dflags = DSIG_NOCASE | ((posixly_correct == 0) ? DSIG_SIGPREFIX : 0);
103  /* Process options. */
104  while (list)
105    {
106      word = list->word->word;
107
108      if (ISOPTION (word, 'l'))
109	{
110	  listing++;
111	  list = list->next;
112	}
113      else if (ISOPTION (word, 's') || ISOPTION (word, 'n'))
114	{
115	  list = list->next;
116	  if (list)
117	    {
118	      sigspec = list->word->word;
119	      if (sigspec[0] == '0' && sigspec[1] == '\0')
120		sig = 0;
121	      else
122		sig = decode_signal (sigspec, dflags);
123	      list = list->next;
124	    }
125	  else
126	    {
127	      sh_needarg (word);
128	      return (EXECUTION_FAILURE);
129	    }
130	}
131      else if (ISOPTION (word, '-'))
132	{
133	  list = list->next;
134	  break;
135	}
136      else if (ISOPTION (word, '?'))
137	{
138	  builtin_usage ();
139	  return (EXECUTION_SUCCESS);
140	}
141      /* If this is a signal specification then process it.  We only process
142	 the first one seen; other arguments may signify process groups (e.g,
143	 -num == process group num). */
144      else if ((*word == '-') && !saw_signal)
145	{
146	  sigspec = word + 1;
147	  sig = decode_signal (sigspec, dflags);
148	  saw_signal++;
149	  list = list->next;
150	}
151      else
152	break;
153    }
154
155  if (listing)
156    return (display_signal_list (list, 0));
157
158  /* OK, we are killing processes. */
159  if (sig == NO_SIG)
160    {
161      sh_invalidsig (sigspec);
162      return (EXECUTION_FAILURE);
163    }
164
165  if (list == 0)
166    {
167      builtin_usage ();
168      return (EXECUTION_FAILURE);
169    }
170
171  while (list)
172    {
173      word = list->word->word;
174
175      if (*word == '-')
176	word++;
177
178      /* Use the entire argument in case of minus sign presence. */
179      if (*word && legal_number (list->word->word, &pid_value) && (pid_value == (pid_t)pid_value))
180	{
181	  pid = (pid_t) pid_value;
182
183	  if (kill_pid (pid, sig, pid < -1) < 0)
184	    {
185	      if (errno == EINVAL)
186		sh_invalidsig (sigspec);
187	      else
188		kill_error (pid, errno);
189	      CONTINUE_OR_FAIL;
190	    }
191	  else
192	    any_succeeded++;
193	}
194#if defined (JOB_CONTROL)
195      else if (*list->word->word && *list->word->word != '%')
196	{
197	  builtin_error (_("%s: arguments must be process or job IDs"), list->word->word);
198	  CONTINUE_OR_FAIL;
199	}
200      else if (*word)
201	/* Posix.2 says you can kill without job control active (4.32.4) */
202	{			/* Must be a job spec.  Check it out. */
203	  int job;
204	  sigset_t set, oset;
205	  JOB *j;
206
207	  BLOCK_CHILD (set, oset);
208	  job = get_job_spec (list);
209
210	  if (INVALID_JOB (job))
211	    {
212	      if (job != DUP_JOB)
213		sh_badjob (list->word->word);
214	      UNBLOCK_CHILD (oset);
215	      CONTINUE_OR_FAIL;
216	    }
217
218	  j = get_job_by_jid (job);
219	  /* Job spec used.  Kill the process group. If the job was started
220	     without job control, then its pgrp == shell_pgrp, so we have
221	     to be careful.  We take the pid of the first job in the pipeline
222	     in that case. */
223	  pid = IS_JOBCONTROL (job) ? j->pgrp : j->pipe->pid;
224
225	  UNBLOCK_CHILD (oset);
226
227	  if (kill_pid (pid, sig, 1) < 0)
228	    {
229	      if (errno == EINVAL)
230		sh_invalidsig (sigspec);
231	      else
232		kill_error (pid, errno);
233	      CONTINUE_OR_FAIL;
234	    }
235	  else
236	    any_succeeded++;
237	}
238#endif /* !JOB_CONTROL */
239      else
240	{
241	  sh_badpid (list->word->word);
242	  CONTINUE_OR_FAIL;
243	}
244    continue_killing:
245      list = list->next;
246    }
247
248  return (any_succeeded ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
249}
250
251static void
252kill_error (pid, e)
253     pid_t pid;
254     int e;
255{
256  char *x;
257
258  x = strerror (e);
259  if (x == 0)
260    x = _("Unknown error");
261  builtin_error ("(%ld) - %s", (long)pid, x);
262}
263