1This file is kill.def, from which is created kill.c.
2It implements the builtin "kill" in Bash.
3
4Copyright (C) 1987-2020 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  -L	synonym for -l
38
39Kill is a shell builtin for two reasons: it allows job IDs to be used
40instead of process IDs, and allows processes to be killed if the limit
41on processes that you can create is reached.
42
43Exit Status:
44Returns success unless an invalid option is given or an error occurs.
45$END
46
47#include <config.h>
48
49#include <stdio.h>
50#include <errno.h>
51#if defined (HAVE_UNISTD_H)
52#  ifdef _MINIX
53#    include <sys/types.h>
54#  endif
55#  include <unistd.h>
56#endif
57
58#include "../bashansi.h"
59#include "../bashintl.h"
60
61#include <signal.h>
62
63#include "../shell.h"
64#include "../trap.h"
65#include "../jobs.h"
66#include "common.h"
67
68/* Not all systems declare ERRNO in errno.h... and some systems #define it! */
69#if !defined (errno)
70extern int errno;
71#endif /* !errno */
72
73static void kill_error PARAMS((pid_t, int));
74
75#if !defined (CONTINUE_AFTER_KILL_ERROR)
76#  define CONTINUE_OR_FAIL return (EXECUTION_FAILURE)
77#else
78#  define CONTINUE_OR_FAIL goto continue_killing
79#endif /* CONTINUE_AFTER_KILL_ERROR */
80
81/* Here is the kill builtin.  We only have it so that people can type
82   kill -KILL %1?  No, if you fill up the process table this way you
83   can still kill some. */
84int
85kill_builtin (list)
86     WORD_LIST *list;
87{
88  int sig, any_succeeded, listing, saw_signal, dflags;
89  char *sigspec, *word;
90  pid_t pid;
91  intmax_t pid_value;
92
93  if (list == 0)
94    {
95      builtin_usage ();
96      return (EX_USAGE);
97    }
98  CHECK_HELPOPT (list);
99
100  any_succeeded = listing = saw_signal = 0;
101  sig = SIGTERM;
102  sigspec = "TERM";
103
104  dflags = DSIG_NOCASE | ((posixly_correct == 0) ? DSIG_SIGPREFIX : 0);
105  /* Process options. */
106  while (list)
107    {
108      word = list->word->word;
109
110      if (ISOPTION (word, 'l') || ISOPTION (word, 'L'))
111	{
112	  listing++;
113	  list = list->next;
114	}
115      else if (ISOPTION (word, 's') || ISOPTION (word, 'n'))
116	{
117	  list = list->next;
118	  if (list)
119	    {
120	      sigspec = list->word->word;
121use_sigspec:
122	      if (sigspec[0] == '0' && sigspec[1] == '\0')
123		sig = 0;
124	      else
125		sig = decode_signal (sigspec, dflags);
126	      list = list->next;
127	      saw_signal++;
128	    }
129	  else
130	    {
131	      sh_needarg (word);
132	      return (EXECUTION_FAILURE);
133	    }
134	}
135      else if (word[0] == '-' && word[1] == 's' && ISALPHA (word[2]))
136	{
137	  sigspec = word + 2;
138	  goto use_sigspec;
139	}
140      else if (word[0] == '-' && word[1] == 'n' && ISDIGIT (word[2]))
141	{
142	  sigspec = word + 2;
143	  goto use_sigspec;
144	}
145      else if (ISOPTION (word, '-'))
146	{
147	  list = list->next;
148	  break;
149	}
150      else if (ISOPTION (word, '?'))
151	{
152	  builtin_usage ();
153	  return (EX_USAGE);
154	}
155      /* If this is a signal specification then process it.  We only process
156	 the first one seen; other arguments may signify process groups (e.g,
157	 -num == process group num). */
158      else if (*word == '-' && saw_signal == 0)
159	{
160	  sigspec = word + 1;
161	  sig = decode_signal (sigspec, dflags);
162	  saw_signal++;
163	  list = list->next;
164	}
165      else
166	break;
167    }
168
169  if (listing)
170    return (display_signal_list (list, 0));
171
172  /* OK, we are killing processes. */
173  if (sig == NO_SIG)
174    {
175      sh_invalidsig (sigspec);
176      return (EXECUTION_FAILURE);
177    }
178
179  if (list == 0)
180    {
181      builtin_usage ();
182      return (EX_USAGE);
183    }
184
185  while (list)
186    {
187      word = list->word->word;
188
189      if (*word == '-')
190	word++;
191
192      /* Use the entire argument in case of minus sign presence. */
193      if (*word && legal_number (list->word->word, &pid_value) && (pid_value == (pid_t)pid_value))
194	{
195	  pid = (pid_t) pid_value;
196
197	  if (kill_pid (pid, sig, pid < -1) < 0)
198	    {
199	      if (errno == EINVAL)
200		sh_invalidsig (sigspec);
201	      else
202		kill_error (pid, errno);
203	      CONTINUE_OR_FAIL;
204	    }
205	  else
206	    any_succeeded++;
207	}
208#if defined (JOB_CONTROL)
209      else if (*list->word->word && *list->word->word != '%')
210	{
211	  builtin_error (_("%s: arguments must be process or job IDs"), list->word->word);
212	  CONTINUE_OR_FAIL;
213	}
214      else if (*word)
215	/* Posix.2 says you can kill without job control active (4.32.4) */
216	{			/* Must be a job spec.  Check it out. */
217	  int job;
218	  sigset_t set, oset;
219	  JOB *j;
220
221	  BLOCK_CHILD (set, oset);
222	  job = get_job_spec (list);
223
224	  if (INVALID_JOB (job))
225	    {
226	      if (job != DUP_JOB)
227		sh_badjob (list->word->word);
228	      UNBLOCK_CHILD (oset);
229	      CONTINUE_OR_FAIL;
230	    }
231
232	  j = get_job_by_jid (job);
233	  /* Job spec used.  Kill the process group. If the job was started
234	     without job control, then its pgrp == shell_pgrp, so we have
235	     to be careful.  We take the pid of the first job in the pipeline
236	     in that case. */
237	  pid = IS_JOBCONTROL (job) ? j->pgrp : j->pipe->pid;
238
239	  UNBLOCK_CHILD (oset);
240
241	  if (kill_pid (pid, sig, 1) < 0)
242	    {
243	      if (errno == EINVAL)
244		sh_invalidsig (sigspec);
245	      else
246		kill_error (pid, errno);
247	      CONTINUE_OR_FAIL;
248	    }
249	  else
250	    any_succeeded++;
251	}
252#endif /* !JOB_CONTROL */
253      else
254	{
255	  sh_badpid (list->word->word);
256	  CONTINUE_OR_FAIL;
257	}
258    continue_killing:
259      list = list->next;
260    }
261
262  return (any_succeeded ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
263}
264
265static void
266kill_error (pid, e)
267     pid_t pid;
268     int e;
269{
270  char *x;
271
272  x = strerror (e);
273  if (x == 0)
274    x = _("Unknown error");
275  builtin_error ("(%ld) - %s", (long)pid, x);
276}
277