aboutsummaryrefslogtreecommitdiff
path: root/toys
diff options
context:
space:
mode:
authorDaniel Walter <d.walter@0x90.at>2012-02-21 19:45:19 -0600
committerDaniel Walter <d.walter@0x90.at>2012-02-21 19:45:19 -0600
commiteb7204b52ded2b2e8fc10b6af4ae9deb77cd550d (patch)
tree042231a176d27efbbe72c71cbe524b4d673eb30e /toys
parented505e8b16eecc984759415efad56dc6e47afb70 (diff)
downloadtoybox-eb7204b52ded2b2e8fc10b6af4ae9deb77cd550d.tar.gz
Add new kill toy. Used to send signals to a process or a process group.
Diffstat (limited to 'toys')
-rw-r--r--toys/kill.c186
1 files changed, 186 insertions, 0 deletions
diff --git a/toys/kill.c b/toys/kill.c
new file mode 100644
index 00000000..10c784b2
--- /dev/null
+++ b/toys/kill.c
@@ -0,0 +1,186 @@
+/* vi: set sw=4 ts=4:
+ *
+ * kill.c - a program to send signals to processes
+ *
+ * Copyright 2012 Daniel Walter <d.walter@0x90.at>
+ *
+ * See http://opengroup.org/onlinepubs/9699919799/utilities/kill.html
+
+USE_KILL(NEWTOY(kill, NULL, TOYFLAG_BIN))
+
+config KILL
+ bool "kill"
+ default y
+ help
+ usage: kill [-l signal_number | -s signal_name | -signal_name | -signal_number] pid...
+
+ Send a signal to a process
+
+*/
+
+#include "toys.h"
+
+#define TT this.kill
+
+typedef struct {
+ int signum;
+ char *signame;
+} signals_t;
+
+const signals_t signals[] = {
+ { 1, "HUP"},
+ { 2, "INT"},
+ { 3, "QUIT"},
+ { 4, "ILL"},
+ { 5, "TRAP"},
+ { 6, "ABRT"},
+ { 7, "BUS"},
+ { 8, "FPE"},
+ { 9, "KILL"},
+ { 10, "USR1"},
+ { 11, "SEGV"},
+ { 12, "USR2"},
+ { 13, "PIPE"},
+ { 14, "ALRM"},
+ { 15, "TERM"},
+ { 16, "STKFLT"},
+ { 17, "CHLD"},
+ { 18, "CONT"},
+ { 19, "STOP"},
+ { 20, "TSTP"},
+ { 21, "TTIN"},
+ { 22, "TTOU"},
+ { 23, "URG"},
+ { 24, "XCPU"},
+ { 25, "XFSZ"},
+ { 26, "VTALRM"},
+ { 27, "PROF"},
+ { 28, "WINCH"},
+ { 29, "POLL"},
+ { 30, "PWR"},
+ { 31, "SYS"},
+ /* terminator */
+ { -1, NULL},
+};
+
+static char* signum_to_signame(int sig)
+{
+ int i = 0;
+ for (;;) {
+ if (signals[i].signum == sig)
+ return signals[i].signame;
+
+ if (signals[++i].signum == -1)
+ break;
+ }
+ return NULL;
+}
+
+static int signame_to_signum(char *signame)
+{
+ int i=0;
+ for (;;) {
+ if (!strcmp(signals[i].signame, signame))
+ return signals[i].signum;
+ if (signals[++i].signum == -1)
+ break;
+ }
+ return -1;
+}
+
+static int send_signal(int sig, pid_t pid)
+{
+ if (kill(pid, sig) < 0) {
+ perror("kill");
+ return -1;
+ }
+ return 0;
+}
+
+static void list_all_signals()
+{
+ int i = 0;
+ for (;;) {
+ printf("%s ", signals[i++].signame);
+ if (i % 16 == 0)
+ printf("\n");
+ if (signals[i].signum == -1)
+ break;
+ }
+ printf("\n");
+}
+
+static int list_signal(int signum)
+{
+ char *signam = signum_to_signame(signum);
+ if (signam) {
+ printf("%s\n", signam);
+ return 0;
+ } else {
+ printf("Unknown signal %d\n", signum);
+ return -1;
+ }
+}
+
+static int list_signal_by_name(char *signame)
+{
+ int signum = signame_to_signum(signame);
+ if (signum > 0) {
+ printf("%d\n", signum);
+ return 0;
+ } else {
+ printf("Unknown signal %s\n", signame);
+ return -1;
+ }
+}
+
+void kill_main(void)
+{
+ int signum = 0;
+ int have_signal = 0;
+ char *signame, *tmp;
+ pid_t pid;
+ while (*toys.optargs) {
+ char *arg = *(toys.optargs++);
+ if (arg[0] == '-' && !have_signal) {
+ arg++;
+ switch(arg[0]) {
+ case 'l':
+ if (!*toys.optargs)
+ list_all_signals();
+ else {
+ signum = strtol(*(toys.optargs), &signame, 10);
+ if (signame == *(toys.optargs))
+ list_signal_by_name(signame);
+ else
+ list_signal(signum);
+ }
+ return;
+ case 's':
+ arg = *(toys.optargs++);
+ default:
+ signum = strtol(arg, &signame, 10);
+ if (signame == arg) {
+ signum = signame_to_signum(signame);
+ if (signum < 0) {
+ toys.exitval = EXIT_FAILURE;
+ return;
+ }
+ }
+ have_signal = 1;
+ }
+ } else {
+ /* pids */
+ pid = strtol(arg, &tmp, 10);
+ if (tmp == arg) {
+ toys.exitval = EXIT_FAILURE;
+ return;
+ }
+ if (send_signal(signum, pid) < 0) {
+ toys.exitval = EXIT_FAILURE;
+ return;
+ }
+
+ }
+ }
+}