Skip to content

Commit

Permalink
psh: reimplement 'kill' command
Browse files Browse the repository at this point in the history
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
gerard5 committed Feb 26, 2024
1 parent cdd944d commit ad86483
Showing 1 changed file with 98 additions and 19 deletions.
117 changes: 98 additions & 19 deletions psh/kill/kill.c
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);
}

0 comments on commit ad86483

Please sign in to comment.