diff options
Diffstat (limited to 'procps')
-rw-r--r-- | procps/kill.c | 57 |
1 files changed, 48 insertions, 9 deletions
diff --git a/procps/kill.c b/procps/kill.c index 140550018..1f8206986 100644 --- a/procps/kill.c +++ b/procps/kill.c @@ -92,11 +92,18 @@ int kill_main(int argc, char **argv) quiet = 1; arg = *++argv; argc--; - if (argc < 1) bb_show_usage(); - if (arg[0] != '-') goto do_it_now; + if (argc < 1) + bb_show_usage(); + if (arg[0] != '-') + goto do_it_now; } arg++; /* skip '-' */ + + /* -o PID? (if present, it always is at the end of command line) */ + if (killall5 && arg[0] == 'o') + goto do_it_now; + if (argc > 1 && arg[0] == 's' && arg[1] == '\0') { /* -s SIG? */ argc--; arg = *++argv; @@ -109,25 +116,57 @@ int kill_main(int argc, char **argv) arg = *++argv; argc--; -do_it_now: + do_it_now: pid = getpid(); if (killall5) { pid_t sid; procps_status_t* p = NULL; + int ret = 0; - /* Find out our own session id */ + /* Find out our session id */ sid = getsid(pid); - /* Now stop all processes */ + /* Stop all processes */ kill(-1, SIGSTOP); - /* Now kill all processes except our session */ + /* Signal all processes except those in our session */ while ((p = procps_scan(p, PSSCAN_PID|PSSCAN_SID))) { - if (p->sid != (unsigned)sid && p->pid != (unsigned)pid && p->pid != 1) - kill(p->pid, signo); + int i; + + if (p->sid == (unsigned)sid + || p->pid == (unsigned)pid + || p->pid == 1) + continue; + + /* All remaining args must be -o PID options. + * Check p->pid against them. */ + for (i = 0; i < argc; i++) { + pid_t omit; + + arg = argv[i]; + if (arg[0] != '-' || arg[1] != 'o') { + bb_error_msg("bad option '%s'", arg); + ret = 1; + goto resume; + } + arg += 2; + if (!arg[0] && argv[++i]) + arg = argv[i]; + omit = bb_strtoi(arg, NULL, 10); + if (errno) { + bb_error_msg("bad pid '%s'", arg); + ret = 1; + goto resume; + } + if (p->pid == omit) + goto dont_kill; + } + kill(p->pid, signo); + dont_kill: ; } + resume: /* And let them continue */ kill(-1, SIGCONT); - return 0; + return ret; } /* Pid or name is required for kill/killall */ |