5dd748559325375c0c3f4534fc1f8ef66abc55d5
[staptrace.git] / src / staptrace.c
1 #include <error.h>
2 #include <errno.h>
3 #include <stdlib.h>
4 #include <unistd.h>
5 #include <libintl.h>
6 #include <stdio.h>
7 #include <string.h>
8 #include <signal.h>
9
10 #ifndef STAP_SCRIPT_FILENAME
11 #error "STAP_SCRIPT_FILENAME is required"
12 #endif
13
14 #define STRINGIFY1(lit) #lit
15 #define STRINGIFY(lit) STRINGIFY1 (lit)
16 #define _(x) gettext (x)
17
18 static int opt_d, opt_f, opt_q, opt_p;
19
20 /* Script filename.  */
21 static char *opt_Z = STRINGIFY (STAP_SCRIPT_FILENAME);
22
23 static void *
24 xmalloc (size_t size)
25 {
26   void *retval = malloc (size);
27
28   if (retval == NULL)
29     error (EXIT_FAILURE, errno, _("memory allocation of %zu bytes"), size);
30
31   return retval;
32 }
33
34 static void
35 usage (int status)
36 {
37   printf ("\
38 usage: staptrace [-dfq] [-o file] [-p pid] [command [arg ...]]\n\
39                  [-Z <stap script>]\n\
40 \n\
41 Default -Z is: %s\n\
42 ",
43           opt_Z);
44   exit (status);
45 }
46
47 static void
48 dump_args (char **args)
49 {
50   char **argp;
51
52   for (argp = args; *argp; argp++)
53     {
54       if (argp > args)
55         fputc (' ', stderr);
56       fputs (*argp, stderr);
57     }
58   fputc ('\n', stderr);
59 }
60
61 int
62 main (int argc, char **argv)
63 {
64   char **args, **argp;
65
66   args = xmalloc (sizeof (*args) * argc * 2 + 32);
67   argp = args;
68   *argp++ = "stap";
69
70   for (;;)
71     {
72       int i;
73
74       i = getopt (argc, argv, "+dfqo:p:hZ:");
75       if (i == EOF)
76         break;
77       switch (i)
78         {
79         case 'd':
80           opt_d = 1;
81           break;
82         case 'f':
83           if (opt_f)
84             error (EXIT_FAILURE, 0, _("-ff is unsupported"));
85           *argp++ = "-G";
86           *argp++ = "opt_f=1";
87           opt_f = 1;
88           break;
89         case 'q':
90           *argp++ = "-G";
91           *argp++ = "opt_q=1";
92           opt_q = 1;
93           break;
94         case 'o':
95           *argp++ = "-o";
96           *argp++ = optarg;
97           break;
98         case 'p':
99           *argp++ = "-x";
100           *argp++ = optarg;
101           opt_p = 1;
102           break;
103         case 'Z':
104           opt_Z = optarg;
105           break;
106         case 'h':
107           usage (EXIT_SUCCESS);
108         default:
109           usage (EXIT_FAILURE);
110         }
111     }
112
113   if ((optind == argc) == !opt_p)
114     usage (EXIT_FAILURE);
115
116   if (optind < argc)
117     {
118       pid_t child;
119       int i;
120       static char kill_s[64];
121       static char opt_s[64];
122
123       child = fork ();
124       switch (child)
125         {
126         case -1:
127           error (EXIT_FAILURE, errno, _("Error calling fork"));
128         case 0:
129           i = raise (SIGSTOP);
130           if (i != 0)
131             error (EXIT_FAILURE, errno, _("Error calling raise (SIGSTOP)"));
132
133           execvp (argv[optind], &argv[optind]);
134           error (EXIT_FAILURE, errno, "Error executing child command");
135         default:
136           break;
137         }
138
139       /* FIXME: Call `kill -CONT' from the systamtap script.  How?  */
140       i = sprintf (kill_s, "kill -CONT %lu; "
141                            "while [ -e /proc/%lu/root ]; do sleep 0.1; done",
142                    (unsigned long) child, (unsigned long) child);
143       if (i <= 0)
144           error (EXIT_FAILURE, errno, _("Error calling sprintf"));
145       *argp++ = "-c";
146       *argp++ = kill_s;
147       i = sprintf (opt_s, "opt_child=%lu", (unsigned long) child);
148       if (i <= 0)
149           error (EXIT_FAILURE, errno, _("Error calling sprintf"));
150       *argp++ = "-G";
151       *argp++ = opt_s;
152     }
153   *argp++ = opt_Z;
154   *argp = NULL;
155
156   if (opt_d)
157     dump_args (args);
158   execvp ("stap", args);
159
160   if (!opt_d)
161     dump_args (args);
162   error (EXIT_FAILURE, errno, "Error executing stap");
163 }