aboutsummaryrefslogtreecommitdiff
path: root/procps
diff options
context:
space:
mode:
Diffstat (limited to 'procps')
-rw-r--r--procps/Config.in12
-rw-r--r--procps/Kbuild2
-rw-r--r--procps/kill.c48
-rw-r--r--procps/pgrep.c136
4 files changed, 172 insertions, 26 deletions
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
49 help 49 help
50 Prints selected system stats continuously, one line per update. 50 Prints selected system stats continuously, one line per update.
51 51
52config PGREP
53 bool "pgrep"
54 default n
55 help
56 Look for processes by name.
57
52config PIDOF 58config PIDOF
53 bool "pidof" 59 bool "pidof"
54 default n 60 default n
@@ -72,6 +78,12 @@ config FEATURE_PIDOF_OMIT
72 The special pid %PPID can be used to name the parent process 78 The special pid %PPID can be used to name the parent process
73 of the pidof, in other words the calling shell or shell script. 79 of the pidof, in other words the calling shell or shell script.
74 80
81config PKILL
82 bool "pkill"
83 default n
84 help
85 Send signals to processes by name.
86
75config PS 87config PS
76 bool "ps" 88 bool "ps"
77 default n 89 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
10lib-$(CONFIG_KILL) += kill.o 10lib-$(CONFIG_KILL) += kill.o
11lib-$(CONFIG_ASH) += kill.o # used for built-in kill by ash 11lib-$(CONFIG_ASH) += kill.o # used for built-in kill by ash
12lib-$(CONFIG_NMETER) += nmeter.o 12lib-$(CONFIG_NMETER) += nmeter.o
13lib-$(CONFIG_PGREP) += pgrep.o
14lib-$(CONFIG_PKILL) += pgrep.o
13lib-$(CONFIG_PIDOF) += pidof.o 15lib-$(CONFIG_PIDOF) += pidof.o
14lib-$(CONFIG_PS) += ps.o 16lib-$(CONFIG_PS) += ps.o
15lib-$(CONFIG_RENICE) += renice.o 17lib-$(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)
58 if (arg[1] == 'l' && arg[2] == '\0') { 58 if (arg[1] == 'l' && arg[2] == '\0') {
59 if (argc == 1) { 59 if (argc == 1) {
60 /* Print the whole signal list */ 60 /* Print the whole signal list */
61 for (signo = 1; signo < 32; signo++) { 61 print_signames_and_exit();
62 const char *name = get_signame(signo); 62 }
63 if (!isdigit(name[0])) 63 /* -l <sig list> */
64 puts(name); 64 while ((arg = *++argv)) {
65 } 65 if (isdigit(arg[0])) {
66 } else { /* -l <sig list> */ 66 signo = bb_strtou(arg, NULL, 10);
67 while ((arg = *++argv)) { 67 if (errno) {
68 if (isdigit(arg[0])) { 68 bb_error_msg("unknown signal '%s'", arg);
69 signo = bb_strtou(arg, NULL, 10); 69 return EXIT_FAILURE;
70 if (errno) { 70 }
71 bb_error_msg("unknown signal '%s'", arg); 71 /* Exitcodes >= 0x80 are to be treated
72 return EXIT_FAILURE; 72 * as "killed by signal (exitcode & 0x7f)" */
73 } 73 puts(get_signame(signo & 0x7f));
74 /* Exitcodes >= 0x80 are to be treated 74 /* TODO: 'bad' signal# - coreutils says:
75 * as "killed by signal (exitcode & 0x7f)" */ 75 * kill: 127: invalid signal
76 puts(get_signame(signo & 0x7f)); 76 * we just print "127" instead */
77 /* TODO: 'bad' signal# - coreutils says: 77 } else {
78 * kill: 127: invalid signal 78 signo = get_signum(arg);
79 * we just print "127" instead */ 79 if (signo < 0) {
80 } else { 80 bb_error_msg("unknown signal '%s'", arg);
81 signo = get_signum(arg); 81 return EXIT_FAILURE;
82 if (signo < 0) {
83 bb_error_msg("unknown signal '%s'", arg);
84 return EXIT_FAILURE;
85 }
86 printf("%d\n", signo);
87 } 82 }
83 printf("%d\n", signo);
88 } 84 }
89 } 85 }
90 /* If they specified -l, we are all done */ 86 /* 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 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Mini pgrep/pkill implementation for busybox
4 *
5 * Copyright (C) 2007 Loic Grenie <loic.grenie@gmail.com>
6 *
7 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
8 */
9
10#include <getopt.h>
11
12#include "libbb.h"
13#include "xregex.h"
14
15/* Idea taken from kill.c */
16#define pgrep (ENABLE_PGREP && applet_name[1] == 'g')
17#define pkill (ENABLE_PKILL && applet_name[1] == 'k')
18
19enum {
20 /* "vlfxon" */
21 PGREPOPTBIT_V = 0, /* must be first, we need OPT_INVERT = 0/1 */
22 PGREPOPTBIT_L,
23 PGREPOPTBIT_F,
24 PGREPOPTBIT_X,
25 PGREPOPTBIT_O,
26 PGREPOPTBIT_N,
27};
28
29#define OPT_INVERT (opt & (1 << PGREPOPTBIT_V))
30#define OPT_LIST (opt & (1 << PGREPOPTBIT_L))
31#define OPT_FULL (opt & (1 << PGREPOPTBIT_F))
32#define OPT_ANCHOR (opt & (1 << PGREPOPTBIT_X))
33#define OPT_FIRST (opt & (1 << PGREPOPTBIT_O))
34#define OPT_LAST (opt & (1 << PGREPOPTBIT_N))
35
36static void act(unsigned pid, char *cmd, int signo, unsigned opt)
37{
38 if (pgrep) {
39 if (OPT_LIST)
40 printf("%d %s\n", pid, cmd);
41 else
42 printf("%d\n", pid);
43 } else
44 kill(pid, signo);
45}
46
47int pgrep_main(int argc, char **argv);
48int pgrep_main(int argc, char **argv)
49{
50 unsigned pid = getpid();
51 int signo = SIGTERM;
52 unsigned opt;
53 int scan_mask = PSSCAN_COMM;
54 char *first_arg;
55 int first_arg_idx;
56 int matched_pid;
57 char *cmd_last;
58 procps_status_t *proc;
59 /* These are initialized to 0 */
60 struct {
61 regex_t re_buffer;
62 regmatch_t re_match[1];
63 } Z;
64#define re_buffer (Z.re_buffer)
65#define re_match (Z.re_match )
66
67 memset(&Z, 0, sizeof(Z));
68
69 /* We must avoid interpreting -NUM (signal num) as an option */
70 first_arg_idx = 1;
71 while (1) {
72 first_arg = argv[first_arg_idx];
73 if (!first_arg)
74 break;
75 if (first_arg[0] != '-' || first_arg[1] < 'a' || first_arg[1] > 'z') {
76 argv[first_arg_idx] = NULL;
77 break;
78 }
79 first_arg_idx++;
80 }
81 opt = getopt32(argv, "vlfxon");
82 argv[first_arg_idx] = first_arg;
83
84 argv += optind;
85 //argc -= optind; - unused anyway
86 if (OPT_FULL)
87 scan_mask |= PSSCAN_ARGVN;
88
89 if (pkill) {
90 if (OPT_LIST) /* -l: print the whole signal list */
91 print_signames_and_exit();
92 if (first_arg && first_arg[0] == '-') {
93 signo = get_signum(&first_arg[1]);
94 if (signo < 0) /* || signo > MAX_SIGNUM ? */
95 bb_error_msg_and_die("bad signal name '%s'", &first_arg[1]);
96 argv++;
97 }
98 }
99
100 /* One pattern is required */
101 if (!argv[0] || argv[1])
102 bb_show_usage();
103
104 xregcomp(&re_buffer, argv[0], 0);
105 matched_pid = 0;
106 cmd_last = NULL;
107 proc = NULL;
108 while ((proc = procps_scan(proc, scan_mask)) != NULL) {
109 char *cmd;
110 if (proc->pid == pid)
111 continue;
112 cmd = proc->argv0;
113 if (!cmd)
114 cmd = proc->comm;
115 /* NB: OPT_INVERT is always 0 or 1 */
116 if ((regexec(&re_buffer, cmd, 1, re_match, 0) == 0 /* match found */
117 && (!OPT_ANCHOR || (re_match[0].rm_so == 0 && re_match[0].rm_eo == strlen(cmd)))) ^ OPT_INVERT
118 ) {
119 matched_pid = proc->pid;
120 if (OPT_LAST) {
121 free(cmd_last);
122 cmd_last = xstrdup(cmd_last);
123 continue;
124 }
125 act(proc->pid, cmd, signo, opt);
126 if (OPT_FIRST)
127 break;
128 }
129 }
130 if (cmd_last) {
131 act(matched_pid, cmd_last, signo, opt);
132 if (ENABLE_FEATURE_CLEAN_UP)
133 free(cmd_last);
134 }
135 return matched_pid == 0; /* return 1 if no processes listed/signaled */
136}