2007/9/29, Denys Vlasenko <[EMAIL PROTECTED]>:
> On Friday 28 September 2007 16:51, Loïc Grenié wrote:
> > These are three patches for busybox.
>
> Sending patches separately makes it easy to have one thread per patch.
> With mnay patches in one mail, it's a mess.
Sorry about that.
>> 3) The third one adds functions pgrep and pkill (this one includes
>> the "procps.diff" that I've sent before).
>
> +static char char2;
> +/* Idea taken from kill.c */
> +#define pgrep (ENABLE_PGREP && char2 == 'g')
> +#define pkill (ENABLE_PKILL && char2 == 'k')
> You don't need that static. Use existing global char* applet_name.
Done. I've changed kill as well.
> + if (opt & 0x04)
> + anchor = 0;
>
> You mean:
>
> enum { /* correspond to getopt32 option string */
> OPTBIT_ANCHOR = 0,
> OPTBIT_X,
> OPTBIT_Y,
> OPTBIT_Z,
> };
> #define OPT_ANCHOR (opt & (1 << OPTBIT_ANCHOR))
> #define OPT_X (opt & (1 << OPTBIT_X ))
> ...
>
> if (OPT_ANCHOR) ...
>
> This produces smaller code.
Done.
> Generally I can accept pgrep/pkill, looking forward for next
> iteration of the patch.
Here it is. I've tried to take care of all the remarks.
Loïc
Index: libbb/procps.c
===================================================================
--- libbb/procps.c (révision 20109)
+++ libbb/procps.c (copie de travail)
@@ -375,15 +375,21 @@
}
}
#else
- if (flags & PSSCAN_ARGV0) {
+ if (flags & (PSSCAN_ARGV0|PSSCAN_ARGVN)) {
free(sp->argv0);
sp->argv0 = NULL;
strcpy(filename_tail, "/cmdline");
n = read_to_buf(filename, buf);
if (n <= 0)
break;
- if (flags & PSSCAN_ARGV0)
- sp->argv0 = xstrdup(buf);
+ if (flags & PSSCAN_ARGVN) {
+ do {
+ n--;
+ if (buf[n] == '\0')
+ buf[n] = ' ';
+ } while (n);
+ }
+ sp->argv0 = xstrdup(buf);
}
#endif
break;
Index: libbb/u_signal_names.c
===================================================================
--- libbb/u_signal_names.c (révision 20109)
+++ libbb/u_signal_names.c (copie de travail)
@@ -159,3 +159,18 @@
return itoa(number);
}
+
+
+// Print the whole signal list
+
+void print_signames_and_exit(void)
+{
+ int signo;
+
+ for (signo = 1; signo < ARRAY_SIZE(signals); signo++) {
+ const char *name = signals[signo];
+ if (name[0])
+ puts(name);
+ }
+ exit(EXIT_SUCCESS);
+}
Index: include/libbb.h
===================================================================
--- include/libbb.h (révision 20109)
+++ include/libbb.h (copie de travail)
@@ -787,6 +787,7 @@
int get_signum(const char *name);
const char *get_signame(int number);
+void print_signames_and_exit(void) ATTRIBUTE_NORETURN;
char *bb_simplify_path(const char *path);
@@ -974,6 +975,7 @@
PSSCAN_TTY = 1 << 14,
PSSCAN_SMAPS = (1 << 15) * ENABLE_FEATURE_TOPMEM,
USE_SELINUX(PSSCAN_CONTEXT = 1 << 16,)
+ PSSCAN_ARGVN = 1 << 17,
/* These are all retrieved from proc/NN/stat in one go: */
PSSCAN_STAT = PSSCAN_PPID | PSSCAN_PGID | PSSCAN_SID
| PSSCAN_COMM | PSSCAN_STATE
Index: include/usage.h
===================================================================
--- include/usage.h (révision 20109)
+++ include/usage.h (copie de travail)
@@ -2558,6 +2558,18 @@
"$ patch -p1 < example.diff\n" \
"$ patch -p0 -i example.diff"
+#define pgrep_trivial_usage \
+ "[-flnovx] pattern"
+#define pgrep_full_usage \
+ " pattern to look for in the name of the process" \
+ "\n\nOptions:\n" \
+ " -f Match against the command line instead of process name\n" \
+ " -l Give command name in addition to process number\n" \
+ " -n Select the last started process of the list\n" \
+ " -o Select the first started process of the list\n" \
+ " -v Negate the matching\n" \
+ " -x Match the complete name"
+
#if (ENABLE_FEATURE_PIDOF_SINGLE || ENABLE_FEATURE_PIDOF_OMIT)
#define USAGE_PIDOF "Options:"
#else
@@ -2640,6 +2652,18 @@
"Move the current root file system to PUT_OLD and make NEW_ROOT\n" \
"the new root file system"
+#define pkill_trivial_usage \
+ "[-l] | [-fnovx] [-signal] pattern"
+#define pkill_full_usage \
+ "Send a signal (default is TERM) to the process(es) specified by name" \
+ "\n\nOptions:\n" \
+ " -l List all signal names and numbers\n" \
+ " -f Match against the command line instead of process name\n" \
+ " -n Select the last started process of the list\n" \
+ " -o Select the first started process of the list\n" \
+ " -v Negate the matching\n" \
+ " -x Match the complete name"
+
#define poweroff_trivial_usage \
"[-d delay] [-n] [-f]"
#define poweroff_full_usage \
Index: include/applets.h
===================================================================
--- include/applets.h (révision 20109)
+++ include/applets.h (copie de travail)
@@ -251,11 +251,13 @@
USE_OPENVT(APPLET(openvt, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
USE_PASSWD(APPLET(passwd, _BB_DIR_USR_BIN, _BB_SUID_ALWAYS))
USE_PATCH(APPLET(patch, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_PGREP(APPLET(pgrep, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
USE_PIDOF(APPLET(pidof, _BB_DIR_BIN, _BB_SUID_NEVER))
USE_PING(APPLET(ping, _BB_DIR_BIN, _BB_SUID_MAYBE))
USE_PING6(APPLET(ping6, _BB_DIR_BIN, _BB_SUID_NEVER))
USE_PIPE_PROGRESS(APPLET_NOUSAGE(pipe_progress, pipe_progress, _BB_DIR_BIN, _BB_SUID_NEVER))
USE_PIVOT_ROOT(APPLET(pivot_root, _BB_DIR_SBIN, _BB_SUID_NEVER))
+USE_PKILL(APPLET_ODDNAME(pkill, pgrep, _BB_DIR_USR_BIN, _BB_SUID_NEVER, pkill))
USE_HALT(APPLET_ODDNAME(poweroff, halt, _BB_DIR_SBIN, _BB_SUID_NEVER, poweroff))
USE_PRINTENV(APPLET(printenv, _BB_DIR_BIN, _BB_SUID_NEVER))
USE_PRINTF(APPLET(printf, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
Index: procps/Config.in
===================================================================
--- procps/Config.in (révision 20109)
+++ procps/Config.in (copie de travail)
@@ -49,6 +49,12 @@
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 @@
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
Index: procps/Kbuild
===================================================================
--- procps/Kbuild (révision 20109)
+++ procps/Kbuild (copie de travail)
@@ -10,6 +10,8 @@
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
Index: procps/kill.c
===================================================================
--- procps/kill.c (révision 20109)
+++ procps/kill.c (copie de travail)
@@ -36,11 +36,11 @@
#else
/* How to determine who we are? find 3rd char from the end:
* kill, killall, killall5
- * ^i ^a ^l - it's unique
- * (checking from the start is complicated by /bin/kill... case) */
- const char char3 = argv[0][strlen(argv[0]) - 3];
-#define killall (ENABLE_KILLALL && char3 == 'a')
-#define killall5 (ENABLE_KILLALL5 && char3 == 'l')
+ * 4 7 8 - the number of characters of the name is unique
+ */
+ const char namelen = strlen(applet_name);
+#define killall (ENABLE_KILLALL && namelen == 7)
+#define killall5 (ENABLE_KILLALL5 && namelen == 8)
#endif
/* Parse any options */
@@ -58,11 +58,7 @@
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);
- }
+ print_signames_and_exit();
} else { /* -l <sig list> */
while ((arg = *++argv)) {
if (isdigit(arg[0])) {
--- /dev/null 2007-09-26 12:43:34.255962088 +0200
+++ procps/pgrep.c 2007-09-29 04:59:25.000000000 +0200
@@ -0,0 +1,139 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini pgrep/pkill implementation for busybox
+ *
+ * Copyright (C) 2007
+ *
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ */
+
+#include <getopt.h>
+
+#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, // invert match. Must be first.
+ 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, int opt)
+{
+ if (pgrep)
+ {
+ if (opt)
+ 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)
+{
+ char *first_arg, *cmdm = NULL;
+ procps_status_t *p = NULL;
+ regex_t re_buffer;
+ const int NMATCH = 2;
+ regmatch_t re_regs[NMATCH];
+ int match = 0;
+ unsigned pid = getpid();
+ int signo = SIGTERM, i;
+ uint32_t opt;
+ int scan_mask = PSSCAN_STAT;
+ bool list;
+
+ for (i = 1; ; i++)
+ {
+ first_arg = argv[i];
+ if (!first_arg)
+ break;
+ if (first_arg[0] != '-' || first_arg[1] < 'a' || first_arg[1] > 'z')
+ {
+ argv[i] = NULL;
+ break;
+ }
+ }
+ opt = getopt32(argv, "vlfxon");
+ for (i = 1; argv[i]; i++)
+ ;
+ argv[i] = first_arg;
+ argc -= optind;
+ argv += optind;
+ list = OPT_LIST;
+ if (OPT_FULL)
+ scan_mask |= PSSCAN_ARGVN;
+
+ if (pkill && list) { // -l
+ if (argc || opt & ~0x01)
+ bb_perror_nomsg_and_die();
+ /* Print the whole signal list */
+ print_signames_and_exit();
+ }
+
+ if (pkill && first_arg && first_arg[0] == '-')
+ {
+ signo = get_signum(&first_arg[1]);
+ ++argv;
+ --argc;
+ }
+ if (signo < 0) { /* || signo > MAX_SIGNUM ? */
+ bb_error_msg_and_die("bad signal name '%s'", &first_arg[1]);
+ }
+
+ /* Name is required */
+ if (argc != 1)
+ bb_error_msg_and_die("You need to specify one matching criteria");
+
+ memset(&re_buffer, 0, sizeof(re_buffer));
+ memset(re_regs, 0, sizeof(*re_regs));
+ xregcomp(&re_buffer, argv[0], 0);
+
+ while ((p = procps_scan(p, scan_mask)) != NULL) {
+ char *cmd;
+ cmd = p->argv0;
+ if (!cmd)
+ cmd = p->comm;
+ if (p->pid != pid &&
+ (regexec(&re_buffer, cmd, NMATCH, re_regs, 0) != REG_NOMATCH &&
+ (OPT_ANCHOR ||
+ (re_regs[0].rm_so == 0 && re_regs[0].rm_eo == strlen(cmd))))
+ ^ OPT_INVERT)
+ {
+ match = p->pid;
+ if (OPT_LAST)
+ {
+ free(cmdm);
+ cmdm = xstrdup(cmd);
+ continue;
+ }
+ act(p->pid, cmd, signo, list);
+ if (OPT_FIRST)
+ break;
+ }
+ }
+ if (OPT_LAST && match)
+ {
+ act(match, cmdm, signo, list);
+ free(cmdm);
+ }
+ return !match;
+}
_______________________________________________
busybox mailing list
[email protected]
http://busybox.net/cgi-bin/mailman/listinfo/busybox