-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
The purpose of this change is to implement the `kill` command to accept a POSIX-compliant signal number or signal name, which then can be sent to one or more processes. JIRA: RTOS-760
- Loading branch information
Showing
1 changed file
with
98 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,54 +1,133 @@ | ||
/* | ||
* Phoenix-RTOS | ||
* | ||
* kill - send signal_kill to process | ||
* kill - send a signal to a process | ||
* | ||
* Copyright 2017, 2018, 2020, 2021 Phoenix Systems | ||
* Author: Pawel Pisarczyk, Jan Sikorski, Maciej Purski, Lukasz Kosinski, Mateusz Niewiadomski | ||
* Copyright 2017, 2018, 2020, 2021, 2024 Phoenix Systems | ||
* Author: Pawel Pisarczyk, Jan Sikorski, Maciej Purski, | ||
* Lukasz Kosinski, Mateusz Niewiadomski, Gerard Swiderski | ||
* | ||
* This file is part of Phoenix-RTOS. | ||
* | ||
* %LICENSE% | ||
*/ | ||
|
||
#include <errno.h> | ||
#include <ctype.h> | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <string.h> | ||
|
||
#include <sys/threads.h> | ||
#include <signal.h> | ||
|
||
#include "../psh.h" | ||
|
||
|
||
void psh_killinfo(void) | ||
static void psh_killInfo(void) | ||
{ | ||
printf("sends a signal to a process"); | ||
} | ||
|
||
|
||
static void killUsage(void) | ||
{ | ||
printf("terminates process"); | ||
puts("Usage: kill [-s signal | -signal] <pid [...]>"); | ||
} | ||
|
||
|
||
static int signalByName(const char *name) | ||
{ | ||
static const struct { | ||
const char *name; | ||
int signal; | ||
} sigNames[] = { | ||
/* clang-format on */ | ||
|
||
{ "HUP", SIGHUP }, { "INT", SIGINT }, { "QUIT", SIGQUIT }, { "ILL", SIGILL }, | ||
{ "TRAP", SIGTRAP }, { "ABRT", SIGABRT }, { "EMT", SIGEMT }, { "FPE", SIGFPE }, | ||
{ "KILL", SIGKILL }, { "BUS", SIGBUS }, { "SEGV", SIGSEGV }, { "SYS", SIGSYS }, | ||
{ "PIPE", SIGPIPE }, { "ALRM", SIGALRM }, { "TERM", SIGTERM }, { "USR1", SIGUSR1 }, | ||
{ "USR2", SIGUSR2 }, { "CHLD", SIGCHLD }, { "WINCH", SIGWINCH }, { "URG", SIGURG }, | ||
{ "IO", SIGIO }, { "STOP", SIGSTOP }, { "TSTP", SIGTSTP }, { "CONT", SIGCONT }, | ||
{ "TTIN", SIGTTIN }, { "TTOU", SIGTTOU }, { "VTALRM", SIGVTALRM }, { "PROF", SIGPROF }, | ||
{ "XCPU", SIGXCPU }, { "XFSZ", SIGXFSZ }, { "INFO", SIGINFO } | ||
|
||
/* clang-format off */ | ||
}; | ||
|
||
if ((name[0] == 'S') && (name[1] == 'I') && (name[2] == 'G')) { | ||
name += 3; | ||
} | ||
|
||
for (size_t i = 0; i < sizeof(sigNames) / sizeof(sigNames[0]); ++i) { | ||
if (strcmp(name, sigNames[i].name) == 0) { | ||
return sigNames[i].signal; | ||
} | ||
} | ||
|
||
return -1; | ||
} | ||
|
||
|
||
int psh_kill(int argc, char **argv) | ||
static int psh_killMain(int argc, char **argv) | ||
{ | ||
unsigned int pid; | ||
char *end; | ||
int sigNo = SIGTERM; | ||
int argn = 1; | ||
|
||
if (argc != 2) { | ||
fprintf(stderr, "usage: %s <pid>\n", argv[0]); | ||
return -EINVAL; | ||
if (argc <= argn) { | ||
killUsage(); | ||
return EXIT_FAILURE; | ||
} | ||
|
||
pid = strtoul(argv[1], &end, 10); | ||
if (*end != '\0') { | ||
fprintf(stderr, "kill: could not parse process id: %s\n", argv[1]); | ||
return -EINVAL; | ||
if (argv[1][0] == '-') { | ||
char *sigArg = argv[argn++] + 1; | ||
if (argv[1][1] == 's') { | ||
if ((argv[1][2] != '\0')) { | ||
killUsage(); | ||
return EXIT_FAILURE; | ||
} | ||
sigArg = argv[argn++]; | ||
} | ||
if ((argc <= argn) || (argv[1][1] == '-') || (argv[1][1] == '\0')) { | ||
killUsage(); | ||
return EXIT_FAILURE; | ||
} | ||
|
||
unsigned long int signalValue = strtoul(sigArg, &end, 10); | ||
|
||
if (*end == '\0') { | ||
sigNo = (int)signalValue; | ||
} | ||
else { | ||
sigNo = signalByName(sigArg); | ||
if (sigNo < 0) { | ||
fprintf(stderr, "kill: invalid signal name: %s\n", sigArg); | ||
return EXIT_FAILURE; | ||
} | ||
} | ||
} | ||
|
||
for (; argn < argc; ++argn) { | ||
errno = 0; | ||
pid_t pid = (pid_t)strtol(argv[argn], &end, 10); | ||
|
||
if ((argv[argn][0] == '-') || (*end != '\0') || ((pid == 0) && (errno == EINVAL))) { | ||
fprintf(stderr, "kill: invalid process id: %s\n", argv[argn]); | ||
return EXIT_FAILURE; | ||
} | ||
|
||
if (kill(pid, sigNo) != 0) { | ||
fprintf(stderr, "kill: failed to send signal to process %d\n", pid); | ||
return EXIT_FAILURE; | ||
} | ||
} | ||
|
||
return signalPost(pid, -1, signal_kill); | ||
return EXIT_SUCCESS; | ||
} | ||
|
||
|
||
void __attribute__((constructor)) kill_registerapp(void) | ||
static void __attribute__((constructor)) kill_registerapp(void) | ||
{ | ||
static psh_appentry_t app = {.name = "kill", .run = psh_kill, .info = psh_killinfo}; | ||
static psh_appentry_t app = { .name = "kill", .run = psh_killMain, .info = psh_killInfo }; | ||
psh_registerapp(&app); | ||
} |