Add killall by Andreas Heck, and factor out common pid code to lib.h.
authorRob Landley <rob@landley.net>
Sat, 18 Feb 2012 21:12:41 +0000 (15:12 -0600)
committerRob Landley <rob@landley.net>
Sat, 18 Feb 2012 21:12:41 +0000 (15:12 -0600)
lib/lib.c
lib/lib.h
toys/killall.c [new file with mode: 0644]
toys/pidof.c

index 887910f..8cc85a9 100644 (file)
--- a/lib/lib.c
+++ b/lib/lib.c
@@ -809,3 +809,58 @@ int yesno(int def)
        }
        return def;
 }
+
+// Execute a callback for each PID that matches a process name from a list.
+int for_each_pid_with_name_in(char **names,
+        void (*callback) (const char *pid)) {
+#define PATH_LEN 64
+
+    DIR *dp;
+    struct dirent *entry;
+    FILE *fp;
+    int n, pathpos;
+    char cmd[PATH_MAX];
+    char path[PATH_LEN];
+    char **curname;
+
+    dp = opendir("/proc");
+    if (!dp) {
+        perror("opendir");
+        return 1;
+    }
+
+    while ((entry = readdir(dp))) {
+        if (!isdigit(entry->d_name[0])) continue;
+        strcpy(path, "/proc/");
+        pathpos = 6;
+
+        if (pathpos + strlen(entry->d_name) + 1 > PATH_LEN) continue;
+
+        strcpy(&path[pathpos], entry->d_name);
+        pathpos += strlen(entry->d_name);
+
+        if (pathpos + strlen("/cmdline") + 1 > PATH_LEN) continue;
+        strcpy(&path[pathpos], "/cmdline");
+
+        fp = fopen(path, "r");
+        if (!fp) {
+            perror("fopen");
+            continue;
+        }
+
+        n = fread(cmd, 1, PATH_MAX, fp); 
+        fclose(fp);
+        if (n == 0) continue;
+
+        for (curname = names; *curname; curname++) {
+            if (strcmp(basename(cmd), *curname) == 0) {
+                callback(entry->d_name);
+            }
+        }
+    }
+
+    closedir(dp);
+
+    return 0;
+#undef PATH_LEN
+}
index b7f250b..0193ebd 100644 (file)
--- a/lib/lib.h
+++ b/lib/lib.h
@@ -110,6 +110,8 @@ void replace_tempfile(int fdin, int fdout, char **tempname);
 void crc_init(unsigned int *crc_table, int little_endian);
 void terminal_size(unsigned *x, unsigned *y);
 int yesno(int def);
+int for_each_pid_with_name_in(char **names,
+               void (*callback) (const char *pid));
 
 
 // getmountlist.c
diff --git a/toys/killall.c b/toys/killall.c
new file mode 100644 (file)
index 0000000..fb3e8cb
--- /dev/null
@@ -0,0 +1,229 @@
+/* vi: set sw=4 ts=4:
+ *
+ * killall.c - Send a signal (default: TERM) to all processes with the given names.
+ *
+ * Copyright 2012 Andreas Heck <aheck@gmx.de>
+ *
+ * Not in SUSv4.
+ * See http://opengroup.org/onlinepubs/9699919799/utilities/
+
+USE_KILLALL(NEWTOY(killall, "?lq", TOYFLAG_USR|TOYFLAG_BIN))
+
+config KILLALL
+       bool "killall"
+       default y
+       help
+         usage: killall [-l] [-q] [-SIG] PROCESS_NAME...
+
+         Send a signal (default: TERM) to all processes with the given names.
+
+               -l      print list of all available signals
+               -q      don't print any warnings or error messages
+*/
+
+#include "toys.h"
+
+#define FLAG_q 1
+#define FLAG_l 2
+
+DEFINE_GLOBALS(
+               int matched;
+               int signum;
+)
+#define TT this.killall
+
+struct signame {
+       int num;
+       const char *name;
+};
+
+static struct signame signames[] = {
+#ifdef SIGHUP
+       {SIGHUP, "HUP"},
+#endif
+#ifdef SIGINT
+       {SIGINT, "INT"},
+#endif
+#ifdef SIGQUIT
+       {SIGQUIT, "QUIT"},
+#endif
+#ifdef SIGILL
+       {SIGILL, "ILL"},
+#endif
+#ifdef SIGTRAP
+       {SIGTRAP, "TRAP"},
+#endif
+#ifdef SIGTABRT
+       {SIGABRT, "ABRT"},
+#endif
+#ifdef SIGTABRT
+       {SIGIOT, "IOT"},
+#endif
+#ifdef SIGBUS
+       {SIGBUS, "BUS"},
+#endif
+#ifdef SIGFPE
+       {SIGFPE, "FPE"},
+#endif
+#ifdef SIGKILL
+       {SIGKILL, "KILL"},
+#endif
+#ifdef SIGUSR1
+       {SIGUSR1, "USR1"},
+#endif
+#ifdef SIGSEGV
+       {SIGSEGV, "SEGV"},
+#endif
+#ifdef SIGUSR2
+       {SIGUSR2, "USR2"},
+#endif
+#ifdef SIGPIPE
+       {SIGPIPE, "PIPE"},
+#endif
+#ifdef SIGALRM
+       {SIGALRM, "ALRM"},
+#endif
+#ifdef SIGTERM
+       {SIGTERM, "TERM"},
+#endif
+#ifdef SIGSTKFLT
+       {SIGSTKFLT, "STKFLT"},
+#endif
+#ifdef SIGCHLD
+       {SIGCHLD, "CHLD"},
+#endif
+#ifdef SIGCONT
+       {SIGCONT, "CONT"},
+#endif
+#ifdef SIGSTOP
+       {SIGSTOP, "STOP"},
+#endif
+#ifdef SIGSTOP
+       {SIGSTOP, "STOP"},
+#endif
+#ifdef SIGTSTP
+       {SIGTSTP, "TSTP"},
+#endif
+#ifdef SIGTTIN
+       {SIGTTIN, "TTIN"},
+#endif
+#ifdef SIGTTOU
+       {SIGTTOU, "TTOU"},
+#endif
+#ifdef SIGURG
+       {SIGURG, "URG"},
+#endif
+#ifdef SIGXCPU
+       {SIGXCPU, "XCPU"},
+#endif
+#ifdef SIGXFSZ
+       {SIGXFSZ, "XFSZ"},
+#endif
+#ifdef SIGVTALRM
+       {SIGVTALRM, "VTALRM"},
+#endif
+#ifdef SIGVTALRM
+       {SIGVTALRM, "VTALRM"},
+#endif
+#ifdef SIGPROF
+       {SIGPROF, "PROF"},
+#endif
+#ifdef SIGWINCH
+       {SIGWINCH, "WINCH"},
+#endif
+#ifdef SIGIO
+       {SIGIO, "IO"},
+#endif
+#ifdef SIGPOLL
+       {SIGPOLL, "POLL"},
+#endif
+#ifdef SIGPWR
+       {SIGPWR, "PWR"},
+#endif
+#ifdef SIGSYS
+       {SIGSYS, "SYS"},
+#endif
+#ifdef SIGUNUSED
+       {SIGUNUSED, "UNUSED"},
+#endif
+       {0, NULL}
+};
+
+static int sig_to_num(const char *pidstr) {
+       int i, num;
+
+       if (isdigit(pidstr[0])) {
+               num = atoi(pidstr);
+
+               return num;
+       }
+
+       for (i = 0; signames[i].num; i++) {
+               if (strcmp(pidstr, signames[i].name) == 0) {
+                       return signames[i].num;
+               }
+       }
+
+       return -1;
+}
+
+static void print_signals() {
+       int i;
+
+       for (i = 0; signames[i].num; i++) {
+               puts(signames[i].name);
+       }
+}
+
+static void kill_process(const char *pidstr) {
+       int ret;
+       pid_t pid = atoi(pidstr);
+
+       TT.matched = 1;
+       ret = kill(pid, TT.signum);
+
+       if (ret == -1) {
+               if (toys.optflags & FLAG_q) perror("kill");
+       }
+}
+
+void killall_main(void)
+{
+       char **names;
+
+       TT.matched = 0;
+       TT.signum = SIGTERM;
+
+       if (toys.optflags & FLAG_l) {
+               print_signals();
+               exit(0);
+       }
+
+       if (!*toys.optargs) {
+               toys.exithelp = 1;
+               error_exit("Process name missing!");
+       }
+
+       names = toys.optargs;
+
+       if ((*toys.optargs)[0] == '-') {
+               TT.signum = sig_to_num(&(*toys.optargs)[1]);
+               if (TT.signum <= 0) {
+                       if (toys.optflags & FLAG_q) fprintf(stderr, "Invalid signal\n");
+                       exit(1);
+               }
+               names = ++toys.optargs;
+       }
+
+       if (!*names) {
+               toys.exithelp = 1;
+               error_exit("Process name missing!");
+       }
+
+       for_each_pid_with_name_in(names, kill_process);
+
+       if (!TT.matched) {
+               if (!(toys.optflags & FLAG_q)) fprintf(stderr, "No such process\n");
+               exit(1);
+       }
+}
index c6f0d55..329b008 100644 (file)
@@ -7,7 +7,7 @@
  * Not in SUSv4.
  * See http://opengroup.org/onlinepubs/9699919799/utilities/
 
-USE_PIDOF(NEWTOY(pidof, "e@d*c#b:a", TOYFLAG_USR|TOYFLAG_BIN))
+USE_PIDOF(NEWTOY(pidof, "", TOYFLAG_USR|TOYFLAG_BIN))
 
 config PIDOF
        bool "pidof"
@@ -20,80 +20,30 @@ config PIDOF
 
 #include "toys.h"
 
+DEFINE_GLOBALS(
+               int matched;
+)
 #define TT this.pidof
 
-#define PATH_LEN 64
-#define PROC_DIR "/proc/"
-#define CMD_LINE "/cmdline"
-
-static int matched = 0;
-
-static int for_each_pid(void (*callback) (const char *pid)) {
-    DIR *dp;
-    struct dirent *entry;
-    FILE *fp;
-    int n, pathpos;
-    char cmd[PATH_MAX];
-    char path[PATH_LEN];
-    char **curname;
-
-    dp = opendir(PROC_DIR);
-    if (!dp) {
-        perror("opendir");
-        return 1;
-    }
-
-    while ((entry = readdir(dp))) {
-        if (!isdigit(entry->d_name[0])) continue;
-        strcpy(path, PROC_DIR);
-        pathpos = strlen(PROC_DIR);
-
-        if (pathpos + strlen(entry->d_name) + 1 > PATH_LEN) continue;
-
-        strcpy(&path[pathpos], entry->d_name);
-        pathpos += strlen(entry->d_name);
-
-        if (pathpos + strlen(CMD_LINE) + 1 > PATH_LEN) continue;
-        strcpy(&path[pathpos], CMD_LINE);
-
-        fp = fopen(path, "r");
-        if (!fp) {
-            perror("fopen");
-            continue;
-        }
-
-        n = fread(cmd, 1, PATH_MAX, fp); 
-        fclose(fp);
-        if (n == 0) continue;
-
-        for (curname = toys.optargs; *curname; curname++) {
-            if (strcmp(basename(cmd), *curname) == 0) {
-                callback(entry->d_name);
-            }
-        }
-    }
-
-    closedir(dp);
-
-    return 0;
-}
 
 static void print_pid (const char *pid) {
-    if (matched) putchar(' ');
+    if (TT.matched) putchar(' ');
     fputs(pid, stdout);
-    matched = 1;
+    TT.matched = 1;
 }
 
 void pidof_main(void)
 {
     int err;
 
+       TT.matched = 0;
+
     if (!toys.optargs) exit(1);
 
-    err = for_each_pid(print_pid);
+    err = for_each_pid_with_name_in(toys.optargs, print_pid);
     if (err) exit(1);
 
-    if (!matched)
+    if (!TT.matched)
         exit(1);
     else
         putchar('\n');