2 * Copyright (C) 2011 EfficiOS Inc.
3 * Copyright (C) 2014 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
4 * Copyright (C) 2020 Francis Deslauriers <francis.deslauriers@efficios.com>
6 * SPDX-License-Identifier: LGPL-2.1-only
12 #include <sys/types.h>
15 #include <lttng/constant.h>
17 #include <common/compat/errno.h>
20 #include "spawn-viewer.h"
23 static const char *babeltrace_bin
= CONFIG_BABELTRACE_BIN
;
24 static const char *babeltrace2_bin
= CONFIG_BABELTRACE2_BIN
;
27 * This is needed for each viewer since we are using execvp().
29 static const char *babeltrace_opts
[] = { "babeltrace" };
30 static const char *babeltrace2_opts
[] = { "babeltrace2" };
33 * Type is also use as the index in the viewers array. So please, make sure
34 * your enum value is in the right order in the array below.
37 VIEWER_BABELTRACE
= 0,
38 VIEWER_BABELTRACE2
= 1,
39 VIEWER_USER_DEFINED
= 2,
42 static const struct viewer
{
43 const char *exec_name
;
44 enum viewer_type type
;
46 { "babeltrace", VIEWER_BABELTRACE
},
47 { "babeltrace2", VIEWER_BABELTRACE2
},
48 { NULL
, VIEWER_USER_DEFINED
},
51 static const struct viewer
*parse_viewer_option(const char *opt_viewer
)
53 if (opt_viewer
== NULL
) {
54 /* Default is babeltrace2 */
55 return &(viewers
[VIEWER_BABELTRACE2
]);
58 return &(viewers
[VIEWER_USER_DEFINED
]);
62 * Alloc an array of string pointer from a simple string having all options
63 * seperated by spaces. Also adds the trace path to the arguments.
65 * The returning pointer is ready to be passed to execvp().
67 static char **alloc_argv_from_user_opts(char *opts
, const char *trace_path
)
69 int i
= 0, ignore_space
= 0;
70 unsigned int num_opts
= 1;
71 char **argv
, *token
= opts
, *saveptr
= NULL
;
73 /* Count number of arguments. */
76 /* Use to ignore consecutive spaces */
85 } while (*token
!= '\0');
87 /* Add two here for the NULL terminating element and trace path */
88 argv
= (char **) zmalloc(sizeof(char *) * (num_opts
+ 2));
93 token
= strtok_r(opts
, " ", &saveptr
);
94 while (token
!= NULL
) {
95 argv
[i
] = strdup(token
);
96 if (argv
[i
] == NULL
) {
99 token
= strtok_r(NULL
, " ", &saveptr
);
103 argv
[num_opts
] = (char *) trace_path
;
104 argv
[num_opts
+ 1] = NULL
;
110 for (i
= 0; i
< num_opts
+ 2; i
++) {
120 * Alloc an array of string pointer from an array of strings. It also adds
121 * the trace path to the argv.
123 * The returning pointer is ready to be passed to execvp().
125 static char **alloc_argv_from_local_opts(const char **opts
, size_t opts_len
,
126 const char *trace_path
, bool opt_live_mode
)
129 size_t size
, mem_len
;
131 /* Add one for the NULL terminating element. */
132 mem_len
= opts_len
+ 1;
134 /* Add 3 option for the live mode being "-i lttng-live URL". */
137 /* Add option for the trace path. */
141 size
= sizeof(char *) * mem_len
;
143 /* Add two here for the trace_path and the NULL terminating element. */
144 argv
= (char **) zmalloc(size
);
149 memcpy(argv
, opts
, sizeof(char *) * opts_len
);
152 argv
[opts_len
] = (char *) "-i";
153 argv
[opts_len
+ 1] = (char *) "lttng-live";
154 argv
[opts_len
+ 2] = (char *) trace_path
;
155 argv
[opts_len
+ 3] = NULL
;
157 argv
[opts_len
] = (char *) trace_path
;
158 argv
[opts_len
+ 1] = NULL
;
167 * Spawn viewer with the trace directory path.
169 int spawn_viewer(const char *trace_path
, char *opt_viewer
, bool opt_live_mode
)
173 const char *viewer_bin
= NULL
;
174 const struct viewer
*viewer
;
177 /* Check for --viewer option. */
178 viewer
= parse_viewer_option(opt_viewer
);
179 if (viewer
== NULL
) {
185 switch (viewer
->type
) {
186 case VIEWER_BABELTRACE2
:
187 if (stat(babeltrace2_bin
, &status
) == 0) {
188 viewer_bin
= babeltrace2_bin
;
190 viewer_bin
= viewer
->exec_name
;
192 argv
= alloc_argv_from_local_opts(babeltrace2_opts
,
193 ARRAY_SIZE(babeltrace2_opts
), trace_path
,
196 case VIEWER_BABELTRACE
:
197 if (stat(babeltrace_bin
, &status
) == 0) {
198 viewer_bin
= babeltrace_bin
;
200 viewer_bin
= viewer
->exec_name
;
202 argv
= alloc_argv_from_local_opts(babeltrace_opts
,
203 ARRAY_SIZE(babeltrace_opts
), trace_path
,
206 case VIEWER_USER_DEFINED
:
207 argv
= alloc_argv_from_user_opts(opt_viewer
, trace_path
);
209 viewer_bin
= argv
[0];
216 if (argv
== NULL
|| !viewer_bin
) {
221 DBG("Using %s viewer", viewer_bin
);
223 ret
= execvp(viewer_bin
, argv
);
225 if (errno
== ENOENT
&& viewer
->exec_name
) {
226 if (viewer
->type
== VIEWER_BABELTRACE2
) {
227 /* Fallback to legacy babeltrace. */
228 DBG("Default viewer \"%s\" not installed on the system, falling back to \"%s\"",
229 viewers
[VIEWER_BABELTRACE2
].exec_name
,
230 viewers
[VIEWER_BABELTRACE
].exec_name
);
231 viewer
= &viewers
[VIEWER_BABELTRACE
];
236 ERR("Default viewer \"%s\" (and fallback \"%s\") not found on the system",
237 viewers
[VIEWER_BABELTRACE2
].exec_name
,
238 viewers
[VIEWER_BABELTRACE
].exec_name
);
241 PERROR("Failed to launch \"%s\" viewer", viewer_bin
);
248 * This function should never return if successfull because `execvp(3)`
249 * onle returns if an error has occurred.
251 LTTNG_ASSERT(ret
!= 0);
This page took 0.036529 seconds and 5 git commands to generate.