Upload Tizen:Base source
[framework/base/util-linux-ng.git] / misc-utils / kill.c
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  *  1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>
39  *  - added Native Language Support
40  *
41  *  1999-11-13 aeb Accept signal numers 128+s.
42  *
43  */
44
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <strings.h>
49 #include <ctype.h>              /* for isdigit() */
50 #include <unistd.h>
51 #include <signal.h>
52 #include "kill.h"
53 #include "nls.h"
54
55 #define SIZE(a) (sizeof(a)/sizeof(a[0]))
56
57 struct signv {
58         char *name;
59         int val;
60 } sys_signame[] = {
61         /* POSIX signals */
62         { "HUP",        SIGHUP },       /* 1 */
63         { "INT",        SIGINT },       /* 2 */
64         { "QUIT",       SIGQUIT },      /* 3 */
65         { "ILL",        SIGILL },       /* 4 */
66         { "ABRT",       SIGABRT },      /* 6 */
67         { "FPE",        SIGFPE },       /* 8 */
68         { "KILL",       SIGKILL },      /* 9 */
69         { "SEGV",       SIGSEGV },      /* 11 */
70         { "PIPE",       SIGPIPE },      /* 13 */
71         { "ALRM",       SIGALRM },      /* 14 */
72         { "TERM",       SIGTERM },      /* 15 */
73         { "USR1",       SIGUSR1 },      /* 10 (arm,i386,m68k,ppc), 30 (alpha,sparc*), 16 (mips) */
74         { "USR2",       SIGUSR2 },      /* 12 (arm,i386,m68k,ppc), 31 (alpha,sparc*), 17 (mips) */
75         { "CHLD",       SIGCHLD },      /* 17 (arm,i386,m68k,ppc), 20 (alpha,sparc*), 18 (mips) */
76         { "CONT",       SIGCONT },      /* 18 (arm,i386,m68k,ppc), 19 (alpha,sparc*), 25 (mips) */
77         { "STOP",       SIGSTOP },      /* 19 (arm,i386,m68k,ppc), 17 (alpha,sparc*), 23 (mips) */
78         { "TSTP",       SIGTSTP },      /* 20 (arm,i386,m68k,ppc), 18 (alpha,sparc*), 24 (mips) */
79         { "TTIN",       SIGTTIN },      /* 21 (arm,i386,m68k,ppc,alpha,sparc*), 26 (mips) */
80         { "TTOU",       SIGTTOU },      /* 22 (arm,i386,m68k,ppc,alpha,sparc*), 27 (mips) */
81         /* Miscellaneous other signals */
82 #ifdef SIGTRAP
83         { "TRAP",       SIGTRAP },      /* 5 */
84 #endif
85 #ifdef SIGIOT
86         { "IOT",        SIGIOT },       /* 6, same as SIGABRT */
87 #endif
88 #ifdef SIGEMT
89         { "EMT",        SIGEMT },       /* 7 (mips,alpha,sparc*) */
90 #endif
91 #ifdef SIGBUS
92         { "BUS",        SIGBUS },       /* 7 (arm,i386,m68k,ppc), 10 (mips,alpha,sparc*) */
93 #endif
94 #ifdef SIGSYS
95         { "SYS",        SIGSYS },       /* 12 (mips,alpha,sparc*) */
96 #endif
97 #ifdef SIGSTKFLT
98         { "STKFLT",     SIGSTKFLT },    /* 16 (arm,i386,m68k,ppc) */
99 #endif
100 #ifdef SIGURG
101         { "URG",        SIGURG },       /* 23 (arm,i386,m68k,ppc), 16 (alpha,sparc*), 21 (mips) */
102 #endif
103 #ifdef SIGIO
104         { "IO",         SIGIO },        /* 29 (arm,i386,m68k,ppc), 23 (alpha,sparc*), 22 (mips) */
105 #endif
106 #ifdef SIGPOLL
107         { "POLL",       SIGPOLL },      /* same as SIGIO */
108 #endif
109 #ifdef SIGCLD
110         { "CLD",        SIGCLD },       /* same as SIGCHLD (mips) */
111 #endif
112 #ifdef SIGXCPU
113         { "XCPU",       SIGXCPU },      /* 24 (arm,i386,m68k,ppc,alpha,sparc*), 30 (mips) */
114 #endif
115 #ifdef SIGXFSZ
116         { "XFSZ",       SIGXFSZ },      /* 25 (arm,i386,m68k,ppc,alpha,sparc*), 31 (mips) */
117 #endif
118 #ifdef SIGVTALRM
119         { "VTALRM",     SIGVTALRM },    /* 26 (arm,i386,m68k,ppc,alpha,sparc*), 28 (mips) */
120 #endif
121 #ifdef SIGPROF
122         { "PROF",       SIGPROF },      /* 27 (arm,i386,m68k,ppc,alpha,sparc*), 29 (mips) */
123 #endif
124 #ifdef SIGPWR
125         { "PWR",        SIGPWR },       /* 30 (arm,i386,m68k,ppc), 29 (alpha,sparc*), 19 (mips) */
126 #endif
127 #ifdef SIGINFO
128         { "INFO",       SIGINFO },      /* 29 (alpha) */
129 #endif
130 #ifdef SIGLOST
131         { "LOST",       SIGLOST },      /* 29 (arm,i386,m68k,ppc,sparc*) */
132 #endif
133 #ifdef SIGWINCH
134         { "WINCH",      SIGWINCH },     /* 28 (arm,i386,m68k,ppc,alpha,sparc*), 20 (mips) */
135 #endif
136 #ifdef SIGUNUSED
137         { "UNUSED",     SIGUNUSED },    /* 31 (arm,i386,m68k,ppc) */
138 #endif
139 };
140
141 int main (int argc, char *argv[]);
142 extern char *mybasename(char *);
143 int signame_to_signum (char *sig);
144 int arg_to_signum (char *arg, int mask);
145 void nosig (char *name);
146 void printsig (int sig);
147 void printsignals (FILE *fp);
148 int usage (int status);
149 int kill_verbose (char *procname, int pid, int sig);
150
151 extern int *get_pids (char *, int);
152
153 static char *progname;
154
155 int main (int argc, char *argv[])
156 {
157     int errors, numsig, pid;
158     char *ep, *arg, *p;
159     int do_pid, do_kill, check_all;
160     int *pids, *ip;
161
162     progname = argv[0];
163     if ((p = strrchr(progname, '/')) != NULL)
164             progname = p+1;
165
166     setlocale(LC_ALL, "");
167     bindtextdomain(PACKAGE, LOCALEDIR);
168     textdomain(PACKAGE);
169
170     numsig = SIGTERM;
171     do_pid = (! strcmp (progname, "pid"));      /* Yecch */
172     do_kill = 0;
173     check_all = 0;
174
175     /*  loop through the arguments.
176         actually, -a is the only option can be used with other options.
177         `kill' is basically a one-option-at-most program.  */
178     for (argc--, argv++; argc > 0; argc--, argv++) {
179         arg = *argv;
180         if (*arg != '-') {
181             break;
182         }
183         if (! strcmp (arg, "--")) {
184             argc--, argv++;
185             break;
186         }
187         if (! strcmp (arg, "-v") || ! strcmp (arg, "-V") ||
188             ! strcmp (arg, "--version")) {
189             printf(_("%s from %s\n"), progname, PACKAGE_STRING);
190             return 0;
191         }
192         if (! strcmp (arg, "-a")) {
193             check_all++;
194             continue;
195         }
196         if (! strcmp (arg, "-l")) {
197             if (argc < 2) {
198                 printsignals (stdout);
199                 return 0;
200             }
201             if (argc > 2) {
202                 return usage (1);
203             }
204             /* argc == 2, accept "kill -l $?" */
205             arg = argv[1];
206             if ((numsig = arg_to_signum (arg, 1)) < 0) {
207                 fprintf (stderr, _("%s: unknown signal %s\n"), progname, arg);
208                 return 1;
209             }
210             printsig (numsig);
211             return 0;
212         }
213         if (! strcmp (arg, "-p")) {
214             do_pid++;
215             if (do_kill)
216                 return usage (1);
217             continue;
218         }
219         if (! strcmp (arg, "-s")) {
220             if (argc < 2) {
221                 return usage (1);
222             }
223             do_kill++;
224             if (do_pid)
225                 return usage (1);
226             argc--, argv++;
227             arg = *argv;
228             if ((numsig = arg_to_signum (arg, 0)) < 0) {
229                 nosig (arg);
230                 return 1;
231             }
232             continue;
233         }
234         /*  `arg' begins with a dash but is not a known option.
235             so it's probably something like -HUP, or -1/-n
236             try to deal with it.
237             -n could be signal n, or pid -n (i.e. process group n).
238             In case of doubt POSIX tells us to assume a signal.
239             If a signal has been parsed, assume it's a pid, break */
240         if (do_kill)
241           break;
242         arg++;
243         if ((numsig = arg_to_signum (arg, 0)) < 0) {
244             return usage (1);
245         }
246         do_kill++;
247         if (do_pid)
248             return usage (1);
249         continue;
250     }
251
252     if (! *argv) {
253         return usage (1);
254     }
255     if (do_pid) {
256         numsig = -1;
257     }
258
259     /*  we're done with the options.
260         the rest of the arguments should be process ids and names.
261         kill them.  */
262     for (errors = 0; (arg = *argv) != NULL; argv++) {
263         pid = strtol (arg, &ep, 10);
264         if (! *ep)
265             errors += kill_verbose (arg, pid, numsig);
266         else {
267             pids = get_pids (arg, check_all);
268             if (! pids) {
269                 errors++;
270                 fprintf (stderr, _("%s: can't find process \"%s\"\n"),
271                          progname, arg);
272                 continue;
273             }
274             for (ip = pids; *ip >= 0; ip++)
275                 errors += kill_verbose (arg, *ip, numsig);
276             free (pids);
277         }
278     }
279     return (errors);
280 }
281
282
283 int signame_to_signum (char *sig)
284 {
285     int n;
286
287     if (! strncasecmp (sig, "sig", 3))
288         sig += 3;
289     for (n = 0; n < SIZE(sys_signame); n++) {
290         if (! strcasecmp (sys_signame[n].name, sig))
291             return sys_signame[n].val;
292     }
293     return (-1);
294 }
295
296 int arg_to_signum (char *arg, int maskbit)
297 {
298     int numsig;
299     char *ep;
300
301     if (isdigit (*arg)) {
302         numsig = strtol (arg, &ep, 10);
303         if (numsig >= NSIG && maskbit && (numsig & 128) != 0)
304             numsig -= 128;
305         if (*ep != 0 || numsig < 0 || numsig >= NSIG)
306             return (-1);
307         return (numsig);
308     }
309     return (signame_to_signum (arg));
310 }
311
312 void nosig (char *name)
313 {
314     fprintf (stderr, _("%s: unknown signal %s; valid signals:\n"), progname, name);
315     printsignals (stderr);
316 }
317
318 void printsig (int sig)
319 {
320     int n;
321
322     for (n = 0; n < SIZE(sys_signame); n++) {
323         if (sys_signame[n].val == sig) {
324             printf ("%s\n", sys_signame[n].name);
325             return;
326         }
327     }
328     printf("%d\n", sig);
329 }
330
331 void printsignals (FILE *fp)
332 {
333     int n, lth;
334     int lpos = 0;
335
336     for (n = 0; n < SIZE(sys_signame); n++) {
337         lth = 1+strlen(sys_signame[n].name);
338         if (lpos+lth > 72) {
339             fputc ('\n', fp);
340             lpos = 0;
341         } else if (lpos)
342             fputc (' ', fp);
343         lpos += lth;
344         fputs (sys_signame[n].name, fp);
345     }
346     fputc ('\n', fp);
347 }
348
349 int usage (int status)
350 {
351     FILE *fp;
352
353     fp = (status == 0 ? stdout : stderr);
354     fprintf (fp, _("usage: %s [ -s signal | -p ] [ -a ] pid ...\n"), progname);
355     fprintf (fp, _("       %s -l [ signal ]\n"), progname);
356     return status;
357 }
358
359 int kill_verbose (char *procname, int pid, int sig)
360 {
361     if (sig < 0) {
362         printf ("%d\n", pid);
363         return 0;
364     }
365     if (kill (pid, sig) < 0) {
366         fprintf (stderr, "%s ", progname);
367         perror (procname);
368         return 1;
369     }
370     return 0;
371 }