implemented numeric sort (sort -g)
[oweals/busybox.git] / kill.c
1 /*
2  * Mini kill implementation for busybox
3  *
4  * Copyright (C) 1995, 1996 by Bruce Perens <bruce@pixar.com>.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  *
20  */
21
22
23 #include "internal.h"
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include <signal.h>
28 #include <ctype.h>
29 #include <sys/stat.h>
30 #include <unistd.h>
31
32 static const char* kill_usage = "kill [-signal] process-id [process-id ...]\n\n"
33 "Send a signal (default is SIGTERM) to the specified process(es).\n\n"
34 "Options:\n"
35 "\t-l\tList all signal names and numbers.\n\n";
36
37
38 struct signal_name {
39     const char *name;
40     int number;
41 };
42
43 const struct signal_name signames[] = {
44     {"HUP", SIGHUP},
45     {"INT", SIGINT},
46     {"QUIT", SIGQUIT},
47     {"ILL", SIGILL},
48     {"TRAP", SIGTRAP},
49     {"ABRT", SIGABRT},
50 #ifndef __alpha__
51     {"IOT", SIGIOT},
52 #endif
53 #if defined(__sparc__) || defined(__alpha__)
54     {"EMT", SIGEMT},
55 #else
56     {"BUS", SIGBUS},
57 #endif
58     {"FPE", SIGFPE},
59     {"KILL", SIGKILL},
60 #if defined(__sparc__) || defined(__alpha__)
61     {"BUS", SIGBUS},
62 #else
63     {"USR1", SIGUSR1},
64 #endif
65     {"SEGV", SIGSEGV},
66 #if defined(__sparc__) || defined(__alpha__)
67     {"SYS", SIGSYS},
68 #else
69     {"USR2", SIGUSR2},
70 #endif
71     {"PIPE", SIGPIPE},
72     {"ALRM", SIGALRM},
73     {"TERM", SIGTERM},
74 #if defined(__sparc__) || defined(__alpha__)
75     {"URG", SIGURG},
76     {"STOP", SIGSTOP},
77     {"TSTP", SIGTSTP},
78     {"CONT", SIGCONT},
79     {"CHLD", SIGCHLD},
80     {"TTIN", SIGTTIN},
81     {"TTOU", SIGTTOU},
82     {"IO", SIGIO},
83 # ifndef __alpha__
84     {"POLL", SIGIO},
85 # endif
86     {"XCPU", SIGXCPU},
87     {"XFSZ", SIGXFSZ},
88     {"VTALRM", SIGVTALRM},
89     {"PROF", SIGPROF},
90     {"WINCH", SIGWINCH},
91 # ifdef __alpha__
92     {"INFO", SIGINFO},
93 # else
94     {"LOST", SIGLOST},
95 # endif
96     {"USR1", SIGUSR1},
97     {"USR2", SIGUSR2},
98 #else
99     {"STKFLT", SIGSTKFLT},
100     {"CHLD", SIGCHLD},
101     {"CONT", SIGCONT},
102     {"STOP", SIGSTOP},
103     {"TSTP", SIGTSTP},
104     {"TTIN", SIGTTIN},
105     {"TTOU", SIGTTOU},
106     {"URG", SIGURG},
107     {"XCPU", SIGXCPU},
108     {"XFSZ", SIGXFSZ},
109     {"VTALRM", SIGVTALRM},
110     {"PROF", SIGPROF},
111     {"WINCH", SIGWINCH},
112     {"IO", SIGIO},
113     {"POLL", SIGPOLL},
114     {"PWR", SIGPWR},
115     {"UNUSED", SIGUNUSED},
116 #endif
117     {0, 0}
118 };
119
120 extern int kill_main (int argc, char **argv)
121 {
122     int sig = SIGTERM;
123     
124     argc--;
125     argv++;
126     /* Parse any options */
127     if (argc < 1) 
128         usage(kill_usage);
129
130     while (argc > 0 && **argv == '-') {
131         while (*++(*argv)) {
132             switch (**argv) {
133             case 'l': 
134                 {
135                     int col=0;
136                     const struct signal_name *s = signames;
137
138                     while (s->name != 0) {
139                         col+=fprintf(stderr, "%2d) %-8s", s->number, (s++)->name);
140                         if (col>60) {
141                             fprintf(stderr, "\n");
142                             col=0;
143                         }
144                     }
145                     fprintf(stderr, "\n\n");
146                     exit( TRUE);
147                 }
148                 break;
149             case '-':
150                 usage(kill_usage);
151             default:
152                 {
153                     if (isdigit( **argv)) {
154                         sig = atoi (*argv);
155                         if (sig < 0 || sig >= NSIG)
156                             goto end;
157                         else {
158                             argc--;
159                             argv++;
160                             goto do_it_now;
161                         }
162                     }
163                     else {
164                         const struct signal_name *s = signames;
165                         while (s->name != 0) {
166                             if (strcasecmp (s->name, *argv) == 0) {
167                                 sig = s->number;
168                                 argc--;
169                                 argv++;
170                                 goto do_it_now;
171                             }
172                             s++;
173                         }
174                         if (s->name == 0)
175                             goto end;
176                     }
177                 }
178             }
179         argc--;
180         argv++;
181         }
182     }
183
184 do_it_now:
185
186     while (argc >= 1) {
187         int pid;
188         struct stat statbuf;
189         char pidpath[20]="/proc/";
190         
191         if (! isdigit( **argv)) {
192             fprintf(stderr, "bad PID: %s\n", *argv);
193             exit( FALSE);
194         }
195         pid = atoi (*argv);
196         snprintf(pidpath, 20, "/proc/%s/stat", *argv);
197         if (stat( pidpath, &statbuf)!=0) {
198             fprintf(stderr, "kill: (%d) - No such pid\n", pid);
199             exit( FALSE);
200         }
201         if (kill (pid, sig) != 0) {
202             perror (*argv);
203             exit ( FALSE);
204         }
205         argv++;
206     }
207     exit ( TRUE);
208
209
210 end:
211     fprintf(stderr, "bad signal name: %s\n", *argv);
212     exit (TRUE);
213 }
214
215