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

Reply via email to