8f48ba0269967e23de90e37d1c3dcf688befc056
[oweals/busybox.git] / 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 <unistd.h>
32
33 #define KILL    0
34 #define KILLALL 1
35
36 struct signal_name {
37         const char *name;
38         int number;
39 };
40
41 const struct signal_name signames[] = {
42         /* POSIX signals */
43         { "HUP",        SIGHUP },       /* 1 */
44         { "INT",        SIGINT },       /* 2 */
45         { "QUIT",       SIGQUIT },      /* 3 */
46         { "ILL",        SIGILL },       /* 4 */
47         { "ABRT",       SIGABRT },      /* 6 */
48         { "FPE",        SIGFPE },       /* 8 */
49         { "KILL",       SIGKILL },      /* 9 */
50         { "SEGV",       SIGSEGV },      /* 11 */
51         { "PIPE",       SIGPIPE },      /* 13 */
52         { "ALRM",       SIGALRM },      /* 14 */
53         { "TERM",       SIGTERM },      /* 15 */
54         { "USR1",       SIGUSR1 },      /* 10 (arm,i386,m68k,ppc), 30 (alpha,sparc*), 16 (mips) */
55         { "USR2",       SIGUSR2 },      /* 12 (arm,i386,m68k,ppc), 31 (alpha,sparc*), 17 (mips) */
56         { "CHLD",       SIGCHLD },      /* 17 (arm,i386,m68k,ppc), 20 (alpha,sparc*), 18 (mips) */
57         { "CONT",       SIGCONT },      /* 18 (arm,i386,m68k,ppc), 19 (alpha,sparc*), 25 (mips) */
58         { "STOP",       SIGSTOP },      /* 19 (arm,i386,m68k,ppc), 17 (alpha,sparc*), 23 (mips) */
59         { "TSTP",       SIGTSTP },      /* 20 (arm,i386,m68k,ppc), 18 (alpha,sparc*), 24 (mips) */
60         { "TTIN",       SIGTTIN },      /* 21 (arm,i386,m68k,ppc,alpha,sparc*), 26 (mips) */
61         { "TTOU",       SIGTTOU },      /* 22 (arm,i386,m68k,ppc,alpha,sparc*), 27 (mips) */
62         /* Miscellaneous other signals */
63 #ifdef SIGTRAP
64         { "TRAP",       SIGTRAP },      /* 5 */
65 #endif
66 #ifdef SIGIOT
67         { "IOT",        SIGIOT },       /* 6, same as SIGABRT */
68 #endif
69 #ifdef SIGEMT
70         { "EMT",        SIGEMT },       /* 7 (mips,alpha,sparc*) */
71 #endif
72 #ifdef SIGBUS
73         { "BUS",        SIGBUS },       /* 7 (arm,i386,m68k,ppc), 10 (mips,alpha,sparc*) */
74 #endif
75 #ifdef SIGSYS
76         { "SYS",        SIGSYS },       /* 12 (mips,alpha,sparc*) */
77 #endif
78 #ifdef SIGSTKFLT
79         { "STKFLT",     SIGSTKFLT },    /* 16 (arm,i386,m68k,ppc) */
80 #endif
81 #ifdef SIGURG
82         { "URG",        SIGURG },       /* 23 (arm,i386,m68k,ppc), 16 (alpha,sparc*), 21 (mips) */
83 #endif
84 #ifdef SIGIO
85         { "IO",         SIGIO },        /* 29 (arm,i386,m68k,ppc), 23 (alpha,sparc*), 22 (mips) */
86 #endif
87 #ifdef SIGPOLL
88         { "POLL",       SIGPOLL },      /* same as SIGIO */
89 #endif
90 #ifdef SIGCLD
91         { "CLD",        SIGCLD },       /* same as SIGCHLD (mips) */
92 #endif
93 #ifdef SIGXCPU
94         { "XCPU",       SIGXCPU },      /* 24 (arm,i386,m68k,ppc,alpha,sparc*), 30 (mips) */
95 #endif
96 #ifdef SIGXFSZ
97         { "XFSZ",       SIGXFSZ },      /* 25 (arm,i386,m68k,ppc,alpha,sparc*), 31 (mips) */
98 #endif
99 #ifdef SIGVTALRM
100         { "VTALRM",     SIGVTALRM },    /* 26 (arm,i386,m68k,ppc,alpha,sparc*), 28 (mips) */
101 #endif
102 #ifdef SIGPROF
103         { "PROF",       SIGPROF },      /* 27 (arm,i386,m68k,ppc,alpha,sparc*), 29 (mips) */
104 #endif
105 #ifdef SIGPWR
106         { "PWR",        SIGPWR },       /* 30 (arm,i386,m68k,ppc), 29 (alpha,sparc*), 19 (mips) */
107 #endif
108 #ifdef SIGINFO
109         { "INFO",       SIGINFO },      /* 29 (alpha) */
110 #endif
111 #ifdef SIGLOST
112         { "LOST",       SIGLOST },      /* 29 (arm,i386,m68k,ppc,sparc*) */
113 #endif
114 #ifdef SIGWINCH
115         { "WINCH",      SIGWINCH },     /* 28 (arm,i386,m68k,ppc,alpha,sparc*), 20 (mips) */
116 #endif
117 #ifdef SIGUNUSED
118         { "UNUSED",     SIGUNUSED },    /* 31 (arm,i386,m68k,ppc) */
119 #endif
120         {0, 0}
121 };
122
123 extern int kill_main(int argc, char **argv)
124 {
125         int whichApp, sig = SIGTERM;
126         const char *appUsage;
127
128 #ifdef BB_KILLALL
129         /* Figure out what we are trying to do here */
130         whichApp = (strcmp(applet_name, "killall") == 0)? KILLALL : KILL; 
131         appUsage = (whichApp == KILLALL)?  killall_usage : kill_usage;
132 #else
133         whichApp = KILL;
134         appUsage = kill_usage;
135 #endif
136
137         argc--;
138         argv++;
139         /* Parse any options */
140         if (argc < 1)
141                 usage(appUsage);
142
143         while (argc > 0 && **argv == '-') {
144                 while (*++(*argv)) {
145                         switch (**argv) {
146                         case 'l':
147                                 {
148                                         int col = 0;
149                                         const struct signal_name *s = signames;
150
151                                         while (s->name != 0) {
152                                                 col +=
153                                                         fprintf(stderr, "%2d) %-8s", s->number,
154                                                                         (s++)->name);
155                                                 if (col > 60) {
156                                                         fprintf(stderr, "\n");
157                                                         col = 0;
158                                                 }
159                                         }
160                                         fprintf(stderr, "\n\n");
161                                         exit(TRUE);
162                                 }
163                                 break;
164                         case '-':
165                                 usage(appUsage);
166                         default:
167                                 {
168                                         if (isdigit(**argv)) {
169                                                 sig = atoi(*argv);
170                                                 if (sig < 0 || sig >= NSIG)
171                                                         goto end;
172                                                 else {
173                                                         argc--;
174                                                         argv++;
175                                                         goto do_it_now;
176                                                 }
177                                         } else {
178                                                 const struct signal_name *s = signames;
179
180                                                 while (s->name != 0) {
181                                                         if (strcasecmp(s->name, *argv) == 0) {
182                                                                 sig = s->number;
183                                                                 argc--;
184                                                                 argv++;
185                                                                 goto do_it_now;
186                                                         }
187                                                         s++;
188                                                 }
189                                                 if (s->name == 0)
190                                                         goto end;
191                                         }
192                                 }
193                         }
194                         argc--;
195                         argv++;
196                 }
197         }
198
199   do_it_now:
200
201         if (whichApp == KILL) {
202                 /* Looks like they want to do a kill. Do that */
203                 while (--argc >= 0) {
204                         int pid;
205
206                         if (!isdigit(**argv))
207                                 fatalError( "Bad PID: %s\n", strerror(errno));
208                         pid = strtol(*argv, NULL, 0);
209                         if (kill(pid, sig) != 0) 
210                                 fatalError( "Could not kill pid '%d': %s\n", pid, strerror(errno));
211                         argv++;
212                 }
213         } 
214 #ifdef BB_KILLALL
215         else {
216                 int all_found = TRUE;
217                 pid_t myPid=getpid();
218                 /* Looks like they want to do a killall.  Do that */
219                 while (--argc >= 0) {
220                         pid_t* pidList;
221
222                         pidList = findPidByName( *argv);
223                         if (!pidList) {
224                                 all_found = FALSE;
225                                 errorMsg( "%s: no process killed\n", *argv);
226                         }
227
228                         for(; pidList && *pidList!=0; pidList++) {
229                                 if (*pidList==myPid)
230                                         continue;
231                                 if (kill(*pidList, sig) != 0) 
232                                         fatalError( "Could not kill pid '%d': %s\n", *pidList, strerror(errno));
233                         }
234                         /* Note that we don't bother to free the memory
235                          * allocated in findPidByName().  It will be freed
236                          * upon exit, so we can save a byte or two */
237                         argv++;
238                 }
239                 exit (all_found);
240         }
241 #endif
242
243         exit(TRUE);
244
245
246   end:
247         fatalError( "bad signal name: %s\n", *argv);
248 }