]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
kill: return 64 on partial success
authorKarel Zak <kzak@redhat.com>
Mon, 7 Apr 2014 09:07:00 +0000 (11:07 +0200)
committerKarel Zak <kzak@redhat.com>
Mon, 7 Apr 2014 09:07:00 +0000 (11:07 +0200)
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>
misc-utils/kill.1
misc-utils/kill.c

index bd29dc4f6c172ccf38b959bd99ec2650d1465311..a3bc9ee050896765823e0bc497513d6dd853d231 100644 (file)
@@ -126,7 +126,21 @@ accepts TID (thread ID, see
 .BR gettid (2))
 as argument.  In this case the kill behavior is not changed and the signal is
 also delivered to the thread group rather than to the specified thread.
-.SH "SEE ALSO"
+
+.SH RETURN CODES
+.B kill
+has the following return codes:
+.TP
+.BR 0
+success
+.TP
+.BR 1
+failure
+.TP
+.BR 64
+partial success (when more than one process specified)
+
+.SH SEE ALSO
 .BR bash (1),
 .BR tcsh (1),
 .BR kill (2),
index d97a4c54e40abfde7589dd933b0255443aac54fb..358ba290aabebf7a8bfc040680e9efe0033e8e5f 100644 (file)
@@ -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 */
 }