changeset 475:1fb149e75ebf

Add killall by Andreas Heck, and factor out common pid code to lib.h.
author Rob Landley <rob@landley.net>
date Sat, 18 Feb 2012 15:12:41 -0600
parents d76583999029
children d10b58563cff
files lib/lib.c lib/lib.h toys/killall.c toys/pidof.c
diffstat 4 files changed, 296 insertions(+), 60 deletions(-) [+]
line wrap: on
line diff
--- a/lib/lib.c	Sat Feb 18 15:08:31 2012 -0600
+++ b/lib/lib.c	Sat Feb 18 15:12:41 2012 -0600
@@ -809,3 +809,58 @@
 	}
 	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
+}
--- a/lib/lib.h	Sat Feb 18 15:08:31 2012 -0600
+++ b/lib/lib.h	Sat Feb 18 15:12:41 2012 -0600
@@ -110,6 +110,8 @@
 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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/killall.c	Sat Feb 18 15:12:41 2012 -0600
@@ -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);
+	}
+}
--- a/toys/pidof.c	Sat Feb 18 15:08:31 2012 -0600
+++ b/toys/pidof.c	Sat Feb 18 15:12:41 2012 -0600
@@ -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 @@
 
 #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');