sbase

suckless unix tools
git clone git://git.2f30.org/sbase.git
Log | Files | Refs | README | LICENSE

commit 237673302d5f3454e6c7b1873281b99d3e3ed3a2
parent 0444d16475c22a2377ab408ed67fb8a4d753931e
Author: sin <sin@2f30.org>
Date:   Tue Nov 11 14:40:47 +0000

Make kill(1) POSIX conformant

* XSI extensions support is missing, -signal_name and -signal_number.

Diffstat:
kill.1 | 17+++++++++--------
kill.c | 128+++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------
2 files changed, 99 insertions(+), 46 deletions(-)
diff --git a/kill.1 b/kill.1 @@ -4,25 +4,26 @@ KILL \- signal processes .SH SYNOPSIS .B kill .RB [ \-s -.IR signal ] -.RI [ pid ...] +.IR signal_name ] +.IR pid +.IR ... .P .B kill .B -l -.RI [ signum ] +.RI [ exit_status ] .SH DESCRIPTION .B kill -sends a +by default sends a .I TERM signal to the given processes. .SH OPTIONS .TP -.BI \-s " signal" -sends the named signal. +.BI \-s " signal_name" +Sends the named signal. .TP .B \-l -lists available signals. If a -.I signum +Lists available signals. If an +.I exit_status is given, only the corresponding signal name will be printed. .SH SEE ALSO .IR kill (2), diff --git a/kill.c b/kill.c @@ -1,11 +1,13 @@ /* See LICENSE file for copyright and license details. */ +#include <sys/wait.h> +#include <errno.h> #include <signal.h> #include <stdbool.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> #include <strings.h> #include <unistd.h> -#include <sys/wait.h> #include "util.h" struct { @@ -19,60 +21,110 @@ struct { #undef SIG }; +const char *sig2name(int); + static void usage(void) { - eprintf("usage: %s [-s signal] [pid...]\n" - " %s -l [signum]\n", argv0, argv0); + weprintf("usage: %s -s signal_name pid...\n", argv0); + weprintf(" %s -l [exit_status]\n", argv0); + exit(1); } int main(int argc, char *argv[]) { - bool lflag = false; - char *end, *v; + char *end; + const char *name; + int ret = 0; int sig = SIGTERM; pid_t pid; size_t i; - ARGBEGIN { - case 'l': - lflag = true; - break; - case 's': - v = EARGF(usage()); - sig = strtol(v, &end, 0); - if(*end == '\0') - break; - for(i = 0; i < LEN(sigs); i++) { - if(!strcasecmp(v, sigs[i].name)) { - sig = sigs[i].sig; - break; + argv0 = argv[0]; + if (argc < 2) + usage(); + + argc--; + argv++; + if (strcmp(argv[0], "-l") == 0) { + argc--; + argv++; + if (argc == 0) { + for (i = 0; i < LEN(sigs); i++) + puts(sigs[i].name); + exit(0); + } + for (; argc; argc--, argv++) { + errno = 0; + sig = strtol(argv[0], &end, 0); + if (*end == '\0' && errno == 0) { + name = sig2name(sig); + if (!name) + printf("%d\n", sig); + else + puts(name); + } else { + weprintf("%s: bad signal number\n", argv[0]); + ret = 1; } } - if(i == LEN(sigs)) - eprintf("%s: unknown signal\n", v); - break; - default: - usage(); - } ARGEND; + exit(0); + } else if (strcmp(argv[0], "-s") == 0) { + argc--; + argv++; + if (argc == 0) + usage(); + if (strcmp(argv[0], "0") == 0) { + sig = 0; + } else { + for (i = 0; i < LEN(sigs); i++) { + if (strcasecmp(sigs[i].name, argv[0]) == 0) { + sig = sigs[i].sig; + break; + } + } + if (i == LEN(sigs)) + eprintf("%s: bad signal number\n", argv[0]); + } + argc--; + argv++; + } else if (strcmp(argv[0], "--") == 0) { + argc--; + argv++; + if (argc == 0) + usage(); + } - if(argc < 1 && !lflag) + if (argc == 0) usage(); - if(lflag) { - sig = (argc > 0) ? estrtol(argv[0], 0) : 0; - if(sig > 128) - sig = WTERMSIG(sig); - for(i = 0; i < LEN(sigs); i++) - if(sigs[i].sig == sig || sig == 0) - putword(sigs[i].name); - putchar('\n'); - } else for(; argc > 0; argc--, argv++) { - pid = estrtol(argv[0], 0); - if(kill(pid, sig) == -1) - eprintf("kill %d:", pid); + for (; argc; argc--, argv++) { + errno = 0; + pid = strtol(argv[0], &end, 0); + if (*end == '\0' && errno == 0) { + if (kill(pid, sig) < 0) { + weprintf("kill %d:", pid); + ret = 1; + } + } else { + weprintf("%s: bad pid\n", argv[0]); + ret = 1; + } } - return 0; + exit(ret); +} + +const char * +sig2name(int sig) +{ + size_t i; + + if (sig > 128) + sig = WTERMSIG(sig); + for (i = 0; i < LEN(sigs); i++) + if (sigs[i].sig == sig) + return sigs[i].name; + return NULL; }