From: Karel Zak Date: Mon, 7 Apr 2014 09:07:00 +0000 (+0200) Subject: kill: return 64 on partial success X-Git-Tag: v2.25-rc1~322 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a01f4d4323d5ca17c4d9773cbb7abd22d701e276;p=thirdparty%2Futil-linux.git 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 --- diff --git a/misc-utils/kill.1 b/misc-utils/kill.1 index bd29dc4f6c..a3bc9ee050 100644 --- a/misc-utils/kill.1 +++ b/misc-utils/kill.1 @@ -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), diff --git a/misc-utils/kill.c b/misc-utils/kill.c index d97a4c54e4..358ba290aa 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 */ }