From 72e1c89d971aa2e37abf705c6a01f002deac09b8 Mon Sep 17 00:00:00 2001 From: Denis Vlasenko Date: Sat, 29 Sep 2007 22:26:01 +0000 Subject: pgrep,pkill: new applets by Loic Grenie --- procps/Config.in | 12 +++++ procps/Kbuild | 2 + procps/kill.c | 48 +++++++++----------- procps/pgrep.c | 136 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 172 insertions(+), 26 deletions(-) create mode 100644 procps/pgrep.c (limited to 'procps') diff --git a/procps/Config.in b/procps/Config.in index 2bd3cd245..7e7ee7922 100644 --- a/procps/Config.in +++ b/procps/Config.in @@ -49,6 +49,12 @@ config NMETER help Prints selected system stats continuously, one line per update. +config PGREP + bool "pgrep" + default n + help + Look for processes by name. + config PIDOF bool "pidof" default n @@ -72,6 +78,12 @@ config FEATURE_PIDOF_OMIT The special pid %PPID can be used to name the parent process of the pidof, in other words the calling shell or shell script. +config PKILL + bool "pkill" + default n + help + Send signals to processes by name. + config PS bool "ps" default n diff --git a/procps/Kbuild b/procps/Kbuild index c75be291b..8e62fdfa6 100644 --- a/procps/Kbuild +++ b/procps/Kbuild @@ -10,6 +10,8 @@ lib-$(CONFIG_FUSER) += fuser.o lib-$(CONFIG_KILL) += kill.o lib-$(CONFIG_ASH) += kill.o # used for built-in kill by ash lib-$(CONFIG_NMETER) += nmeter.o +lib-$(CONFIG_PGREP) += pgrep.o +lib-$(CONFIG_PKILL) += pgrep.o lib-$(CONFIG_PIDOF) += pidof.o lib-$(CONFIG_PS) += ps.o lib-$(CONFIG_RENICE) += renice.o diff --git a/procps/kill.c b/procps/kill.c index 892a798c5..961f8cb14 100644 --- a/procps/kill.c +++ b/procps/kill.c @@ -58,33 +58,29 @@ int kill_main(int argc, char **argv) if (arg[1] == 'l' && arg[2] == '\0') { if (argc == 1) { /* Print the whole signal list */ - for (signo = 1; signo < 32; signo++) { - const char *name = get_signame(signo); - if (!isdigit(name[0])) - puts(name); - } - } else { /* -l */ - while ((arg = *++argv)) { - if (isdigit(arg[0])) { - signo = bb_strtou(arg, NULL, 10); - if (errno) { - bb_error_msg("unknown signal '%s'", arg); - return EXIT_FAILURE; - } - /* Exitcodes >= 0x80 are to be treated - * as "killed by signal (exitcode & 0x7f)" */ - puts(get_signame(signo & 0x7f)); - /* TODO: 'bad' signal# - coreutils says: - * kill: 127: invalid signal - * we just print "127" instead */ - } else { - signo = get_signum(arg); - if (signo < 0) { - bb_error_msg("unknown signal '%s'", arg); - return EXIT_FAILURE; - } - printf("%d\n", signo); + print_signames_and_exit(); + } + /* -l */ + while ((arg = *++argv)) { + if (isdigit(arg[0])) { + signo = bb_strtou(arg, NULL, 10); + if (errno) { + bb_error_msg("unknown signal '%s'", arg); + return EXIT_FAILURE; + } + /* Exitcodes >= 0x80 are to be treated + * as "killed by signal (exitcode & 0x7f)" */ + puts(get_signame(signo & 0x7f)); + /* TODO: 'bad' signal# - coreutils says: + * kill: 127: invalid signal + * we just print "127" instead */ + } else { + signo = get_signum(arg); + if (signo < 0) { + bb_error_msg("unknown signal '%s'", arg); + return EXIT_FAILURE; } + printf("%d\n", signo); } } /* If they specified -l, we are all done */ diff --git a/procps/pgrep.c b/procps/pgrep.c new file mode 100644 index 000000000..3bf087f28 --- /dev/null +++ b/procps/pgrep.c @@ -0,0 +1,136 @@ +/* vi: set sw=4 ts=4: */ +/* + * Mini pgrep/pkill implementation for busybox + * + * Copyright (C) 2007 Loic Grenie + * + * Licensed under the GPL v2 or later, see the file LICENSE in this tarball. + */ + +#include + +#include "libbb.h" +#include "xregex.h" + +/* Idea taken from kill.c */ +#define pgrep (ENABLE_PGREP && applet_name[1] == 'g') +#define pkill (ENABLE_PKILL && applet_name[1] == 'k') + +enum { + /* "vlfxon" */ + PGREPOPTBIT_V = 0, /* must be first, we need OPT_INVERT = 0/1 */ + PGREPOPTBIT_L, + PGREPOPTBIT_F, + PGREPOPTBIT_X, + PGREPOPTBIT_O, + PGREPOPTBIT_N, +}; + +#define OPT_INVERT (opt & (1 << PGREPOPTBIT_V)) +#define OPT_LIST (opt & (1 << PGREPOPTBIT_L)) +#define OPT_FULL (opt & (1 << PGREPOPTBIT_F)) +#define OPT_ANCHOR (opt & (1 << PGREPOPTBIT_X)) +#define OPT_FIRST (opt & (1 << PGREPOPTBIT_O)) +#define OPT_LAST (opt & (1 << PGREPOPTBIT_N)) + +static void act(unsigned pid, char *cmd, int signo, unsigned opt) +{ + if (pgrep) { + if (OPT_LIST) + printf("%d %s\n", pid, cmd); + else + printf("%d\n", pid); + } else + kill(pid, signo); +} + +int pgrep_main(int argc, char **argv); +int pgrep_main(int argc, char **argv) +{ + unsigned pid = getpid(); + int signo = SIGTERM; + unsigned opt; + int scan_mask = PSSCAN_COMM; + char *first_arg; + int first_arg_idx; + int matched_pid; + char *cmd_last; + procps_status_t *proc; + /* These are initialized to 0 */ + struct { + regex_t re_buffer; + regmatch_t re_match[1]; + } Z; +#define re_buffer (Z.re_buffer) +#define re_match (Z.re_match ) + + memset(&Z, 0, sizeof(Z)); + + /* We must avoid interpreting -NUM (signal num) as an option */ + first_arg_idx = 1; + while (1) { + first_arg = argv[first_arg_idx]; + if (!first_arg) + break; + if (first_arg[0] != '-' || first_arg[1] < 'a' || first_arg[1] > 'z') { + argv[first_arg_idx] = NULL; + break; + } + first_arg_idx++; + } + opt = getopt32(argv, "vlfxon"); + argv[first_arg_idx] = first_arg; + + argv += optind; + //argc -= optind; - unused anyway + if (OPT_FULL) + scan_mask |= PSSCAN_ARGVN; + + if (pkill) { + if (OPT_LIST) /* -l: print the whole signal list */ + print_signames_and_exit(); + if (first_arg && first_arg[0] == '-') { + signo = get_signum(&first_arg[1]); + if (signo < 0) /* || signo > MAX_SIGNUM ? */ + bb_error_msg_and_die("bad signal name '%s'", &first_arg[1]); + argv++; + } + } + + /* One pattern is required */ + if (!argv[0] || argv[1]) + bb_show_usage(); + + xregcomp(&re_buffer, argv[0], 0); + matched_pid = 0; + cmd_last = NULL; + proc = NULL; + while ((proc = procps_scan(proc, scan_mask)) != NULL) { + char *cmd; + if (proc->pid == pid) + continue; + cmd = proc->argv0; + if (!cmd) + cmd = proc->comm; + /* NB: OPT_INVERT is always 0 or 1 */ + if ((regexec(&re_buffer, cmd, 1, re_match, 0) == 0 /* match found */ + && (!OPT_ANCHOR || (re_match[0].rm_so == 0 && re_match[0].rm_eo == strlen(cmd)))) ^ OPT_INVERT + ) { + matched_pid = proc->pid; + if (OPT_LAST) { + free(cmd_last); + cmd_last = xstrdup(cmd_last); + continue; + } + act(proc->pid, cmd, signo, opt); + if (OPT_FIRST) + break; + } + } + if (cmd_last) { + act(matched_pid, cmd_last, signo, opt); + if (ENABLE_FEATURE_CLEAN_UP) + free(cmd_last); + } + return matched_pid == 0; /* return 1 if no processes listed/signaled */ +} -- cgit v1.2.3