summaryrefslogtreecommitdiffstats
path: root/misc-utils/kill.c
diff options
context:
space:
mode:
authorKarel Zak2014-04-07 11:07:00 +0200
committerKarel Zak2014-04-07 11:07:00 +0200
commita01f4d4323d5ca17c4d9773cbb7abd22d701e276 (patch)
tree0e70e590cc350ce7af4c220a1b602ebf8db6f1c4 /misc-utils/kill.c
parentkill: tiny change in man page (diff)
downloadkernel-qcow2-util-linux-a01f4d4323d5ca17c4d9773cbb7abd22d701e276.tar.gz
kernel-qcow2-util-linux-a01f4d4323d5ca17c4d9773cbb7abd22d701e276.tar.xz
kernel-qcow2-util-linux-a01f4d4323d5ca17c4d9773cbb7abd22d701e276.zip
kill: return 64 on partial success
Return 64 (aka SOME_OK) when more than process specified and the operation success only for subset of the processes. # kill -s 0 firefox mutt xxx; echo $? kill: cannot find process "xxx" 64 We already use this concept for chcpu(8) or mount(8). Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'misc-utils/kill.c')
-rw-r--r--misc-utils/kill.c60
1 files changed, 37 insertions, 23 deletions
diff --git a/misc-utils/kill.c b/misc-utils/kill.c
index d97a4c54e..358ba290a 100644
--- a/misc-utils/kill.c
+++ b/misc-utils/kill.c
@@ -57,6 +57,9 @@
#include "ttyutils.h"
#include "xalloc.h"
+/* partial success, otherwise we return regular EXIT_{SUCCESS,FAILURE} */
+#define KILL_EXIT_SOMEOK 64
+
enum {
KILL_FIELD_WIDTH = 11,
KILL_OUTPUT_WIDTH = 72
@@ -443,57 +446,68 @@ static int kill_verbose(const struct kill_control *ctl)
else
#endif
rc = kill(ctl->pid, ctl->numsig);
- if (rc < 0) {
+
+ if (rc < 0)
warn(_("sending signal to %s failed"), ctl->arg);
- return EXIT_FAILURE;
- }
- return EXIT_SUCCESS;
+ return rc;
}
int main(int argc, char **argv)
{
- struct kill_control ctl;
- int errors = EXIT_SUCCESS;
+ struct kill_control ctl = { .numsig = SIGTERM };
+ int nerrs = 0, ct = 0;
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
atexit(close_stdout);
- memset(&ctl, 0, sizeof(ctl));
- ctl.numsig = SIGTERM;
ctl.do_pid = (!strcmp(program_invocation_short_name, "pid")); /* Yecch */
if (ctl.do_pid) /* FIXME: remove in March 2016. */
warnx(_("use of 'kill --pid' option as command name is deprecated"));
+
argv = parse_arguments(argc, argv, &ctl);
- /* We are done with the options. The rest of the arguments
- * should be process ids and names, kill them. */
- for (/* nothing */; (ctl.arg = *argv) != NULL; argv++) {
- char *ep;
+ /* The rest of the arguments should be process ids and names. */
+ for ( ; (ctl.arg = *argv) != NULL; argv++) {
+ char *ep = NULL;
+
+ errno = 0;
ctl.pid = strtol(ctl.arg, &ep, 10);
- if (!*ep)
- errors |= kill_verbose(&ctl);
- else {
+ if (errno == 0 && ep && *ep == '\0' && ctl.arg < ep) {
+ if (kill_verbose(&ctl) != 0)
+ nerrs++;
+ ct++;
+ } else {
struct proc_processes *ps = proc_open_processes();
- int ct = 0;
+ int found = 0;
if (!ps)
continue;
if (ctl.check_all)
proc_processes_filter_by_uid(ps, getuid());
+
proc_processes_filter_by_name(ps, ctl.arg);
- while (proc_next_pid(ps, &(ctl.pid)) == 0) {
- errors |= kill_verbose(&ctl);
+ while (proc_next_pid(ps, &ctl.pid) == 0) {
+ if (kill_verbose(&ctl) != 0)
+ nerrs++;
ct++;
- }
- if (!ct) {
- errors = EXIT_FAILURE;
- warnx(_("cannot find process \"%s\""), ctl.arg);
+ found = 1;
}
proc_close_processes(ps);
+
+ if (!found) {
+ nerrs++, ct++;
+ warnx(_("cannot find process \"%s\"."), ctl.arg);
+ }
}
}
- return errors;
+
+ if (ct && nerrs == 0)
+ return EXIT_SUCCESS; /* full success */
+ else if (ct == nerrs)
+ return EXIT_FAILURE; /* all failed */
+
+ return KILL_EXIT_SOMEOK; /* partial success */
}