fixes
[staptrace.git] / src / staptrace.c
index 2f6f328..5dd7485 100644 (file)
@@ -5,6 +5,7 @@
 #include <libintl.h>
 #include <stdio.h>
 #include <string.h>
+#include <signal.h>
 
 #ifndef STAP_SCRIPT_FILENAME
 #error "STAP_SCRIPT_FILENAME is required"
@@ -51,8 +52,8 @@ dump_args (char **args)
   for (argp = args; *argp; argp++)
     {
       if (argp > args)
-       fputs (", ", stderr);
-      fprintf (stderr, "'%s'", *argp);
+       fputc (' ', stderr);
+      fputs (*argp, stderr);
     }
   fputc ('\n', stderr);
 }
@@ -62,9 +63,9 @@ main (int argc, char **argv)
 {
   char **args, **argp;
 
-  args = xmalloc (sizeof (*args) * argc * 2);
+  args = xmalloc (sizeof (*args) * argc * 2 + 32);
   argp = args;
-  *argp++ = argv[0];
+  *argp++ = "stap";
 
   for (;;)
     {
@@ -114,39 +115,40 @@ main (int argc, char **argv)
 
   if (optind < argc)
     {
-      size_t len;
+      pid_t child;
       int i;
-      char *d;
-      const char *s;
+      static char kill_s[64];
+      static char opt_s[64];
 
-      *argp++ = "-c";
-
-      len = 32;
-      for (i = optind; i < argc; i++)
-       len += 3 + strlen (argv[i]) * 4;
-
-      d = *argp++ = xmalloc (len);
-      d = stpcpy (d, "(exec");
-      for (i = optind; i < argc; i++)
+      child = fork ();
+      switch (child)
        {
-         *d++ = ' ';
-         *d++ = '\'';
-         for (s = argv[optind]; *s; s++)
-           switch (*s)
-             {
-             case '\'':
-               d = stpcpy (d, "'\\''");
-               break;
-             case '\\':
-               *d++ = '\\';
-               /* FALLTHRU */
-             default:
-               *d++ = *s;
-             }
-         *d++ = '\'';
+       case -1:
+         error (EXIT_FAILURE, errno, _("Error calling fork"));
+       case 0:
+         i = raise (SIGSTOP);
+         if (i != 0)
+           error (EXIT_FAILURE, errno, _("Error calling raise (SIGSTOP)"));
+
+         execvp (argv[optind], &argv[optind]);
+         error (EXIT_FAILURE, errno, "Error executing child command");
+       default:
+         break;
        }
-      *d++ = ')';
-      *d++ = 0;
+
+      /* FIXME: Call `kill -CONT' from the systamtap script.  How?  */
+      i = sprintf (kill_s, "kill -CONT %lu; "
+                          "while [ -e /proc/%lu/root ]; do sleep 0.1; done",
+                  (unsigned long) child, (unsigned long) child);
+      if (i <= 0)
+         error (EXIT_FAILURE, errno, _("Error calling sprintf"));
+      *argp++ = "-c";
+      *argp++ = kill_s;
+      i = sprintf (opt_s, "opt_child=%lu", (unsigned long) child);
+      if (i <= 0)
+         error (EXIT_FAILURE, errno, _("Error calling sprintf"));
+      *argp++ = "-G";
+      *argp++ = opt_s;
     }
   *argp++ = opt_Z;
   *argp = NULL;