From ff9ee8fc15e1a41bffe06bfcee30368e7c117601 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Sat, 18 Feb 2012 15:12:41 -0600 Subject: Add killall by Andreas Heck, and factor out common pid code to lib.h. --- lib/lib.c | 55 ++++++++++++++ lib/lib.h | 2 + toys/killall.c | 229 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ toys/pidof.c | 70 +++--------------- 4 files changed, 296 insertions(+), 60 deletions(-) create mode 100644 toys/killall.c diff --git a/lib/lib.c b/lib/lib.c index 887910fb..8cc85a9f 100644 --- 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 +} diff --git a/lib/lib.h b/lib/lib.h index b7f250b8..0193ebd0 100644 --- 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 index 00000000..fb3e8cb3 --- /dev/null +++ b/toys/killall.c @@ -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 + * + * 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); + } +} diff --git a/toys/pidof.c b/toys/pidof.c index c6f0d556..329b0084 100644 --- a/toys/pidof.c +++ b/toys/pidof.c @@ -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'); -- cgit v1.2.3