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
.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),

116
kill.c
View File

@ -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;
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;
}
}
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(v, sigs[i].name)) {
if (strcasecmp(sigs[i].name, argv[0]) == 0) {
sig = sigs[i].sig;
break;
}
}
if (i == LEN(sigs))
eprintf("%s: unknown signal\n", v);
break;
default:
eprintf("%s: bad signal number\n", argv[0]);
}
argc--;
argv++;
} else if (strcmp(argv[0], "--") == 0) {
argc--;
argv++;
if (argc == 0)
usage();
} ARGEND;
}
if(argc < 1 && !lflag)
if (argc == 0)
usage();
if(lflag) {
sig = (argc > 0) ? estrtol(argv[0], 0) : 0;
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 || 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);
}
return 0;
if (sigs[i].sig == sig)
return sigs[i].name;
return NULL;
}