Hello Dave,

The patch is used to add a new option, "-E regex", to perform the
command(s) on all commands whose names contains a match to "regex".
"regex" is interpreted as an POSIX extended regular expression.

The new option is helpful when using to search some commands whose names
are similar. And I think it is more reliable than "foreach <name>
<command> | grep xxx", for information comes from command may have a
match to "xxx".

P.S.
The patch uses some function defined in regex.h, which is offered by glibc.

-- 
--
Regards
Qiao Nuohan

diff --git a/defs.h b/defs.h
index a942dbb..deabe91 100755
--- a/defs.h
+++ b/defs.h
@@ -47,6 +47,7 @@
 #include <sys/wait.h>
 #include <sys/time.h>
 #include <execinfo.h> /* backtrace() */
+#include <regex.h>
 
 #ifndef ATTRIBUTE_UNUSED
 #define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
@@ -977,6 +978,7 @@ extern struct machdep_table *machdep;
 #define FOREACH_F_FLAG  (0x400000)
 #define FOREACH_x_FLAG  (0x800000)
 #define FOREACH_d_FLAG (0x1000000)
+#define FOREACH_E_FLAG (0x2000000)
 
 struct foreach_data {
        ulong flags;
@@ -985,6 +987,7 @@ struct foreach_data {
         char *comm_array[MAX_FOREACH_COMMS];
         ulong pid_array[MAX_FOREACH_PIDS];
        ulong arg_array[MAX_FOREACH_ARGS];
+       regex_t regex;
        char *reference;
        int keys;
        int pids;
diff --git a/help.c b/help.c
index f752283..03f8b84 100755
--- a/help.c
+++ b/help.c
@@ -725,7 +725,7 @@ NULL,
 char *help_foreach[] = {
 "foreach",
 "display command data for multiple tasks in the system",
-"[[pid | taskp | name | [kernel | user]] ...] command [flag] [argument]",
+"[[pid | taskp | name | [kernel | user]] ... | -E regex] command [flag] 
[argument]",
 "  This command allows for a an examination of various kernel data associated",
 "  with any, or all, tasks in the system, without having to set the context",
 "  to each targeted task.\n",
@@ -737,7 +737,10 @@ char *help_foreach[] = {
 "           precede the name string with a \"\\\".",
 "     user  perform the command(s) on all user (non-kernel) threads.",
 "   kernel  perform the command(s) on all kernel threads.",
-"   active  perform the command(s) on the active thread on each CPU.\n",
+"   active  perform the command(s) on the active thread on each CPU.",
+" -E regex  perform the command(s) on all commands whose names contains a 
match",
+"           to the given regex. regex is interpreted as an POSIX extended 
regular",
+"           expression.\n",
 "  If none of the task-identifying arguments above are entered, the command",
 "  will be performed on all tasks.\n",
 "  command  select one or more of the following commands to be run on the 
tasks",
@@ -794,6 +797,17 @@ char *help_foreach[] = {
 "  Display the open files for all tasks:\n",
 "    %s> foreach files",
 "    ...\n",
+"  Display the state of tasks whose name contains a match to 'event.*':\n",
+"    %s> foreach -E 'event.*' task -R state",
+"    PID: 99     TASK: ffff8804750d5500  CPU: 0   COMMAND: \"events/0\"",
+"      state = 1,",
+"    ",
+"    PID: 100    TASK: ffff8804750d4ac0  CPU: 1   COMMAND: \"events/1\"",
+"      state = 1,"
+"    ",
+"    PID: 101    TASK: ffff8804750d4080  CPU: 2   COMMAND: \"events/2\"",
+"      state = 1,",
+"    ...\n",
 NULL
 };
 
diff --git a/task.c b/task.c
index fde86eb..b8b709d 100755
--- a/task.c
+++ b/task.c
@@ -4896,9 +4896,14 @@ cmd_foreach(void)
        BZERO(&foreach_data, sizeof(struct foreach_data));
        fd = &foreach_data;
 
-        while ((c = getopt(argcnt, args, "R:vomlgersStTpukcfFxhd")) != EOF) {
+        while ((c = getopt(argcnt, args, "E:R:vomlgersStTpukcfFxhd")) != EOF) {
                 switch(c)
                {
+               case 'E':
+                       if (regcomp(&fd->regex, optarg, REG_EXTENDED|REG_NOSUB))
+                               error(FATAL, "invalid regular expression!\n");
+                       fd->flags |= FOREACH_E_FLAG;
+                       break;
                case 'R':
                        fd->reference = optarg;
                        break;
@@ -5021,6 +5026,9 @@ cmd_foreach(void)
                        switch (str_to_context(args[optind], &value, &tc))
                        {
                        case STR_PID:
+                                if (fd->flags & FOREACH_E_FLAG)
+                                        error(FATAL, "'-E regex' and 'pid' "
+                                            "are mutually exclusive!\n");
                                 if (p == MAX_FOREACH_PIDS)
                                         error(INFO,
                                             "too many pids specified!\n");
@@ -5033,6 +5041,9 @@ cmd_foreach(void)
                                break;
 
                        case STR_TASK:
+                                if (fd->flags & FOREACH_E_FLAG)
+                                        error(FATAL, "'-E regex' and 'taskp' "
+                                            "are mutually exclusive!\n");
                                 if (t == MAX_FOREACH_TASKS)
                                         error(INFO,
                                             "too many tasks specified!\n");
@@ -5053,6 +5064,9 @@ cmd_foreach(void)
                 *  Select all kernel threads.
                 */
                if (STREQ(args[optind], "kernel")) {
+                        if (fd->flags & FOREACH_E_FLAG)
+                                error(FATAL, "'-E regex' and 'kernel' "
+                                   "are mutually exclusive!\n");
                        if (fd->flags & FOREACH_USER)
                                error(FATAL, 
                                   "user and kernel are mutually exclusive!\n");
@@ -5065,6 +5079,9 @@ cmd_foreach(void)
                 *  Select only user threads.
                 */
                 if (STREQ(args[optind], "user")) {
+                        if (fd->flags & FOREACH_E_FLAG)
+                                error(FATAL, "'-E regex' and 'user' "
+                                   "are mutually exclusive!\n");
                         if (fd->flags & FOREACH_KERNEL)
                                 error(FATAL, 
                                    "user and kernel are mutually 
exclusive!\n");
@@ -5077,6 +5094,9 @@ cmd_foreach(void)
                 *  Select only active tasks (dumpfile only)
                 */
                 if (STREQ(args[optind], "active")) {
+                        if (fd->flags & FOREACH_E_FLAG)
+                                error(FATAL, "'-E regex' and 'active' "
+                                   "are mutually exclusive!\n");
                        if (!DUMPFILE())
                                error(FATAL, 
                                 "active option not allowed on live systems\n");
@@ -5092,6 +5112,9 @@ cmd_foreach(void)
                        &args[optind][1] : args[optind];
 
                if (comm_exists(p1)) {
+                        if (fd->flags & FOREACH_E_FLAG)
+                                error(FATAL, "'-E regex' and 'name' "
+                                   "are mutually exclusive!\n");
                        if (c == MAX_FOREACH_COMMS)
                                error(INFO, "too many commands specified!\n");
                        else {
@@ -5335,6 +5358,10 @@ foreach(struct foreach_data *fd)
                                if (STREQ(fd->comm_array[j], tc->comm))
                                        doit = TRUE;
                }
+               else if (fd->flags & FOREACH_E_FLAG) {
+                       if (regexec(&fd->regex, tc->comm, 0, NULL, 0) == 0)
+                               doit = TRUE;
+               }
                else 
                        doit = TRUE;
 
--
Crash-utility mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/crash-utility

Reply via email to