Commit | Line | Data |
---|---|---|
ccf10263 | 1 | /* |
21cf9b6b | 2 | * Copyright (C) 2011 EfficiOS Inc. |
ab5be9fa | 3 | * Copyright (C) 2015 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
159b042f | 4 | * Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com> |
ccf10263 | 5 | * |
ab5be9fa | 6 | * SPDX-License-Identifier: GPL-2.0-only |
ccf10263 | 7 | * |
ccf10263 MD |
8 | */ |
9 | ||
ccf10263 | 10 | #define _LGPL_SOURCE |
28ab034a JG |
11 | #include "../command.hpp" |
12 | ||
13 | #include <common/dynamic-array.hpp> | |
14 | #include <common/dynamic-buffer.hpp> | |
15 | #include <common/mi-lttng.hpp> | |
16 | #include <common/optional.hpp> | |
17 | #include <common/tracker.hpp> | |
18 | ||
19 | #include <lttng/lttng.h> | |
20 | ||
ccf10263 MD |
21 | #include <ctype.h> |
22 | #include <popt.h> | |
adce7589 | 23 | #include <stdbool.h> |
ccf10263 MD |
24 | #include <stdio.h> |
25 | #include <stdlib.h> | |
26 | #include <string.h> | |
27 | #include <sys/stat.h> | |
28 | #include <sys/types.h> | |
29 | #include <unistd.h> | |
ccf10263 MD |
30 | #include <urcu/list.h> |
31 | ||
f1494934 | 32 | namespace { |
159b042f JG |
33 | struct process_attr_command_args { |
34 | enum lttng_process_attr process_attr; | |
35 | /* Present in the user's command. */ | |
36 | bool requested; | |
37 | bool all; | |
38 | struct lttng_dynamic_pointer_array string_args; | |
39 | }; | |
f1494934 | 40 | } /* namespace */ |
159b042f | 41 | |
ccf10263 MD |
42 | enum cmd_type { |
43 | CMD_TRACK, | |
44 | CMD_UNTRACK, | |
45 | }; | |
46 | ||
159b042f | 47 | /* Offset OPT_ values by one since libpopt gives '0' a special meaning. */ |
ccf10263 | 48 | enum { |
159b042f JG |
49 | OPT_PID = LTTNG_PROCESS_ATTR_PROCESS_ID + 1, |
50 | OPT_VPID = LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID + 1, | |
51 | OPT_UID = LTTNG_PROCESS_ATTR_USER_ID + 1, | |
52 | OPT_VUID = LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID + 1, | |
53 | OPT_GID = LTTNG_PROCESS_ATTR_GROUP_ID + 1, | |
54 | OPT_VGID = LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID + 1, | |
55 | OPT_HELP, | |
ccf10263 MD |
56 | OPT_LIST_OPTIONS, |
57 | OPT_SESSION, | |
83d6d6c4 | 58 | OPT_ALL, |
ccf10263 MD |
59 | }; |
60 | ||
159b042f JG |
61 | static char *opt_session_name; |
62 | static int opt_kernel; | |
63 | static int opt_userspace; | |
64 | static char *opt_str_arg; | |
65 | ||
ccf10263 MD |
66 | static struct poptOption long_options[] = { |
67 | /* { longName, shortName, argInfo, argPtr, value, descrip, argDesc, } */ | |
28ab034a JG |
68 | { |
69 | "help", | |
70 | 'h', | |
71 | POPT_ARG_NONE, | |
cd9adb8b | 72 | nullptr, |
28ab034a | 73 | OPT_HELP, |
cd9adb8b JG |
74 | nullptr, |
75 | nullptr, | |
28ab034a JG |
76 | }, |
77 | { | |
78 | "session", | |
79 | 's', | |
80 | POPT_ARG_STRING, | |
81 | &opt_session_name, | |
82 | OPT_SESSION, | |
cd9adb8b JG |
83 | nullptr, |
84 | nullptr, | |
28ab034a JG |
85 | }, |
86 | { | |
87 | "kernel", | |
88 | 'k', | |
89 | POPT_ARG_VAL, | |
90 | &opt_kernel, | |
91 | 1, | |
cd9adb8b JG |
92 | nullptr, |
93 | nullptr, | |
28ab034a JG |
94 | }, |
95 | { | |
96 | "userspace", | |
97 | 'u', | |
98 | POPT_ARG_VAL, | |
99 | &opt_userspace, | |
100 | 1, | |
cd9adb8b JG |
101 | nullptr, |
102 | nullptr, | |
28ab034a JG |
103 | }, |
104 | { | |
105 | "pid", | |
106 | 'p', | |
107 | POPT_ARG_STRING | POPT_ARGFLAG_OPTIONAL, | |
108 | &opt_str_arg, | |
109 | OPT_PID, | |
cd9adb8b JG |
110 | nullptr, |
111 | nullptr, | |
28ab034a JG |
112 | }, |
113 | { | |
114 | "vpid", | |
115 | 0, | |
116 | POPT_ARG_STRING | POPT_ARGFLAG_OPTIONAL, | |
117 | &opt_str_arg, | |
118 | OPT_VPID, | |
cd9adb8b JG |
119 | nullptr, |
120 | nullptr, | |
28ab034a JG |
121 | }, |
122 | { | |
123 | "uid", | |
124 | 0, | |
125 | POPT_ARG_STRING | POPT_ARGFLAG_OPTIONAL, | |
126 | &opt_str_arg, | |
127 | OPT_UID, | |
cd9adb8b JG |
128 | nullptr, |
129 | nullptr, | |
28ab034a JG |
130 | }, |
131 | { | |
132 | "vuid", | |
133 | 0, | |
134 | POPT_ARG_STRING | POPT_ARGFLAG_OPTIONAL, | |
135 | &opt_str_arg, | |
136 | OPT_VUID, | |
cd9adb8b JG |
137 | nullptr, |
138 | nullptr, | |
28ab034a JG |
139 | }, |
140 | { | |
141 | "gid", | |
142 | 0, | |
143 | POPT_ARG_STRING | POPT_ARGFLAG_OPTIONAL, | |
144 | &opt_str_arg, | |
145 | OPT_GID, | |
cd9adb8b JG |
146 | nullptr, |
147 | nullptr, | |
28ab034a JG |
148 | }, |
149 | { | |
150 | "vgid", | |
151 | 0, | |
152 | POPT_ARG_STRING | POPT_ARGFLAG_OPTIONAL, | |
153 | &opt_str_arg, | |
154 | OPT_VGID, | |
cd9adb8b JG |
155 | nullptr, |
156 | nullptr, | |
28ab034a JG |
157 | }, |
158 | { | |
159 | "all", | |
160 | 'a', | |
161 | POPT_ARG_NONE, | |
cd9adb8b | 162 | nullptr, |
28ab034a | 163 | OPT_ALL, |
cd9adb8b JG |
164 | nullptr, |
165 | nullptr, | |
28ab034a JG |
166 | }, |
167 | { | |
168 | "list-options", | |
169 | 0, | |
170 | POPT_ARG_NONE, | |
cd9adb8b | 171 | nullptr, |
28ab034a | 172 | OPT_LIST_OPTIONS, |
cd9adb8b JG |
173 | nullptr, |
174 | nullptr, | |
28ab034a JG |
175 | }, |
176 | { | |
cd9adb8b | 177 | nullptr, |
28ab034a JG |
178 | 0, |
179 | 0, | |
cd9adb8b | 180 | nullptr, |
28ab034a | 181 | 0, |
cd9adb8b JG |
182 | nullptr, |
183 | nullptr, | |
28ab034a | 184 | }, |
ccf10263 MD |
185 | }; |
186 | ||
159b042f | 187 | static struct process_attr_command_args |
28ab034a | 188 | process_attr_commands[LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID + 1]; |
83d6d6c4 | 189 | |
159b042f | 190 | static void process_attr_command_init(struct process_attr_command_args *cmd, |
28ab034a | 191 | enum lttng_process_attr process_attr) |
83d6d6c4 | 192 | { |
159b042f JG |
193 | cmd->process_attr = process_attr; |
194 | cmd->all = false; | |
cfaa204e | 195 | lttng_dynamic_pointer_array_init(&cmd->string_args, free); |
83d6d6c4 JR |
196 | } |
197 | ||
159b042f | 198 | static void process_attr_command_fini(struct process_attr_command_args *cmd) |
83d6d6c4 | 199 | { |
159b042f | 200 | lttng_dynamic_pointer_array_reset(&cmd->string_args); |
ccf10263 MD |
201 | } |
202 | ||
159b042f | 203 | static const char *get_capitalized_process_attr_str(enum lttng_process_attr process_attr) |
83d6d6c4 | 204 | { |
159b042f JG |
205 | switch (process_attr) { |
206 | case LTTNG_PROCESS_ATTR_PROCESS_ID: | |
207 | return "Process ID"; | |
208 | case LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID: | |
209 | return "Virtual process ID"; | |
210 | case LTTNG_PROCESS_ATTR_USER_ID: | |
211 | return "User ID"; | |
212 | case LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID: | |
213 | return "Virtual user ID"; | |
214 | case LTTNG_PROCESS_ATTR_GROUP_ID: | |
215 | return "Group ID"; | |
216 | case LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID: | |
217 | return "Virtual group ID"; | |
83d6d6c4 | 218 | default: |
159b042f | 219 | return "Unknown"; |
83d6d6c4 | 220 | } |
cd9adb8b | 221 | return nullptr; |
83d6d6c4 JR |
222 | } |
223 | ||
159b042f | 224 | static bool ust_process_attr_supported(enum lttng_process_attr *process_attr) |
ef440343 | 225 | { |
159b042f JG |
226 | bool supported; |
227 | ||
228 | switch (*process_attr) { | |
229 | case LTTNG_PROCESS_ATTR_PROCESS_ID: | |
230 | *process_attr = LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID; | |
231 | /* fall-through. */ | |
232 | case LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID: | |
233 | case LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID: | |
234 | case LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID: | |
235 | supported = true; | |
ef440343 JR |
236 | break; |
237 | default: | |
159b042f | 238 | ERR("The %s process attribute cannot be tracked in the user space domain.", |
28ab034a | 239 | lttng_process_attr_to_string(*process_attr)); |
159b042f | 240 | supported = false; |
ef440343 JR |
241 | break; |
242 | } | |
159b042f | 243 | return supported; |
ef440343 JR |
244 | } |
245 | ||
159b042f | 246 | static const char *get_mi_element_command(enum cmd_type cmd_type) |
ccf10263 | 247 | { |
ccf10263 MD |
248 | switch (cmd_type) { |
249 | case CMD_TRACK: | |
159b042f | 250 | return mi_lttng_element_command_track; |
ccf10263 | 251 | case CMD_UNTRACK: |
159b042f | 252 | return mi_lttng_element_command_untrack; |
ccf10263 | 253 | default: |
159b042f | 254 | abort(); |
ccf10263 | 255 | } |
159b042f JG |
256 | } |
257 | ||
258 | static enum cmd_error_code run_command_all(enum cmd_type cmd_type, | |
28ab034a JG |
259 | const char *session_name, |
260 | enum lttng_domain_type domain_type, | |
261 | enum lttng_process_attr process_attr, | |
262 | struct mi_writer *writer) | |
159b042f | 263 | { |
cd9adb8b | 264 | struct lttng_process_attr_tracker_handle *tracker_handle = nullptr; |
28ab034a JG |
265 | const enum lttng_error_code handle_ret_code = lttng_session_get_tracker_handle( |
266 | session_name, domain_type, process_attr, &tracker_handle); | |
159b042f JG |
267 | enum cmd_error_code cmd_ret = CMD_SUCCESS; |
268 | enum lttng_process_attr_tracker_handle_status status; | |
269 | ||
270 | if (writer) { | |
28ab034a | 271 | const int ret = mi_lttng_all_process_attribute_value(writer, process_attr, true); |
ef440343 | 272 | if (ret) { |
159b042f | 273 | cmd_ret = CMD_FATAL; |
ef440343 | 274 | goto end; |
83d6d6c4 | 275 | } |
ccf10263 MD |
276 | } |
277 | ||
159b042f JG |
278 | if (handle_ret_code != LTTNG_OK) { |
279 | ERR("Session `%s` does not exist", session_name); | |
280 | cmd_ret = CMD_FATAL; | |
ccf10263 MD |
281 | goto end; |
282 | } | |
283 | ||
159b042f | 284 | status = lttng_process_attr_tracker_handle_set_tracking_policy( |
28ab034a JG |
285 | tracker_handle, |
286 | cmd_type == CMD_TRACK ? LTTNG_TRACKING_POLICY_INCLUDE_ALL : | |
159b042f JG |
287 | LTTNG_TRACKING_POLICY_EXCLUDE_ALL); |
288 | switch (status) { | |
289 | case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK: | |
290 | if (cmd_type == CMD_TRACK) { | |
291 | MSG("%s tracking policy set to `include all`", | |
28ab034a | 292 | get_capitalized_process_attr_str(process_attr)); |
159b042f JG |
293 | } else { |
294 | MSG("%s tracking policy set to `exclude all`", | |
28ab034a | 295 | get_capitalized_process_attr_str(process_attr)); |
159b042f JG |
296 | } |
297 | break; | |
298 | case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_SESSION_DOES_NOT_EXIST: | |
299 | ERR("%s", lttng_strerror(-LTTNG_ERR_SESS_NOT_FOUND)); | |
300 | break; | |
301 | default: | |
302 | ERR("Unknown error encountered while setting tracking policy of %s tracker to `%s`", | |
28ab034a JG |
303 | lttng_process_attr_to_string(process_attr), |
304 | cmd_type == CMD_TRACK ? "include all" : "exclude all"); | |
159b042f JG |
305 | cmd_ret = CMD_FATAL; |
306 | break; | |
307 | } | |
308 | end: | |
ccf10263 | 309 | if (writer) { |
28ab034a JG |
310 | int ret = mi_lttng_writer_write_element_bool( |
311 | writer, mi_lttng_element_success, cmd_ret == CMD_SUCCESS); | |
159b042f | 312 | |
ccf10263 | 313 | if (ret) { |
159b042f JG |
314 | cmd_ret = CMD_FATAL; |
315 | } else { | |
316 | ret = mi_lttng_writer_close_element(writer); | |
317 | cmd_ret = ret == 0 ? cmd_ret : CMD_FATAL; | |
ccf10263 MD |
318 | } |
319 | } | |
159b042f JG |
320 | lttng_process_attr_tracker_handle_destroy(tracker_handle); |
321 | return cmd_ret; | |
322 | } | |
ccf10263 | 323 | |
159b042f | 324 | static enum cmd_error_code run_command_string(enum cmd_type cmd_type, |
28ab034a JG |
325 | const char *session_name, |
326 | enum lttng_domain_type domain_type, | |
327 | enum lttng_process_attr process_attr, | |
328 | const char *_args, | |
329 | struct mi_writer *writer) | |
159b042f | 330 | { |
cd9adb8b | 331 | struct lttng_process_attr_tracker_handle *tracker_handle = nullptr; |
28ab034a JG |
332 | const enum lttng_error_code handle_ret_code = lttng_session_get_tracker_handle( |
333 | session_name, domain_type, process_attr, &tracker_handle); | |
159b042f JG |
334 | enum cmd_error_code cmd_ret = CMD_SUCCESS; |
335 | const char *one_value_str; | |
336 | char *args = strdup(_args); | |
337 | char *iter = args; | |
338 | bool policy_set = false; | |
339 | ||
340 | if (!args) { | |
341 | ERR("%s", lttng_strerror(-LTTNG_ERR_NOMEM)); | |
342 | cmd_ret = CMD_FATAL; | |
343 | goto end; | |
344 | } | |
83d6d6c4 | 345 | |
159b042f JG |
346 | if (handle_ret_code != LTTNG_OK) { |
347 | ERR("%s", lttng_strerror(-handle_ret_code)); | |
348 | cmd_ret = CMD_FATAL; | |
349 | goto end; | |
350 | } | |
2d97a006 | 351 | |
cd9adb8b | 352 | while ((one_value_str = strtok_r(iter, ",", &iter)) != nullptr) { |
159b042f JG |
353 | const bool is_numerical_argument = isdigit(one_value_str[0]); |
354 | enum lttng_process_attr_tracker_handle_status status; | |
355 | enum lttng_tracking_policy policy; | |
356 | int ret; | |
357 | char *prettified_arg; | |
358 | ||
359 | if (!policy_set) { | |
360 | status = lttng_process_attr_tracker_handle_get_tracking_policy( | |
28ab034a | 361 | tracker_handle, &policy); |
159b042f JG |
362 | if (status != LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK) { |
363 | break; | |
364 | } | |
365 | ||
366 | if (policy != LTTNG_TRACKING_POLICY_INCLUDE_SET) { | |
367 | status = lttng_process_attr_tracker_handle_set_tracking_policy( | |
28ab034a | 368 | tracker_handle, LTTNG_TRACKING_POLICY_INCLUDE_SET); |
159b042f JG |
369 | if (status != LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK) { |
370 | break; | |
371 | } | |
372 | } | |
373 | policy_set = true; | |
83d6d6c4 | 374 | } |
2d97a006 | 375 | |
159b042f | 376 | if (is_numerical_argument) { |
cd9adb8b | 377 | const unsigned long one_value_int = strtoul(one_value_str, nullptr, 10); |
159b042f JG |
378 | |
379 | if (writer) { | |
d89dd55e | 380 | ret = mi_lttng_integral_process_attribute_value( |
28ab034a | 381 | writer, process_attr, (int64_t) one_value_int, true); |
159b042f JG |
382 | if (ret) { |
383 | cmd_ret = CMD_FATAL; | |
384 | goto end; | |
385 | } | |
386 | } | |
83d6d6c4 | 387 | |
159b042f JG |
388 | switch (process_attr) { |
389 | case LTTNG_PROCESS_ATTR_PROCESS_ID: | |
390 | status = cmd_type == CMD_TRACK ? | |
28ab034a JG |
391 | lttng_process_attr_process_id_tracker_handle_add_pid( |
392 | tracker_handle, (pid_t) one_value_int) : | |
393 | lttng_process_attr_process_id_tracker_handle_remove_pid( | |
394 | tracker_handle, (pid_t) one_value_int); | |
b93a4a13 | 395 | break; |
159b042f JG |
396 | case LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID: |
397 | status = cmd_type == CMD_TRACK ? | |
28ab034a JG |
398 | lttng_process_attr_virtual_process_id_tracker_handle_add_pid( |
399 | tracker_handle, (pid_t) one_value_int) : | |
400 | lttng_process_attr_virtual_process_id_tracker_handle_remove_pid( | |
401 | tracker_handle, (pid_t) one_value_int); | |
b93a4a13 | 402 | break; |
159b042f JG |
403 | case LTTNG_PROCESS_ATTR_USER_ID: |
404 | status = cmd_type == CMD_TRACK ? | |
28ab034a JG |
405 | lttng_process_attr_user_id_tracker_handle_add_uid( |
406 | tracker_handle, (uid_t) one_value_int) : | |
407 | lttng_process_attr_user_id_tracker_handle_remove_uid( | |
408 | tracker_handle, (uid_t) one_value_int); | |
159b042f JG |
409 | break; |
410 | case LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID: | |
411 | status = cmd_type == CMD_TRACK ? | |
28ab034a JG |
412 | lttng_process_attr_virtual_user_id_tracker_handle_add_uid( |
413 | tracker_handle, (uid_t) one_value_int) : | |
414 | lttng_process_attr_virtual_user_id_tracker_handle_remove_uid( | |
415 | tracker_handle, (uid_t) one_value_int); | |
159b042f JG |
416 | break; |
417 | case LTTNG_PROCESS_ATTR_GROUP_ID: | |
418 | status = cmd_type == CMD_TRACK ? | |
28ab034a JG |
419 | lttng_process_attr_group_id_tracker_handle_add_gid( |
420 | tracker_handle, (gid_t) one_value_int) : | |
421 | lttng_process_attr_group_id_tracker_handle_remove_gid( | |
422 | tracker_handle, (gid_t) one_value_int); | |
b93a4a13 | 423 | break; |
159b042f JG |
424 | case LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID: |
425 | status = cmd_type == CMD_TRACK ? | |
28ab034a JG |
426 | lttng_process_attr_virtual_group_id_tracker_handle_add_gid( |
427 | tracker_handle, (gid_t) one_value_int) : | |
428 | lttng_process_attr_virtual_group_id_tracker_handle_remove_gid( | |
429 | tracker_handle, (gid_t) one_value_int); | |
159b042f JG |
430 | break; |
431 | default: | |
432 | abort(); | |
b93a4a13 | 433 | } |
159b042f JG |
434 | |
435 | } else { | |
436 | if (writer) { | |
d89dd55e | 437 | ret = mi_lttng_string_process_attribute_value( |
28ab034a | 438 | writer, process_attr, one_value_str, true); |
159b042f JG |
439 | if (ret) { |
440 | cmd_ret = CMD_FATAL; | |
83d6d6c4 JR |
441 | goto end; |
442 | } | |
443 | } | |
159b042f JG |
444 | |
445 | switch (process_attr) { | |
446 | case LTTNG_PROCESS_ATTR_USER_ID: | |
447 | status = cmd_type == CMD_TRACK ? | |
28ab034a JG |
448 | lttng_process_attr_user_id_tracker_handle_add_user_name( |
449 | tracker_handle, one_value_str) : | |
450 | lttng_process_attr_user_id_tracker_handle_remove_user_name( | |
451 | tracker_handle, one_value_str); | |
83d6d6c4 | 452 | break; |
159b042f JG |
453 | case LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID: |
454 | status = cmd_type == CMD_TRACK ? | |
28ab034a JG |
455 | lttng_process_attr_virtual_user_id_tracker_handle_add_user_name( |
456 | tracker_handle, one_value_str) : | |
457 | lttng_process_attr_virtual_user_id_tracker_handle_remove_user_name( | |
458 | tracker_handle, one_value_str); | |
83d6d6c4 | 459 | break; |
159b042f JG |
460 | case LTTNG_PROCESS_ATTR_GROUP_ID: |
461 | status = cmd_type == CMD_TRACK ? | |
28ab034a JG |
462 | lttng_process_attr_group_id_tracker_handle_add_group_name( |
463 | tracker_handle, one_value_str) : | |
464 | lttng_process_attr_group_id_tracker_handle_remove_group_name( | |
465 | tracker_handle, one_value_str); | |
159b042f JG |
466 | break; |
467 | case LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID: | |
468 | status = cmd_type == CMD_TRACK ? | |
28ab034a JG |
469 | lttng_process_attr_virtual_group_id_tracker_handle_add_group_name( |
470 | tracker_handle, one_value_str) : | |
471 | lttng_process_attr_virtual_group_id_tracker_handle_remove_group_name( | |
472 | tracker_handle, one_value_str); | |
83d6d6c4 JR |
473 | break; |
474 | default: | |
159b042f | 475 | ERR("%s is not a valid %s value; expected an integer", |
28ab034a JG |
476 | one_value_str, |
477 | lttng_process_attr_to_string(process_attr)); | |
159b042f | 478 | cmd_ret = CMD_FATAL; |
83d6d6c4 | 479 | goto end; |
efcbc78c | 480 | } |
ebbf5ab7 JR |
481 | } |
482 | ||
28ab034a JG |
483 | ret = asprintf( |
484 | &prettified_arg, is_numerical_argument ? "%s" : "`%s`", one_value_str); | |
159b042f JG |
485 | if (ret < 0) { |
486 | PERROR("Failed to format argument `%s`", one_value_str); | |
487 | cmd_ret = CMD_FATAL; | |
488 | goto end; | |
489 | } | |
ebbf5ab7 | 490 | |
159b042f JG |
491 | switch (status) { |
492 | case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK: | |
493 | if (cmd_type == CMD_TRACK) { | |
494 | MSG("Added %s to the %s tracker inclusion set", | |
28ab034a JG |
495 | one_value_str, |
496 | lttng_process_attr_to_string(process_attr)); | |
159b042f JG |
497 | } else { |
498 | MSG("Removed %s from the %s tracker inclusion set", | |
28ab034a JG |
499 | one_value_str, |
500 | lttng_process_attr_to_string(process_attr)); | |
ebbf5ab7 | 501 | } |
159b042f JG |
502 | break; |
503 | case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_SESSION_DOES_NOT_EXIST: | |
504 | ERR("Session `%s` not found", session_name); | |
505 | break; | |
506 | case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_EXISTS: | |
507 | WARN("%s is already in the %s inclusion set", | |
28ab034a JG |
508 | prettified_arg, |
509 | lttng_process_attr_to_string(process_attr)); | |
159b042f JG |
510 | break; |
511 | case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_MISSING: | |
512 | WARN("%s is not in the %s the inclusion set", | |
28ab034a JG |
513 | prettified_arg, |
514 | lttng_process_attr_to_string(process_attr)); | |
159b042f JG |
515 | break; |
516 | case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_USER_NOT_FOUND: | |
517 | ERR("User %s was not found", prettified_arg); | |
518 | cmd_ret = CMD_ERROR; | |
519 | break; | |
520 | case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_GROUP_NOT_FOUND: | |
521 | ERR("Group %s was not found", prettified_arg); | |
522 | cmd_ret = CMD_ERROR; | |
523 | break; | |
524 | default: | |
525 | ERR("Unknown error encountered while %s %s %s %s tracker's inclusion set", | |
28ab034a JG |
526 | cmd_type == CMD_TRACK ? "adding" : "removing", |
527 | lttng_process_attr_to_string(process_attr), | |
528 | prettified_arg, | |
529 | cmd_type == CMD_TRACK ? "to" : "from"); | |
159b042f JG |
530 | cmd_ret = CMD_FATAL; |
531 | break; | |
532 | } | |
533 | free(prettified_arg); | |
534 | ||
535 | if (writer) { | |
28ab034a JG |
536 | ret = mi_lttng_writer_write_element_bool( |
537 | writer, mi_lttng_element_success, cmd_ret == CMD_SUCCESS); | |
ebbf5ab7 | 538 | |
ebbf5ab7 | 539 | if (ret) { |
159b042f JG |
540 | cmd_ret = CMD_FATAL; |
541 | } else { | |
542 | ret = mi_lttng_writer_close_element(writer); | |
543 | cmd_ret = ret == 0 ? cmd_ret : CMD_FATAL; | |
ebbf5ab7 | 544 | } |
ccf10263 MD |
545 | } |
546 | } | |
159b042f JG |
547 | end: |
548 | free(args); | |
549 | lttng_process_attr_tracker_handle_destroy(tracker_handle); | |
550 | return cmd_ret; | |
551 | } | |
552 | ||
553 | static enum cmd_error_code run_command(enum cmd_type cmd_type, | |
28ab034a JG |
554 | const char *session_name, |
555 | const struct process_attr_command_args *command_args, | |
556 | struct mi_writer *writer) | |
159b042f | 557 | { |
28ab034a JG |
558 | const enum lttng_domain_type domain_type = opt_kernel ? LTTNG_DOMAIN_KERNEL : |
559 | LTTNG_DOMAIN_UST; | |
159b042f JG |
560 | enum cmd_error_code cmd_ret = CMD_SUCCESS; |
561 | unsigned int i; | |
562 | const unsigned int string_arg_count = | |
28ab034a | 563 | lttng_dynamic_pointer_array_get_count(&command_args->string_args); |
159b042f JG |
564 | enum lttng_process_attr process_attr = command_args->process_attr; |
565 | ||
566 | if (opt_userspace) { | |
567 | /* | |
568 | * Check that this process attribute can be tracked | |
569 | * in the user space domain. Backward-compatibility | |
570 | * changes are be applied to process_attr as needed. | |
571 | */ | |
572 | if (!ust_process_attr_supported(&process_attr)) { | |
573 | cmd_ret = CMD_ERROR; | |
574 | goto end; | |
575 | } | |
576 | } | |
ccf10263 MD |
577 | |
578 | if (writer) { | |
159b042f | 579 | /* Open tracker and trackers elements */ |
28ab034a | 580 | const int ret = mi_lttng_process_attribute_tracker_open(writer, process_attr); |
ccf10263 | 581 | if (ret) { |
159b042f | 582 | cmd_ret = CMD_FATAL; |
ccf10263 MD |
583 | goto end; |
584 | } | |
585 | } | |
586 | ||
159b042f | 587 | if (command_args->all) { |
28ab034a JG |
588 | cmd_ret = |
589 | run_command_all(cmd_type, session_name, domain_type, process_attr, writer); | |
159b042f JG |
590 | } else { |
591 | bool error_occurred = false; | |
ccf10263 | 592 | |
159b042f | 593 | for (i = 0; i < string_arg_count; i++) { |
48a40005 | 594 | const char *arg = (const char *) lttng_dynamic_pointer_array_get_pointer( |
28ab034a | 595 | &command_args->string_args, i); |
159b042f | 596 | |
28ab034a JG |
597 | cmd_ret = run_command_string( |
598 | cmd_type, session_name, domain_type, process_attr, arg, writer); | |
159b042f JG |
599 | if (cmd_ret != CMD_SUCCESS) { |
600 | error_occurred = true; | |
601 | if (cmd_ret == CMD_FATAL) { | |
602 | break; | |
603 | } | |
604 | goto end; | |
605 | } | |
606 | } | |
607 | if (error_occurred) { | |
608 | cmd_ret = CMD_ERROR; | |
609 | } | |
ccf10263 | 610 | } |
ccf10263 | 611 | |
159b042f JG |
612 | if (writer) { |
613 | /* Close tracker and trackers elements */ | |
28ab034a | 614 | const int ret = mi_lttng_close_multi_element(writer, 2); |
159b042f JG |
615 | if (ret) { |
616 | cmd_ret = CMD_FATAL; | |
617 | goto end; | |
618 | } | |
619 | } | |
620 | end: | |
621 | return cmd_ret; | |
83d6d6c4 JR |
622 | } |
623 | ||
ccf10263 MD |
624 | /* |
625 | * Add/remove tracker to/from session. | |
626 | */ | |
159b042f | 627 | static int cmd_track_untrack(enum cmd_type cmd_type, |
28ab034a JG |
628 | int argc, |
629 | const char **argv, | |
630 | const char *help_msg __attribute__((unused))) | |
ccf10263 | 631 | { |
159b042f JG |
632 | int opt, ret = 0; |
633 | bool sub_command_failed = false; | |
634 | bool opt_all = false; | |
635 | unsigned int selected_process_attr_tracker_count = 0; | |
636 | const unsigned int command_count = | |
28ab034a | 637 | sizeof(process_attr_commands) / sizeof(struct process_attr_command_args); |
c51da673 | 638 | enum cmd_error_code command_ret = CMD_SUCCESS; |
ccf10263 | 639 | static poptContext pc; |
cd9adb8b JG |
640 | char *session_name = nullptr; |
641 | const char *leftover = nullptr; | |
642 | struct mi_writer *writer = nullptr; | |
159b042f JG |
643 | size_t i; |
644 | ||
645 | for (i = 0; i < command_count; i++) { | |
48a40005 | 646 | process_attr_command_init(&process_attr_commands[i], (lttng_process_attr) i); |
159b042f | 647 | } |
ccf10263 MD |
648 | |
649 | if (argc < 1) { | |
c51da673 | 650 | command_ret = CMD_ERROR; |
ccf10263 MD |
651 | goto end; |
652 | } | |
653 | ||
cd9adb8b | 654 | pc = poptGetContext(nullptr, argc, argv, long_options, 0); |
ccf10263 MD |
655 | poptReadDefaultConfig(pc, 0); |
656 | ||
657 | while ((opt = poptGetNextOpt(pc)) != -1) { | |
658 | switch (opt) { | |
659 | case OPT_HELP: | |
4ba92f18 | 660 | SHOW_HELP(); |
ccf10263 MD |
661 | goto end; |
662 | case OPT_LIST_OPTIONS: | |
663 | list_cmd_options(stdout, long_options); | |
664 | goto end; | |
665 | case OPT_SESSION: | |
83d6d6c4 | 666 | break; |
ccf10263 | 667 | case OPT_PID: |
83d6d6c4 | 668 | case OPT_VPID: |
83d6d6c4 | 669 | case OPT_UID: |
83d6d6c4 | 670 | case OPT_VUID: |
83d6d6c4 | 671 | case OPT_GID: |
83d6d6c4 | 672 | case OPT_VGID: |
159b042f JG |
673 | /* See OPT_ enum declaration comment. */ |
674 | opt--; | |
675 | selected_process_attr_tracker_count++; | |
676 | process_attr_commands[opt].requested = true; | |
677 | if (!opt_str_arg) { | |
678 | continue; | |
679 | } | |
680 | ret = lttng_dynamic_pointer_array_add_pointer( | |
28ab034a | 681 | &process_attr_commands[opt].string_args, opt_str_arg); |
159b042f JG |
682 | if (ret) { |
683 | ERR("Allocation failed while parsing command arguments"); | |
83d6d6c4 JR |
684 | command_ret = CMD_ERROR; |
685 | goto end; | |
686 | } | |
83d6d6c4 JR |
687 | break; |
688 | case OPT_ALL: | |
159b042f | 689 | opt_all = true; |
ccf10263 MD |
690 | break; |
691 | default: | |
c51da673 | 692 | command_ret = CMD_UNDEFINED; |
ccf10263 MD |
693 | goto end; |
694 | } | |
695 | } | |
696 | ||
28ab034a | 697 | ret = print_missing_or_multiple_domains(opt_kernel + opt_userspace, false); |
3ecec76a | 698 | if (ret) { |
5061fb43 | 699 | command_ret = CMD_ERROR; |
ccf10263 MD |
700 | goto end; |
701 | } | |
702 | ||
159b042f JG |
703 | if (selected_process_attr_tracker_count == 0) { |
704 | ERR("At least one process attribute must be specified"); | |
705 | command_ret = CMD_ERROR; | |
706 | goto end; | |
707 | } | |
708 | if (opt_all) { | |
709 | /* | |
710 | * Only one process attribute tracker was specified; find it | |
711 | * and set it in 'all' mode. | |
712 | */ | |
713 | for (i = 0; i < command_count; i++) { | |
714 | if (!process_attr_commands[i].requested) { | |
715 | continue; | |
716 | } | |
717 | process_attr_commands[i].all = true; | |
718 | if (lttng_dynamic_pointer_array_get_count( | |
28ab034a | 719 | &process_attr_commands[i].string_args)) { |
159b042f JG |
720 | ERR("The --all option cannot be used with a list of process attribute values"); |
721 | command_ret = CMD_ERROR; | |
722 | goto end; | |
723 | } | |
724 | } | |
725 | } else { | |
726 | for (i = 0; i < command_count; i++) { | |
727 | if (!process_attr_commands[i].requested) { | |
728 | continue; | |
729 | } | |
730 | if (lttng_dynamic_pointer_array_get_count( | |
28ab034a | 731 | &process_attr_commands[i].string_args) == 0) { |
159b042f | 732 | ERR("No process attribute value specified for %s tracker", |
28ab034a JG |
733 | get_capitalized_process_attr_str( |
734 | process_attr_commands[i].process_attr)); | |
159b042f JG |
735 | command_ret = CMD_ERROR; |
736 | goto end; | |
737 | } | |
adce7589 FD |
738 | } |
739 | } | |
740 | ||
ccf10263 MD |
741 | if (!opt_session_name) { |
742 | session_name = get_session_name(); | |
cd9adb8b | 743 | if (session_name == nullptr) { |
c51da673 | 744 | command_ret = CMD_ERROR; |
ccf10263 MD |
745 | goto end; |
746 | } | |
747 | } else { | |
748 | session_name = opt_session_name; | |
749 | } | |
750 | ||
c47a705b FD |
751 | leftover = poptGetArg(pc); |
752 | if (leftover) { | |
753 | ERR("Unknown argument: %s", leftover); | |
a28dd43d | 754 | command_ret = CMD_ERROR; |
c47a705b FD |
755 | goto end; |
756 | } | |
757 | ||
ccf10263 MD |
758 | /* Mi check */ |
759 | if (lttng_opt_mi) { | |
760 | writer = mi_lttng_writer_create(fileno(stdout), lttng_opt_mi); | |
761 | if (!writer) { | |
c51da673 | 762 | command_ret = CMD_ERROR; |
ccf10263 MD |
763 | goto end; |
764 | } | |
765 | } | |
766 | ||
767 | if (writer) { | |
768 | /* Open command element */ | |
28ab034a | 769 | ret = mi_lttng_writer_command_open(writer, get_mi_element_command(cmd_type)); |
ccf10263 | 770 | if (ret) { |
c51da673 | 771 | command_ret = CMD_ERROR; |
ccf10263 MD |
772 | goto end; |
773 | } | |
774 | ||
775 | /* Open output element */ | |
28ab034a | 776 | ret = mi_lttng_writer_open_element(writer, mi_lttng_element_command_output); |
ccf10263 | 777 | if (ret) { |
c51da673 | 778 | command_ret = CMD_ERROR; |
ccf10263 MD |
779 | goto end; |
780 | } | |
83d6d6c4 JR |
781 | |
782 | ret = mi_lttng_trackers_open(writer); | |
783 | if (ret) { | |
784 | goto end; | |
785 | } | |
ccf10263 MD |
786 | } |
787 | ||
159b042f JG |
788 | /* Execute sub-commands. */ |
789 | for (i = 0; i < command_count; i++) { | |
790 | if (!process_attr_commands[i].requested) { | |
791 | continue; | |
83d6d6c4 | 792 | } |
28ab034a JG |
793 | command_ret = |
794 | run_command(cmd_type, session_name, &process_attr_commands[i], writer); | |
83d6d6c4 | 795 | if (command_ret != CMD_SUCCESS) { |
159b042f JG |
796 | sub_command_failed = true; |
797 | if (command_ret == CMD_FATAL) { | |
798 | break; | |
799 | } | |
83d6d6c4 | 800 | } |
ccf10263 MD |
801 | } |
802 | ||
803 | /* Mi closing */ | |
804 | if (writer) { | |
83d6d6c4 JR |
805 | /* Close trackers and output elements */ |
806 | ret = mi_lttng_close_multi_element(writer, 2); | |
ccf10263 | 807 | if (ret) { |
c51da673 | 808 | command_ret = CMD_ERROR; |
ccf10263 MD |
809 | goto end; |
810 | } | |
811 | ||
812 | /* Success ? */ | |
28ab034a JG |
813 | ret = mi_lttng_writer_write_element_bool( |
814 | writer, mi_lttng_element_command_success, !sub_command_failed); | |
ccf10263 | 815 | if (ret) { |
c51da673 | 816 | command_ret = CMD_ERROR; |
ccf10263 MD |
817 | goto end; |
818 | } | |
819 | ||
820 | /* Command element close */ | |
821 | ret = mi_lttng_writer_command_close(writer); | |
822 | if (ret) { | |
c51da673 | 823 | command_ret = CMD_ERROR; |
ccf10263 MD |
824 | goto end; |
825 | } | |
826 | } | |
827 | ||
828 | end: | |
829 | if (!opt_session_name) { | |
830 | free(session_name); | |
831 | } | |
832 | ||
833 | /* Mi clean-up */ | |
834 | if (writer && mi_lttng_writer_destroy(writer)) { | |
835 | /* Preserve original error code */ | |
c51da673 | 836 | command_ret = CMD_ERROR; |
ccf10263 MD |
837 | } |
838 | ||
159b042f JG |
839 | for (i = 0; i < command_count; i++) { |
840 | process_attr_command_fini(&process_attr_commands[i]); | |
841 | } | |
842 | ||
ccf10263 | 843 | poptFreeContext(pc); |
c51da673 | 844 | return (int) command_ret; |
ccf10263 MD |
845 | } |
846 | ||
847 | int cmd_track(int argc, const char **argv) | |
848 | { | |
4fc83d94 PP |
849 | static const char *help_msg = |
850 | #ifdef LTTNG_EMBED_HELP | |
851 | #include <lttng-track.1.h> | |
852 | #else | |
cd9adb8b | 853 | nullptr |
4fc83d94 | 854 | #endif |
28ab034a | 855 | ; |
4fc83d94 | 856 | |
159b042f | 857 | return cmd_track_untrack(CMD_TRACK, argc, argv, help_msg); |
ccf10263 MD |
858 | } |
859 | ||
860 | int cmd_untrack(int argc, const char **argv) | |
861 | { | |
4fc83d94 PP |
862 | static const char *help_msg = |
863 | #ifdef LTTNG_EMBED_HELP | |
864 | #include <lttng-untrack.1.h> | |
865 | #else | |
cd9adb8b | 866 | nullptr |
4fc83d94 | 867 | #endif |
28ab034a | 868 | ; |
4fc83d94 | 869 | |
159b042f | 870 | return cmd_track_untrack(CMD_UNTRACK, argc, argv, help_msg); |
ccf10263 | 871 | } |