Clean-up: replace uses of `int enabled` with boolean flags
[lttng-tools.git] / src / bin / lttng / commands / add_trigger.cpp
1 /*
2 * Copyright (C) 2021 Simon Marchi <simon.marchi@efficios.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 */
7
8 #include "../command.hpp"
9 #include "../loglevel.hpp"
10 #include "../uprobe.hpp"
11 #include "common/argpar-utils/argpar-utils.hpp"
12 #include "common/argpar/argpar.h"
13 #include "common/dynamic-array.hpp"
14 #include "common/mi-lttng.hpp"
15 #include "common/string-utils/string-utils.hpp"
16 #include "common/utils.hpp"
17
18 #include <lttng/domain-internal.hpp>
19
20 #include <ctype.h>
21 #include <stdarg.h>
22 #include <stdio.h>
23 #include <string.h>
24 /* For lttng_event_rule_type_str(). */
25 #include "common/dynamic-array.hpp"
26 #include "common/filter/filter-ast.hpp"
27 #include "common/filter/filter-ir.hpp"
28
29 #include <lttng/event-rule/event-rule-internal.hpp>
30 #include <lttng/lttng.h>
31
32 #if (LTTNG_SYMBOL_NAME_LEN == 256)
33 #define LTTNG_SYMBOL_NAME_LEN_SCANF_IS_A_BROKEN_API "255"
34 #endif
35
36 #ifdef LTTNG_EMBED_HELP
37 static const char help_msg[] =
38 #include <lttng-add-trigger.1.h>
39 ;
40 #endif
41
42 enum {
43 OPT_HELP,
44 OPT_LIST_OPTIONS,
45
46 OPT_CONDITION,
47 OPT_ACTION,
48 OPT_ID,
49 OPT_OWNER_UID,
50 OPT_RATE_POLICY,
51
52 OPT_NAME,
53 OPT_FILTER,
54 OPT_EXCLUDE_NAME,
55 OPT_EVENT_NAME,
56 OPT_LOG_LEVEL,
57
58 OPT_TYPE,
59 OPT_LOCATION,
60
61 OPT_MAX_SIZE,
62 OPT_DATA_URL,
63 OPT_CTRL_URL,
64 OPT_URL,
65 OPT_PATH,
66
67 OPT_CAPTURE,
68 };
69
70 static const struct argpar_opt_descr event_rule_opt_descrs[] = {
71 { OPT_FILTER, 'f', "filter", true },
72 { OPT_NAME, 'n', "name", true },
73 { OPT_EXCLUDE_NAME, 'x', "exclude-name", true },
74 { OPT_LOG_LEVEL, 'l', "log-level", true },
75 { OPT_EVENT_NAME, 'E', "event-name", true },
76
77 { OPT_TYPE, 't', "type", true },
78 { OPT_LOCATION, 'L', "location", true },
79
80 /* Capture descriptor */
81 { OPT_CAPTURE, '\0', "capture", true },
82
83 ARGPAR_OPT_DESCR_SENTINEL
84 };
85
86 static bool has_syscall_prefix(const char *arg)
87 {
88 bool matches = false;
89 const char kernel_syscall_type_opt_prefix[] = "kernel:syscall";
90 const size_t kernel_syscall_type_opt_prefix_len =
91 sizeof(kernel_syscall_type_opt_prefix) - 1;
92 const char syscall_type_opt_prefix[] = "syscall";
93 const size_t syscall_type_opt_prefix_len = sizeof(syscall_type_opt_prefix) - 1;
94
95 if (strncmp(arg, syscall_type_opt_prefix, syscall_type_opt_prefix_len) == 0) {
96 matches = true;
97 } else if (strncmp(arg,
98 kernel_syscall_type_opt_prefix,
99 kernel_syscall_type_opt_prefix_len) == 0) {
100 matches = true;
101 } else {
102 matches = false;
103 }
104
105 return matches;
106 }
107
108 static bool assign_event_rule_type(enum lttng_event_rule_type *dest, const char *arg)
109 {
110 bool ret;
111
112 if (*dest != LTTNG_EVENT_RULE_TYPE_UNKNOWN) {
113 ERR("More than one `--type` was specified.");
114 goto error;
115 }
116
117 if (strcmp(arg, "user") == 0 || strcmp(arg, "user:tracepoint") == 0) {
118 *dest = LTTNG_EVENT_RULE_TYPE_USER_TRACEPOINT;
119 } else if (strcmp(arg, "kernel") == 0 || strcmp(arg, "kernel:tracepoint") == 0) {
120 *dest = LTTNG_EVENT_RULE_TYPE_KERNEL_TRACEPOINT;
121 } else if (strcmp(arg, "jul") == 0 || strcmp(arg, "jul:logging") == 0) {
122 *dest = LTTNG_EVENT_RULE_TYPE_JUL_LOGGING;
123 } else if (strcmp(arg, "log4j") == 0 || strcmp(arg, "log4j:logging") == 0) {
124 *dest = LTTNG_EVENT_RULE_TYPE_LOG4J_LOGGING;
125 } else if (strcmp(arg, "python") == 0 || strcmp(arg, "python:logging") == 0) {
126 *dest = LTTNG_EVENT_RULE_TYPE_PYTHON_LOGGING;
127 } else if (strcmp(arg, "kprobe") == 0 || strcmp(arg, "kernel:kprobe") == 0) {
128 *dest = LTTNG_EVENT_RULE_TYPE_KERNEL_KPROBE;
129 } else if (strcmp(arg, "kernel:uprobe") == 0) {
130 *dest = LTTNG_EVENT_RULE_TYPE_KERNEL_UPROBE;
131 } else if (has_syscall_prefix(arg)) {
132 /*
133 * Matches the following:
134 * - syscall
135 * - syscall:entry
136 * - syscall:exit
137 * - syscall:entry+exit
138 * - syscall:*
139 * - kernel:syscall
140 * - kernel:syscall:entry
141 * - kernel:syscall:exit
142 * - kernel:syscall:entry+exit
143 * - kernel:syscall:*
144 *
145 * Validation for the right side is left to further usage sites.
146 */
147 *dest = LTTNG_EVENT_RULE_TYPE_KERNEL_SYSCALL;
148 } else {
149 ERR("Invalid `--type` value: %s", arg);
150 goto error;
151 }
152
153 ret = true;
154 goto end;
155
156 error:
157 ret = false;
158
159 end:
160 return ret;
161 }
162
163 static bool assign_string(char **dest, const char *src, const char *opt_name)
164 {
165 bool ret;
166
167 if (*dest) {
168 ERR("Duplicate '%s' given.", opt_name);
169 goto error;
170 }
171
172 *dest = strdup(src);
173 if (!*dest) {
174 PERROR("Failed to allocate string '%s'.", opt_name);
175 goto error;
176 }
177
178 ret = true;
179 goto end;
180
181 error:
182 ret = false;
183
184 end:
185 return ret;
186 }
187
188 static bool
189 parse_syscall_emission_site_from_type(const char *str,
190 enum lttng_event_rule_kernel_syscall_emission_site *type)
191 {
192 bool ret = false;
193 const char kernel_prefix[] = "kernel:";
194 const size_t kernel_prefix_len = sizeof(kernel_prefix) - 1;
195
196 /*
197 * If the passed string is of the form "kernel:syscall*", move the
198 * pointer passed "kernel:".
199 */
200 if (strncmp(str, kernel_prefix, kernel_prefix_len) == 0) {
201 str = &str[kernel_prefix_len];
202 }
203
204 if (strcmp(str, "syscall") == 0 || strcmp(str, "syscall:entry+exit") == 0) {
205 *type = LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_ENTRY_EXIT;
206 } else if (strcmp(str, "syscall:entry") == 0) {
207 *type = LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_ENTRY;
208 } else if (strcmp(str, "syscall:exit") == 0) {
209 *type = LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_EXIT;
210 } else {
211 goto error;
212 }
213
214 ret = true;
215
216 error:
217 return ret;
218 }
219
220 /*
221 * Parse `str` as a log level against the passed event rule type.
222 *
223 * Return the log level in `*log_level`. Return true in `*log_level_only` if
224 * the string specifies exactly this log level, false if it specifies at least
225 * this log level.
226 *
227 * Return true if the string was successfully parsed as a log level string.
228 */
229 static bool parse_log_level_string(const char *str,
230 enum lttng_event_rule_type event_rule_type,
231 int *log_level,
232 bool *log_level_only)
233 {
234 bool ret;
235
236 switch (event_rule_type) {
237 case LTTNG_EVENT_RULE_TYPE_USER_TRACEPOINT:
238 {
239 enum lttng_loglevel log_level_min, log_level_max;
240 if (!loglevel_parse_range_string(str, &log_level_min, &log_level_max)) {
241 goto error;
242 }
243
244 /* Only support VAL and VAL.. for now. */
245 if (log_level_min != log_level_max && log_level_max != LTTNG_LOGLEVEL_EMERG) {
246 goto error;
247 }
248
249 *log_level = (int) log_level_min;
250 *log_level_only = log_level_min == log_level_max;
251 break;
252 }
253 case LTTNG_EVENT_RULE_TYPE_LOG4J_LOGGING:
254 {
255 enum lttng_loglevel_log4j log_level_min, log_level_max;
256 if (!loglevel_log4j_parse_range_string(str, &log_level_min, &log_level_max)) {
257 goto error;
258 }
259
260 /* Only support VAL and VAL.. for now. */
261 if (log_level_min != log_level_max && log_level_max != LTTNG_LOGLEVEL_LOG4J_FATAL) {
262 goto error;
263 }
264
265 *log_level = (int) log_level_min;
266 *log_level_only = log_level_min == log_level_max;
267 break;
268 }
269 case LTTNG_EVENT_RULE_TYPE_JUL_LOGGING:
270 {
271 enum lttng_loglevel_jul log_level_min, log_level_max;
272 if (!loglevel_jul_parse_range_string(str, &log_level_min, &log_level_max)) {
273 goto error;
274 }
275
276 /* Only support VAL and VAL.. for now. */
277 if (log_level_min != log_level_max && log_level_max != LTTNG_LOGLEVEL_JUL_SEVERE) {
278 goto error;
279 }
280
281 *log_level = (int) log_level_min;
282 *log_level_only = log_level_min == log_level_max;
283 break;
284 }
285 case LTTNG_EVENT_RULE_TYPE_PYTHON_LOGGING:
286 {
287 enum lttng_loglevel_python log_level_min, log_level_max;
288 if (!loglevel_python_parse_range_string(str, &log_level_min, &log_level_max)) {
289 goto error;
290 }
291
292 /* Only support VAL and VAL.. for now. */
293 if (log_level_min != log_level_max &&
294 log_level_max != LTTNG_LOGLEVEL_PYTHON_CRITICAL) {
295 goto error;
296 }
297
298 *log_level = (int) log_level_min;
299 *log_level_only = log_level_min == log_level_max;
300 break;
301 }
302 default:
303 /* Invalid domain type. */
304 abort();
305 }
306
307 ret = true;
308 goto end;
309
310 error:
311 ret = false;
312
313 end:
314 return ret;
315 }
316
317 static int parse_kernel_probe_opts(const char *source,
318 struct lttng_kernel_probe_location **location)
319 {
320 int ret = 0;
321 int match;
322 char s_hex[19];
323 char name[LTTNG_SYMBOL_NAME_LEN];
324 char *symbol_name = nullptr;
325 uint64_t offset;
326
327 /* Check for symbol+offset. */
328 match = sscanf(
329 source, "%" LTTNG_SYMBOL_NAME_LEN_SCANF_IS_A_BROKEN_API "[^'+']+%18s", name, s_hex);
330 if (match == 2) {
331 if (*s_hex == '\0') {
332 ERR("Kernel probe symbol offset is missing.");
333 goto error;
334 }
335
336 symbol_name = strndup(name, LTTNG_SYMBOL_NAME_LEN);
337 if (!symbol_name) {
338 PERROR("Failed to copy kernel probe location symbol name.");
339 goto error;
340 }
341 offset = strtoull(s_hex, nullptr, 0);
342
343 *location = lttng_kernel_probe_location_symbol_create(symbol_name, offset);
344 if (!*location) {
345 ERR("Failed to create symbol kernel probe location.");
346 goto error;
347 }
348
349 goto end;
350 }
351
352 /* Check for symbol. */
353 if (isalpha(name[0]) || name[0] == '_') {
354 match = sscanf(source, "%" LTTNG_SYMBOL_NAME_LEN_SCANF_IS_A_BROKEN_API "s", name);
355 if (match == 1) {
356 symbol_name = strndup(name, LTTNG_SYMBOL_NAME_LEN);
357 if (!symbol_name) {
358 ERR("Failed to copy kernel probe location symbol name.");
359 goto error;
360 }
361
362 *location = lttng_kernel_probe_location_symbol_create(symbol_name, 0);
363 if (!*location) {
364 ERR("Failed to create symbol kernel probe location.");
365 goto error;
366 }
367
368 goto end;
369 }
370 }
371
372 /* Check for address. */
373 match = sscanf(source, "%18s", s_hex);
374 if (match > 0) {
375 uint64_t address;
376
377 if (*s_hex == '\0') {
378 ERR("Invalid kernel probe location address.");
379 goto error;
380 }
381
382 address = strtoull(s_hex, nullptr, 0);
383 *location = lttng_kernel_probe_location_address_create(address);
384 if (!*location) {
385 ERR("Failed to create symbol kernel probe location.");
386 goto error;
387 }
388
389 goto end;
390 }
391
392 error:
393 /* No match */
394 ret = -1;
395 *location = nullptr;
396
397 end:
398 free(symbol_name);
399 return ret;
400 }
401
402 static struct lttng_event_expr *
403 ir_op_load_expr_to_event_expr(const struct ir_load_expression *load_expr, const char *capture_str)
404 {
405 char *provider_name = nullptr;
406 struct lttng_event_expr *event_expr = nullptr;
407 const struct ir_load_expression_op *load_expr_op = load_expr->child;
408 const enum ir_load_expression_type load_expr_child_type = load_expr_op->type;
409
410 switch (load_expr_child_type) {
411 case IR_LOAD_EXPRESSION_GET_PAYLOAD_ROOT:
412 case IR_LOAD_EXPRESSION_GET_CONTEXT_ROOT:
413 {
414 const char *field_name;
415
416 load_expr_op = load_expr_op->next;
417 LTTNG_ASSERT(load_expr_op);
418 LTTNG_ASSERT(load_expr_op->type == IR_LOAD_EXPRESSION_GET_SYMBOL);
419 field_name = load_expr_op->u.symbol;
420 LTTNG_ASSERT(field_name);
421
422 event_expr = load_expr_child_type == IR_LOAD_EXPRESSION_GET_PAYLOAD_ROOT ?
423 lttng_event_expr_event_payload_field_create(field_name) :
424 lttng_event_expr_channel_context_field_create(field_name);
425 if (!event_expr) {
426 ERR("Failed to create %s event expression: field name = `%s`.",
427 load_expr_child_type == IR_LOAD_EXPRESSION_GET_PAYLOAD_ROOT ?
428 "payload field" :
429 "channel context",
430 field_name);
431 goto error;
432 }
433
434 break;
435 }
436 case IR_LOAD_EXPRESSION_GET_APP_CONTEXT_ROOT:
437 {
438 const char *colon;
439 const char *type_name;
440 const char *field_name;
441
442 load_expr_op = load_expr_op->next;
443 LTTNG_ASSERT(load_expr_op);
444 LTTNG_ASSERT(load_expr_op->type == IR_LOAD_EXPRESSION_GET_SYMBOL);
445 field_name = load_expr_op->u.symbol;
446 LTTNG_ASSERT(field_name);
447
448 /*
449 * The field name needs to be of the form PROVIDER:TYPE. We
450 * split it here.
451 */
452 colon = strchr(field_name, ':');
453 if (!colon) {
454 ERR("Invalid app-specific context field name: missing colon in `%s`.",
455 field_name);
456 goto error;
457 }
458
459 type_name = colon + 1;
460 if (*type_name == '\0') {
461 ERR("Invalid app-specific context field name: missing type name after colon in `%s`.",
462 field_name);
463 goto error;
464 }
465
466 provider_name = strndup(field_name, colon - field_name);
467 if (!provider_name) {
468 PERROR("Failed to allocate field name string");
469 goto error;
470 }
471
472 event_expr = lttng_event_expr_app_specific_context_field_create(provider_name,
473 type_name);
474 if (!event_expr) {
475 ERR("Failed to create app-specific context field event expression: provider name = `%s`, type name = `%s`",
476 provider_name,
477 type_name);
478 goto error;
479 }
480
481 break;
482 }
483 default:
484 ERR("%s: unexpected load expr type %d.", __func__, load_expr_op->type);
485 abort();
486 }
487
488 load_expr_op = load_expr_op->next;
489
490 /* There may be a single array index after that. */
491 if (load_expr_op->type == IR_LOAD_EXPRESSION_GET_INDEX) {
492 struct lttng_event_expr *index_event_expr;
493 const uint64_t index = load_expr_op->u.index;
494
495 index_event_expr = lttng_event_expr_array_field_element_create(event_expr, index);
496 if (!index_event_expr) {
497 ERR("Failed to create array field element event expression.");
498 goto error;
499 }
500
501 event_expr = index_event_expr;
502 load_expr_op = load_expr_op->next;
503 }
504
505 switch (load_expr_op->type) {
506 case IR_LOAD_EXPRESSION_LOAD_FIELD:
507 /*
508 * This is what we expect, IR_LOAD_EXPRESSION_LOAD_FIELD is
509 * always found at the end of the chain.
510 */
511 break;
512 case IR_LOAD_EXPRESSION_GET_SYMBOL:
513 ERR("While parsing expression `%s`: Capturing subfields is not supported.",
514 capture_str);
515 goto error;
516
517 default:
518 ERR("%s: unexpected load expression operator %s.",
519 __func__,
520 ir_load_expression_type_str(load_expr_op->type));
521 abort();
522 }
523
524 goto end;
525
526 error:
527 lttng_event_expr_destroy(event_expr);
528 event_expr = nullptr;
529
530 end:
531 free(provider_name);
532
533 return event_expr;
534 }
535
536 static struct lttng_event_expr *ir_op_load_to_event_expr(const struct ir_op *ir,
537 const char *capture_str)
538 {
539 struct lttng_event_expr *event_expr = nullptr;
540
541 LTTNG_ASSERT(ir->op == IR_OP_LOAD);
542
543 switch (ir->data_type) {
544 case IR_DATA_EXPRESSION:
545 {
546 const struct ir_load_expression *ir_load_expr = ir->u.load.u.expression;
547
548 event_expr = ir_op_load_expr_to_event_expr(ir_load_expr, capture_str);
549 break;
550 }
551 default:
552 ERR("%s: unexpected data type: %s.", __func__, ir_data_type_str(ir->data_type));
553 abort();
554 }
555
556 return event_expr;
557 }
558
559 static const char *ir_operator_type_human_str(enum ir_op_type op)
560 {
561 const char *name;
562
563 switch (op) {
564 case IR_OP_BINARY:
565 name = "Binary";
566 break;
567 case IR_OP_UNARY:
568 name = "Unary";
569 break;
570 case IR_OP_LOGICAL:
571 name = "Logical";
572 break;
573 default:
574 abort();
575 }
576
577 return name;
578 }
579
580 static struct lttng_event_expr *ir_op_root_to_event_expr(const struct ir_op *ir,
581 const char *capture_str)
582 {
583 struct lttng_event_expr *event_expr = nullptr;
584
585 LTTNG_ASSERT(ir->op == IR_OP_ROOT);
586 ir = ir->u.root.child;
587
588 switch (ir->op) {
589 case IR_OP_LOAD:
590 event_expr = ir_op_load_to_event_expr(ir, capture_str);
591 break;
592 case IR_OP_BINARY:
593 case IR_OP_UNARY:
594 case IR_OP_LOGICAL:
595 ERR("While parsing expression `%s`: %s operators are not allowed in capture expressions.",
596 capture_str,
597 ir_operator_type_human_str(ir->op));
598 break;
599 default:
600 ERR("%s: unexpected IR op type: %s.", __func__, ir_op_type_str(ir->op));
601 abort();
602 }
603
604 return event_expr;
605 }
606
607 static void destroy_event_expr(void *ptr)
608 {
609 lttng_event_expr_destroy((lttng_event_expr *) ptr);
610 }
611
612 namespace {
613 struct parse_event_rule_res {
614 /* Owned by this. */
615 struct lttng_event_rule *er;
616
617 /* Array of `struct lttng_event_expr *` */
618 struct lttng_dynamic_pointer_array capture_descriptors;
619 };
620 } /* namespace */
621
622 static struct parse_event_rule_res parse_event_rule(int *argc, const char ***argv, int argc_offset)
623 {
624 enum lttng_event_rule_type event_rule_type = LTTNG_EVENT_RULE_TYPE_UNKNOWN;
625 struct argpar_iter *argpar_iter = nullptr;
626 const struct argpar_item *argpar_item = nullptr;
627 int consumed_args = -1;
628 struct lttng_kernel_probe_location *kernel_probe_location = nullptr;
629 struct lttng_userspace_probe_location *userspace_probe_location = nullptr;
630 struct parse_event_rule_res res = {};
631 struct lttng_event_expr *event_expr = nullptr;
632 struct filter_parser_ctx *parser_ctx = nullptr;
633 struct lttng_log_level_rule *log_level_rule = nullptr;
634
635 /* Event rule type option */
636 char *event_rule_type_str = nullptr;
637
638 /* Tracepoint and syscall options. */
639 char *name = nullptr;
640 /* Array of strings. */
641 struct lttng_dynamic_pointer_array exclude_names;
642
643 /* For userspace / kernel probe and function. */
644 char *location = nullptr;
645 char *event_name = nullptr;
646
647 /* Filter. */
648 char *filter = nullptr;
649
650 /* Log level. */
651 char *log_level_str = nullptr;
652
653 lttng_dynamic_pointer_array_init(&res.capture_descriptors, destroy_event_expr);
654
655 lttng_dynamic_pointer_array_init(&exclude_names, free);
656
657 argpar_iter = argpar_iter_create(*argc, *argv, event_rule_opt_descrs);
658 if (!argpar_iter) {
659 ERR("Failed to allocate an argpar iter.");
660 goto error;
661 }
662
663 while (true) {
664 enum parse_next_item_status status;
665
666 status = parse_next_item(
667 argpar_iter, &argpar_item, argc_offset, *argv, false, nullptr, nullptr);
668 if (status == PARSE_NEXT_ITEM_STATUS_ERROR ||
669 status == PARSE_NEXT_ITEM_STATUS_ERROR_MEMORY) {
670 goto error;
671 } else if (status == PARSE_NEXT_ITEM_STATUS_END) {
672 break;
673 }
674
675 LTTNG_ASSERT(status == PARSE_NEXT_ITEM_STATUS_OK);
676
677 if (argpar_item_type(argpar_item) == ARGPAR_ITEM_TYPE_OPT) {
678 const struct argpar_opt_descr *descr = argpar_item_opt_descr(argpar_item);
679 const char *arg = argpar_item_opt_arg(argpar_item);
680
681 switch (descr->id) {
682 case OPT_TYPE:
683 if (!assign_event_rule_type(&event_rule_type, arg)) {
684 goto error;
685 }
686
687 /* Save the string for later use. */
688 if (!assign_string(&event_rule_type_str, arg, "--type/-t")) {
689 goto error;
690 }
691
692 break;
693 case OPT_LOCATION:
694 if (!assign_string(&location, arg, "--location/-L")) {
695 goto error;
696 }
697
698 break;
699 case OPT_EVENT_NAME:
700 if (!assign_string(&event_name, arg, "--event-name/-E")) {
701 goto error;
702 }
703
704 break;
705 case OPT_FILTER:
706 if (!assign_string(&filter, arg, "--filter/-f")) {
707 goto error;
708 }
709
710 break;
711 case OPT_NAME:
712 if (!assign_string(&name, arg, "--name/-n")) {
713 goto error;
714 }
715
716 break;
717 case OPT_EXCLUDE_NAME:
718 {
719 int ret;
720
721 ret = lttng_dynamic_pointer_array_add_pointer(&exclude_names,
722 strdup(arg));
723 if (ret != 0) {
724 ERR("Failed to add pointer to dynamic pointer array.");
725 goto error;
726 }
727
728 break;
729 }
730 case OPT_LOG_LEVEL:
731 if (!assign_string(&log_level_str, arg, "--log-level/-l")) {
732 goto error;
733 }
734
735 break;
736 case OPT_CAPTURE:
737 {
738 int ret;
739
740 ret = filter_parser_ctx_create_from_filter_expression(arg,
741 &parser_ctx);
742 if (ret) {
743 ERR("Failed to parse capture expression `%s`.", arg);
744 goto error;
745 }
746
747 event_expr = ir_op_root_to_event_expr(parser_ctx->ir_root, arg);
748 filter_parser_ctx_free(parser_ctx);
749 parser_ctx = nullptr;
750 if (!event_expr) {
751 /*
752 * ir_op_root_to_event_expr has printed
753 * an error message.
754 */
755 goto error;
756 }
757
758 ret = lttng_dynamic_pointer_array_add_pointer(
759 &res.capture_descriptors, event_expr);
760 if (ret) {
761 goto error;
762 }
763
764 /*
765 * The ownership of event expression was
766 * transferred to the dynamic array.
767 */
768 event_expr = nullptr;
769
770 break;
771 }
772 default:
773 abort();
774 }
775 } else {
776 const char *arg = argpar_item_non_opt_arg(argpar_item);
777
778 /* Don't accept non-option arguments. */
779 ERR("Unexpected argument '%s'", arg);
780 goto error;
781 }
782 }
783
784 if (event_rule_type == LTTNG_EVENT_RULE_TYPE_UNKNOWN) {
785 ERR("Event rule requires a --type.");
786 goto error;
787 }
788
789 /*
790 * Option --name is applicable to event rules of type kernel, user, jul,
791 * log4j,python and syscall. If --name is omitted, it is implicitly
792 * "*".
793 */
794 switch (event_rule_type) {
795 case LTTNG_EVENT_RULE_TYPE_USER_TRACEPOINT:
796 case LTTNG_EVENT_RULE_TYPE_KERNEL_TRACEPOINT:
797 case LTTNG_EVENT_RULE_TYPE_JUL_LOGGING:
798 case LTTNG_EVENT_RULE_TYPE_LOG4J_LOGGING:
799 case LTTNG_EVENT_RULE_TYPE_PYTHON_LOGGING:
800 case LTTNG_EVENT_RULE_TYPE_KERNEL_SYSCALL:
801 if (!name) {
802 name = strdup("*");
803 }
804 break;
805
806 default:
807 if (name) {
808 ERR("Can't use --name with %s event rules.",
809 lttng_event_rule_type_str(event_rule_type));
810 goto error;
811 }
812
813 if (lttng_dynamic_pointer_array_get_count(&exclude_names) > 0) {
814 ERR("Can't use --exclude-name/-x with %s event rules.",
815 lttng_event_rule_type_str(event_rule_type));
816 goto error;
817 }
818 }
819
820 /*
821 * Option --location is only applicable to (and mandatory for) event
822 * rules of type {k,u}probe and function.
823 *
824 * Option --event-name is only applicable to event rules of type probe.
825 * If omitted, it defaults to the location.
826 */
827 switch (event_rule_type) {
828 case LTTNG_EVENT_RULE_TYPE_KERNEL_KPROBE:
829 case LTTNG_EVENT_RULE_TYPE_KERNEL_UPROBE:
830 if (!location) {
831 ERR("Event rule of type %s requires a --location.",
832 lttng_event_rule_type_str(event_rule_type));
833 goto error;
834 }
835
836 if (!event_name) {
837 event_name = strdup(location);
838 }
839
840 break;
841
842 default:
843 if (location) {
844 ERR("Can't use --location with %s event rules.",
845 lttng_event_rule_type_str(event_rule_type));
846 goto error;
847 }
848
849 if (event_name) {
850 ERR("Can't use --event-name with %s event rules.",
851 lttng_event_rule_type_str(event_rule_type));
852 goto error;
853 }
854 }
855
856 /*
857 * Update *argc and *argv so our caller can keep parsing what follows.
858 */
859 consumed_args = argpar_iter_ingested_orig_args(argpar_iter);
860 LTTNG_ASSERT(consumed_args >= 0);
861 *argc -= consumed_args;
862 *argv += consumed_args;
863
864 /*
865 * Adding a filter to a probe, function or userspace-probe would be
866 * denied by the kernel tracer as it's not supported at the moment. We
867 * do an early check here to warn the user.
868 */
869 if (filter) {
870 switch (event_rule_type) {
871 case LTTNG_EVENT_RULE_TYPE_USER_TRACEPOINT:
872 case LTTNG_EVENT_RULE_TYPE_KERNEL_TRACEPOINT:
873 case LTTNG_EVENT_RULE_TYPE_JUL_LOGGING:
874 case LTTNG_EVENT_RULE_TYPE_LOG4J_LOGGING:
875 case LTTNG_EVENT_RULE_TYPE_PYTHON_LOGGING:
876 case LTTNG_EVENT_RULE_TYPE_KERNEL_SYSCALL:
877 break;
878 default:
879 ERR("Filter expressions are not supported for %s event rules.",
880 lttng_event_rule_type_str(event_rule_type));
881 goto error;
882 }
883 }
884
885 /*
886 * If --exclude-name/-x was passed, split it into an exclusion list.
887 * Exclusions are only supported by
888 * LTTNG_EVENT_RULE_TYPE_USER_TRACEPOINT for now.
889 */
890 if (lttng_dynamic_pointer_array_get_count(&exclude_names) > 0) {
891 if (event_rule_type != LTTNG_EVENT_RULE_TYPE_USER_TRACEPOINT) {
892 ERR("Event name exclusions are not yet implemented for %s event rules.",
893 lttng_event_rule_type_str(event_rule_type));
894 goto error;
895 }
896
897 if (validate_exclusion_list(name, &exclude_names) != 0) {
898 /*
899 * Assume validate_exclusion_list already prints an
900 * error message.
901 */
902 goto error;
903 }
904 }
905
906 if (log_level_str) {
907 switch (event_rule_type) {
908 case LTTNG_EVENT_RULE_TYPE_USER_TRACEPOINT:
909 case LTTNG_EVENT_RULE_TYPE_JUL_LOGGING:
910 case LTTNG_EVENT_RULE_TYPE_LOG4J_LOGGING:
911 case LTTNG_EVENT_RULE_TYPE_PYTHON_LOGGING:
912 {
913 int log_level;
914 bool log_level_only;
915
916 if (strcmp(log_level_str, "..") == 0) {
917 /*
918 * ".." is the same as passing no log level
919 * option and correspond to the "ANY" case.
920 */
921 break;
922 }
923
924 if (!parse_log_level_string(
925 log_level_str, event_rule_type, &log_level, &log_level_only)) {
926 ERR("Failed to parse log level string `%s`.", log_level_str);
927 goto error;
928 }
929
930 if (log_level_only) {
931 log_level_rule = lttng_log_level_rule_exactly_create(log_level);
932 } else {
933 log_level_rule = lttng_log_level_rule_at_least_as_severe_as_create(
934 log_level);
935 }
936
937 if (log_level_rule == nullptr) {
938 ERR("Failed to create log level rule object.");
939 goto error;
940 }
941 break;
942 }
943 default:
944 ERR("Log levels are not supported for %s event rules.",
945 lttng_event_rule_type_str(event_rule_type));
946 goto error;
947 }
948 }
949
950 /* Finally, create the event rule object. */
951 switch (event_rule_type) {
952 case LTTNG_EVENT_RULE_TYPE_USER_TRACEPOINT:
953 {
954 enum lttng_event_rule_status event_rule_status;
955
956 res.er = lttng_event_rule_user_tracepoint_create();
957 if (!res.er) {
958 ERR("Failed to create user_tracepoint event rule.");
959 goto error;
960 }
961
962 /* Set pattern. */
963 event_rule_status = lttng_event_rule_user_tracepoint_set_name_pattern(res.er, name);
964 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
965 ERR("Failed to set user_tracepoint event rule's pattern to '%s'.", name);
966 goto error;
967 }
968
969 /* Set filter. */
970 if (filter) {
971 event_rule_status =
972 lttng_event_rule_user_tracepoint_set_filter(res.er, filter);
973 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
974 ERR("Failed to set user_tracepoint event rule's filter to '%s'.",
975 filter);
976 goto error;
977 }
978 }
979
980 /* Set exclusion list. */
981 if (lttng_dynamic_pointer_array_get_count(&exclude_names) > 0) {
982 int n;
983 int count = lttng_dynamic_pointer_array_get_count(&exclude_names);
984
985 for (n = 0; n < count; n++) {
986 const char *exclude_name =
987 (const char *) lttng_dynamic_pointer_array_get_pointer(
988 &exclude_names, n);
989
990 event_rule_status =
991 lttng_event_rule_user_tracepoint_add_name_pattern_exclusion(
992 res.er, exclude_name);
993 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
994 ERR("Failed to set user_tracepoint exclusion list element '%s'",
995 exclude_name);
996 goto error;
997 }
998 }
999 }
1000
1001 if (log_level_rule) {
1002 event_rule_status = lttng_event_rule_user_tracepoint_set_log_level_rule(
1003 res.er, log_level_rule);
1004
1005 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
1006 ERR("Failed to set log level on event fule.");
1007 goto error;
1008 }
1009 }
1010
1011 break;
1012 }
1013 case LTTNG_EVENT_RULE_TYPE_KERNEL_TRACEPOINT:
1014 {
1015 enum lttng_event_rule_status event_rule_status;
1016
1017 res.er = lttng_event_rule_kernel_tracepoint_create();
1018 if (!res.er) {
1019 ERR("Failed to create kernel_tracepoint event rule.");
1020 goto error;
1021 }
1022
1023 /* Set pattern. */
1024 event_rule_status =
1025 lttng_event_rule_kernel_tracepoint_set_name_pattern(res.er, name);
1026 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
1027 ERR("Failed to set kernel_tracepoint event rule's pattern to '%s'.", name);
1028 goto error;
1029 }
1030
1031 /* Set filter. */
1032 if (filter) {
1033 event_rule_status =
1034 lttng_event_rule_kernel_tracepoint_set_filter(res.er, filter);
1035 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
1036 ERR("Failed to set kernel_tracepoint event rule's filter to '%s'.",
1037 filter);
1038 goto error;
1039 }
1040 }
1041 break;
1042 }
1043 case LTTNG_EVENT_RULE_TYPE_JUL_LOGGING:
1044 {
1045 enum lttng_event_rule_status event_rule_status;
1046
1047 res.er = lttng_event_rule_jul_logging_create();
1048 if (!res.er) {
1049 ERR("Failed to create jul_logging event rule.");
1050 goto error;
1051 }
1052
1053 /* Set pattern. */
1054 event_rule_status = lttng_event_rule_jul_logging_set_name_pattern(res.er, name);
1055 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
1056 ERR("Failed to set jul_logging event rule's pattern to '%s'.", name);
1057 goto error;
1058 }
1059
1060 /* Set filter. */
1061 if (filter) {
1062 event_rule_status = lttng_event_rule_jul_logging_set_filter(res.er, filter);
1063 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
1064 ERR("Failed to set jul_logging event rule's filter to '%s'.",
1065 filter);
1066 goto error;
1067 }
1068 }
1069
1070 if (log_level_rule) {
1071 event_rule_status = lttng_event_rule_jul_logging_set_log_level_rule(
1072 res.er, log_level_rule);
1073
1074 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
1075 ERR("Failed to set log level on event fule.");
1076 goto error;
1077 }
1078 }
1079 break;
1080 }
1081 case LTTNG_EVENT_RULE_TYPE_LOG4J_LOGGING:
1082 {
1083 enum lttng_event_rule_status event_rule_status;
1084
1085 res.er = lttng_event_rule_log4j_logging_create();
1086 if (!res.er) {
1087 ERR("Failed to create jul_logging event rule.");
1088 goto error;
1089 }
1090
1091 /* Set pattern. */
1092 event_rule_status = lttng_event_rule_log4j_logging_set_name_pattern(res.er, name);
1093 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
1094 ERR("Failed to set jul_logging event rule's pattern to '%s'.", name);
1095 goto error;
1096 }
1097
1098 /* Set filter. */
1099 if (filter) {
1100 event_rule_status =
1101 lttng_event_rule_log4j_logging_set_filter(res.er, filter);
1102 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
1103 ERR("Failed to set jul_logging event rule's filter to '%s'.",
1104 filter);
1105 goto error;
1106 }
1107 }
1108
1109 if (log_level_rule) {
1110 event_rule_status = lttng_event_rule_log4j_logging_set_log_level_rule(
1111 res.er, log_level_rule);
1112
1113 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
1114 ERR("Failed to set log level on event fule.");
1115 goto error;
1116 }
1117 }
1118 break;
1119 }
1120 case LTTNG_EVENT_RULE_TYPE_PYTHON_LOGGING:
1121 {
1122 enum lttng_event_rule_status event_rule_status;
1123
1124 res.er = lttng_event_rule_python_logging_create();
1125 if (!res.er) {
1126 ERR("Failed to create jul_logging event rule.");
1127 goto error;
1128 }
1129
1130 /* Set pattern. */
1131 event_rule_status = lttng_event_rule_python_logging_set_name_pattern(res.er, name);
1132 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
1133 ERR("Failed to set jul_logging event rule's pattern to '%s'.", name);
1134 goto error;
1135 }
1136
1137 /* Set filter. */
1138 if (filter) {
1139 event_rule_status =
1140 lttng_event_rule_python_logging_set_filter(res.er, filter);
1141 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
1142 ERR("Failed to set jul_logging event rule's filter to '%s'.",
1143 filter);
1144 goto error;
1145 }
1146 }
1147
1148 if (log_level_rule) {
1149 event_rule_status = lttng_event_rule_python_logging_set_log_level_rule(
1150 res.er, log_level_rule);
1151
1152 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
1153 ERR("Failed to set log level on event fule.");
1154 goto error;
1155 }
1156 }
1157 break;
1158 }
1159 case LTTNG_EVENT_RULE_TYPE_KERNEL_KPROBE:
1160 {
1161 int ret;
1162 enum lttng_event_rule_status event_rule_status;
1163
1164 ret = parse_kernel_probe_opts(location, &kernel_probe_location);
1165 if (ret) {
1166 ERR("Failed to parse kernel probe location.");
1167 goto error;
1168 }
1169
1170 LTTNG_ASSERT(kernel_probe_location);
1171 res.er = lttng_event_rule_kernel_kprobe_create(kernel_probe_location);
1172 if (!res.er) {
1173 ERR("Failed to create kprobe event rule.");
1174 goto error;
1175 }
1176
1177 event_rule_status =
1178 lttng_event_rule_kernel_kprobe_set_event_name(res.er, event_name);
1179 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
1180 ERR("Failed to set kprobe event rule's name to '%s'.", event_name);
1181 goto error;
1182 }
1183
1184 break;
1185 }
1186 case LTTNG_EVENT_RULE_TYPE_KERNEL_UPROBE:
1187 {
1188 int ret;
1189 enum lttng_event_rule_status event_rule_status;
1190
1191 ret = parse_userspace_probe_opts(location, &userspace_probe_location);
1192 if (ret) {
1193 ERR("Failed to parse user space probe location.");
1194 goto error;
1195 }
1196
1197 res.er = lttng_event_rule_kernel_uprobe_create(userspace_probe_location);
1198 if (!res.er) {
1199 ERR("Failed to create userspace probe event rule.");
1200 goto error;
1201 }
1202
1203 event_rule_status =
1204 lttng_event_rule_kernel_uprobe_set_event_name(res.er, event_name);
1205 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
1206 ERR("Failed to set user space probe event rule's name to '%s'.",
1207 event_name);
1208 goto error;
1209 }
1210
1211 break;
1212 }
1213 case LTTNG_EVENT_RULE_TYPE_KERNEL_SYSCALL:
1214 {
1215 enum lttng_event_rule_status event_rule_status;
1216 enum lttng_event_rule_kernel_syscall_emission_site emission_site;
1217
1218 if (!parse_syscall_emission_site_from_type(event_rule_type_str, &emission_site)) {
1219 ERR("Failed to parse syscall type '%s'.", event_rule_type_str);
1220 goto error;
1221 }
1222
1223 res.er = lttng_event_rule_kernel_syscall_create(emission_site);
1224 if (!res.er) {
1225 ERR("Failed to create syscall event rule.");
1226 goto error;
1227 }
1228
1229 event_rule_status = lttng_event_rule_kernel_syscall_set_name_pattern(res.er, name);
1230 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
1231 ERR("Failed to set syscall event rule's pattern to '%s'.", name);
1232 goto error;
1233 }
1234
1235 if (filter) {
1236 event_rule_status =
1237 lttng_event_rule_kernel_syscall_set_filter(res.er, filter);
1238 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
1239 ERR("Failed to set syscall event rule's filter to '%s'.", filter);
1240 goto error;
1241 }
1242 }
1243
1244 break;
1245 }
1246 default:
1247 abort();
1248 goto error;
1249 }
1250
1251 goto end;
1252
1253 error:
1254 lttng_event_rule_destroy(res.er);
1255 res.er = nullptr;
1256 lttng_dynamic_pointer_array_reset(&res.capture_descriptors);
1257
1258 end:
1259 if (parser_ctx) {
1260 filter_parser_ctx_free(parser_ctx);
1261 }
1262
1263 lttng_event_expr_destroy(event_expr);
1264 argpar_item_destroy(argpar_item);
1265 argpar_iter_destroy(argpar_iter);
1266 free(filter);
1267 free(name);
1268 lttng_dynamic_pointer_array_reset(&exclude_names);
1269 free(log_level_str);
1270 free(location);
1271 free(event_name);
1272 free(event_rule_type_str);
1273
1274 lttng_kernel_probe_location_destroy(kernel_probe_location);
1275 lttng_userspace_probe_location_destroy(userspace_probe_location);
1276 lttng_log_level_rule_destroy(log_level_rule);
1277 return res;
1278 }
1279
1280 static struct lttng_condition *
1281 handle_condition_event(int *argc, const char ***argv, int argc_offset)
1282 {
1283 struct parse_event_rule_res res;
1284 struct lttng_condition *c;
1285 size_t i;
1286
1287 res = parse_event_rule(argc, argv, argc_offset);
1288 if (!res.er) {
1289 c = nullptr;
1290 goto error;
1291 }
1292
1293 c = lttng_condition_event_rule_matches_create(res.er);
1294 lttng_event_rule_destroy(res.er);
1295 res.er = nullptr;
1296 if (!c) {
1297 goto error;
1298 }
1299
1300 for (i = 0; i < lttng_dynamic_pointer_array_get_count(&res.capture_descriptors); i++) {
1301 enum lttng_condition_status status;
1302 struct lttng_event_expr **expr =
1303 (lttng_event_expr **) lttng_dynamic_array_get_element(
1304 &res.capture_descriptors.array, i);
1305
1306 LTTNG_ASSERT(expr);
1307 LTTNG_ASSERT(*expr);
1308 status = lttng_condition_event_rule_matches_append_capture_descriptor(c, *expr);
1309 if (status != LTTNG_CONDITION_STATUS_OK) {
1310 if (status == LTTNG_CONDITION_STATUS_UNSUPPORTED) {
1311 ERR("The capture feature is unsupported by the event-rule condition type");
1312 }
1313
1314 goto error;
1315 }
1316
1317 /* Ownership of event expression moved to `c` */
1318 *expr = nullptr;
1319 }
1320
1321 goto end;
1322
1323 error:
1324 lttng_condition_destroy(c);
1325 c = nullptr;
1326
1327 end:
1328 lttng_dynamic_pointer_array_reset(&res.capture_descriptors);
1329 lttng_event_rule_destroy(res.er);
1330 return c;
1331 }
1332
1333 namespace {
1334 struct condition_descr {
1335 const char *name;
1336 struct lttng_condition *(*handler)(int *argc, const char ***argv, int argc_offset);
1337 };
1338 } /* namespace */
1339
1340 static const struct condition_descr condition_descrs[] = {
1341 { "event-rule-matches", handle_condition_event },
1342 };
1343
1344 static void print_valid_condition_names()
1345 {
1346 unsigned int i;
1347
1348 ERR("Valid condition names are:");
1349
1350 for (i = 0; i < ARRAY_SIZE(condition_descrs); ++i) {
1351 ERR(" %s", condition_descrs[i].name);
1352 }
1353 }
1354
1355 static struct lttng_condition *parse_condition(const char *condition_name,
1356 int *argc,
1357 const char ***argv,
1358 int argc_offset,
1359 int orig_arg_index,
1360 const char *orig_arg)
1361 {
1362 int i;
1363 struct lttng_condition *cond;
1364 const struct condition_descr *descr = nullptr;
1365
1366 for (i = 0; i < ARRAY_SIZE(condition_descrs); i++) {
1367 if (strcmp(condition_name, condition_descrs[i].name) == 0) {
1368 descr = &condition_descrs[i];
1369 break;
1370 }
1371 }
1372
1373 if (!descr) {
1374 ERR(WHILE_PARSING_ARG_N_ARG_FMT "Unknown condition name '%s'",
1375 orig_arg_index + 1,
1376 orig_arg,
1377 condition_name);
1378 print_valid_condition_names();
1379 goto error;
1380 }
1381
1382 cond = descr->handler(argc, argv, argc_offset);
1383 if (!cond) {
1384 /* The handler has already printed an error message. */
1385 goto error;
1386 }
1387
1388 goto end;
1389 error:
1390 cond = nullptr;
1391 end:
1392 return cond;
1393 }
1394
1395 static struct lttng_rate_policy *parse_rate_policy(const char *policy_str)
1396 {
1397 int ret;
1398 size_t num_token = 0;
1399 struct lttng_dynamic_pointer_array tokens;
1400 struct lttng_rate_policy *policy = nullptr;
1401 enum lttng_rate_policy_type policy_type;
1402 unsigned long long value;
1403 char *policy_type_str;
1404 char *policy_value_str;
1405
1406 LTTNG_ASSERT(policy_str);
1407 lttng_dynamic_pointer_array_init(&tokens, nullptr);
1408
1409 /* Rate policy fields are separated by ':'. */
1410 ret = strutils_split(policy_str, ':', true, &tokens);
1411 if (ret == 0) {
1412 num_token = lttng_dynamic_pointer_array_get_count(&tokens);
1413 }
1414
1415 /*
1416 * Early sanity check that the number of parameter is exactly 2.
1417 * i.e : type:value
1418 */
1419 if (num_token != 2) {
1420 ERR("Rate policy format is invalid.");
1421 goto end;
1422 }
1423
1424 policy_type_str = (char *) lttng_dynamic_pointer_array_get_pointer(&tokens, 0);
1425 policy_value_str = (char *) lttng_dynamic_pointer_array_get_pointer(&tokens, 1);
1426
1427 /* Parse the type. */
1428 if (strcmp(policy_type_str, "once-after") == 0) {
1429 policy_type = LTTNG_RATE_POLICY_TYPE_ONCE_AFTER_N;
1430 } else if (strcmp(policy_type_str, "every") == 0) {
1431 policy_type = LTTNG_RATE_POLICY_TYPE_EVERY_N;
1432 } else {
1433 ERR("Rate policy type `%s` unknown.", policy_type_str);
1434 goto end;
1435 }
1436
1437 /* Parse the value. */
1438 if (utils_parse_unsigned_long_long(policy_value_str, &value) != 0) {
1439 ERR("Failed to parse rate policy value `%s` as an integer.", policy_value_str);
1440 goto end;
1441 }
1442
1443 if (value == 0) {
1444 ERR("Rate policy value `%s` must be > 0.", policy_value_str);
1445 goto end;
1446 }
1447
1448 switch (policy_type) {
1449 case LTTNG_RATE_POLICY_TYPE_EVERY_N:
1450 policy = lttng_rate_policy_every_n_create(value);
1451 break;
1452 case LTTNG_RATE_POLICY_TYPE_ONCE_AFTER_N:
1453 policy = lttng_rate_policy_once_after_n_create(value);
1454 break;
1455 default:
1456 abort();
1457 }
1458
1459 if (policy == nullptr) {
1460 ERR("Failed to create rate policy `%s`.", policy_str);
1461 }
1462
1463 end:
1464 lttng_dynamic_pointer_array_reset(&tokens);
1465 return policy;
1466 }
1467
1468 static const struct argpar_opt_descr notify_action_opt_descrs[] = {
1469 { OPT_RATE_POLICY, '\0', "rate-policy", true }, ARGPAR_OPT_DESCR_SENTINEL
1470 };
1471
1472 static struct lttng_action *handle_action_notify(int *argc, const char ***argv, int argc_offset)
1473 {
1474 struct lttng_action *action = nullptr;
1475 struct argpar_iter *argpar_iter = nullptr;
1476 const struct argpar_item *argpar_item = nullptr;
1477 struct lttng_rate_policy *policy = nullptr;
1478
1479 argpar_iter = argpar_iter_create(*argc, *argv, notify_action_opt_descrs);
1480 if (!argpar_iter) {
1481 ERR("Failed to allocate an argpar iter.");
1482 goto error;
1483 }
1484
1485 while (true) {
1486 enum parse_next_item_status status;
1487
1488 status = parse_next_item(argpar_iter,
1489 &argpar_item,
1490 argc_offset,
1491 *argv,
1492 false,
1493 nullptr,
1494 "While parsing `notify` action:");
1495 if (status == PARSE_NEXT_ITEM_STATUS_ERROR ||
1496 status == PARSE_NEXT_ITEM_STATUS_ERROR_MEMORY) {
1497 goto error;
1498 } else if (status == PARSE_NEXT_ITEM_STATUS_END) {
1499 break;
1500 }
1501
1502 LTTNG_ASSERT(status == PARSE_NEXT_ITEM_STATUS_OK);
1503
1504 if (argpar_item_type(argpar_item) == ARGPAR_ITEM_TYPE_OPT) {
1505 const struct argpar_opt_descr *descr = argpar_item_opt_descr(argpar_item);
1506 const char *arg = argpar_item_opt_arg(argpar_item);
1507
1508 switch (descr->id) {
1509 case OPT_RATE_POLICY:
1510 {
1511 policy = parse_rate_policy(arg);
1512 if (!policy) {
1513 goto error;
1514 }
1515 break;
1516 }
1517 default:
1518 abort();
1519 }
1520 } else {
1521 const char *arg = argpar_item_non_opt_arg(argpar_item);
1522
1523 ERR("Unexpected argument `%s`.", arg);
1524 goto error;
1525 }
1526 }
1527
1528 *argc -= argpar_iter_ingested_orig_args(argpar_iter);
1529 *argv += argpar_iter_ingested_orig_args(argpar_iter);
1530
1531 action = lttng_action_notify_create();
1532 if (!action) {
1533 ERR("Failed to create notify action");
1534 goto error;
1535 }
1536
1537 if (policy) {
1538 enum lttng_action_status status;
1539 status = lttng_action_notify_set_rate_policy(action, policy);
1540 if (status != LTTNG_ACTION_STATUS_OK) {
1541 ERR("Failed to set rate policy");
1542 goto error;
1543 }
1544 }
1545
1546 goto end;
1547
1548 error:
1549 lttng_action_destroy(action);
1550 action = nullptr;
1551 end:
1552 lttng_rate_policy_destroy(policy);
1553 argpar_item_destroy(argpar_item);
1554 argpar_iter_destroy(argpar_iter);
1555 return action;
1556 }
1557
1558 /*
1559 * Generic handler for a kind of action that takes a session name and an
1560 * optional rate policy.
1561 */
1562
1563 static struct lttng_action *handle_action_simple_session_with_policy(
1564 int *argc,
1565 const char ***argv,
1566 int argc_offset,
1567 struct lttng_action *(*create_action_cb)(),
1568 enum lttng_action_status (*set_session_name_cb)(struct lttng_action *, const char *),
1569 enum lttng_action_status (*set_rate_policy_cb)(struct lttng_action *,
1570 const struct lttng_rate_policy *),
1571 const char *action_name)
1572 {
1573 struct lttng_action *action = nullptr;
1574 struct argpar_iter *argpar_iter = nullptr;
1575 const struct argpar_item *argpar_item = nullptr;
1576 const char *session_name_arg = nullptr;
1577 enum lttng_action_status action_status;
1578 struct lttng_rate_policy *policy = nullptr;
1579
1580 LTTNG_ASSERT(set_session_name_cb);
1581 LTTNG_ASSERT(set_rate_policy_cb);
1582
1583 const struct argpar_opt_descr rate_policy_opt_descrs[] = {
1584 { OPT_RATE_POLICY, '\0', "rate-policy", true }, ARGPAR_OPT_DESCR_SENTINEL
1585 };
1586
1587 argpar_iter = argpar_iter_create(*argc, *argv, rate_policy_opt_descrs);
1588 if (!argpar_iter) {
1589 ERR("Failed to allocate an argpar iter.");
1590 goto error;
1591 }
1592
1593 while (true) {
1594 enum parse_next_item_status status;
1595
1596 status = parse_next_item(argpar_iter,
1597 &argpar_item,
1598 argc_offset,
1599 *argv,
1600 false,
1601 nullptr,
1602 "While parsing `%s` action:",
1603 action_name);
1604 if (status == PARSE_NEXT_ITEM_STATUS_ERROR ||
1605 status == PARSE_NEXT_ITEM_STATUS_ERROR_MEMORY) {
1606 goto error;
1607 } else if (status == PARSE_NEXT_ITEM_STATUS_END) {
1608 break;
1609 }
1610
1611 LTTNG_ASSERT(status == PARSE_NEXT_ITEM_STATUS_OK);
1612
1613 if (argpar_item_type(argpar_item) == ARGPAR_ITEM_TYPE_OPT) {
1614 const struct argpar_opt_descr *descr = argpar_item_opt_descr(argpar_item);
1615 const char *arg = argpar_item_opt_arg(argpar_item);
1616
1617 switch (descr->id) {
1618 case OPT_RATE_POLICY:
1619 {
1620 policy = parse_rate_policy(arg);
1621 if (!policy) {
1622 goto error;
1623 }
1624 break;
1625 }
1626 default:
1627 abort();
1628 }
1629 } else {
1630 const char *arg = argpar_item_non_opt_arg(argpar_item);
1631 unsigned int idx = argpar_item_non_opt_non_opt_index(argpar_item);
1632
1633 switch (idx) {
1634 case 0:
1635 session_name_arg = arg;
1636 break;
1637 default:
1638 ERR("Unexpected argument `%s`.", arg);
1639 goto error;
1640 }
1641 }
1642 }
1643
1644 *argc -= argpar_iter_ingested_orig_args(argpar_iter);
1645 *argv += argpar_iter_ingested_orig_args(argpar_iter);
1646
1647 if (!session_name_arg) {
1648 ERR("Missing session name.");
1649 goto error;
1650 }
1651
1652 action = create_action_cb();
1653 if (!action) {
1654 ERR("Failed to allocate %s session action.", action_name);
1655 goto error;
1656 }
1657
1658 action_status = set_session_name_cb(action, session_name_arg);
1659 if (action_status != LTTNG_ACTION_STATUS_OK) {
1660 ERR("Failed to set action %s session's session name to '%s'.",
1661 action_name,
1662 session_name_arg);
1663 goto error;
1664 }
1665
1666 if (policy) {
1667 action_status = set_rate_policy_cb(action, policy);
1668 if (action_status != LTTNG_ACTION_STATUS_OK) {
1669 ERR("Failed to set rate policy");
1670 goto error;
1671 }
1672 }
1673
1674 goto end;
1675
1676 error:
1677 lttng_action_destroy(action);
1678 action = nullptr;
1679
1680 end:
1681 lttng_rate_policy_destroy(policy);
1682 argpar_item_destroy(argpar_item);
1683 argpar_iter_destroy(argpar_iter);
1684 return action;
1685 }
1686
1687 static struct lttng_action *
1688 handle_action_start_session(int *argc, const char ***argv, int argc_offset)
1689 {
1690 return handle_action_simple_session_with_policy(argc,
1691 argv,
1692 argc_offset,
1693 lttng_action_start_session_create,
1694 lttng_action_start_session_set_session_name,
1695 lttng_action_start_session_set_rate_policy,
1696 "start");
1697 }
1698
1699 static struct lttng_action *
1700 handle_action_stop_session(int *argc, const char ***argv, int argc_offset)
1701 {
1702 return handle_action_simple_session_with_policy(argc,
1703 argv,
1704 argc_offset,
1705 lttng_action_stop_session_create,
1706 lttng_action_stop_session_set_session_name,
1707 lttng_action_stop_session_set_rate_policy,
1708 "stop");
1709 }
1710
1711 static struct lttng_action *
1712 handle_action_rotate_session(int *argc, const char ***argv, int argc_offset)
1713 {
1714 return handle_action_simple_session_with_policy(
1715 argc,
1716 argv,
1717 argc_offset,
1718 lttng_action_rotate_session_create,
1719 lttng_action_rotate_session_set_session_name,
1720 lttng_action_rotate_session_set_rate_policy,
1721 "rotate");
1722 }
1723
1724 static const struct argpar_opt_descr snapshot_action_opt_descrs[] = {
1725 { OPT_NAME, 'n', "name", true },
1726 { OPT_MAX_SIZE, 'm', "max-size", true },
1727 { OPT_CTRL_URL, '\0', "ctrl-url", true },
1728 { OPT_DATA_URL, '\0', "data-url", true },
1729 { OPT_URL, '\0', "url", true },
1730 { OPT_PATH, '\0', "path", true },
1731 { OPT_RATE_POLICY, '\0', "rate-policy", true },
1732 ARGPAR_OPT_DESCR_SENTINEL
1733 };
1734
1735 static struct lttng_action *
1736 handle_action_snapshot_session(int *argc, const char ***argv, int argc_offset)
1737 {
1738 struct lttng_action *action = nullptr;
1739 struct argpar_iter *argpar_iter = nullptr;
1740 const struct argpar_item *argpar_item = nullptr;
1741 const char *session_name_arg = nullptr;
1742 char *snapshot_name_arg = nullptr;
1743 char *ctrl_url_arg = nullptr;
1744 char *data_url_arg = nullptr;
1745 char *max_size_arg = nullptr;
1746 char *url_arg = nullptr;
1747 char *path_arg = nullptr;
1748 char *error = nullptr;
1749 enum lttng_action_status action_status;
1750 struct lttng_snapshot_output *snapshot_output = nullptr;
1751 struct lttng_rate_policy *policy = nullptr;
1752 int ret;
1753 unsigned int locations_specified = 0;
1754
1755 argpar_iter = argpar_iter_create(*argc, *argv, snapshot_action_opt_descrs);
1756 if (!argpar_iter) {
1757 ERR("Failed to allocate an argpar iter.");
1758 goto error;
1759 }
1760
1761 while (true) {
1762 enum parse_next_item_status status;
1763
1764 status = parse_next_item(argpar_iter,
1765 &argpar_item,
1766 argc_offset,
1767 *argv,
1768 false,
1769 nullptr,
1770 "While parsing `snapshot` action:");
1771 if (status == PARSE_NEXT_ITEM_STATUS_ERROR ||
1772 status == PARSE_NEXT_ITEM_STATUS_ERROR_MEMORY) {
1773 goto error;
1774 } else if (status == PARSE_NEXT_ITEM_STATUS_END) {
1775 break;
1776 }
1777
1778 LTTNG_ASSERT(status == PARSE_NEXT_ITEM_STATUS_OK);
1779
1780 if (argpar_item_type(argpar_item) == ARGPAR_ITEM_TYPE_OPT) {
1781 const struct argpar_opt_descr *descr = argpar_item_opt_descr(argpar_item);
1782 const char *arg = argpar_item_opt_arg(argpar_item);
1783
1784 switch (descr->id) {
1785 case OPT_NAME:
1786 if (!assign_string(&snapshot_name_arg, arg, "--name/-n")) {
1787 goto error;
1788 }
1789
1790 break;
1791 case OPT_MAX_SIZE:
1792 if (!assign_string(&max_size_arg, arg, "--max-size/-m")) {
1793 goto error;
1794 }
1795
1796 break;
1797 case OPT_CTRL_URL:
1798 if (!assign_string(&ctrl_url_arg, arg, "--ctrl-url")) {
1799 goto error;
1800 }
1801
1802 break;
1803 case OPT_DATA_URL:
1804 if (!assign_string(&data_url_arg, arg, "--data-url")) {
1805 goto error;
1806 }
1807
1808 break;
1809 case OPT_URL:
1810 if (!assign_string(&url_arg, arg, "--url")) {
1811 goto error;
1812 }
1813
1814 break;
1815 case OPT_PATH:
1816 if (!assign_string(&path_arg, arg, "--path")) {
1817 goto error;
1818 }
1819
1820 break;
1821 case OPT_RATE_POLICY:
1822 {
1823 policy = parse_rate_policy(arg);
1824 if (!policy) {
1825 goto error;
1826 }
1827 break;
1828 }
1829 default:
1830 abort();
1831 }
1832 } else {
1833 const char *arg = argpar_item_non_opt_arg(argpar_item);
1834 const unsigned int idx = argpar_item_non_opt_non_opt_index(argpar_item);
1835
1836 switch (idx) {
1837 case 0:
1838 session_name_arg = arg;
1839 break;
1840 default:
1841 ERR("Unexpected argument `%s`.", arg);
1842 goto error;
1843 }
1844 }
1845 }
1846
1847 *argc -= argpar_iter_ingested_orig_args(argpar_iter);
1848 *argv += argpar_iter_ingested_orig_args(argpar_iter);
1849
1850 if (!session_name_arg) {
1851 ERR("Missing session name.");
1852 goto error;
1853 }
1854
1855 /* --ctrl-url and --data-url must come in pair. */
1856 if (ctrl_url_arg && !data_url_arg) {
1857 ERR("--ctrl-url is specified, but --data-url is missing.");
1858 goto error;
1859 }
1860
1861 if (!ctrl_url_arg && data_url_arg) {
1862 ERR("--data-url is specified, but --ctrl-url is missing.");
1863 goto error;
1864 }
1865
1866 locations_specified += !!(ctrl_url_arg || data_url_arg);
1867 locations_specified += !!url_arg;
1868 locations_specified += !!path_arg;
1869
1870 /* --ctrl-url/--data-url, --url and --path are mutually exclusive. */
1871 if (locations_specified > 1) {
1872 ERR("The --ctrl-url/--data-url, --url, and --path options can't be used together.");
1873 goto error;
1874 }
1875
1876 /*
1877 * Did the user specify an option that implies using a
1878 * custom/unregistered output?
1879 */
1880 if (url_arg || ctrl_url_arg || path_arg) {
1881 snapshot_output = lttng_snapshot_output_create();
1882 if (!snapshot_output) {
1883 ERR("Failed to allocate a snapshot output.");
1884 goto error;
1885 }
1886 }
1887
1888 action = lttng_action_snapshot_session_create();
1889 if (!action) {
1890 ERR("Failed to allocate snapshot session action.");
1891 goto error;
1892 }
1893
1894 action_status = lttng_action_snapshot_session_set_session_name(action, session_name_arg);
1895 if (action_status != LTTNG_ACTION_STATUS_OK) {
1896 ERR("Failed to set action snapshot session's session name to '%s'.",
1897 session_name_arg);
1898 goto error;
1899 }
1900
1901 if (snapshot_name_arg) {
1902 if (!snapshot_output) {
1903 ERR("Can't provide a snapshot output name without a snapshot output destination.");
1904 goto error;
1905 }
1906
1907 ret = lttng_snapshot_output_set_name(snapshot_name_arg, snapshot_output);
1908 if (ret != 0) {
1909 ERR("Failed to set name of snapshot output.");
1910 goto error;
1911 }
1912 }
1913
1914 if (max_size_arg) {
1915 uint64_t max_size;
1916
1917 if (!snapshot_output) {
1918 ERR("Can't provide a snapshot output max size without a snapshot output destination.");
1919 goto error;
1920 }
1921
1922 ret = utils_parse_size_suffix(max_size_arg, &max_size);
1923 if (ret != 0) {
1924 ERR("Failed to parse `%s` as a size.", max_size_arg);
1925 goto error;
1926 }
1927
1928 ret = lttng_snapshot_output_set_size(max_size, snapshot_output);
1929 if (ret != 0) {
1930 ERR("Failed to set snapshot output's max size to %" PRIu64 " bytes.",
1931 max_size);
1932 goto error;
1933 }
1934 }
1935
1936 if (url_arg) {
1937 int num_uris;
1938 struct lttng_uri *uris;
1939
1940 if (!strstr(url_arg, "://")) {
1941 ERR("Failed to parse '%s' as an URL.", url_arg);
1942 goto error;
1943 }
1944
1945 num_uris = uri_parse_str_urls(url_arg, nullptr, &uris);
1946 if (num_uris < 1) {
1947 ERR("Failed to parse '%s' as an URL.", url_arg);
1948 goto error;
1949 }
1950
1951 if (uris[0].dtype == LTTNG_DST_PATH) {
1952 ret = lttng_snapshot_output_set_local_path(uris[0].dst.path,
1953 snapshot_output);
1954 free(uris);
1955 if (ret != 0) {
1956 ERR("Failed to assign '%s' as a local destination.", url_arg);
1957 goto error;
1958 }
1959 } else {
1960 ret = lttng_snapshot_output_set_network_url(url_arg, snapshot_output);
1961 free(uris);
1962 if (ret != 0) {
1963 ERR("Failed to assign '%s' as a network URL.", url_arg);
1964 goto error;
1965 }
1966 }
1967 }
1968
1969 if (path_arg) {
1970 ret = lttng_snapshot_output_set_local_path(path_arg, snapshot_output);
1971 if (ret != 0) {
1972 ERR("Failed to parse '%s' as a local path.", path_arg);
1973 goto error;
1974 }
1975 }
1976
1977 if (ctrl_url_arg) {
1978 /*
1979 * Two argument form, network output with separate control and
1980 * data URLs.
1981 */
1982 ret = lttng_snapshot_output_set_network_urls(
1983 ctrl_url_arg, data_url_arg, snapshot_output);
1984 if (ret != 0) {
1985 ERR("Failed to parse `%s` and `%s` as control and data URLs.",
1986 ctrl_url_arg,
1987 data_url_arg);
1988 goto error;
1989 }
1990 }
1991
1992 if (snapshot_output) {
1993 action_status = lttng_action_snapshot_session_set_output(action, snapshot_output);
1994 if (action_status != LTTNG_ACTION_STATUS_OK) {
1995 ERR("Failed to set snapshot session action's output.");
1996 goto error;
1997 }
1998
1999 /* Ownership of `snapshot_output` has been transferred to the action. */
2000 snapshot_output = nullptr;
2001 }
2002
2003 if (policy) {
2004 enum lttng_action_status status;
2005 status = lttng_action_snapshot_session_set_rate_policy(action, policy);
2006 if (status != LTTNG_ACTION_STATUS_OK) {
2007 ERR("Failed to set rate policy");
2008 goto error;
2009 }
2010 }
2011
2012 goto end;
2013
2014 error:
2015 lttng_action_destroy(action);
2016 action = nullptr;
2017 free(error);
2018 end:
2019 free(snapshot_name_arg);
2020 free(path_arg);
2021 free(url_arg);
2022 free(ctrl_url_arg);
2023 free(data_url_arg);
2024 free(snapshot_output);
2025 free(max_size_arg);
2026 lttng_rate_policy_destroy(policy);
2027 argpar_item_destroy(argpar_item);
2028 argpar_iter_destroy(argpar_iter);
2029 return action;
2030 }
2031
2032 namespace {
2033 struct action_descr {
2034 const char *name;
2035 struct lttng_action *(*handler)(int *argc, const char ***argv, int argc_offset);
2036 };
2037 } /* namespace */
2038
2039 static const struct action_descr action_descrs[] = {
2040 { "notify", handle_action_notify },
2041 { "start-session", handle_action_start_session },
2042 { "stop-session", handle_action_stop_session },
2043 { "rotate-session", handle_action_rotate_session },
2044 { "snapshot-session", handle_action_snapshot_session },
2045 };
2046
2047 static void print_valid_action_names()
2048 {
2049 unsigned int i;
2050
2051 ERR("Valid action names are:");
2052
2053 for (i = 0; i < ARRAY_SIZE(condition_descrs); ++i) {
2054 ERR(" %s", action_descrs[i].name);
2055 }
2056 }
2057
2058 static struct lttng_action *parse_action(const char *action_name,
2059 int *argc,
2060 const char ***argv,
2061 int argc_offset,
2062 int orig_arg_index,
2063 const char *orig_arg)
2064 {
2065 int i;
2066 struct lttng_action *action;
2067 const struct action_descr *descr = nullptr;
2068
2069 for (i = 0; i < ARRAY_SIZE(action_descrs); i++) {
2070 if (strcmp(action_name, action_descrs[i].name) == 0) {
2071 descr = &action_descrs[i];
2072 break;
2073 }
2074 }
2075
2076 if (!descr) {
2077 ERR(WHILE_PARSING_ARG_N_ARG_FMT "Unknown action name '%s'",
2078 orig_arg_index + 1,
2079 orig_arg,
2080 action_name);
2081 print_valid_action_names();
2082 goto error;
2083 }
2084
2085 action = descr->handler(argc, argv, argc_offset);
2086 if (!action) {
2087 /* The handler has already printed an error message. */
2088 goto error;
2089 }
2090
2091 goto end;
2092 error:
2093 action = nullptr;
2094 end:
2095 return action;
2096 }
2097
2098 static const struct argpar_opt_descr add_trigger_options[] = {
2099 { OPT_HELP, 'h', "help", false },
2100 { OPT_LIST_OPTIONS, '\0', "list-options", false },
2101 { OPT_CONDITION, '\0', "condition", true },
2102 { OPT_ACTION, '\0', "action", true },
2103 { OPT_NAME, '\0', "name", true },
2104 { OPT_OWNER_UID, '\0', "owner-uid", true },
2105 ARGPAR_OPT_DESCR_SENTINEL,
2106 };
2107
2108 static void lttng_actions_destructor(void *p)
2109 {
2110 struct lttng_action *action = (lttng_action *) p;
2111
2112 lttng_action_destroy(action);
2113 }
2114
2115 int cmd_add_trigger(int argc, const char **argv)
2116 {
2117 int ret;
2118 int my_argc = argc - 1;
2119 const char **my_argv = argv + 1;
2120 struct lttng_condition *condition = nullptr;
2121 struct lttng_dynamic_pointer_array actions;
2122 struct argpar_iter *argpar_iter = nullptr;
2123 const struct argpar_item *argpar_item = nullptr;
2124 const struct argpar_error *argpar_error = nullptr;
2125 struct lttng_action *action_list = nullptr;
2126 struct lttng_action *action = nullptr;
2127 struct lttng_trigger *trigger = nullptr;
2128 char *name = nullptr;
2129 int i;
2130 char *owner_uid = nullptr;
2131 enum lttng_error_code ret_code;
2132 struct mi_writer *mi_writer = nullptr;
2133
2134 lttng_dynamic_pointer_array_init(&actions, lttng_actions_destructor);
2135
2136 if (lttng_opt_mi) {
2137 mi_writer = mi_lttng_writer_create(fileno(stdout), lttng_opt_mi);
2138 if (!mi_writer) {
2139 ret = CMD_ERROR;
2140 goto error;
2141 }
2142
2143 /* Open command element. */
2144 ret = mi_lttng_writer_command_open(mi_writer, mi_lttng_element_command_add_trigger);
2145 if (ret) {
2146 ret = CMD_ERROR;
2147 goto error;
2148 }
2149
2150 /* Open output element. */
2151 ret = mi_lttng_writer_open_element(mi_writer, mi_lttng_element_command_output);
2152 if (ret) {
2153 ret = CMD_ERROR;
2154 goto error;
2155 }
2156 }
2157
2158 while (true) {
2159 enum parse_next_item_status status;
2160 int ingested_args;
2161 const struct argpar_opt_descr *descr;
2162 const char *arg;
2163
2164 argpar_iter_destroy(argpar_iter);
2165 argpar_iter = argpar_iter_create(my_argc, my_argv, add_trigger_options);
2166 if (!argpar_iter) {
2167 ERR("Failed to create argpar iter.");
2168 goto error;
2169 }
2170
2171 status = parse_next_item(argpar_iter,
2172 &argpar_item,
2173 argc - my_argc,
2174 my_argv,
2175 true,
2176 &argpar_error,
2177 nullptr);
2178 if (status == PARSE_NEXT_ITEM_STATUS_ERROR) {
2179 if (argpar_error_type(argpar_error) == ARGPAR_ERROR_TYPE_MISSING_OPT_ARG) {
2180 int opt_id = argpar_error_opt_descr(argpar_error, nullptr)->id;
2181
2182 if (opt_id == OPT_CONDITION) {
2183 print_valid_condition_names();
2184 } else if (opt_id == OPT_ACTION) {
2185 print_valid_action_names();
2186 }
2187 }
2188
2189 goto error;
2190 } else if (status == PARSE_NEXT_ITEM_STATUS_ERROR_MEMORY) {
2191 goto error;
2192 } else if (status == PARSE_NEXT_ITEM_STATUS_END) {
2193 break;
2194 }
2195
2196 LTTNG_ASSERT(status == PARSE_NEXT_ITEM_STATUS_OK);
2197
2198 if (argpar_item_type(argpar_item) == ARGPAR_ITEM_TYPE_NON_OPT) {
2199 ERR("Unexpected argument `%s`.", argpar_item_non_opt_arg(argpar_item));
2200 goto error;
2201 }
2202
2203 ingested_args = argpar_iter_ingested_orig_args(argpar_iter);
2204
2205 my_argc -= ingested_args;
2206 my_argv += ingested_args;
2207
2208 descr = argpar_item_opt_descr(argpar_item);
2209 arg = argpar_item_opt_arg(argpar_item);
2210
2211 switch (descr->id) {
2212 case OPT_HELP:
2213 SHOW_HELP();
2214 ret = 0;
2215 goto end;
2216 case OPT_LIST_OPTIONS:
2217 list_cmd_options_argpar(stdout, add_trigger_options);
2218 ret = 0;
2219 goto end;
2220 case OPT_CONDITION:
2221 {
2222 if (condition) {
2223 ERR("A --condition was already given.");
2224 goto error;
2225 }
2226
2227 condition = parse_condition(arg,
2228 &my_argc,
2229 &my_argv,
2230 argc - my_argc,
2231 argc - my_argc - ingested_args,
2232 my_argv[-ingested_args]);
2233 if (!condition) {
2234 /*
2235 * An error message was already printed by
2236 * parse_condition.
2237 */
2238 goto error;
2239 }
2240
2241 break;
2242 }
2243 case OPT_ACTION:
2244 {
2245 action = parse_action(arg,
2246 &my_argc,
2247 &my_argv,
2248 argc - my_argc,
2249 argc - my_argc - ingested_args,
2250 my_argv[-ingested_args]);
2251 if (!action) {
2252 /*
2253 * An error message was already printed by
2254 * parse_condition.
2255 */
2256 goto error;
2257 }
2258
2259 ret = lttng_dynamic_pointer_array_add_pointer(&actions, action);
2260 if (ret) {
2261 ERR("Failed to add pointer to pointer array.");
2262 goto error;
2263 }
2264
2265 /* Ownership of the action was transferred to the list. */
2266 action = nullptr;
2267
2268 break;
2269 }
2270 case OPT_NAME:
2271 {
2272 if (!assign_string(&name, arg, "--name")) {
2273 goto error;
2274 }
2275
2276 break;
2277 }
2278 case OPT_OWNER_UID:
2279 {
2280 if (!assign_string(&owner_uid, arg, "--owner-uid")) {
2281 goto error;
2282 }
2283
2284 break;
2285 }
2286 default:
2287 abort();
2288 }
2289 }
2290
2291 if (!condition) {
2292 ERR("Missing --condition.");
2293 goto error;
2294 }
2295
2296 if (lttng_dynamic_pointer_array_get_count(&actions) == 0) {
2297 ERR("Need at least one --action.");
2298 goto error;
2299 }
2300
2301 action_list = lttng_action_list_create();
2302 if (!action_list) {
2303 goto error;
2304 }
2305
2306 for (i = 0; i < lttng_dynamic_pointer_array_get_count(&actions); i++) {
2307 enum lttng_action_status status;
2308
2309 action = (lttng_action *) lttng_dynamic_pointer_array_steal_pointer(&actions, i);
2310
2311 status = lttng_action_list_add_action(action_list, action);
2312 if (status != LTTNG_ACTION_STATUS_OK) {
2313 goto error;
2314 }
2315
2316 /*
2317 * The `lttng_action_list_add_action()` takes a reference to
2318 * the action. We can destroy ours.
2319 */
2320 lttng_action_destroy(action);
2321 action = nullptr;
2322 }
2323
2324 trigger = lttng_trigger_create(condition, action_list);
2325 if (!trigger) {
2326 goto error;
2327 }
2328
2329 if (owner_uid) {
2330 enum lttng_trigger_status trigger_status;
2331 char *end;
2332 long long uid;
2333
2334 errno = 0;
2335 uid = strtol(owner_uid, &end, 10);
2336 if (end == owner_uid || *end != '\0' || errno != 0) {
2337 ERR("Failed to parse `%s` as a user id.", owner_uid);
2338 goto error;
2339 }
2340
2341 trigger_status = lttng_trigger_set_owner_uid(trigger, uid);
2342 if (trigger_status != LTTNG_TRIGGER_STATUS_OK) {
2343 ERR("Failed to set trigger's user identity.");
2344 goto error;
2345 }
2346 }
2347
2348 if (name) {
2349 ret_code = lttng_register_trigger_with_name(trigger, name);
2350 } else {
2351 ret_code = lttng_register_trigger_with_automatic_name(trigger);
2352 }
2353
2354 if (ret_code != LTTNG_OK) {
2355 ERR("Failed to register trigger: %s.", lttng_strerror(-ret_code));
2356 goto error;
2357 }
2358
2359 if (lttng_opt_mi) {
2360 ret_code = lttng_trigger_mi_serialize(trigger, mi_writer, nullptr);
2361 if (ret_code != LTTNG_OK) {
2362 goto error;
2363 }
2364 } else {
2365 const char *returned_trigger_name;
2366 const enum lttng_trigger_status trigger_status =
2367 lttng_trigger_get_name(trigger, &returned_trigger_name);
2368
2369 if (trigger_status != LTTNG_TRIGGER_STATUS_OK) {
2370 WARN("Failed to retrieve the added trigger's name.");
2371 } else {
2372 MSG("Added trigger `%s`.", returned_trigger_name);
2373 }
2374 }
2375
2376 ret = 0;
2377
2378 goto end;
2379
2380 error:
2381 ret = 1;
2382
2383 end:
2384 /* Mi closing. */
2385 if (lttng_opt_mi && mi_writer) {
2386 int mi_ret;
2387
2388 /* Close output element. */
2389 mi_ret = mi_lttng_writer_close_element(mi_writer);
2390 if (mi_ret) {
2391 ret = 1;
2392 goto cleanup;
2393 }
2394
2395 mi_ret = mi_lttng_writer_write_element_bool(
2396 mi_writer, mi_lttng_element_command_success, ret ? 0 : 1);
2397 if (mi_ret) {
2398 ret = 1;
2399 goto cleanup;
2400 }
2401
2402 /* Command element close. */
2403 mi_ret = mi_lttng_writer_command_close(mi_writer);
2404 if (mi_ret) {
2405 ret = 1;
2406 goto cleanup;
2407 }
2408 }
2409
2410 cleanup:
2411 argpar_error_destroy(argpar_error);
2412 argpar_iter_destroy(argpar_iter);
2413 argpar_item_destroy(argpar_item);
2414 lttng_dynamic_pointer_array_reset(&actions);
2415 lttng_condition_destroy(condition);
2416 lttng_action_destroy(action_list);
2417 lttng_action_destroy(action);
2418 lttng_trigger_destroy(trigger);
2419 free(name);
2420 free(owner_uid);
2421 if (mi_writer && mi_lttng_writer_destroy(mi_writer)) {
2422 /* Preserve original error code. */
2423 ret = ret ? ret : CMD_ERROR;
2424 }
2425
2426 return ret;
2427 }
This page took 0.083619 seconds and 4 git commands to generate.