]> git.ipfire.org Git - thirdparty/util-linux.git/blame - misc-utils/kill.c
Imported from util-linux-2.9i tarball.
[thirdparty/util-linux.git] / misc-utils / kill.c
CommitLineData
6dbe3af9
KZ
1/*
2 * Copyright (c) 1988, 1993, 1994
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33/*
34 * oct 5 1994 -- almost entirely re-written to allow for process names.
35 * modifications (c) salvatore valente <svalente@mit.edu>
36 * may be used / modified / distributed under the same terms as the original.
37 */
38
39#include <stdio.h>
40#include <stdlib.h>
41#include <string.h>
42#include <ctype.h>
43#include <unistd.h>
44#include <signal.h>
45
5c36a0eb
KZ
46#define SIZE(a) (sizeof(a)/sizeof(a[0]))
47
48struct signv {
49 char *name;
50 int val;
51} sys_signame[] = {
52 /* POSIX signals */
53 { "HUP", SIGHUP }, /* 1 */
54 { "INT", SIGINT }, /* 2 */
55 { "QUIT", SIGQUIT }, /* 3 */
56 { "ILL", SIGILL }, /* 4 */
57 { "ABRT", SIGABRT }, /* 6 */
58 { "FPE", SIGFPE }, /* 8 */
59 { "KILL", SIGKILL }, /* 9 */
60 { "SEGV", SIGSEGV }, /* 11 */
61 { "PIPE", SIGPIPE }, /* 13 */
62 { "ALRM", SIGALRM }, /* 14 */
63 { "TERM", SIGTERM }, /* 15 */
64 { "USR1", SIGUSR1 }, /* 10 (arm,i386,m68k,ppc), 30 (alpha,sparc*), 16 (mips) */
65 { "USR2", SIGUSR2 }, /* 12 (arm,i386,m68k,ppc), 31 (alpha,sparc*), 17 (mips) */
66 { "CHLD", SIGCHLD }, /* 17 (arm,i386,m68k,ppc), 20 (alpha,sparc*), 18 (mips) */
67 { "CONT", SIGCONT }, /* 18 (arm,i386,m68k,ppc), 19 (alpha,sparc*), 25 (mips) */
68 { "STOP", SIGSTOP }, /* 19 (arm,i386,m68k,ppc), 17 (alpha,sparc*), 23 (mips) */
69 { "TSTP", SIGTSTP }, /* 20 (arm,i386,m68k,ppc), 18 (alpha,sparc*), 24 (mips) */
70 { "TTIN", SIGTTIN }, /* 21 (arm,i386,m68k,ppc,alpha,sparc*), 26 (mips) */
71 { "TTOU", SIGTTOU }, /* 22 (arm,i386,m68k,ppc,alpha,sparc*), 27 (mips) */
72 /* Miscellaneous other signals */
73#ifdef SIGTRAP
74 { "TRAP", SIGTRAP }, /* 5 */
75#endif
76#ifdef SIGIOT
77 { "IOT", SIGIOT }, /* 6, same as SIGABRT */
78#endif
79#ifdef SIGEMT
80 { "EMT", SIGEMT }, /* 7 (mips,alpha,sparc*) */
81#endif
82#ifdef SIGBUS
83 { "BUS", SIGBUS }, /* 7 (arm,i386,m68k,ppc), 10 (mips,alpha,sparc*) */
84#endif
85#ifdef SIGSYS
86 { "SYS", SIGSYS }, /* 12 (mips,alpha,sparc*) */
87#endif
88#ifdef SIGSTKFLT
89 { "STKFLT", SIGSTKFLT }, /* 16 (arm,i386,m68k,ppc) */
90#endif
91#ifdef SIGURG
92 { "URG", SIGURG }, /* 23 (arm,i386,m68k,ppc), 16 (alpha,sparc*), 21 (mips) */
93#endif
94#ifdef SIGIO
95 { "IO", SIGIO }, /* 29 (arm,i386,m68k,ppc), 23 (alpha,sparc*), 22 (mips) */
96#endif
97#ifdef SIGPOLL
98 { "POLL", SIGPOLL }, /* same as SIGIO */
99#endif
100#ifdef SIGCLD
101 { "CLD", SIGCLD }, /* same as SIGCHLD (mips) */
102#endif
103#ifdef SIGXCPU
104 { "XCPU", SIGXCPU }, /* 24 (arm,i386,m68k,ppc,alpha,sparc*), 30 (mips) */
6dbe3af9 105#endif
5c36a0eb
KZ
106#ifdef SIGXFSZ
107 { "XFSZ", SIGXFSZ }, /* 25 (arm,i386,m68k,ppc,alpha,sparc*), 31 (mips) */
108#endif
109#ifdef SIGVTALRM
110 { "VTALRM", SIGVTALRM }, /* 26 (arm,i386,m68k,ppc,alpha,sparc*), 28 (mips) */
111#endif
112#ifdef SIGPROF
113 { "PROF", SIGPROF }, /* 27 (arm,i386,m68k,ppc,alpha,sparc*), 29 (mips) */
114#endif
115#ifdef SIGPWR
116 { "PWR", SIGPWR }, /* 30 (arm,i386,m68k,ppc), 29 (alpha,sparc*), 19 (mips) */
117#endif
118#ifdef SIGINFO
119 { "INFO", SIGINFO }, /* 29 (alpha) */
120#endif
121#ifdef SIGLOST
122 { "LOST", SIGLOST }, /* 29 (arm,i386,m68k,ppc,sparc*) */
123#endif
124#ifdef SIGWINCH
125 { "WINCH", SIGWINCH }, /* 28 (arm,i386,m68k,ppc,alpha,sparc*), 20 (mips) */
126#endif
127#ifdef SIGUNUSED
128 { "UNUSED", SIGUNUSED }, /* 31 (arm,i386,m68k,ppc) */
129#endif
130};
6dbe3af9
KZ
131
132int main (int argc, char *argv[]);
fd6b7a7f 133extern char *mybasename(char *);
6dbe3af9
KZ
134int signame_to_signum (char *sig);
135int arg_to_signum (char *arg);
136void nosig (char *name);
137void printsig (int sig);
138void printsignals (FILE *fp);
139int usage (int status);
140int kill_verbose (char *procname, int pid, int sig);
141
142extern int *get_pids (char *, int);
143
144char version_string[] = "kill v2.0\n";
145char *whoami;
146
147int main (int argc, char *argv[])
148{
149 int errors, numsig, pid;
150 char *ep, *arg;
151 int do_pid, do_kill, check_all;
152 int *pids, *ip;
153
154 whoami = mybasename (*argv);
155 numsig = SIGTERM;
156 do_pid = (! strcmp (whoami, "pid"));
157 do_kill = 0;
158 check_all = 0;
159
160 /* loop through the arguments.
161 actually, -a is the only option can be used with other options.
162 `kill' is basically a one-option-at-most program. */
163 for (argc--, argv++; argc > 0; argc--, argv++) {
164 arg = *argv;
165 if (*arg != '-') {
166 break;
167 }
168 if (! strcmp (arg, "-u")) {
169 return usage (0);
170 }
171 if (! strcmp (arg, "-v")) {
172 fputs (version_string, stdout);
173 return 0;
174 }
175 if (! strcmp (arg, "-a")) {
176 check_all++;
177 continue;
178 }
179 if (! strcmp (arg, "-l")) {
180 if (argc < 2) {
181 printsignals (stdout);
182 return 0;
183 }
184 if (argc > 2) {
185 return usage (1);
186 }
187 /* argc == 2 */
188 arg = argv[1];
189 if ((numsig = arg_to_signum (arg)) < 0) {
190 fprintf (stderr, "%s: unknown signal %s\n", whoami, arg);
191 return 1;
192 }
193 printsig (numsig);
194 return 0;
195 }
196 if (! strcmp (arg, "-p")) {
197 do_pid++;
198 if (do_kill)
199 return usage (1);
200 continue;
201 }
202 if (! strcmp (arg, "-s")) {
203 if (argc < 2) {
204 return usage (1);
205 }
206 do_kill++;
207 if (do_pid)
208 return usage (1);
209 argc--, argv++;
210 arg = *argv;
211 if ((numsig = arg_to_signum (arg)) < 0) {
212 nosig (arg);
213 return 1;
214 }
215 continue;
216 }
217 /* `arg' begins with a dash but is not a known option.
fd6b7a7f
KZ
218 so it's probably something like -HUP, or -1/-n
219 try to deal with it.
220 -n could be signal n, or pid -n (i.e. process group n).
221 If a signal has been parsed, assume it's a pid, break */
222 if (do_kill)
223 break;
6dbe3af9
KZ
224 arg++;
225 if ((numsig = arg_to_signum (arg)) < 0) {
226 return usage (1);
227 }
228 do_kill++;
229 if (do_pid)
230 return usage (1);
231 continue;
232 }
233
234 if (! *argv) {
235 return usage (1);
236 }
237 if (do_pid) {
238 numsig = -1;
239 }
240
241 /* we're done with the options.
242 the rest of the arguments should be process ids and names.
243 kill them. */
244 for (errors = 0; (arg = *argv) != NULL; argv++) {
245 pid = strtol (arg, &ep, 10);
246 if (! *ep)
247 errors += kill_verbose (arg, pid, numsig);
248 else {
249 pids = get_pids (arg, check_all);
250 if (! pids) {
251 errors++;
252 fprintf (stderr, "%s: can't find process \"%s\"\n",
253 whoami, arg);
254 continue;
255 }
256 for (ip = pids; *ip >= 0; ip++)
257 errors += kill_verbose (arg, *ip, numsig);
258 free (pids);
259 }
260 }
261 return (errors);
262}
263
6dbe3af9
KZ
264
265int signame_to_signum (char *sig)
266{
267 int n;
268
269 if (! strncasecmp (sig, "sig", 3))
270 sig += 3;
5c36a0eb
KZ
271 for (n = 0; n < SIZE(sys_signame); n++) {
272 if (! strcasecmp (sys_signame[n].name, sig))
273 return sys_signame[n].val;
6dbe3af9
KZ
274 }
275 return (-1);
276}
277
278int arg_to_signum (char *arg)
279{
280 int numsig;
281 char *ep;
282
283 if (isdigit (*arg)) {
284 numsig = strtol (arg, &ep, 10);
285 if (*ep != 0 || numsig < 0 || numsig >= NSIG)
286 return (-1);
287 return (numsig);
288 }
289 return (signame_to_signum (arg));
290}
291
292void nosig (char *name)
293{
294 fprintf (stderr, "%s: unknown signal %s; valid signals:\n", whoami, name);
295 printsignals (stderr);
296}
297
298void printsig (int sig)
299{
5c36a0eb
KZ
300 int n;
301
302 for (n = 0; n < SIZE(sys_signame); n++) {
303 if (sys_signame[n].val == sig) {
304 printf ("%s\n", sys_signame[n].name);
305 return;
306 }
307 }
308 printf("%d\n", sig);
6dbe3af9
KZ
309}
310
311void printsignals (FILE *fp)
312{
5c36a0eb
KZ
313 int n, lth;
314 int lpos = 0;
6dbe3af9 315
5c36a0eb
KZ
316 for (n = 0; n < SIZE(sys_signame); n++) {
317 lth = 1+strlen(sys_signame[n].name);
318 if (lpos+lth > 72) {
6dbe3af9 319 fputc ('\n', fp);
5c36a0eb
KZ
320 lpos = 0;
321 } else if (lpos)
6dbe3af9 322 fputc (' ', fp);
5c36a0eb
KZ
323 lpos += lth;
324 fputs (sys_signame[n].name, fp);
6dbe3af9 325 }
5c36a0eb 326 fputc ('\n', fp);
6dbe3af9
KZ
327}
328
329int usage (int status)
330{
331 FILE *fp;
332
333 fp = (status == 0 ? stdout : stderr);
334 fprintf (fp, "usage: %s [ -s signal | -p ] [ -a ] pid ...\n", whoami);
335 fprintf (fp, " %s -l [ signal ]\n", whoami);
336 return status;
337}
338
339int kill_verbose (char *procname, int pid, int sig)
340{
341 if (sig < 0) {
342 printf ("%d\n", pid);
343 return 0;
344 }
345 if (kill (pid, sig) < 0) {
346 fprintf (stderr, "%s ", whoami);
347 perror (procname);
348 return 1;
349 }
350 return 0;
351}