userspace: Implement kill utility
This commit is contained in:
parent
acd792d8b4
commit
c6ef4b5840
|
|
@ -20,6 +20,7 @@ set(USERSPACE_PROGRAMS
|
|||
id
|
||||
image
|
||||
init
|
||||
kill
|
||||
less
|
||||
ln
|
||||
loadfont
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
set(SOURCES
|
||||
main.cpp
|
||||
)
|
||||
|
||||
add_executable(kill ${SOURCES})
|
||||
banan_link_library(kill ban)
|
||||
banan_link_library(kill libc)
|
||||
|
||||
install(TARGETS kill OPTIONAL)
|
||||
|
|
@ -0,0 +1,174 @@
|
|||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
struct signal_t
|
||||
{
|
||||
const char* name;
|
||||
int value;
|
||||
};
|
||||
|
||||
static constexpr signal_t s_signals[] {
|
||||
#define SIGNAL(name) { #name, name }
|
||||
SIGNAL(SIGABRT),
|
||||
SIGNAL(SIGALRM),
|
||||
SIGNAL(SIGBUS),
|
||||
SIGNAL(SIGCHLD),
|
||||
SIGNAL(SIGCONT),
|
||||
SIGNAL(SIGFPE),
|
||||
SIGNAL(SIGHUP),
|
||||
SIGNAL(SIGILL),
|
||||
SIGNAL(SIGINT),
|
||||
SIGNAL(SIGKILL),
|
||||
SIGNAL(SIGPIPE),
|
||||
SIGNAL(SIGQUIT),
|
||||
SIGNAL(SIGSEGV),
|
||||
SIGNAL(SIGSTOP),
|
||||
SIGNAL(SIGTERM),
|
||||
SIGNAL(SIGTSTP),
|
||||
SIGNAL(SIGTTIN),
|
||||
SIGNAL(SIGTTOU),
|
||||
SIGNAL(SIGUSR1),
|
||||
SIGNAL(SIGUSR2),
|
||||
SIGNAL(SIGPOLL),
|
||||
SIGNAL(SIGPROF),
|
||||
SIGNAL(SIGSYS),
|
||||
SIGNAL(SIGTRAP),
|
||||
SIGNAL(SIGURG),
|
||||
SIGNAL(SIGVTALRM),
|
||||
SIGNAL(SIGXCPU),
|
||||
SIGNAL(SIGXFSZ),
|
||||
SIGNAL(SIGWINCH),
|
||||
SIGNAL(SIGCANCEL),
|
||||
#undef SIGNAL
|
||||
};
|
||||
|
||||
[[noreturn]] static void exit_with_error(const char* format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
vfprintf(stderr, format, args);
|
||||
va_end(args);
|
||||
exit(1);
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
static int signal_name_to_number(const char* name)
|
||||
{
|
||||
for (const auto& signal : s_signals)
|
||||
if (strcasecmp(signal.name + 3, name) == 0 || strcasecmp(signal.name, name) == 0)
|
||||
return signal.value;
|
||||
exit_with_error("unknown signal '%s'\n", name);
|
||||
}
|
||||
|
||||
static int parse_int(const char* string)
|
||||
{
|
||||
errno = 0;
|
||||
char* endptr;
|
||||
const int result = strtol(string, &endptr, 0);
|
||||
if (*endptr != '\0' || errno)
|
||||
exit_with_error("invalid integer '%s'\n", string);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int list_signals(char** signals)
|
||||
{
|
||||
if (signals[0] == nullptr)
|
||||
{
|
||||
for (const auto& signal : s_signals)
|
||||
{
|
||||
if (&signal != s_signals)
|
||||
printf(" ");
|
||||
printf("%s", signal.name);
|
||||
}
|
||||
printf("\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ret = 0;
|
||||
|
||||
while (*signals)
|
||||
{
|
||||
bool found = false;
|
||||
|
||||
if (isdigit(**signals))
|
||||
{
|
||||
const int sig = parse_int(*signals);
|
||||
for (const auto& signal : s_signals)
|
||||
{
|
||||
if (signal.value != sig)
|
||||
continue;
|
||||
printf("%s\n", signal.name + 3);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (const auto& signal : s_signals)
|
||||
{
|
||||
if (strcasecmp(signal.name, *signals) != 0 && strcasecmp(signal.name + 3, *signals) != 0)
|
||||
continue;
|
||||
printf("%d\n", signal.value);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
fprintf(stderr, "unknown signal: %s\n", *signals);
|
||||
|
||||
signals++;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
if (argc >= 2 && strcmp(argv[1], "-l") == 0)
|
||||
return list_signals(argv + 2);
|
||||
|
||||
int sig = SIGTERM;
|
||||
|
||||
int i = 1;
|
||||
for (; i < argc; i++)
|
||||
{
|
||||
if (argv[i][0] != '-')
|
||||
break;
|
||||
if (argv[i][1] == '-' && argv[i][2] == '\0')
|
||||
{
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
|
||||
if (argv[i][1] == 's' && argv[i][2] == '\0')
|
||||
{
|
||||
if (i + 1 >= argc)
|
||||
exit_with_error("missing signal name\n");
|
||||
sig = signal_name_to_number(argv[i + 1]);
|
||||
i++;
|
||||
}
|
||||
else if (argv[i][2] == '-' || isdigit(argv[i][1]))
|
||||
{
|
||||
sig = parse_int(argv[i] + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
sig = signal_name_to_number(argv[i] + 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (i >= argc)
|
||||
exit_with_error("missing pids\n");
|
||||
|
||||
for (; i < argc; i++)
|
||||
if (kill(parse_int(argv[i]), sig) == -1)
|
||||
perror("kill");
|
||||
|
||||
return 0;
|
||||
}
|
||||
Loading…
Reference in New Issue