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