A number of additional fixed from Pavel Roskin, note some more bugs in the
[platform/upstream/busybox.git] / procps / kill.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * Mini kill/killall implementation for busybox
4  *
5  * Copyright (C) 1995, 1996 by Bruce Perens <bruce@pixar.com>.
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20  *
21  */
22
23
24 #include "internal.h"
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <errno.h>
28 #include <unistd.h>
29 #include <signal.h>
30 #include <ctype.h>
31 #include <sys/stat.h>
32 #include <unistd.h>
33
34 static const char *kill_usage =
35         "kill [-signal] process-id [process-id ...]\n"
36 #ifndef BB_FEATURE_TRIVIAL_HELP
37         "\nSend a signal (default is SIGTERM) to the specified process(es).\n\n"
38         "Options:\n" "\t-l\tList all signal names and numbers.\n\n"
39 #endif
40         ;
41
42 #ifdef BB_KILLALL
43 static const char *killall_usage =
44         "killall [-signal] process-name [process-name ...]\n"
45 #ifndef BB_FEATURE_TRIVIAL_HELP
46         "\nSend a signal (default is SIGTERM) to the specified process(es).\n\n"
47         "Options:\n" "\t-l\tList all signal names and numbers.\n\n"
48 #endif
49 #endif
50         ;
51
52 #define KILL    0
53 #define KILLALL 1
54
55 struct signal_name {
56         const char *name;
57         int number;
58 };
59
60 const struct signal_name signames[] = {
61         {"HUP", SIGHUP},
62         {"INT", SIGINT},
63         {"QUIT", SIGQUIT},
64         {"ILL", SIGILL},
65         {"TRAP", SIGTRAP},
66         {"ABRT", SIGABRT},
67 #ifndef __alpha__
68         {"IOT", SIGIOT},
69 #endif
70 #if defined(__sparc__) || defined(__alpha__)
71         {"EMT", SIGEMT},
72 #else
73         {"BUS", SIGBUS},
74 #endif
75         {"FPE", SIGFPE},
76         {"KILL", SIGKILL},
77 #if defined(__sparc__) || defined(__alpha__)
78         {"BUS", SIGBUS},
79 #else
80         {"USR1", SIGUSR1},
81 #endif
82         {"SEGV", SIGSEGV},
83 #if defined(__sparc__) || defined(__alpha__)
84         {"SYS", SIGSYS},
85 #else
86         {"USR2", SIGUSR2},
87 #endif
88         {"PIPE", SIGPIPE},
89         {"ALRM", SIGALRM},
90         {"TERM", SIGTERM},
91 #if defined(__sparc__) || defined(__alpha__)
92         {"URG", SIGURG},
93         {"STOP", SIGSTOP},
94         {"TSTP", SIGTSTP},
95         {"CONT", SIGCONT},
96         {"CHLD", SIGCHLD},
97         {"TTIN", SIGTTIN},
98         {"TTOU", SIGTTOU},
99         {"IO", SIGIO},
100 # ifndef __alpha__
101         {"POLL", SIGIO},
102 # endif
103         {"XCPU", SIGXCPU},
104         {"XFSZ", SIGXFSZ},
105         {"VTALRM", SIGVTALRM},
106         {"PROF", SIGPROF},
107         {"WINCH", SIGWINCH},
108 # ifdef __alpha__
109         {"INFO", SIGINFO},
110 # else
111         {"LOST", SIGLOST},
112 # endif
113         {"USR1", SIGUSR1},
114         {"USR2", SIGUSR2},
115 #else
116         {"STKFLT", SIGSTKFLT},
117         {"CHLD", SIGCHLD},
118         {"CONT", SIGCONT},
119         {"STOP", SIGSTOP},
120         {"TSTP", SIGTSTP},
121         {"TTIN", SIGTTIN},
122         {"TTOU", SIGTTOU},
123         {"URG", SIGURG},
124         {"XCPU", SIGXCPU},
125         {"XFSZ", SIGXFSZ},
126         {"VTALRM", SIGVTALRM},
127         {"PROF", SIGPROF},
128         {"WINCH", SIGWINCH},
129         {"IO", SIGIO},
130         {"POLL", SIGPOLL},
131         {"PWR", SIGPWR},
132         {"UNUSED", SIGUNUSED},
133 #endif
134         {0, 0}
135 };
136
137 extern int kill_main(int argc, char **argv)
138 {
139         int whichApp, sig = SIGTERM;
140         const char *appUsage;
141
142 #ifdef BB_KILLALL
143         /* Figure out what we are trying to do here */
144         whichApp = (strcmp(*argv, "killall") == 0)? 
145                 KILLALL : KILL; 
146         appUsage = (whichApp == KILLALL)?  killall_usage : kill_usage;
147 #else
148         whichApp = KILL;
149         appUsage = kill_usage;
150 #endif
151
152         argc--;
153         argv++;
154         /* Parse any options */
155         if (argc < 1)
156                 usage(appUsage);
157
158         while (argc > 0 && **argv == '-') {
159                 while (*++(*argv)) {
160                         switch (**argv) {
161                         case 'l':
162                                 {
163                                         int col = 0;
164                                         const struct signal_name *s = signames;
165
166                                         while (s->name != 0) {
167                                                 col +=
168                                                         fprintf(stderr, "%2d) %-8s", s->number,
169                                                                         (s++)->name);
170                                                 if (col > 60) {
171                                                         fprintf(stderr, "\n");
172                                                         col = 0;
173                                                 }
174                                         }
175                                         fprintf(stderr, "\n\n");
176                                         exit(TRUE);
177                                 }
178                                 break;
179                         case '-':
180                                 usage(appUsage);
181                         default:
182                                 {
183                                         if (isdigit(**argv)) {
184                                                 sig = atoi(*argv);
185                                                 if (sig < 0 || sig >= NSIG)
186                                                         goto end;
187                                                 else {
188                                                         argc--;
189                                                         argv++;
190                                                         goto do_it_now;
191                                                 }
192                                         } else {
193                                                 const struct signal_name *s = signames;
194
195                                                 while (s->name != 0) {
196                                                         if (strcasecmp(s->name, *argv) == 0) {
197                                                                 sig = s->number;
198                                                                 argc--;
199                                                                 argv++;
200                                                                 goto do_it_now;
201                                                         }
202                                                         s++;
203                                                 }
204                                                 if (s->name == 0)
205                                                         goto end;
206                                         }
207                                 }
208                         }
209                         argc--;
210                         argv++;
211                 }
212         }
213
214   do_it_now:
215
216         if (whichApp == KILL) {
217                 /* Looks like they want to do a kill. Do that */
218                 while (--argc >= 0) {
219                         int pid;
220
221                         if (!isdigit(**argv))
222                                 fatalError( "Bad PID: %s\n", strerror(errno));
223                         pid = strtol(*argv, NULL, 0);
224                         if (kill(pid, sig) != 0) 
225                                 fatalError( "Could not kill pid '%d': %s\n", pid, strerror(errno));
226                         argv++;
227                 }
228         } 
229 #ifdef BB_KILLALL
230         else {
231                 pid_t myPid=getpid();
232                 /* Looks like they want to do a killall.  Do that */
233                 while (--argc >= 0) {
234                         pid_t* pidList;
235
236                         pidList = findPidByName( *argv);
237                         if (!pidList)
238                                 errorMsg( "%s: no process killed\n", *argv);
239
240                         for(; pidList && *pidList!=0; pidList++) {
241                                 if (*pidList==myPid)
242                                         continue;
243                                 if (kill(*pidList, sig) != 0) 
244                                         fatalError( "Could not kill pid '%d': %s\n", *pidList, strerror(errno));
245                         }
246                         /* Note that we don't bother to free the memory
247                          * allocated in findPidByName().  It will be freed
248                          * upon exit, so we can save a byte or two */
249                         argv++;
250                 }
251         }
252 #endif
253
254         exit(TRUE);
255
256
257   end:
258         fatalError( "bad signal name: %s\n", *argv);
259 }