aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2007-09-29 22:26:01 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2007-09-29 22:26:01 +0000
commit72e1c89d971aa2e37abf705c6a01f002deac09b8 (patch)
tree6edb25e260701f9f6e49769e4bb7e31e7e2e6063
parent2450e4ba44707a64920ea6c9276930a1210e76cc (diff)
downloadbusybox-w32-72e1c89d971aa2e37abf705c6a01f002deac09b8.tar.gz
busybox-w32-72e1c89d971aa2e37abf705c6a01f002deac09b8.tar.bz2
busybox-w32-72e1c89d971aa2e37abf705c6a01f002deac09b8.zip
pgrep,pkill: new applets by Loic Grenie <loic.grenie@gmail.com>
-rw-r--r--include/applets.h2
-rw-r--r--include/libbb.h4
-rw-r--r--include/usage.h24
-rw-r--r--libbb/procps.c11
-rw-r--r--libbb/u_signal_names.c15
-rw-r--r--procps/Config.in12
-rw-r--r--procps/Kbuild2
-rw-r--r--procps/kill.c48
-rw-r--r--procps/pgrep.c136
9 files changed, 226 insertions, 28 deletions
diff --git a/include/applets.h b/include/applets.h
index f162c5479..e88192d24 100644
--- a/include/applets.h
+++ b/include/applets.h
@@ -251,11 +251,13 @@ USE_OD(APPLET(od, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
251USE_OPENVT(APPLET(openvt, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) 251USE_OPENVT(APPLET(openvt, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
252USE_PASSWD(APPLET(passwd, _BB_DIR_USR_BIN, _BB_SUID_ALWAYS)) 252USE_PASSWD(APPLET(passwd, _BB_DIR_USR_BIN, _BB_SUID_ALWAYS))
253USE_PATCH(APPLET(patch, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) 253USE_PATCH(APPLET(patch, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
254USE_PGREP(APPLET(pgrep, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
254USE_PIDOF(APPLET(pidof, _BB_DIR_BIN, _BB_SUID_NEVER)) 255USE_PIDOF(APPLET(pidof, _BB_DIR_BIN, _BB_SUID_NEVER))
255USE_PING(APPLET(ping, _BB_DIR_BIN, _BB_SUID_MAYBE)) 256USE_PING(APPLET(ping, _BB_DIR_BIN, _BB_SUID_MAYBE))
256USE_PING6(APPLET(ping6, _BB_DIR_BIN, _BB_SUID_NEVER)) 257USE_PING6(APPLET(ping6, _BB_DIR_BIN, _BB_SUID_NEVER))
257USE_PIPE_PROGRESS(APPLET_NOUSAGE(pipe_progress, pipe_progress, _BB_DIR_BIN, _BB_SUID_NEVER)) 258USE_PIPE_PROGRESS(APPLET_NOUSAGE(pipe_progress, pipe_progress, _BB_DIR_BIN, _BB_SUID_NEVER))
258USE_PIVOT_ROOT(APPLET(pivot_root, _BB_DIR_SBIN, _BB_SUID_NEVER)) 259USE_PIVOT_ROOT(APPLET(pivot_root, _BB_DIR_SBIN, _BB_SUID_NEVER))
260USE_PKILL(APPLET_ODDNAME(pkill, pgrep, _BB_DIR_USR_BIN, _BB_SUID_NEVER, pkill))
259USE_HALT(APPLET_ODDNAME(poweroff, halt, _BB_DIR_SBIN, _BB_SUID_NEVER, poweroff)) 261USE_HALT(APPLET_ODDNAME(poweroff, halt, _BB_DIR_SBIN, _BB_SUID_NEVER, poweroff))
260USE_PRINTENV(APPLET(printenv, _BB_DIR_BIN, _BB_SUID_NEVER)) 262USE_PRINTENV(APPLET(printenv, _BB_DIR_BIN, _BB_SUID_NEVER))
261USE_PRINTF(APPLET(printf, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) 263USE_PRINTF(APPLET(printf, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
diff --git a/include/libbb.h b/include/libbb.h
index a6709c95d..34b978452 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -787,6 +787,7 @@ int bb_make_directory(char *path, long mode, int flags);
787 787
788int get_signum(const char *name); 788int get_signum(const char *name);
789const char *get_signame(int number); 789const char *get_signame(int number);
790void print_signames_and_exit(void) ATTRIBUTE_NORETURN;
790 791
791char *bb_simplify_path(const char *path); 792char *bb_simplify_path(const char *path);
792 793
@@ -973,7 +974,8 @@ enum {
973 PSSCAN_UTIME = 1 << 13, 974 PSSCAN_UTIME = 1 << 13,
974 PSSCAN_TTY = 1 << 14, 975 PSSCAN_TTY = 1 << 14,
975 PSSCAN_SMAPS = (1 << 15) * ENABLE_FEATURE_TOPMEM, 976 PSSCAN_SMAPS = (1 << 15) * ENABLE_FEATURE_TOPMEM,
976 USE_SELINUX(PSSCAN_CONTEXT = 1 << 16,) 977 PSSCAN_ARGVN = (1 << 16) * (ENABLE_PGREP | ENABLE_PKILL),
978 USE_SELINUX(PSSCAN_CONTEXT = 1 << 17,)
977 /* These are all retrieved from proc/NN/stat in one go: */ 979 /* These are all retrieved from proc/NN/stat in one go: */
978 PSSCAN_STAT = PSSCAN_PPID | PSSCAN_PGID | PSSCAN_SID 980 PSSCAN_STAT = PSSCAN_PPID | PSSCAN_PGID | PSSCAN_SID
979 | PSSCAN_COMM | PSSCAN_STATE 981 | PSSCAN_COMM | PSSCAN_STATE
diff --git a/include/usage.h b/include/usage.h
index 4152fecd3..d7e1dd9f1 100644
--- a/include/usage.h
+++ b/include/usage.h
@@ -2558,6 +2558,18 @@
2558 "$ patch -p1 < example.diff\n" \ 2558 "$ patch -p1 < example.diff\n" \
2559 "$ patch -p0 -i example.diff" 2559 "$ patch -p0 -i example.diff"
2560 2560
2561#define pgrep_trivial_usage \
2562 "[-flnovx] pattern"
2563#define pgrep_full_usage \
2564 "Display process(es) selected by regex pattern" \
2565 "\n\nOptions:\n" \
2566 " -l Show command name too\n" \
2567 " -f Match against entire command line\n" \
2568 " -n Signal the newest process only\n" \
2569 " -o Signal the oldest process only\n" \
2570 " -v Negate the matching\n" \
2571 " -x Match whole name (not substring)"
2572
2561#if (ENABLE_FEATURE_PIDOF_SINGLE || ENABLE_FEATURE_PIDOF_OMIT) 2573#if (ENABLE_FEATURE_PIDOF_SINGLE || ENABLE_FEATURE_PIDOF_OMIT)
2562#define USAGE_PIDOF "Options:" 2574#define USAGE_PIDOF "Options:"
2563#else 2575#else
@@ -2640,6 +2652,18 @@
2640 "Move the current root file system to PUT_OLD and make NEW_ROOT\n" \ 2652 "Move the current root file system to PUT_OLD and make NEW_ROOT\n" \
2641 "the new root file system" 2653 "the new root file system"
2642 2654
2655#define pkill_trivial_usage \
2656 "[-l] | [-fnovx] [-signal] pattern"
2657#define pkill_full_usage \
2658 "Send a signal to process(es) selected by regex pattern" \
2659 "\n\nOptions:\n" \
2660 " -l List all signals\n" \
2661 " -f Match against entire command line\n" \
2662 " -n Signal the newest process only\n" \
2663 " -o Signal the oldest process only\n" \
2664 " -v Negate the matching\n" \
2665 " -x Match whole name (not substring)"
2666
2643#define poweroff_trivial_usage \ 2667#define poweroff_trivial_usage \
2644 "[-d delay] [-n] [-f]" 2668 "[-d delay] [-n] [-f]"
2645#define poweroff_full_usage \ 2669#define poweroff_full_usage \
diff --git a/libbb/procps.c b/libbb/procps.c
index e62e5a1f1..476e1f34d 100644
--- a/libbb/procps.c
+++ b/libbb/procps.c
@@ -375,13 +375,22 @@ procps_status_t *procps_scan(procps_status_t* sp, int flags)
375 } 375 }
376 } 376 }
377#else 377#else
378 if (flags & PSSCAN_ARGV0) { 378 if (flags & *PSSCAN_ARGV0|PSSCAN_ARGVN)) {
379 free(sp->argv0); 379 free(sp->argv0);
380 sp->argv0 = NULL; 380 sp->argv0 = NULL;
381 strcpy(filename_tail, "/cmdline"); 381 strcpy(filename_tail, "/cmdline");
382 n = read_to_buf(filename, buf); 382 n = read_to_buf(filename, buf);
383 if (n <= 0) 383 if (n <= 0)
384 break; 384 break;
385#if ENABLE_PGREP || ENABLE_PKILL
386 if (flags & PSSCAN_ARGVN) {
387 do {
388 n--;
389 if (buf[n] == '\0')
390 buf[n] = ' ';
391 } while (n);
392 }
393#endif
385 sp->argv0 = xstrdup(buf); 394 sp->argv0 = xstrdup(buf);
386 } 395 }
387#endif 396#endif
diff --git a/libbb/u_signal_names.c b/libbb/u_signal_names.c
index f8eaea76d..5a6f592aa 100644
--- a/libbb/u_signal_names.c
+++ b/libbb/u_signal_names.c
@@ -159,3 +159,18 @@ const char *get_signame(int number)
159 159
160 return itoa(number); 160 return itoa(number);
161} 161}
162
163
164// Print the whole signal list
165
166void print_signames_and_exit(void)
167{
168 int signo;
169
170 for (signo = 1; signo < ARRAY_SIZE(signals); signo++) {
171 const char *name = signals[signo];
172 if (name[0])
173 puts(name);
174 }
175 exit(EXIT_SUCCESS);
176}
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}