]> granicus.if.org Git - strace/commitdiff
Allow -p PID to take comma or whitespace-separated list of PIDs
authorDenys Vlasenko <vda.linux@googlemail.com>
Fri, 9 Mar 2012 12:01:04 +0000 (13:01 +0100)
committerDenys Vlasenko <vda.linux@googlemail.com>
Fri, 9 Mar 2012 12:01:04 +0000 (13:01 +0100)
* defs.h: Clarify meaning of TCB_ATTACHED. No code changes.
* strace.c (process_opt_p_list): New function.
(main): Call process_opt_p_list to process -p PIDs argument.

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
defs.h
strace.c

diff --git a/defs.h b/defs.h
index 1f0b7b519f49ab2cabec469787107061786ded51..a14950b3612c0dca35de5a3b149551f623d4e330 100644 (file)
--- a/defs.h
+++ b/defs.h
@@ -352,7 +352,14 @@ struct tcb {
  * Use entering(tcp) / exiting(tcp) to check this bit to make code more readable.
  */
 #define TCB_INSYSCALL  00010
-#define TCB_ATTACHED   00020   /* Process is not our own child */
+/*
+ * Process is not our own child.
+ * In "strace [-f] PROG" case, traced child (PROG) will have this bit not set,
+ * but any its children (including threads) will.
+ * Note: if bit is set, it does *not* mean that attaching was already done.
+ * There is a small window at the init time when it's not true.
+ */
+#define TCB_ATTACHED   00020
 #define TCB_BPTSET     00100   /* "Breakpoint" set after fork(2) */
 #define TCB_REPRINT    01000   /* We should reprint this syscall on exit */
 #define TCB_FILTERED   02000   /* This system call has been filtered out */
index d774611cb4c1081939c714e91875a29928732e70..5e2f9c6c27a6494b1b4edf116e0b0e20a577cf4d 100644 (file)
--- a/strace.c
+++ b/strace.c
@@ -420,6 +420,45 @@ newoutf(struct tcb *tcp)
        }
 }
 
+static void process_opt_p_list(char *opt)
+{
+       while (*opt) {
+               /*
+                * We accept -p PID,PID; -p "`pidof PROG`"; -p "`pgrep PROG`".
+                * pidof uses space as delim, pgrep uses newline. :(
+                */
+               int pid;
+               struct tcb *tcp;
+               char *delim = opt + strcspn(opt, ", \n\t");
+               char c = *delim;
+
+               *delim = '\0';
+               pid = atoi(opt); /* TODO: stricter parsing of the number? */
+               if (pid <= 0) {
+                       error_msg("Invalid process id: '%s'", opt);
+                       *delim = c;
+                       return;
+               }
+               if (pid == strace_tracer_pid) {
+                       error_msg("I'm sorry, I can't let you do that, Dave.");
+                       *delim = c;
+                       return;
+               }
+               *delim = c;
+               tcp = alloc_tcb(pid, 0);
+               tcp->flags |= TCB_ATTACHED;
+               /*
+                * pflag_seen says how many PIDs we handled,
+                * not how many -p opts there were.
+                * Used to decide whether to print pid prefix in logs.
+                */
+               pflag_seen++;
+               if (c == '\0')
+                       break;
+               opt = delim + 1;
+       }
+}
+
 static void
 startup_attach(void)
 {
@@ -1019,7 +1058,7 @@ int
 main(int argc, char *argv[])
 {
        struct tcb *tcp;
-       int c, pid = 0;
+       int c;
        int optF = 0;
        struct sigaction sa;
 
@@ -1126,18 +1165,7 @@ main(int argc, char *argv[])
                        set_overhead(atoi(optarg));
                        break;
                case 'p':
-                       pid = atoi(optarg);
-                       if (pid <= 0) {
-                               error_msg("Invalid process id: '%s'", optarg);
-                               break;
-                       }
-                       if (pid == strace_tracer_pid) {
-                               error_msg("I'm sorry, I can't let you do that, Dave.");
-                               break;
-                       }
-                       tcp = alloc_tcb(pid, 0);
-                       tcp->flags |= TCB_ATTACHED;
-                       pflag_seen++;
+                       process_opt_p_list(optarg);
                        break;
                case 'P':
                        tracing_paths = 1;