Make kill(1) POSIX conformant

* XSI extensions support is missing, -signal_name and -signal_number.
This commit is contained in:
sin 2014-11-11 14:40:47 +00:00
parent 0444d16475
commit 237673302d
2 changed files with 102 additions and 49 deletions

17
kill.1
View File

@ -4,25 +4,26 @@ KILL \- signal processes
.SH SYNOPSIS .SH SYNOPSIS
.B kill .B kill
.RB [ \-s .RB [ \-s
.IR signal ] .IR signal_name ]
.RI [ pid ...] .IR pid
.IR ...
.P .P
.B kill .B kill
.B -l .B -l
.RI [ signum ] .RI [ exit_status ]
.SH DESCRIPTION .SH DESCRIPTION
.B kill .B kill
sends a by default sends a
.I TERM .I TERM
signal to the given processes. signal to the given processes.
.SH OPTIONS .SH OPTIONS
.TP .TP
.BI \-s " signal" .BI \-s " signal_name"
sends the named signal. Sends the named signal.
.TP .TP
.B \-l .B \-l
lists available signals. If a Lists available signals. If an
.I signum .I exit_status
is given, only the corresponding signal name will be printed. is given, only the corresponding signal name will be printed.
.SH SEE ALSO .SH SEE ALSO
.IR kill (2), .IR kill (2),

134
kill.c
View File

@ -1,11 +1,13 @@
/* See LICENSE file for copyright and license details. */ /* See LICENSE file for copyright and license details. */
#include <sys/wait.h>
#include <errno.h>
#include <signal.h> #include <signal.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include <strings.h> #include <strings.h>
#include <unistd.h> #include <unistd.h>
#include <sys/wait.h>
#include "util.h" #include "util.h"
struct { struct {
@ -19,60 +21,110 @@ struct {
#undef SIG #undef SIG
}; };
const char *sig2name(int);
static void static void
usage(void) usage(void)
{ {
eprintf("usage: %s [-s signal] [pid...]\n" weprintf("usage: %s -s signal_name pid...\n", argv0);
" %s -l [signum]\n", argv0, argv0); weprintf(" %s -l [exit_status]\n", argv0);
exit(1);
} }
int int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
bool lflag = false; char *end;
char *end, *v; const char *name;
int ret = 0;
int sig = SIGTERM; int sig = SIGTERM;
pid_t pid; pid_t pid;
size_t i; size_t i;
ARGBEGIN { argv0 = argv[0];
case 'l': if (argc < 2)
lflag = true; usage();
break;
case 's': argc--;
v = EARGF(usage()); argv++;
sig = strtol(v, &end, 0); if (strcmp(argv[0], "-l") == 0) {
if(*end == '\0') argc--;
break; argv++;
for(i = 0; i < LEN(sigs); i++) { if (argc == 0) {
if(!strcasecmp(v, sigs[i].name)) { for (i = 0; i < LEN(sigs); i++)
sig = sigs[i].sig; puts(sigs[i].name);
break; 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)) exit(0);
eprintf("%s: unknown signal\n", v); } else if (strcmp(argv[0], "-s") == 0) {
break; argc--;
default: argv++;
usage(); if (argc == 0)
} ARGEND; usage();
if (strcmp(argv[0], "0") == 0) {
if(argc < 1 && !lflag) sig = 0;
usage(); } else {
for (i = 0; i < LEN(sigs); i++) {
if(lflag) { if (strcasecmp(sigs[i].name, argv[0]) == 0) {
sig = (argc > 0) ? estrtol(argv[0], 0) : 0; sig = sigs[i].sig;
if(sig > 128) break;
sig = WTERMSIG(sig); }
for(i = 0; i < LEN(sigs); i++) }
if(sigs[i].sig == sig || sig == 0) if (i == LEN(sigs))
putword(sigs[i].name); eprintf("%s: bad signal number\n", argv[0]);
putchar('\n'); }
} else for(; argc > 0; argc--, argv++) { argc--;
pid = estrtol(argv[0], 0); argv++;
if(kill(pid, sig) == -1) } else if (strcmp(argv[0], "--") == 0) {
eprintf("kill %d:", pid); argc--;
argv++;
if (argc == 0)
usage();
} }
return 0; if (argc == 0)
usage();
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;
}
}
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;
} }