]>
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 | |
726f6388 JA |
60 | #include "../shell.h" |
61 | #include "../trap.h" | |
62 | #include "../jobs.h" | |
63 | #include "common.h" | |
ccc6cda3 JA |
64 | |
65 | /* Not all systems declare ERRNO in errno.h... and some systems #define it! */ | |
66 | #if !defined (errno) | |
67 | extern int errno; | |
68 | #endif /* !errno */ | |
726f6388 | 69 | |
726f6388 JA |
70 | extern int posixly_correct; |
71 | ||
b80f6443 JA |
72 | static void kill_error __P((pid_t, int)); |
73 | ||
726f6388 JA |
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. */ | |
83 | int | |
84 | kill_builtin (list) | |
85 | WORD_LIST *list; | |
86 | { | |
b80f6443 | 87 | int sig, any_succeeded, listing, saw_signal, dflags; |
ccc6cda3 | 88 | char *sigspec, *word; |
726f6388 | 89 | pid_t pid; |
7117c2d2 | 90 | intmax_t pid_value; |
726f6388 | 91 | |
ccc6cda3 | 92 | if (list == 0) |
cce855bc JA |
93 | { |
94 | builtin_usage (); | |
95 | return (EXECUTION_FAILURE); | |
96 | } | |
726f6388 | 97 | |
ccc6cda3 | 98 | any_succeeded = listing = saw_signal = 0; |
7117c2d2 | 99 | sig = SIGTERM; |
ccc6cda3 JA |
100 | sigspec = "TERM"; |
101 | ||
b80f6443 | 102 | dflags = DSIG_NOCASE | ((posixly_correct == 0) ? DSIG_SIGPREFIX : 0); |
726f6388 JA |
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 | } | |
ccc6cda3 | 113 | else if (ISOPTION (word, 's') || ISOPTION (word, 'n')) |
726f6388 JA |
114 | { |
115 | list = list->next; | |
116 | if (list) | |
117 | { | |
118 | sigspec = list->word->word; | |
ccc6cda3 | 119 | if (sigspec[0] == '0' && sigspec[1] == '\0') |
7117c2d2 | 120 | sig = 0; |
726f6388 | 121 | else |
b80f6443 | 122 | sig = decode_signal (sigspec, dflags); |
726f6388 | 123 | list = list->next; |
495aee44 | 124 | saw_signal++; |
726f6388 JA |
125 | } |
126 | else | |
127 | { | |
7117c2d2 | 128 | sh_needarg (word); |
726f6388 JA |
129 | return (EXECUTION_FAILURE); |
130 | } | |
131 | } | |
132 | else if (ISOPTION (word, '-')) | |
133 | { | |
134 | list = list->next; | |
135 | break; | |
136 | } | |
ccc6cda3 JA |
137 | else if (ISOPTION (word, '?')) |
138 | { | |
139 | builtin_usage (); | |
140 | return (EXECUTION_SUCCESS); | |
141 | } | |
726f6388 JA |
142 | /* If this is a signal specification then process it. We only process |
143 | the first one seen; other arguments may signify process groups (e.g, | |
144 | -num == process group num). */ | |
0001803f | 145 | else if (*word == '-' && saw_signal == 0) |
726f6388 JA |
146 | { |
147 | sigspec = word + 1; | |
b80f6443 | 148 | sig = decode_signal (sigspec, dflags); |
726f6388 JA |
149 | saw_signal++; |
150 | list = list->next; | |
151 | } | |
152 | else | |
153 | break; | |
154 | } | |
155 | ||
156 | if (listing) | |
ccc6cda3 | 157 | return (display_signal_list (list, 0)); |
726f6388 JA |
158 | |
159 | /* OK, we are killing processes. */ | |
7117c2d2 | 160 | if (sig == NO_SIG) |
726f6388 | 161 | { |
7117c2d2 | 162 | sh_invalidsig (sigspec); |
726f6388 JA |
163 | return (EXECUTION_FAILURE); |
164 | } | |
165 | ||
cce855bc JA |
166 | if (list == 0) |
167 | { | |
168 | builtin_usage (); | |
169 | return (EXECUTION_FAILURE); | |
170 | } | |
171 | ||
726f6388 JA |
172 | while (list) |
173 | { | |
174 | word = list->word->word; | |
175 | ||
176 | if (*word == '-') | |
177 | word++; | |
178 | ||
7117c2d2 JA |
179 | /* Use the entire argument in case of minus sign presence. */ |
180 | if (*word && legal_number (list->word->word, &pid_value) && (pid_value == (pid_t)pid_value)) | |
726f6388 | 181 | { |
f73dda09 | 182 | pid = (pid_t) pid_value; |
726f6388 | 183 | |
95732b49 | 184 | if (kill_pid (pid, sig, pid < -1) < 0) |
b80f6443 JA |
185 | { |
186 | if (errno == EINVAL) | |
187 | sh_invalidsig (sigspec); | |
188 | else | |
189 | kill_error (pid, errno); | |
190 | CONTINUE_OR_FAIL; | |
191 | } | |
726f6388 JA |
192 | else |
193 | any_succeeded++; | |
194 | } | |
b80f6443 | 195 | #if defined (JOB_CONTROL) |
cce855bc | 196 | else if (*list->word->word && *list->word->word != '%') |
726f6388 | 197 | { |
b80f6443 | 198 | builtin_error (_("%s: arguments must be process or job IDs"), list->word->word); |
726f6388 JA |
199 | CONTINUE_OR_FAIL; |
200 | } | |
b80f6443 | 201 | else if (*word) |
726f6388 | 202 | /* Posix.2 says you can kill without job control active (4.32.4) */ |
726f6388 JA |
203 | { /* Must be a job spec. Check it out. */ |
204 | int job; | |
205 | sigset_t set, oset; | |
95732b49 | 206 | JOB *j; |
726f6388 JA |
207 | |
208 | BLOCK_CHILD (set, oset); | |
209 | job = get_job_spec (list); | |
210 | ||
95732b49 | 211 | if (INVALID_JOB (job)) |
726f6388 JA |
212 | { |
213 | if (job != DUP_JOB) | |
7117c2d2 | 214 | sh_badjob (list->word->word); |
726f6388 JA |
215 | UNBLOCK_CHILD (oset); |
216 | CONTINUE_OR_FAIL; | |
217 | } | |
218 | ||
95732b49 | 219 | j = get_job_by_jid (job); |
726f6388 JA |
220 | /* Job spec used. Kill the process group. If the job was started |
221 | without job control, then its pgrp == shell_pgrp, so we have | |
222 | to be careful. We take the pid of the first job in the pipeline | |
223 | in that case. */ | |
95732b49 | 224 | pid = IS_JOBCONTROL (job) ? j->pgrp : j->pipe->pid; |
726f6388 JA |
225 | |
226 | UNBLOCK_CHILD (oset); | |
227 | ||
7117c2d2 | 228 | if (kill_pid (pid, sig, 1) < 0) |
726f6388 | 229 | { |
f73dda09 | 230 | if (errno == EINVAL) |
7117c2d2 | 231 | sh_invalidsig (sigspec); |
f73dda09 | 232 | else |
b80f6443 | 233 | kill_error (pid, errno); |
726f6388 JA |
234 | CONTINUE_OR_FAIL; |
235 | } | |
236 | else | |
237 | any_succeeded++; | |
238 | } | |
b80f6443 | 239 | #endif /* !JOB_CONTROL */ |
726f6388 JA |
240 | else |
241 | { | |
7117c2d2 | 242 | sh_badpid (list->word->word); |
726f6388 JA |
243 | CONTINUE_OR_FAIL; |
244 | } | |
245 | continue_killing: | |
246 | list = list->next; | |
247 | } | |
248 | ||
ccc6cda3 | 249 | return (any_succeeded ? EXECUTION_SUCCESS : EXECUTION_FAILURE); |
726f6388 | 250 | } |
b80f6443 JA |
251 | |
252 | static void | |
253 | kill_error (pid, e) | |
254 | pid_t pid; | |
255 | int e; | |
256 | { | |
257 | char *x; | |
258 | ||
259 | x = strerror (e); | |
260 | if (x == 0) | |
261 | x = _("Unknown error"); | |
262 | builtin_error ("(%ld) - %s", (long)pid, x); | |
263 | } |