make LTTV support the facility.xml in eventdefs : multiple facilities found by checksum
[lttv.git] / ltt / branches / poly / lttctl / lttctl.c
CommitLineData
2cdb6fcb 1/* lttctl
2 *
3 * Linux Trace Toolkit Control
4 *
5 * Small program that controls LTT through libltt.
6 *
7 * Copyright 2005 -
8 * Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
9 */
10
4e4d11b3 11#ifdef HAVE_CONFIG_H
12#include <config.h>
13#endif
14
5adba60f 15#include <libltt/libltt.h>
16#include <errno.h>
17#include <stdio.h>
18#include <stdlib.h>
19#include <sys/types.h>
20#include <unistd.h>
21#include <signal.h>
d5fbdb60 22#include <dirent.h>
23#include <string.h>
24#include <sys/stat.h>
25
26/* Buffer for file copy : 4k seems optimal. */
27#define BUF_SIZE 4194304
2cdb6fcb 28
5adba60f 29enum trace_ctl_op {
30 CTL_OP_CREATE,
31 CTL_OP_DESTROY,
32 CTL_OP_START,
33 CTL_OP_STOP,
34 CTL_OP_DAEMON,
35 CTL_OP_NONE
36};
2cdb6fcb 37
5adba60f 38static char *trace_name = NULL;
39static char *mode_name = NULL;
988614ed 40static unsigned subbuf_size = 0;
41static unsigned n_subbufs = 0;
5adba60f 42static enum trace_mode mode = LTT_TRACE_NORMAL;
43static enum trace_ctl_op op = CTL_OP_NONE;
44static char *channel_root = NULL;
45static char *trace_root = NULL;
46
ada84671 47static int sigio_received = 0;
48
5adba60f 49void handler(int signo)
50{
51 printf("signal %d received\n", signo);
ada84671 52 sigio_received = 1;
5adba60f 53}
54
55
56/* Args :
57 *
58 */
59void show_arguments(void)
60{
61 printf("Please use the following arguments :\n");
62 printf("\n");
63 printf("-n name Name of the trace.\n");
64 printf("-c mode Create trace channels in mode normal or flight recorder.\n");
65 printf(" Mode values : normal (default) or flight.\n");
66 printf("-r Destroy trace channels.\n");
67 printf("-s Start tracing.\n");
68 //printf(" Note : will automatically create a normal trace if "
69 // "none exists.\n");
70 printf("-q Stop tracing.\n");
71 printf("-d Create trace, spawn a lttd daemon, start tracing.\n");
d5fbdb60 72 printf(" (optionnaly, you can set LTT_DAEMON\n");
73 printf(" and the LTT_FACILITIES env. vars.)\n");
5adba60f 74 printf("-t Trace root path. (ex. /root/traces/example_trace)\n");
75 printf("-l LTT channels root path. (ex. /mnt/relayfs/ltt)\n");
4085af66 76 printf("-z Size of the subbuffers (will be rounded to next page size)\n");
988614ed 77 printf("-x Number of subbuffers\n");
5adba60f 78 printf("\n");
79}
80
81
82/* parse_arguments
83 *
84 * Parses the command line arguments.
85 *
86 * Returns 1 if the arguments were correct, but doesn't ask for program
87 * continuation. Returns -1 if the arguments are incorrect, or 0 if OK.
88 */
89int parse_arguments(int argc, char **argv)
90{
91 int ret = 0;
92 int argn = 1;
93
94 if(argc == 2) {
95 if(strcmp(argv[1], "-h") == 0) {
96 return 1;
97 }
98 }
99
100 while(argn < argc) {
101
102 switch(argv[argn][0]) {
103 case '-':
104 switch(argv[argn][1]) {
105 case 'n':
106 if(argn+1 < argc) {
107 trace_name = argv[argn+1];
108 argn++;
109 } else {
110 printf("Specify a trace name after -n.\n", argv[argn]);
111 printf("\n");
112 ret = -1;
113 }
114
115 break;
116 case 'c':
117 op = CTL_OP_CREATE;
118 if(argn+1 < argc) {
119 mode_name = argv[argn+1];
120 argn++;
121 if(strcmp(mode_name, "normal") == 0)
122 mode = LTT_TRACE_NORMAL;
123 else if(strcmp(mode_name, "flight") == 0)
124 mode = LTT_TRACE_FLIGHT;
125 else {
126 printf("Invalid mode '%s'.\n", argv[argn]);
127 printf("\n");
128 ret = -1;
129 }
130 } else {
988614ed 131 printf("Specify a mode after -c.\n");
5adba60f 132 printf("\n");
133 ret = -1;
134 }
135 break;
136 case 'r':
137 op = CTL_OP_DESTROY;
138 break;
139 case 's':
140 op = CTL_OP_START;
141 break;
142 case 'q':
143 op = CTL_OP_STOP;
144 break;
988614ed 145 case 'z':
146 if(argn+1 < argc) {
147 subbuf_size = (unsigned)atoi(argv[argn+1]);
148 argn++;
149 } else {
150 printf("Specify a number of subbuffers after -z.\n");
151 printf("\n");
152 ret = -1;
153 }
154 break;
155 case 'x':
156 if(argn+1 < argc) {
157 n_subbufs = (unsigned)atoi(argv[argn+1]);
158 argn++;
159 } else {
160 printf("Specify a subbuffer size after -x.\n");
161 printf("\n");
162 ret = -1;
163 }
164 break;
5adba60f 165 case 'd':
166 op = CTL_OP_DAEMON;
167 break;
168 case 't':
169 if(argn+1 < argc) {
170 trace_root = argv[argn+1];
171 argn++;
172 } else {
988614ed 173 printf("Specify a trace root path after -t.\n");
5adba60f 174 printf("\n");
175 ret = -1;
176 }
177 break;
178 case 'l':
179 if(argn+1 < argc) {
180 channel_root = argv[argn+1];
181 argn++;
182 } else {
988614ed 183 printf("Specify a channel root path after -l.\n");
5adba60f 184 printf("\n");
185 ret = -1;
186 }
187 break;
188 default:
189 printf("Invalid argument '%s'.\n", argv[argn]);
190 printf("\n");
191 ret = -1;
192 }
193 break;
194 default:
195 printf("Invalid argument '%s'.\n", argv[argn]);
196 printf("\n");
197 ret = -1;
198 }
199 argn++;
200 }
201
202 if(trace_name == NULL) {
203 printf("Please specify a trace name.\n");
204 printf("\n");
205 ret = -1;
206 }
207
208 if(op == CTL_OP_NONE) {
209 printf("Please specify an operation.\n");
210 printf("\n");
211 ret = -1;
212 }
213
214 if(op == CTL_OP_DAEMON) {
215 if(trace_root == NULL) {
216 printf("Please specify -t trace_root_path with the -d option.\n");
217 printf("\n");
218 ret = -1;
219 }
220 if(channel_root == NULL) {
221 printf("Please specify -l ltt_root_path with the -d option.\n");
222 printf("\n");
223 ret = -1;
224 }
225 }
226
227 return ret;
228}
229
230void show_info(void)
231{
232 printf("Linux Trace Toolkit Trace Control\n");
233 printf("\n");
234 printf("Controlling trace : %s\n", trace_name);
235 printf("\n");
236}
237
238int lttctl_daemon(struct lttctl_handle *handle, char *trace_name)
239{
240 char channel_path[PATH_MAX] = "";
241 pid_t pid;
242 int ret;
243 char *lttd_path = getenv("LTT_DAEMON");
d5fbdb60 244 char *facilities_path = getenv("LTT_FACILITIES");
5adba60f 245 struct sigaction act;
d5fbdb60 246 char eventdefs_path[PATH_MAX];
247 char eventdefs_file[PATH_MAX];
248 char facilities_file[PATH_MAX];
249 char read_buf[BUF_SIZE];
250 struct dirent *entry;
5adba60f 251
252 if(lttd_path == NULL) lttd_path = "lttd";
d5fbdb60 253 if(facilities_path == NULL) facilities_path =
254 "/usr/share/LinuxTraceToolkitViewer/facilities";
5adba60f 255
256 strcat(channel_path, channel_root);
257 strcat(channel_path, "/");
258 strcat(channel_path, trace_name);
259
260
988614ed 261 ret = lttctl_create_trace(handle, trace_name, mode, subbuf_size, n_subbufs);
5adba60f 262 if(ret != 0) goto create_error;
263
264 act.sa_handler = handler;
265 sigemptyset(&(act.sa_mask));
266 sigaddset(&(act.sa_mask), SIGIO);
267 sigaction(SIGIO, &act, NULL);
268
ada84671 269 sigio_received = 0;
270
5adba60f 271 pid = fork();
272
273 if(pid > 0) {
5adba60f 274 /* parent */
ada84671 275 while(!sigio_received) pause();
5adba60f 276
277 /* Now the trace is created, go on and create the supplementary files... */
d5fbdb60 278
5adba60f 279 printf("Creating supplementary trace files\n");
d5fbdb60 280 size_t trace_root_len = strlen(trace_root);
281 strncpy(eventdefs_path, trace_root, PATH_MAX);
282 strncat(eventdefs_path, "/eventdefs/", PATH_MAX - trace_root_len);
283 size_t eventdefs_path_len = strlen(eventdefs_path);
284 ret = mkdir(eventdefs_path, S_IRWXU|S_IRWXG|S_IRWXO);
285 if(ret) {
286 perror("Cannot create eventdefs directory");
287 goto start_error;
288 }
289
290
291 DIR *facilities_dir = opendir(facilities_path);
292
293 while((entry = readdir(facilities_dir)) != NULL) {
294 if(entry->d_name[0] == '.') continue;
295
296 printf("Appending facility file %s\n", entry->d_name);
297 strncpy(eventdefs_file, eventdefs_path, PATH_MAX);
298 strncat(eventdefs_file, entry->d_name, PATH_MAX - eventdefs_path_len);
299 /* Append to the file */
300 FILE *dest = fopen(eventdefs_file, "a");
301 if(!dest) {
302 perror("Cannot create eventdefs file");
303 continue;
304 }
305 strncpy(facilities_file, facilities_path, PATH_MAX);
306 size_t facilities_dir_len = strlen(facilities_path);
307 strncat(facilities_file, "/", PATH_MAX - facilities_dir_len);
308 strncat(facilities_file, entry->d_name, PATH_MAX - facilities_dir_len-1);
309 FILE *src = fopen(facilities_file, "r");
310 if(!src) {
311 perror("Cannot open eventdefs file for reading");
312 goto close_dest;
313 }
314
315 do {
316 size_t read_size, write_size;
317 read_size = fread(read_buf, sizeof(char), BUF_SIZE, src);
318 if(ferror(src)) {
319 perror("Cannot read eventdefs file");
320 goto close_src;
321 }
322 write_size = fwrite(read_buf, sizeof(char), read_size, dest);
323 if(ferror(dest)) {
324 perror("Cannot write eventdefs file");
325 goto close_src;
326 }
327 } while(!feof(src));
328
329 /* Add spacing between facilities */
330 fwrite("\n", 1, 1, dest);
331
332close_src:
333 fclose(src);
334close_dest:
335 fclose(dest);
336 }
337
338 closedir(facilities_dir);
5adba60f 339
340 } else if(pid == 0) {
341 /* child */
342 int ret =
343 execlp(lttd_path, lttd_path, "-t", trace_root, "-c", channel_path, "-s", NULL);
344 if(ret) {
345 perror("Error in executing the lttd daemon");
346 exit(-1);
347 }
348 } else {
349 /* error */
350 perror("Error in forking for lttd daemon");
351
352 }
353
354 ret = lttctl_start(handle, trace_name);
355 if(ret != 0) goto start_error;
356
357 return 0;
358
359 /* error handling */
360start_error:
361 ret |= lttctl_destroy_trace(handle, trace_name);
362create_error:
363 return ret;
364}
365
366int main(int argc, char ** argv)
367{
368 int ret;
369 struct lttctl_handle *handle;
370
371 ret = parse_arguments(argc, argv);
372
373 if(ret != 0) show_arguments();
374 if(ret < 0) return EINVAL;
375 if(ret > 0) return 0;
376
377 show_info();
378
379 handle = lttctl_create_handle();
380
381 if(handle == NULL) return -1;
382
383 switch(op) {
384 case CTL_OP_CREATE:
988614ed 385 ret = lttctl_create_trace(handle, trace_name, mode, subbuf_size,
386 n_subbufs);
5adba60f 387 case CTL_OP_DESTROY:
388 ret = lttctl_destroy_trace(handle, trace_name);
389 break;
390 case CTL_OP_START:
391 ret = lttctl_start(handle, trace_name);
392 break;
393 case CTL_OP_STOP:
394 ret = lttctl_stop(handle, trace_name);
395 break;
396 case CTL_OP_DAEMON:
397 ret = lttctl_daemon(handle, trace_name);
398 break;
399 case CTL_OP_NONE:
400 break;
401 }
402
403 ret |= lttctl_destroy_handle(handle);
404
405 return ret;
406}
This page took 0.039349 seconds and 4 git commands to generate.