diff --git a/nshlib/Kconfig b/nshlib/Kconfig index 2a183068a..b6899b452 100644 --- a/nshlib/Kconfig +++ b/nshlib/Kconfig @@ -428,6 +428,11 @@ config NSH_DISABLE_KILL bool "Disable kill" default DEFAULT_SMALL +config NSH_DISABLE_PKILL + bool "Disable pkill" + default DEFAULT_SMALL + depends on FS_PROCFS + config NSH_DISABLE_LOSETUP bool "Disable losetup" default DEFAULT_SMALL diff --git a/nshlib/nsh.h b/nshlib/nsh.h index a41778833..9220502f3 100644 --- a/nshlib/nsh.h +++ b/nshlib/nsh.h @@ -1181,6 +1181,9 @@ int cmd_switchboot(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv); #ifndef CONFIG_NSH_DISABLE_KILL int cmd_kill(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv); #endif +#if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_NSH_DISABLE_PKILL) + int cmd_pkill(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv); +#endif #ifndef CONFIG_NSH_DISABLE_SLEEP int cmd_sleep(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv); #endif diff --git a/nshlib/nsh_command.c b/nshlib/nsh_command.c index dce82ef0c..64932e419 100644 --- a/nshlib/nsh_command.c +++ b/nshlib/nsh_command.c @@ -310,6 +310,10 @@ static const struct cmdmap_s g_cmdmap[] = CMD_MAP("kill", cmd_kill, 2, 3, "[-] "), #endif +#if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_NSH_DISABLE_PKILL) + CMD_MAP("pkill", cmd_pkill, 2, 3, "[-] "), +#endif + #ifndef CONFIG_DISABLE_MOUNTPOINT # if defined(CONFIG_DEV_LOOP) && !defined(CONFIG_NSH_DISABLE_LOSETUP) CMD_MAP("losetup", cmd_losetup, 3, 6, diff --git a/nshlib/nsh_proccmds.c b/nshlib/nsh_proccmds.c index f1ce2c11b..8b3d88e7f 100644 --- a/nshlib/nsh_proccmds.c +++ b/nshlib/nsh_proccmds.c @@ -801,6 +801,107 @@ invalid_arg: } #endif +/**************************************************************************** + * Name: cmd_pkill + ****************************************************************************/ + +#if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_NSH_DISABLE_PKILL) +int cmd_pkill(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv) +{ + FAR const char *name; + FAR char *ptr; + pid_t pids[8]; + int signal; + ssize_t ret; + int i; + + /* pkill will send SIGTERM to the task in case no signal is selected by + * - option + */ + + if (argc == 3) /* pkill - */ + { + /* Check incoming parameters. + * The first parameter should be "-" + */ + + ptr = argv[1]; + if (*ptr != '-' || ptr[1] < '0' || ptr[1] > '9') + { + goto invalid_arg; + } + + /* Extract the signal number */ + + signal = atoi(&ptr[1]); + + /* The second parameter should be */ + + name = argv[2]; + } + else if (argc == 2) /* kill */ + { + /* uses default signal number as SIGTERM */ + + signal = SIGTERM; /* SIGTERM is always defined in signal.h */ + + /* The first parameter should be name */ + + name = argv[1]; + } + else + { + /* invalid number of arguments */ + + goto invalid_arg; + } + + ret = nsh_getpid(vtbl, name, pids, nitems(pids)); + if (ret <= 0) + { + nsh_error(vtbl, g_fmtnosuch, argv[0], "task", name); + return ERROR; + } + + /* Send the signal. Kill return values: + * + * EINVAL An invalid signal was specified. + * EPERM The process does not have permission to send the signal to any + * of the target processes. + * ESRCH The pid or process group does not exist. + * ENOSYS Do not support sending signals to process groups. + */ + + for (i = 0; i < ret; i++) + { + if (kill(pids[i], signal) != 0) + { + switch (errno) + { + case EINVAL: + goto invalid_arg; + + case ESRCH: + nsh_error(vtbl, g_fmtnosuch, argv[0], "task", argv[2]); + return ERROR; + + case EPERM: + case ENOSYS: + default: + nsh_error(vtbl, g_fmtcmdfailed, argv[0], "kill", NSH_ERRNO); + return ERROR; + } + } + } + + return OK; + +invalid_arg: + nsh_error(vtbl, g_fmtarginvalid, argv[0]); + return ERROR; +} +#endif + /**************************************************************************** * Name: cmd_sleep ****************************************************************************/