diff options
-rw-r--r-- | include/applets.h | 1 | ||||
-rw-r--r-- | include/usage.h | 15 | ||||
-rw-r--r-- | procps/Config.in | 5 | ||||
-rw-r--r-- | procps/kill.c | 76 |
4 files changed, 65 insertions, 32 deletions
diff --git a/include/applets.h b/include/applets.h index c75866dde..e12f6027c 100644 --- a/include/applets.h +++ b/include/applets.h @@ -159,6 +159,7 @@ USE_IPROUTE(APPLET(iproute, _BB_DIR_BIN, _BB_SUID_NEVER)) USE_IPTUNNEL(APPLET(iptunnel, _BB_DIR_BIN, _BB_SUID_NEVER)) USE_KILL(APPLET(kill, _BB_DIR_BIN, _BB_SUID_NEVER)) USE_KILLALL(APPLET_ODDNAME(killall, kill, _BB_DIR_USR_BIN, _BB_SUID_NEVER, killall)) +USE_KILLALL5(APPLET_ODDNAME(killall5, kill, _BB_DIR_USR_BIN, _BB_SUID_NEVER, killall5)) USE_KLOGD(APPLET(klogd, _BB_DIR_SBIN, _BB_SUID_NEVER)) USE_LASH(APPLET(lash, _BB_DIR_BIN, _BB_SUID_NEVER)) USE_LAST(APPLET(last, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) diff --git a/include/usage.h b/include/usage.h index da176d156..8b8d64e84 100644 --- a/include/usage.h +++ b/include/usage.h @@ -1485,9 +1485,9 @@ USE_FEATURE_DATE_ISOFMT( \ "\t\t\t[ ttl TTL ] [ tos TOS ] [ [no]pmtudisc ] [ dev PHYS_DEV ]" #define kill_trivial_usage \ - "[-signal] process-id [process-id ...]" + "[-l] [-signal] process-id [process-id ...]" #define kill_full_usage \ - "Send a signal (default is SIGTERM) to the specified process(es).\n\n" \ + "Send a signal (default is TERM) to the specified process(es).\n\n" \ "Options:\n" \ "\t-l\tList all signal names and numbers" #define kill_example_usage \ @@ -1501,15 +1501,22 @@ USE_FEATURE_DATE_ISOFMT( \ "$ kill 252\n" #define killall_trivial_usage \ - "[-q] [-signal] process-name [process-name ...]" + "[-l] [-q] [-signal] process-name [process-name ...]" #define killall_full_usage \ - "Send a signal (default is SIGTERM) to the specified process(es).\n\n" \ + "Send a signal (default is TERM) to the specified process(es).\n\n" \ "Options:\n" \ "\t-l\tList all signal names and numbers\n" \ "\t-q\tDo not complain if no processes were killed" #define killall_example_usage \ "$ killall apache\n" +#define killall5_trivial_usage \ + "[-l] [-signal]" +#define killall5_full_usage \ + "Send a signal (default is TERM) to all processes outside current session.\n\n" \ + "Options:\n" \ + "\t-l\tList all signal names and numbers\n" \ + #define klogd_trivial_usage \ "[-c n] [-n]" #define klogd_full_usage \ diff --git a/procps/Config.in b/procps/Config.in index 2183fab9a..2d4ad3bd4 100644 --- a/procps/Config.in +++ b/procps/Config.in @@ -38,6 +38,11 @@ config CONFIG_KILLALL specified commands. If no signal name is specified, SIGTERM is sent. +config CONFIG_KILLALL5 + bool "killall5" + default n + depends on CONFIG_KILL + config CONFIG_PIDOF bool "pidof" default n diff --git a/procps/kill.c b/procps/kill.c index 654467ac1..fe9b24200 100644 --- a/procps/kill.c +++ b/procps/kill.c @@ -13,17 +13,18 @@ int kill_main(int argc, char **argv) { char *arg; - int killall, signo = SIGTERM, errors = 0, quiet = 0; - - killall = (ENABLE_KILLALL && bb_applet_name[4]=='a') ? 1 : 0; + pid_t pid; + int signo = SIGTERM, errors = 0, quiet = 0; + const int killall = (ENABLE_KILLALL && bb_applet_name[4]=='a' + && (!ENABLE_KILLALL5 || bb_applet_name[7]!='5')); + const int killall5 = (ENABLE_KILLALL5 && bb_applet_name[4]=='a' + && (!ENABLE_KILLALL || bb_applet_name[7]=='5')); /* Parse any options */ argc--; arg = *++argv; - if (argc<1) - bb_show_usage(); - if (arg[0]!='-') { + if (argc<1 || arg[0]!='-') { goto do_it_now; } @@ -79,42 +80,48 @@ int kill_main(int argc, char **argv) do_it_now: - /* Pid or name required */ - if (argc<1) - bb_show_usage(); - - if (!killall) { - /* Looks like they want to do a kill. Do that */ - while (arg) { - int pid; - - if (!isdigit(arg[0]) && arg[0]!='-') - bb_error_msg_and_die("bad pid '%s'", arg); - pid = strtol(arg, NULL, 0); - if (kill(pid, signo)!=0) { - bb_perror_msg("cannot kill pid %d", pid); - errors++; - } - arg = *++argv; + if (killall5) { + pid_t sid; + procps_status_t* p; + + /* kill(-1, sig) on Linux (at least 2.1.x) + * might send signal to the calling process too */ + signal(SIGTERM, SIG_IGN); + /* Now stop all processes */ + kill(-1, SIGSTOP); + /* Find out our own session id */ + pid = getpid(); + sid = getsid(pid); + /* Now kill all processes except our session */ + while ((p = procps_scan(0))!=0) { + if (getsid(p->pid)!=sid && p->pid!=pid && p->pid!=1) + kill(p->pid, signo); } + /* And let them continue */ + kill(-1, SIGCONT); + return 0; + } - } else { - pid_t myPid = getpid(); + /* Pid or name required for kill/killall */ + if (argc<1) + bb_show_usage(); + if (killall) { /* Looks like they want to do a killall. Do that */ + pid = getpid(); while (arg) { long* pidList; pidList = find_pid_by_name(arg); if (!pidList || *pidList<=0) { errors++; - if (quiet==0) + if (!quiet) bb_error_msg("%s: no process killed", arg); } else { long *pl; - for (pl = pidList; *pl!=0 ; pl++) { - if (*pl==myPid) + for (pl = pidList; *pl!=0; pl++) { + if (*pl==pid) continue; if (kill(*pl, signo)!=0) { errors++; @@ -126,7 +133,20 @@ do_it_now: free(pidList); arg = *++argv; } + return errors; } + /* Looks like they want to do a kill. Do that */ + while (arg) { + if (!isdigit(arg[0]) && arg[0]!='-') + bb_error_msg_and_die("bad pid '%s'", arg); + pid = strtol(arg, NULL, 0); + /* FIXME: better overflow check? */ + if (kill(pid, signo)!=0) { + bb_perror_msg("cannot kill pid %ld", (long)pid); + errors++; + } + arg = *++argv; + } return errors; } |