Update licensing: lgplv2.1 for libs, gplv2 for programs
[ltt-control.git] / lttctl / lttctl.c
CommitLineData
2727692a 1/* lttctl
2 *
3 * Linux Trace Toolkit Control
4 *
ed2849af 5 * Small program that controls LTTng through liblttctl.
b1f29379 6 *
7 * Copyright 2008 FUJITSU
8 * Zhao Lei <zhaolei@cn.fujitsu.com>
9 * Gui Jianfeng <guijianfeng@cn.fujitsu.com>
ed2849af
MD
10 * Copyright 2009-2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along
23 * with this program; if not, write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
2727692a 25 */
26
27#ifdef HAVE_CONFIG_H
28#include <config.h>
29#endif
30
31#include <liblttctl/lttctl.h>
32#include <errno.h>
33#include <stdio.h>
34#include <stdlib.h>
2727692a 35#include <sys/wait.h>
36#include <unistd.h>
2727692a 37#include <string.h>
a9c10be2 38#include <limits.h>
c928825d 39#define _GNU_SOURCE
40#include <getopt.h>
41
42#define OPT_MAX (1024)
43#define OPT_NAMELEN (256)
44#define OPT_VALSTRINGLEN (256)
45
b1f29379 46enum opt_type {
47 CHANNEL,
48};
49
50struct channel_option {
51 char chan_name[OPT_NAMELEN];
52 int enable;
53 int overwrite;
54 int bufnum;
55 int bufsize;
8d5607b4 56 int switch_timer;
2727692a 57};
58
c928825d 59struct lttctl_option {
c928825d 60 union {
b1f29379 61 struct channel_option chan_opt;
62 } opt_mode;
63 enum opt_type type;
64 struct lttctl_option *next;
c928825d 65};
66
b1f29379 67struct lttctl_option *opt_head, *last_opt;
68
c928825d 69static int opt_create;
70static int opt_destroy;
71static int opt_start;
72static int opt_pause;
73static int opt_help;
74static const char *opt_transport;
c928825d 75static const char *opt_write;
76static int opt_append;
77static unsigned int opt_dump_threads;
a9c10be2 78static char channel_root_default[PATH_MAX];
c928825d 79static const char *opt_channel_root;
80static const char *opt_tracename;
2727692a 81
2727692a 82/* Args :
83 *
84 */
c928825d 85static void show_arguments(void)
2727692a 86{
c928825d 87 printf("Linux Trace Toolkit Trace Control " VERSION"\n");
88 printf("\n");
89 printf("Usage: lttctl [OPTION]... [TRACENAME]\n");
90 printf("\n");
91 printf("Examples:\n");
92 printf(" lttctl -c trace1 "
93 "# Create a trace named trace1.\n");
94 printf(" lttctl -s trace1 "
95 "# start a trace named trace1.\n");
96 printf(" lttctl -p trace1 "
97 "# pause a trace named trace1.\n");
98 printf(" lttctl -d trace1 "
99 "# Destroy a trace named trace1.\n");
100 printf(" lttctl -C -w /tmp/trace1 trace1 "
101 "# Create a trace named trace1, start it and\n"
102 " "
103 "# write non-overwrite channels' data to\n"
104 " "
105 "# /tmp/trace1, debugfs must be mounted for\n"
106 " "
107 "# auto-find\n");
108 printf(" lttctl -D -w /tmp/trace1 trace1 "
109 "# Pause and destroy a trace named trace1 and\n"
110 " "
111 "# write overwrite channels' data to\n"
112 " "
113 "# /tmp/trace1, debugfs must be mounted for\n"
114 " "
115 "# auto-find\n");
116 printf("\n");
117 printf(" Basic options:\n");
118 printf(" -c, --create\n");
119 printf(" Create a trace.\n");
120 printf(" -d, --destroy\n");
121 printf(" Destroy a trace.\n");
122 printf(" -s, --start\n");
123 printf(" Start a trace.\n");
124 printf(" -p, --pause\n");
125 printf(" Pause a trace.\n");
126 printf(" -h, --help\n");
127 printf(" Show this help.\n");
2727692a 128 printf("\n");
c928825d 129 printf(" Advanced options:\n");
130 printf(" --transport TRANSPORT\n");
07d97665 131 printf(" Set trace's transport. (ex. relay-locked or relay)\n");
c928825d 132 printf(" -o, --option OPTION\n");
133 printf(" Set options, following operations are supported:\n");
134 printf(" channel.<channelname>.enable=\n");
135 printf(" channel.<channelname>.overwrite=\n");
136 printf(" channel.<channelname>.bufnum=\n");
c68a7692 137 printf(" channel.<channelname>.bufsize= (in bytes, rounded to "
138 "next power of 2)\n");
c928825d 139 printf(" <channelname> can be set to all for all channels\n");
8d5607b4
MD
140 printf(" channel.<channelname>.switch_timer= (timer interval in "
141 "ms)\n");
c928825d 142 printf("\n");
143 printf(" Integration options:\n");
144 printf(" -C, --create_start\n");
145 printf(" Create and start a trace.\n");
146 printf(" -D, --pause_destroy\n");
147 printf(" Pause and destroy a trace.\n");
148 printf(" -w, --write PATH\n");
149 printf(" Path for write trace datas.\n");
150 printf(" For -c, -C, -d, -D options\n");
151 printf(" -a, --append\n");
152 printf(" Append to trace, For -w option\n");
153 printf(" -n, --dump_threads NUMBER\n");
154 printf(" Number of lttd threads, For -w option\n");
155 printf(" --channel_root PATH\n");
156 printf(" Set channels root path, For -w option."
157 " (ex. /mnt/debugfs/ltt)\n");
2727692a 158 printf("\n");
159}
160
c928825d 161/*
162 * Separate option name to 3 fields
163 * Ex:
164 * Input: name = channel.cpu.bufsize
165 * Output: name1 = channel
166 * name2 = cpu
167 * name3 = bufsize
168 * Ret: 0 on success
169 * 1 on fail
170 *
171 * Note:
172 * Make sure that name1~3 longer than OPT_NAMELEN.
173 * name1~3 can be NULL to discard value
174 *
175 */
176static int separate_opt(const char *name, char *name1, char *name2, char *name3)
177{
178 char *p;
179
180 if (!name)
181 return 1;
182
183 /* segment1 */
184 p = strchr(name, '.');
185 if (!p)
186 return 1;
187 if (p - name >= OPT_NAMELEN)
188 return 1;
189 if (name1) {
190 memcpy(name1, name, p - name);
191 name1[p - name] = 0;
192 }
193 name = p + 1;
194
195 /* segment2 */
196 p = strchr(name, '.');
197 if (!p)
198 return 1;
199 if (p - name >= OPT_NAMELEN)
200 return 1;
201 if (name2) {
202 memcpy(name2, name, p - name);
203 name2[p - name] = 0;
204 }
205 name = p + 1;
206
207 /* segment3 */
208 if (strlen(name) >= OPT_NAMELEN)
209 return 1;
210 if (name3)
211 strcpy(name3, name);
212
213 return 0;
214}
215
b1f29379 216static void init_channel_opt(struct channel_option *opt, char *opt_name)
c928825d 217{
b1f29379 218 if (opt && opt_name) {
219 opt->enable = -1;
220 opt->overwrite = -1;
221 opt->bufnum = -1;
222 opt->bufsize = -1;
8d5607b4 223 opt->switch_timer = -1;
b1f29379 224 strcpy(opt->chan_name, opt_name);
c928825d 225 }
c928825d 226}
227
b1f29379 228static struct lttctl_option *find_insert_channel_opt(char *opt_name)
c928825d 229{
b1f29379 230 struct lttctl_option *iter, *new_opt;
231
232 if (!opt_head) {
233 opt_head = (struct lttctl_option *)malloc(sizeof(struct lttctl_option));
234 init_channel_opt(&opt_head->opt_mode.chan_opt, opt_name);
235 opt_head->type = CHANNEL;
236 opt_head->next = NULL;
237 last_opt = opt_head;
238 return opt_head;
239 }
c928825d 240
b1f29379 241 for (iter = opt_head; iter; iter = iter->next) {
242 if (iter->type != CHANNEL)
243 continue;
244 if (!strcmp(iter->opt_mode.chan_opt.chan_name, opt_name))
245 return iter;
c928825d 246 }
247
b1f29379 248 new_opt = (struct lttctl_option *)malloc(sizeof(struct lttctl_option));
249 init_channel_opt(&new_opt->opt_mode.chan_opt, opt_name);
250 new_opt->type = CHANNEL;
251 new_opt->next = NULL;
252 last_opt->next = new_opt;
253 last_opt = new_opt;
254 return new_opt;
c928825d 255}
256
b1f29379 257int set_channel_opt(struct channel_option *opt, char *opt_name, char *opt_valstr)
c928825d 258{
b1f29379 259 int opt_val, ret;
c928825d 260
b1f29379 261 if (!strcmp("enable", opt_name)) {
262 if (opt_valstr[1] != 0) {
263 return -EINVAL;
264 }
265 if (opt_valstr[0] == 'Y' || opt_valstr[0] == 'y'
266 || opt_valstr[0] == '1')
267 opt_val = 1;
268 else if (opt_valstr[0] == 'N' || opt_valstr[0] == 'n'
269 || opt_valstr[0] == '0')
270 opt_val = 0;
271 else {
272 return -EINVAL;
273 }
c928825d 274
b1f29379 275 opt->enable = opt_val;
276 return 0;
277 } else if (!strcmp("overwrite", opt_name)) {
278 if (opt_valstr[1] != 0) {
279 return -EINVAL;
280 }
281 if (opt_valstr[0] == 'Y' || opt_valstr[0] == 'y'
282 || opt_valstr[0] == '1')
283 opt_val = 1;
284 else if (opt_valstr[0] == 'N' || opt_valstr[0] == 'n'
285 || opt_valstr[0] == '0')
286 opt_val = 0;
287 else {
288 return -EINVAL;
289 }
c928825d 290
b1f29379 291 opt->overwrite = opt_val;
292 return 0;
c928825d 293
b1f29379 294 } else if (!strcmp("bufnum", opt_name)) {
295 ret = sscanf(opt_valstr, "%d", &opt_val);
296 if (ret != 1 || opt_val < 0) {
297 return -EINVAL;
298 }
299
300 opt->bufnum = opt_val;
301 return 0;
302 } else if (!strcmp("bufsize", opt_name)) {
303 ret = sscanf(opt_valstr, "%d", &opt_val);
304 if (ret != 1 || opt_val < 0) {
305 return -EINVAL;
306 }
307
308 opt->bufsize = opt_val;
309 return 0;
8d5607b4
MD
310 } else if (!strcmp("switch_timer", opt_name)) {
311 ret = sscanf(opt_valstr, "%d", &opt_val);
312 if (ret != 1 || opt_val < 0) {
313 return -EINVAL;
314 }
315
316 opt->switch_timer = opt_val;
317 return 0;
b1f29379 318 } else {
319 return -EINVAL;
c928825d 320 }
321
c928825d 322}
323
324static int parst_opt(const char *optarg)
325{
326 int ret;
327 char opt_name[OPT_NAMELEN * 3];
328 char opt_valstr[OPT_VALSTRINGLEN];
329 char *p;
330
331 char name1[OPT_NAMELEN];
332 char name2[OPT_NAMELEN];
333 char name3[OPT_NAMELEN];
334
c928825d 335 int opt_intval;
b1f29379 336 int opt_val;
c928825d 337 unsigned int opt_uintval;
b1f29379 338 struct lttctl_option *opt;
c928825d 339
340 if (!optarg) {
341 fprintf(stderr, "Option empty\n");
342 return -EINVAL;
343 }
344
345 /* Get option name and val_str */
346 p = strchr(optarg, '=');
347 if (!p) {
348 fprintf(stderr, "Option format error: %s\n", optarg);
349 return -EINVAL;
350 }
351
352 if (p - optarg >= sizeof(opt_name)/sizeof(opt_name[0])) {
353 fprintf(stderr, "Option name too long: %s\n", optarg);
354 return -EINVAL;
355 }
356
357 if (strlen(p+1) >= OPT_VALSTRINGLEN) {
358 fprintf(stderr, "Option value too long: %s\n", optarg);
359 return -EINVAL;
360 }
361
362 memcpy(opt_name, optarg, p - optarg);
363 opt_name[p - optarg] = 0;
364 strcpy(opt_valstr, p+1);
365
366 /* separate option name into 3 fields */
367 ret = separate_opt(opt_name, name1, name2, name3);
368 if (ret != 0) {
b1f29379 369 fprintf(stderr, "Option name error1: %s\n", optarg);
c928825d 370 return -EINVAL;
371 }
b1f29379 372
373 if (!strcmp("channel", name1)) {
374 opt = find_insert_channel_opt(name2);
375 if ((ret = set_channel_opt(&opt->opt_mode.chan_opt,
376 name3, opt_valstr) != 0)) {
377 fprintf(stderr, "Option name error2: %s\n", optarg);
378 return ret;
c928825d 379 }
b1f29379 380 } else {
381 fprintf(stderr, "Option name error3: %s\n", optarg);
c928825d 382 return -EINVAL;
383 }
b1f29379 384
385 return 0;
c928825d 386}
387
2727692a 388/* parse_arguments
389 *
390 * Parses the command line arguments.
391 *
392 * Returns -1 if the arguments were correct, but doesn't ask for program
393 * continuation. Returns EINVAL if the arguments are incorrect, or 0 if OK.
394 */
c928825d 395static int parse_arguments(int argc, char **argv)
2727692a 396{
397 int ret = 0;
b1f29379 398
c928825d 399 static struct option longopts[] = {
400 {"create", no_argument, NULL, 'c'},
401 {"destroy", no_argument, NULL, 'd'},
402 {"start", no_argument, NULL, 's'},
403 {"pause", no_argument, NULL, 'p'},
404 {"help", no_argument, NULL, 'h'},
405 {"transport", required_argument, NULL, 2},
406 {"option", required_argument, NULL, 'o'},
407 {"create_start", no_argument, NULL, 'C'},
408 {"pause_destroy", no_argument, NULL, 'D'},
409 {"write", required_argument, NULL, 'w'},
410 {"append", no_argument, NULL, 'a'},
411 {"dump_threads", required_argument, NULL, 'n'},
412 {"channel_root", required_argument, NULL, 3},
413 { NULL, 0, NULL, 0 },
414 };
415
416 /*
417 * Enable all channels in default
418 * To make novice users happy
419 */
420 parst_opt("channel.all.enable=1");
421
422 opterr = 1; /* Print error message on getopt_long */
423 while (1) {
424 int c;
425 c = getopt_long(argc, argv, "cdspho:CDw:an:", longopts, NULL);
426 if (-1 == c) {
427 /* parse end */
428 break;
2727692a 429 }
c928825d 430 switch (c) {
431 case 'c':
432 opt_create = 1;
433 break;
434 case 'd':
435 opt_destroy = 1;
436 break;
437 case 's':
438 opt_start = 1;
439 break;
440 case 'p':
441 opt_pause = 1;
442 break;
443 case 'h':
444 opt_help = 1;
445 break;
446 case 2:
447 if (!opt_transport) {
448 opt_transport = optarg;
449 } else {
450 fprintf(stderr,
451 "Please specify only 1 transport\n");
452 return -EINVAL;
453 }
454 break;
455 case 'o':
456 ret = parst_opt(optarg);
457 if (ret)
458 return ret;
459 break;
460 case 'C':
461 opt_create = 1;
462 opt_start = 1;
463 break;
464 case 'D':
465 opt_pause = 1;
466 opt_destroy = 1;
467 break;
468 case 'w':
469 if (!opt_write) {
470 opt_write = optarg;
471 } else {
472 fprintf(stderr,
473 "Please specify only 1 write dir\n");
474 return -EINVAL;
475 }
476 break;
477 case 'a':
478 opt_append = 1;
479 break;
480 case 'n':
481 if (opt_dump_threads) {
482 fprintf(stderr,
483 "Please specify only 1 dump threads\n");
484 return -EINVAL;
485 }
486
487 ret = sscanf(optarg, "%u", &opt_dump_threads);
488 if (ret != 1) {
489 fprintf(stderr,
490 "Dump threads not positive number\n");
491 return -EINVAL;
492 }
493 break;
494 case 3:
495 if (!opt_channel_root) {
496 opt_channel_root = optarg;
497 } else {
498 fprintf(stderr,
499 "Please specify only 1 channel root\n");
500 return -EINVAL;
501 }
502 break;
503 case '?':
504 return -EINVAL;
505 default:
506 break;
507 };
508 };
509
510 /* Don't check args when user needs help */
511 if (opt_help)
512 return 0;
513
514 /* Get tracename */
515 if (optind < argc - 1) {
516 fprintf(stderr, "Please specify only 1 trace name\n");
517 return -EINVAL;
518 }
519 if (optind > argc - 1) {
520 fprintf(stderr, "Please specify trace name\n");
521 return -EINVAL;
522 }
523 opt_tracename = argv[optind];
524
525 /*
526 * Check arguments
527 */
528 if (!opt_create && !opt_start && !opt_destroy && !opt_pause) {
529 fprintf(stderr,
530 "Please specify a option of "
531 "create, destroy, start, or pause\n");
532 return -EINVAL;
2727692a 533 }
534
c928825d 535 if ((opt_create || opt_start) && (opt_destroy || opt_pause)) {
536 fprintf(stderr,
537 "Create and start conflict with destroy and pause\n");
538 return -EINVAL;
2727692a 539 }
c928825d 540
541 if (opt_create) {
542 if (!opt_transport)
543 opt_transport = "relay";
2727692a 544 }
545
c928825d 546 if (opt_transport) {
547 if (!opt_create) {
548 fprintf(stderr,
549 "Transport option must be combine with create"
550 " option\n");
551 return -EINVAL;
552 }
2727692a 553 }
554
c928825d 555 if (opt_write) {
556 if (!opt_create && !opt_destroy) {
557 fprintf(stderr,
558 "Write option must be combine with create or"
559 " destroy option\n");
560 return -EINVAL;
2727692a 561 }
c928825d 562
563 if (!opt_channel_root)
a9c10be2 564 if (getdebugfsmntdir(channel_root_default) == 0) {
565 strcat(channel_root_default, "/ltt");
c928825d 566 opt_channel_root = channel_root_default;
354b34fd 567 } else {
568 fprintf(stderr,
569 "Channel_root is necessary for -w"
570 " option, but neither --channel_root"
571 " option\n"
572 "specified, nor debugfs's mount dir"
573 " found, mount debugfs also failed\n");
574 return -EINVAL;
a9c10be2 575 }
c928825d 576
577 if (opt_dump_threads == 0)
578 opt_dump_threads = 1;
2727692a 579 }
580
c928825d 581 if (opt_append) {
582 if (!opt_write) {
583 fprintf(stderr,
584 "Append option must be combine with write"
585 " option\n");
586 return -EINVAL;
587 }
588 }
589
590 if (opt_dump_threads) {
591 if (!opt_write) {
592 fprintf(stderr,
593 "Dump_threads option must be combine with write"
594 " option\n");
595 return -EINVAL;
596 }
597 }
598
599 if (opt_channel_root) {
600 if (!opt_write) {
601 fprintf(stderr,
602 "Channel_root option must be combine with write"
603 " option\n");
604 return -EINVAL;
605 }
606 }
607
608 return 0;
2727692a 609}
b1f29379 610
c928825d 611static void show_info(void)
2727692a 612{
15061ecb 613 printf("Linux Trace Toolkit Trace Control " VERSION"\n");
2727692a 614 printf("\n");
c928825d 615 if (opt_tracename != NULL) {
616 printf("Controlling trace : %s\n", opt_tracename);
900b24a9 617 printf("\n");
618 }
2727692a 619}
620
b1f29379 621static int lttctl_channel_setup(struct channel_option *opt)
622{
623 int ret;
624
625 if (opt->enable != -1) {
626 if ((ret = lttctl_set_channel_enable(opt_tracename,
627 opt->chan_name,
628 opt->enable)) != 0)
629 return ret;
630 }
631 if (opt->overwrite != -1) {
632 if ((ret = lttctl_set_channel_overwrite(opt_tracename,
633 opt->chan_name,
634 opt->overwrite)) != 0)
635 return ret;
636 }
637 if (opt->bufnum != -1) {
638 if ((ret = lttctl_set_channel_subbuf_num(opt_tracename,
639 opt->chan_name,
640 opt->bufnum)) != 0)
641 return ret;
642 }
643 if (opt->bufsize != -1) {
644 if ((ret = lttctl_set_channel_subbuf_size(opt_tracename,
645 opt->chan_name,
646 opt->bufsize)) != 0)
647 return ret;
648 }
8d5607b4
MD
649 if (opt->switch_timer != -1) {
650 if ((ret = lttctl_set_channel_switch_timer(opt_tracename,
651 opt->chan_name, opt->switch_timer)) != 0)
652 return ret;
653 }
b1f29379 654
655 return 0;
656}
657
c928825d 658static int lttctl_create_trace(void)
2727692a 659{
2727692a 660 int ret;
c928825d 661 int i;
b1f29379 662 struct lttctl_option *opt;
c928825d 663
664 ret = lttctl_setup_trace(opt_tracename);
665 if (ret)
666 goto setup_trace_fail;
667
b1f29379 668 for (opt = opt_head; opt; opt = opt->next) {
669 if (opt->type != CHANNEL)
c928825d 670 continue;
b1f29379 671 ret = lttctl_channel_setup(&opt->opt_mode.chan_opt);
672 if (ret)
673 goto set_option_fail;;
2727692a 674 }
675
c928825d 676 ret = lttctl_set_trans(opt_tracename, opt_transport);
677 if (ret)
678 goto set_option_fail;
679
680 ret = lttctl_alloc_trace(opt_tracename);
681 if (ret)
682 goto alloc_trace_fail;
2727692a 683
684 return 0;
685
c928825d 686alloc_trace_fail:
687set_option_fail:
688 lttctl_destroy_trace(opt_tracename);
689setup_trace_fail:
2727692a 690 return ret;
691}
692
c928825d 693/*
694 * Start a lttd daemon to write trace datas
695 * Dump overwrite channels on overwrite!=0
696 * Dump normal(non-overwrite) channels on overwrite=0
697 *
698 * ret: 0 on success
699 * !0 on fail
700 */
701static int lttctl_daemon(int overwrite)
89565b43 702{
89565b43 703 pid_t pid;
c928825d 704 int status;
89565b43 705
706 pid = fork();
c928825d 707 if (pid < 0) {
708 perror("Error in forking for lttd daemon");
709 return errno;
710 }
89565b43 711
c928825d 712 if (pid == 0) {
713 /* child */
714 char *argv[16];
715 int argc = 0;
716 char channel_path[PATH_MAX];
717 char thread_num[16];
718
719 /* prog path */
720 argv[argc] = getenv("LTT_DAEMON");
721 if (argv[argc] == NULL)
722 argv[argc] = PACKAGE_BIN_DIR "/lttd";
723 argc++;
724
725 /* -t option */
726 argv[argc] = "-t";
727 argc++;
728 /*
729 * we allow modify of opt_write's content in new process
730 * for get rid of warning of assign char * to const char *
731 */
732 argv[argc] = (char *)opt_write;
733 argc++;
734
735 /* -c option */
736 strcpy(channel_path, opt_channel_root);
737 strcat(channel_path, "/");
738 strcat(channel_path, opt_tracename);
739 argv[argc] = "-c";
740 argc++;
741 argv[argc] = channel_path;
742 argc++;
743
744 /* -N option */
745 sprintf(thread_num, "%u", opt_dump_threads);
746 argv[argc] = "-N";
747 argc++;
748 argv[argc] = thread_num;
749 argc++;
750
751 /* -a option */
752 if (opt_append) {
753 argv[argc] = "-a";
754 argc++;
89565b43 755 }
756
c928825d 757 /* -d option */
758 argv[argc] = "-d";
759 argc++;
89565b43 760
c928825d 761 /* overwrite option */
762 if (overwrite) {
763 argv[argc] = "-f";
764 argc++;
765 } else {
766 argv[argc] = "-n";
767 argc++;
89565b43 768 }
89565b43 769
c928825d 770 argv[argc] = NULL;
89565b43 771
c928825d 772 execvp(argv[0], argv);
89565b43 773
c928825d 774 perror("Error in executing the lttd daemon");
775 exit(errno);
776 }
89565b43 777
c928825d 778 /* parent */
779 if (waitpid(pid, &status, 0) == -1) {
780 perror("Error in waitpid\n");
781 return errno;
782 }
89565b43 783
c928825d 784 if (!WIFEXITED(status)) {
785 fprintf(stderr, "lttd process interrupted\n");
786 return status;
787 }
788
789 if (WEXITSTATUS(status))
790 fprintf(stderr, "lttd process running failed\n");
89565b43 791
c928825d 792 return WEXITSTATUS(status);
793}
794
795int main(int argc, char **argv)
2727692a 796{
797 int ret;
c928825d 798
2727692a 799 ret = parse_arguments(argc, argv);
c928825d 800 /* If user needs show help, we disregard other options */
801 if (opt_help) {
802 show_arguments();
803 return 0;
804 }
2727692a 805
c928825d 806 /* exit program if arguments wrong */
807 if (ret)
808 return 1;
2727692a 809
810 show_info();
c928825d 811
812 ret = lttctl_init();
813 if (ret != 0)
814 return ret;
815
816 if (opt_create) {
817 printf("lttctl: Creating trace\n");
818 ret = lttctl_create_trace();
819 if (ret)
820 goto op_fail;
821
822 if (opt_write) {
823 printf("lttctl: Forking lttd\n");
824 ret = lttctl_daemon(0);
825 if (ret)
826 goto op_fail;
827 }
828 }
829
830 if (opt_start) {
831 printf("lttctl: Starting trace\n");
832 ret = lttctl_start(opt_tracename);
833 if (ret)
834 goto op_fail;
835 }
836
837 if (opt_pause) {
838 printf("lttctl: Pausing trace\n");
839 ret = lttctl_pause(opt_tracename);
840 if (ret)
841 goto op_fail;
2727692a 842 }
843
c928825d 844 if (opt_destroy) {
845 if (opt_write) {
846 printf("lttctl: Forking lttd\n");
847 ret = lttctl_daemon(1);
848 if (ret)
849 goto op_fail;
850 }
851
852 printf("lttctl: Destroying trace\n");
853 ret = lttctl_destroy_trace(opt_tracename);
854 if (ret)
855 goto op_fail;
856 }
857
858op_fail:
859 lttctl_destroy();
860
2727692a 861 return ret;
862}
This page took 0.060496 seconds and 4 git commands to generate.