1/* kill.c, created from kill.def. */
2#line 23 "kill.def"
3
4#line 35 "kill.def"
5
6#include <config.h>
7
8#include <stdio.h>
9#include <errno.h>
10#if defined (HAVE_UNISTD_H)
11#  ifdef _MINIX
12#    include <sys/types.h>
13#  endif
14#  include <unistd.h>
15#endif
16
17#include "../bashansi.h"
18#include "../bashintl.h"
19
20#include "../shell.h"
21#include "../trap.h"
22#include "../jobs.h"
23#include "common.h"
24
25/* Not all systems declare ERRNO in errno.h... and some systems #define it! */
26#if !defined (errno)
27extern int errno;
28#endif /* !errno */
29
30extern int posixly_correct;
31
32static void kill_error __P((pid_t, int));
33
34#if !defined (CONTINUE_AFTER_KILL_ERROR)
35#  define CONTINUE_OR_FAIL return (EXECUTION_FAILURE)
36#else
37#  define CONTINUE_OR_FAIL goto continue_killing
38#endif /* CONTINUE_AFTER_KILL_ERROR */
39
40/* Here is the kill builtin.  We only have it so that people can type
41   kill -KILL %1?  No, if you fill up the process table this way you
42   can still kill some. */
43int
44kill_builtin (list)
45     WORD_LIST *list;
46{
47  int sig, any_succeeded, listing, saw_signal, dflags;
48  char *sigspec, *word;
49  pid_t pid;
50  intmax_t pid_value;
51
52  if (list == 0)
53    {
54      builtin_usage ();
55      return (EXECUTION_FAILURE);
56    }
57
58  any_succeeded = listing = saw_signal = 0;
59  sig = SIGTERM;
60  sigspec = "TERM";
61
62  dflags = DSIG_NOCASE | ((posixly_correct == 0) ? DSIG_SIGPREFIX : 0);
63  /* Process options. */
64  while (list)
65    {
66      word = list->word->word;
67
68      if (ISOPTION (word, 'l'))
69	{
70	  listing++;
71	  list = list->next;
72	}
73      else if (ISOPTION (word, 's') || ISOPTION (word, 'n'))
74	{
75	  list = list->next;
76	  if (list)
77	    {
78	      sigspec = list->word->word;
79	      if (sigspec[0] == '0' && sigspec[1] == '\0')
80		sig = 0;
81	      else
82		sig = decode_signal (sigspec, dflags);
83	      list = list->next;
84	    }
85	  else
86	    {
87	      sh_needarg (word);
88	      return (EXECUTION_FAILURE);
89	    }
90	}
91      else if (ISOPTION (word, '-'))
92	{
93	  list = list->next;
94	  break;
95	}
96      else if (ISOPTION (word, '?'))
97	{
98	  builtin_usage ();
99	  return (EXECUTION_SUCCESS);
100	}
101      /* If this is a signal specification then process it.  We only process
102	 the first one seen; other arguments may signify process groups (e.g,
103	 -num == process group num). */
104      else if ((*word == '-') && !saw_signal)
105	{
106	  sigspec = word + 1;
107	  sig = decode_signal (sigspec, dflags);
108	  saw_signal++;
109	  list = list->next;
110	}
111      else
112	break;
113    }
114
115  if (listing)
116    return (display_signal_list (list, 0));
117
118  /* OK, we are killing processes. */
119  if (sig == NO_SIG)
120    {
121      sh_invalidsig (sigspec);
122      return (EXECUTION_FAILURE);
123    }
124
125  if (list == 0)
126    {
127      builtin_usage ();
128      return (EXECUTION_FAILURE);
129    }
130
131  while (list)
132    {
133      word = list->word->word;
134
135      if (*word == '-')
136	word++;
137
138      /* Use the entire argument in case of minus sign presence. */
139      if (*word && legal_number (list->word->word, &pid_value) && (pid_value == (pid_t)pid_value))
140	{
141	  pid = (pid_t) pid_value;
142
143	  if (kill_pid (pid, sig, pid < -1) < 0)
144	    {
145	      if (errno == EINVAL)
146		sh_invalidsig (sigspec);
147	      else
148		kill_error (pid, errno);
149	      CONTINUE_OR_FAIL;
150	    }
151	  else
152	    any_succeeded++;
153	}
154#if defined (JOB_CONTROL)
155      else if (*list->word->word && *list->word->word != '%')
156	{
157	  builtin_error (_("%s: arguments must be process or job IDs"), list->word->word);
158	  CONTINUE_OR_FAIL;
159	}
160      else if (*word)
161	/* Posix.2 says you can kill without job control active (4.32.4) */
162	{			/* Must be a job spec.  Check it out. */
163	  int job;
164	  sigset_t set, oset;
165	  JOB *j;
166
167	  BLOCK_CHILD (set, oset);
168	  job = get_job_spec (list);
169
170	  if (INVALID_JOB (job))
171	    {
172	      if (job != DUP_JOB)
173		sh_badjob (list->word->word);
174	      UNBLOCK_CHILD (oset);
175	      CONTINUE_OR_FAIL;
176	    }
177
178	  j = get_job_by_jid (job);
179	  /* Job spec used.  Kill the process group. If the job was started
180	     without job control, then its pgrp == shell_pgrp, so we have
181	     to be careful.  We take the pid of the first job in the pipeline
182	     in that case. */
183	  pid = IS_JOBCONTROL (job) ? j->pgrp : j->pipe->pid;
184
185	  UNBLOCK_CHILD (oset);
186
187	  if (kill_pid (pid, sig, 1) < 0)
188	    {
189	      if (errno == EINVAL)
190		sh_invalidsig (sigspec);
191	      else
192		kill_error (pid, errno);
193	      CONTINUE_OR_FAIL;
194	    }
195	  else
196	    any_succeeded++;
197	}
198#endif /* !JOB_CONTROL */
199      else
200	{
201	  sh_badpid (list->word->word);
202	  CONTINUE_OR_FAIL;
203	}
204    continue_killing:
205      list = list->next;
206    }
207
208  return (any_succeeded ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
209}
210
211static void
212kill_error (pid, e)
213     pid_t pid;
214     int e;
215{
216  char *x;
217
218  x = strerror (e);
219  if (x == 0)
220    x = _("Unknown error");
221  builtin_error ("(%ld) - %s", (long)pid, x);
222}
223