source: MondoRescue/branches/3.3/mindi-busybox/procps/kill.c@ 3865

Last change on this file since 3865 was 3621, checked in by Bruno Cornec, 10 years ago

New 3?3 banch for incorporation of latest busybox 1.25. Changing minor version to handle potential incompatibilities.

File size: 7.3 KB
RevLine 
[821]1/* vi: set sw=4 ts=4: */
2/*
[1765]3 * Mini kill/killall[5] implementation for busybox
[821]4 *
5 * Copyright (C) 1995, 1996 by Bruce Perens <bruce@pixar.com>.
6 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
7 *
[2725]8 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
[821]9 */
10
[3232]11//usage:#define kill_trivial_usage
12//usage: "[-l] [-SIG] PID..."
13//usage:#define kill_full_usage "\n\n"
14//usage: "Send a signal (default: TERM) to given PIDs\n"
15//usage: "\n -l List all signal names and numbers"
16/* //usage: "\n -s SIG Yet another way of specifying SIG" */
17//usage:
18//usage:#define kill_example_usage
19//usage: "$ ps | grep apache\n"
20//usage: "252 root root S [apache]\n"
21//usage: "263 www-data www-data S [apache]\n"
22//usage: "264 www-data www-data S [apache]\n"
23//usage: "265 www-data www-data S [apache]\n"
24//usage: "266 www-data www-data S [apache]\n"
25//usage: "267 www-data www-data S [apache]\n"
26//usage: "$ kill 252\n"
27//usage:
28//usage:#define killall_trivial_usage
29//usage: "[-l] [-q] [-SIG] PROCESS_NAME..."
30//usage:#define killall_full_usage "\n\n"
31//usage: "Send a signal (default: TERM) to given processes\n"
32//usage: "\n -l List all signal names and numbers"
33/* //usage: "\n -s SIG Yet another way of specifying SIG" */
34//usage: "\n -q Don't complain if no processes were killed"
35//usage:
36//usage:#define killall_example_usage
37//usage: "$ killall apache\n"
38//usage:
39//usage:#define killall5_trivial_usage
40//usage: "[-l] [-SIG] [-o PID]..."
41//usage:#define killall5_full_usage "\n\n"
42//usage: "Send a signal (default: TERM) to all processes outside current session\n"
43//usage: "\n -l List all signal names and numbers"
44//usage: "\n -o PID Don't signal this PID"
45/* //usage: "\n -s SIG Yet another way of specifying SIG" */
46
[1765]47#include "libbb.h"
[821]48
[1765]49/* Note: kill_main is directly called from shell in order to implement
50 * kill built-in. Shell substitutes job ids with process groups first.
51 *
52 * This brings some complications:
53 *
54 * + we can't use xfunc here
55 * + we can't use applet_name
56 * + we can't use bb_show_usage
57 * (Above doesn't apply for killall[5] cases)
58 *
59 * kill %n gets translated into kill ' -<process group>' by shell (note space!)
60 * This is needed to avoid collision with kill -9 ... syntax
61 */
[821]62
[3621]63int kill_main(int argc UNUSED_PARAM, char **argv)
[821]64{
[1765]65 char *arg;
66 pid_t pid;
67 int signo = SIGTERM, errors = 0, quiet = 0;
68#if !ENABLE_KILLALL && !ENABLE_KILLALL5
69#define killall 0
70#define killall5 0
[821]71#else
[1765]72/* How to determine who we are? find 3rd char from the end:
73 * kill, killall, killall5
74 * ^i ^a ^l - it's unique
75 * (checking from the start is complicated by /bin/kill... case) */
76 const char char3 = argv[0][strlen(argv[0]) - 3];
77#define killall (ENABLE_KILLALL && char3 == 'a')
78#define killall5 (ENABLE_KILLALL5 && char3 == 'l')
[821]79#endif
80
81 /* Parse any options */
[1765]82 arg = *++argv;
[821]83
[3621]84 if (!arg || arg[0] != '-') {
[821]85 goto do_it_now;
86 }
87
[1765]88 /* The -l option, which prints out signal names.
89 * Intended usage in shell:
90 * echo "Died of SIG`kill -l $?`"
91 * We try to mimic what kill from coreutils-6.8 does */
92 if (arg[1] == 'l' && arg[2] == '\0') {
[3621]93 arg = *++argv;
94 if (!arg) {
[821]95 /* Print the whole signal list */
[2725]96 print_signames();
97 return 0;
98 }
99 /* -l <sig list> */
[3621]100 do {
[2725]101 if (isdigit(arg[0])) {
102 signo = bb_strtou(arg, NULL, 10);
103 if (errno) {
104 bb_error_msg("unknown signal '%s'", arg);
105 return EXIT_FAILURE;
[821]106 }
[2725]107 /* Exitcodes >= 0x80 are to be treated
108 * as "killed by signal (exitcode & 0x7f)" */
109 puts(get_signame(signo & 0x7f));
110 /* TODO: 'bad' signal# - coreutils says:
111 * kill: 127: invalid signal
112 * we just print "127" instead */
113 } else {
114 signo = get_signum(arg);
115 if (signo < 0) {
116 bb_error_msg("unknown signal '%s'", arg);
117 return EXIT_FAILURE;
118 }
119 printf("%d\n", signo);
[821]120 }
[3621]121 arg = *++argv;
122 } while (arg);
[821]123 return EXIT_SUCCESS;
124 }
125
126 /* The -q quiet option */
[1765]127 if (killall && arg[1] == 'q' && arg[2] == '\0') {
128 quiet = 1;
129 arg = *++argv;
[3621]130 if (!arg)
[2725]131 bb_show_usage();
132 if (arg[0] != '-')
133 goto do_it_now;
[821]134 }
135
[2725]136 arg++; /* skip '-' */
137
138 /* -o PID? (if present, it always is at the end of command line) */
139 if (killall5 && arg[0] == 'o')
140 goto do_it_now;
141
[3621]142 if (argv[1] && arg[0] == 's' && arg[1] == '\0') { /* -s SIG? */
[2725]143 arg = *++argv;
144 } /* else it must be -SIG */
145 signo = get_signum(arg);
[1765]146 if (signo < 0) { /* || signo > MAX_SIGNUM ? */
[2725]147 bb_error_msg("bad signal name '%s'", arg);
[1765]148 return EXIT_FAILURE;
149 }
150 arg = *++argv;
[821]151
[2725]152 do_it_now:
153 pid = getpid();
[821]154
[1765]155 if (killall5) {
156 pid_t sid;
157 procps_status_t* p = NULL;
[3621]158 /* compat: exitcode 2 is "no one was signaled" */
159 int ret = 2;
[821]160
[2725]161 /* Find out our session id */
162 sid = getsid(pid);
163 /* Stop all processes */
[3232]164 if (signo != SIGSTOP && signo != SIGCONT)
165 kill(-1, SIGSTOP);
[2725]166 /* Signal all processes except those in our session */
[3232]167 while ((p = procps_scan(p, PSSCAN_PID|PSSCAN_SID)) != NULL) {
[3621]168 char **args;
[2725]169
170 if (p->sid == (unsigned)sid
[3621]171 || p->sid == 0 /* compat: kernel thread, don't signal it */
[2725]172 || p->pid == (unsigned)pid
[3232]173 || p->pid == 1
174 ) {
[2725]175 continue;
[3232]176 }
[2725]177
178 /* All remaining args must be -o PID options.
179 * Check p->pid against them. */
[3621]180 args = argv;
181 while (*args) {
[2725]182 pid_t omit;
183
[3621]184 arg = *args++;
[2725]185 if (arg[0] != '-' || arg[1] != 'o') {
186 bb_error_msg("bad option '%s'", arg);
187 ret = 1;
188 goto resume;
189 }
190 arg += 2;
[3621]191 if (!arg[0] && *args)
192 arg = *args++;
[2725]193 omit = bb_strtoi(arg, NULL, 10);
194 if (errno) {
195 bb_error_msg("invalid number '%s'", arg);
196 ret = 1;
197 goto resume;
198 }
199 if (p->pid == omit)
200 goto dont_kill;
201 }
202 kill(p->pid, signo);
[3621]203 ret = 0;
[2725]204 dont_kill: ;
[821]205 }
[2725]206 resume:
[1765]207 /* And let them continue */
[3232]208 if (signo != SIGSTOP && signo != SIGCONT)
209 kill(-1, SIGCONT);
[2725]210 return ret;
[1765]211 }
[821]212
[1765]213 /* Pid or name is required for kill/killall */
[3621]214 if (!arg) {
[2725]215 bb_error_msg("you need to specify whom to kill");
[1765]216 return EXIT_FAILURE;
[821]217 }
[1765]218
219 if (killall) {
[821]220 /* Looks like they want to do a killall. Do that */
[3621]221 do {
[1765]222 pid_t* pidList;
[821]223
[1765]224 pidList = find_pid_by_name(arg);
225 if (*pidList == 0) {
[821]226 errors++;
[1765]227 if (!quiet)
228 bb_error_msg("%s: no process killed", arg);
[821]229 } else {
[1765]230 pid_t *pl;
[821]231
[1765]232 for (pl = pidList; *pl; pl++) {
233 if (*pl == pid)
[821]234 continue;
[1765]235 if (kill(*pl, signo) == 0)
236 continue;
237 errors++;
238 if (!quiet)
[2725]239 bb_perror_msg("can't kill pid %d", (int)*pl);
[821]240 }
241 }
242 free(pidList);
[1765]243 arg = *++argv;
[3621]244 } while (arg);
[1765]245 return errors;
[821]246 }
[1765]247
248 /* Looks like they want to do a kill. Do that */
249 while (arg) {
[3232]250#if ENABLE_ASH || ENABLE_HUSH
251 /*
252 * We need to support shell's "hack formats" of
253 * " -PRGP_ID" (yes, with a leading space)
254 * and " PID1 PID2 PID3" (with degenerate case "")
255 */
256 while (*arg != '\0') {
257 char *end;
258 if (*arg == ' ')
259 arg++;
260 pid = bb_strtoi(arg, &end, 10);
261 if (errno && (errno != EINVAL || *end != ' ')) {
262 bb_error_msg("invalid number '%s'", arg);
263 errors++;
264 break;
265 }
266 if (kill(pid, signo) != 0) {
267 bb_perror_msg("can't kill pid %d", (int)pid);
268 errors++;
269 }
270 arg = end; /* can only point to ' ' or '\0' now */
271 }
272#else
[1765]273 pid = bb_strtoi(arg, NULL, 10);
274 if (errno) {
[2725]275 bb_error_msg("invalid number '%s'", arg);
[1765]276 errors++;
277 } else if (kill(pid, signo) != 0) {
[2725]278 bb_perror_msg("can't kill pid %d", (int)pid);
[1765]279 errors++;
280 }
[3232]281#endif
[1765]282 arg = *++argv;
283 }
[821]284 return errors;
285}
Note: See TracBrowser for help on using the repository browser.