userspace: Implement kill utility
This commit is contained in:
parent
acd792d8b4
commit
c6ef4b5840
|
|
@ -20,6 +20,7 @@ set(USERSPACE_PROGRAMS
|
||||||
id
|
id
|
||||||
image
|
image
|
||||||
init
|
init
|
||||||
|
kill
|
||||||
less
|
less
|
||||||
ln
|
ln
|
||||||
loadfont
|
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