Rename lttng_condition_event_rule to lttng_condition_on_event
[lttng-tools.git] / src / bin / lttng / commands / add_trigger.c
CommitLineData
4624dad0
SM
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 <ctype.h>
9#include <stdio.h>
10
11#include "../command.h"
12#include "../loglevel.h"
13#include "../uprobe.h"
14
15#include "common/argpar/argpar.h"
16#include "common/dynamic-array.h"
17#include "common/string-utils/string-utils.h"
18#include "common/utils.h"
19/* For lttng_event_rule_type_str(). */
20#include <lttng/event-rule/event-rule-internal.h>
21#include <lttng/lttng.h>
20a01d15
SM
22#include "common/filter/filter-ast.h"
23#include "common/filter/filter-ir.h"
24#include "common/dynamic-array.h"
4624dad0
SM
25
26#if (LTTNG_SYMBOL_NAME_LEN == 256)
27#define LTTNG_SYMBOL_NAME_LEN_SCANF_IS_A_BROKEN_API "255"
28#endif
29
30#ifdef LTTNG_EMBED_HELP
31static const char help_msg[] =
32#include <lttng-add-trigger.1.h>
33;
34#endif
35
36enum {
37 OPT_HELP,
38 OPT_LIST_OPTIONS,
39
40 OPT_CONDITION,
41 OPT_ACTION,
42 OPT_ID,
43 OPT_FIRE_ONCE_AFTER,
44 OPT_FIRE_EVERY,
45 OPT_USER_ID,
46
47 OPT_ALL,
48 OPT_FILTER,
49 OPT_EXCLUDE,
50 OPT_LOGLEVEL,
51 OPT_LOGLEVEL_ONLY,
52
53 OPT_USERSPACE,
54 OPT_KERNEL,
55 OPT_LOG4J,
56 OPT_JUL,
57 OPT_PYTHON,
58
59 OPT_FUNCTION,
60 OPT_PROBE,
61 OPT_USERSPACE_PROBE,
62 OPT_SYSCALL,
63 OPT_TRACEPOINT,
64
65 OPT_NAME,
66 OPT_MAX_SIZE,
67 OPT_DATA_URL,
68 OPT_CTRL_URL,
69 OPT_URL,
70 OPT_PATH,
20a01d15
SM
71
72 OPT_CAPTURE,
4624dad0
SM
73};
74
75static const struct argpar_opt_descr event_rule_opt_descrs[] = {
76 { OPT_ALL, 'a', "all", false },
77 { OPT_FILTER, 'f', "filter", true },
78 { OPT_EXCLUDE, 'x', "exclude", true },
79 { OPT_LOGLEVEL, '\0', "loglevel", true },
80 { OPT_LOGLEVEL_ONLY, '\0', "loglevel-only", true },
81
82 /* Domains */
83 { OPT_USERSPACE, 'u', "userspace", false },
84 { OPT_KERNEL, 'k', "kernel", false },
85 { OPT_LOG4J, 'l', "log4j", false },
86 { OPT_JUL, 'j', "jul", false },
87 { OPT_PYTHON, 'p', "python", false },
88
89 /* Event rule types */
90 { OPT_FUNCTION, '\0', "function", true },
91 { OPT_PROBE, '\0', "probe", true },
92 { OPT_USERSPACE_PROBE, '\0', "userspace-probe", true },
93 { OPT_SYSCALL, '\0', "syscall" },
94 { OPT_TRACEPOINT, '\0', "tracepoint" },
95
20a01d15
SM
96 /* Capture descriptor */
97 { OPT_CAPTURE, '\0', "capture", true },
98
4624dad0
SM
99 ARGPAR_OPT_DESCR_SENTINEL
100};
101
102static
103bool assign_domain_type(enum lttng_domain_type *dest,
104 enum lttng_domain_type src)
105{
106 bool ret;
107
108 if (*dest == LTTNG_DOMAIN_NONE || *dest == src) {
109 *dest = src;
110 ret = true;
111 } else {
112 ERR("Multiple domains specified.");
113 ret = false;
114 }
115
116 return ret;
117}
118
119static
120bool assign_event_rule_type(enum lttng_event_rule_type *dest,
121 enum lttng_event_rule_type src)
122{
123 bool ret;
124
125 if (*dest == LTTNG_EVENT_RULE_TYPE_UNKNOWN || *dest == src) {
126 *dest = src;
127 ret = true;
128 } else {
129 ERR("Multiple event types specified.");
130 ret = false;
131 }
132
133 return ret;
134}
135
136static
137bool assign_string(char **dest, const char *src, const char *opt_name)
138{
139 bool ret;
140
141 if (*dest) {
142 ERR("Duplicate '%s' given.", opt_name);
143 goto error;
144 }
145
146 *dest = strdup(src);
147 if (!*dest) {
148 PERROR("Failed to allocate string '%s'.", opt_name);
149 goto error;
150 }
151
152 ret = true;
153 goto end;
154
155error:
156 ret = false;
157
158end:
159 return ret;
160}
161
162/* This is defined in enable_events.c. */
163LTTNG_HIDDEN
164int create_exclusion_list_and_validate(const char *event_name,
165 const char *exclusions_arg,
166 char ***exclusion_list);
167
168/*
169 * Parse `str` as a log level in domain `domain_type`. Return -1 if the string
170 * is not recognized as a valid log level.
171 */
172static
173int parse_loglevel_string(const char *str, enum lttng_domain_type domain_type)
174{
175 switch (domain_type) {
176 case LTTNG_DOMAIN_UST:
177 {
178 enum lttng_loglevel loglevel;
179 const int ret = loglevel_name_to_value(str, &loglevel);
180
181 return ret == -1 ? ret : (int) loglevel;
182 }
183 case LTTNG_DOMAIN_LOG4J:
184 {
185 enum lttng_loglevel_log4j loglevel;
186 const int ret = loglevel_log4j_name_to_value(str, &loglevel);
187
188 return ret == -1 ? ret : (int) loglevel;
189 }
190 case LTTNG_DOMAIN_JUL:
191 {
192 enum lttng_loglevel_jul loglevel;
193 const int ret = loglevel_jul_name_to_value(str, &loglevel);
194
195 return ret == -1 ? ret : (int) loglevel;
196 }
197 case LTTNG_DOMAIN_PYTHON:
198 {
199 enum lttng_loglevel_python loglevel;
200 const int ret = loglevel_python_name_to_value(str, &loglevel);
201
202 return ret == -1 ? ret : (int) loglevel;
203 }
204 default:
205 /* Invalid domain type. */
206 abort();
207 }
208}
209
210static int parse_kernel_probe_opts(const char *source,
211 struct lttng_kernel_probe_location **location)
212{
213 int ret = 0;
214 int match;
215 char s_hex[19];
216 char name[LTTNG_SYMBOL_NAME_LEN];
217 char *symbol_name = NULL;
218 uint64_t offset;
219
220 /* Check for symbol+offset. */
221 match = sscanf(source,
222 "%" LTTNG_SYMBOL_NAME_LEN_SCANF_IS_A_BROKEN_API
223 "[^'+']+%18s",
224 name, s_hex);
225 if (match == 2) {
226 if (*s_hex == '\0') {
227 ERR("Kernel probe symbol offset is missing.");
228 goto error;
229 }
230
231 symbol_name = strndup(name, LTTNG_SYMBOL_NAME_LEN);
232 if (!symbol_name) {
233 PERROR("Failed to copy kernel probe location symbol name.");
234 goto error;
235 }
236 offset = strtoul(s_hex, NULL, 0);
237
238 *location = lttng_kernel_probe_location_symbol_create(
239 symbol_name, offset);
f6e30a8a 240 if (!*location) {
4624dad0
SM
241 ERR("Failed to create symbol kernel probe location.");
242 goto error;
243 }
244
245 goto end;
246 }
247
248 /* Check for symbol. */
249 if (isalpha(name[0]) || name[0] == '_') {
250 match = sscanf(source,
251 "%" LTTNG_SYMBOL_NAME_LEN_SCANF_IS_A_BROKEN_API
252 "s",
253 name);
254 if (match == 1) {
255 symbol_name = strndup(name, LTTNG_SYMBOL_NAME_LEN);
256 if (!symbol_name) {
257 ERR("Failed to copy kernel probe location symbol name.");
258 goto error;
259 }
260
261 *location = lttng_kernel_probe_location_symbol_create(
262 symbol_name, 0);
14f27f79 263 if (!*location) {
4624dad0
SM
264 ERR("Failed to create symbol kernel probe location.");
265 goto error;
266 }
267
268 goto end;
269 }
270 }
271
272 /* Check for address. */
273 match = sscanf(source, "%18s", s_hex);
274 if (match > 0) {
275 uint64_t address;
276
277 if (*s_hex == '\0') {
278 ERR("Invalid kernel probe location address.");
279 goto error;
280 }
281
282 address = strtoul(s_hex, NULL, 0);
283 *location = lttng_kernel_probe_location_address_create(address);
5c6ca809 284 if (!*location) {
4624dad0
SM
285 ERR("Failed to create symbol kernel probe location.");
286 goto error;
287 }
288
289 goto end;
290 }
291
292error:
293 /* No match */
294 ret = -1;
295 *location = NULL;
296
297end:
298 free(symbol_name);
299 return ret;
300}
301
20a01d15
SM
302static
303struct lttng_event_expr *ir_op_load_expr_to_event_expr(
3363a4c3
JG
304 const struct ir_load_expression *load_expr,
305 const char *capture_str)
20a01d15
SM
306{
307 char *provider_name = NULL;
308 struct lttng_event_expr *event_expr = NULL;
3363a4c3
JG
309 const struct ir_load_expression_op *load_expr_op = load_expr->child;
310 const enum ir_load_expression_type load_expr_child_type =
311 load_expr_op->type;
20a01d15 312
3363a4c3 313 switch (load_expr_child_type) {
20a01d15
SM
314 case IR_LOAD_EXPRESSION_GET_PAYLOAD_ROOT:
315 case IR_LOAD_EXPRESSION_GET_CONTEXT_ROOT:
316 {
317 const char *field_name;
318
319 load_expr_op = load_expr_op->next;
320 assert(load_expr_op);
321 assert(load_expr_op->type == IR_LOAD_EXPRESSION_GET_SYMBOL);
322 field_name = load_expr_op->u.symbol;
323 assert(field_name);
324
3363a4c3 325 event_expr = load_expr_child_type == IR_LOAD_EXPRESSION_GET_PAYLOAD_ROOT ?
20a01d15
SM
326 lttng_event_expr_event_payload_field_create(field_name) :
327 lttng_event_expr_channel_context_field_create(field_name);
328 if (!event_expr) {
329 ERR("Failed to create %s event expression: field name = `%s`.",
3363a4c3 330 load_expr_child_type == IR_LOAD_EXPRESSION_GET_PAYLOAD_ROOT ?
20a01d15
SM
331 "payload field" : "channel context",
332 field_name);
333 goto error;
334 }
335
336 break;
337 }
338 case IR_LOAD_EXPRESSION_GET_APP_CONTEXT_ROOT:
339 {
340 const char *colon;
341 const char *type_name;
342 const char *field_name;
343
344 load_expr_op = load_expr_op->next;
345 assert(load_expr_op);
346 assert(load_expr_op->type == IR_LOAD_EXPRESSION_GET_SYMBOL);
347 field_name = load_expr_op->u.symbol;
348 assert(field_name);
349
350 /*
351 * The field name needs to be of the form PROVIDER:TYPE. We
352 * split it here.
353 */
354 colon = strchr(field_name, ':');
355 if (!colon) {
356 ERR("Invalid app-specific context field name: missing colon in `%s`.",
357 field_name);
358 goto error;
359 }
360
361 type_name = colon + 1;
362 if (*type_name == '\0') {
363 ERR("Invalid app-specific context field name: missing type name after colon in `%s`.",
364 field_name);
365 goto error;
366 }
367
368 provider_name = strndup(field_name, colon - field_name);
369 if (!provider_name) {
370 PERROR("Failed to allocate field name string");
371 goto error;
372 }
373
374 event_expr = lttng_event_expr_app_specific_context_field_create(
375 provider_name, type_name);
376 if (!event_expr) {
377 ERR("Failed to create app-specific context field event expression: provider name = `%s`, type name = `%s`",
378 provider_name, type_name);
379 goto error;
380 }
381
382 break;
383 }
384 default:
385 ERR("%s: unexpected load expr type %d.", __func__,
386 load_expr_op->type);
387 abort();
388 }
389
390 load_expr_op = load_expr_op->next;
391
392 /* There may be a single array index after that. */
393 if (load_expr_op->type == IR_LOAD_EXPRESSION_GET_INDEX) {
394 struct lttng_event_expr *index_event_expr;
395 const uint64_t index = load_expr_op->u.index;
396
397 index_event_expr = lttng_event_expr_array_field_element_create(event_expr, index);
398 if (!index_event_expr) {
399 ERR("Failed to create array field element event expression.");
400 goto error;
401 }
402
403 event_expr = index_event_expr;
404 load_expr_op = load_expr_op->next;
405 }
406
407 switch (load_expr_op->type) {
408 case IR_LOAD_EXPRESSION_LOAD_FIELD:
409 /*
410 * This is what we expect, IR_LOAD_EXPRESSION_LOAD_FIELD is
411 * always found at the end of the chain.
412 */
413 break;
414 case IR_LOAD_EXPRESSION_GET_SYMBOL:
415 ERR("While parsing expression `%s`: Capturing subfields is not supported.",
416 capture_str);
417 goto error;
418
419 default:
420 ERR("%s: unexpected load expression operator %s.", __func__,
421 ir_load_expression_type_str(load_expr_op->type));
422 abort();
423 }
424
425 goto end;
426
427error:
428 lttng_event_expr_destroy(event_expr);
429 event_expr = NULL;
430
431end:
432 free(provider_name);
433
434 return event_expr;
435}
436
437static
438struct lttng_event_expr *ir_op_load_to_event_expr(
439 const struct ir_op *ir, const char *capture_str)
440{
441 struct lttng_event_expr *event_expr = NULL;
442
443 assert(ir->op == IR_OP_LOAD);
444
445 switch (ir->data_type) {
446 case IR_DATA_EXPRESSION:
447 {
448 const struct ir_load_expression *ir_load_expr =
449 ir->u.load.u.expression;
450
451 event_expr = ir_op_load_expr_to_event_expr(
452 ir_load_expr, capture_str);
453 break;
454 }
455 default:
456 ERR("%s: unexpected data type: %s.", __func__,
457 ir_data_type_str(ir->data_type));
458 abort();
459 }
460
461 return event_expr;
462}
463
464static
465const char *ir_operator_type_human_str(enum ir_op_type op)
466{
467 const char *name;
468
469 switch (op) {
470 case IR_OP_BINARY:
471 name = "Binary";
472 break;
473 case IR_OP_UNARY:
474 name = "Unary";
475 break;
476 case IR_OP_LOGICAL:
477 name = "Logical";
478 break;
479 default:
480 abort();
481 }
482
483 return name;
484}
485
486static
487struct lttng_event_expr *ir_op_root_to_event_expr(const struct ir_op *ir,
488 const char *capture_str)
489{
490 struct lttng_event_expr *event_expr = NULL;
491
492 assert(ir->op == IR_OP_ROOT);
493 ir = ir->u.root.child;
494
495 switch (ir->op) {
496 case IR_OP_LOAD:
497 event_expr = ir_op_load_to_event_expr(ir, capture_str);
498 break;
499 case IR_OP_BINARY:
500 case IR_OP_UNARY:
501 case IR_OP_LOGICAL:
502 ERR("While parsing expression `%s`: %s operators are not allowed in capture expressions.",
503 capture_str,
504 ir_operator_type_human_str(ir->op));
505 break;
506 default:
507 ERR("%s: unexpected IR op type: %s.", __func__,
508 ir_op_type_str(ir->op));
509 abort();
510 }
511
512 return event_expr;
513}
514
515static
516void destroy_event_expr(void *ptr)
517{
518 lttng_event_expr_destroy(ptr);
519}
520
521struct parse_event_rule_res {
522 /* Owned by this. */
523 struct lttng_event_rule *er;
524
525 /* Array of `struct lttng_event_expr *` */
526 struct lttng_dynamic_pointer_array capture_descriptors;
527};
528
529static
530struct parse_event_rule_res parse_event_rule(int *argc, const char ***argv)
4624dad0 531{
4624dad0
SM
532 enum lttng_domain_type domain_type = LTTNG_DOMAIN_NONE;
533 enum lttng_event_rule_type event_rule_type =
534 LTTNG_EVENT_RULE_TYPE_UNKNOWN;
535 struct argpar_state *state;
536 struct argpar_item *item = NULL;
537 char *error = NULL;
538 int consumed_args = -1;
539 struct lttng_kernel_probe_location *kernel_probe_location = NULL;
540 struct lttng_userspace_probe_location *userspace_probe_location = NULL;
20a01d15
SM
541 struct parse_event_rule_res res = { 0 };
542 struct lttng_event_expr *event_expr = NULL;
543 struct filter_parser_ctx *parser_ctx = NULL;
4624dad0
SM
544
545 /* Was the -a/--all flag provided? */
546 bool all_events = false;
547
548 /* Tracepoint name (non-option argument). */
549 const char *tracepoint_name = NULL;
550
551 /* Holds the argument of --probe / --userspace-probe. */
552 char *source = NULL;
553
554 /* Filter. */
555 char *filter = NULL;
556
557 /* Exclude. */
558 char *exclude = NULL;
559 char **exclusion_list = NULL;
560
561 /* Log level. */
562 char *loglevel_str = NULL;
563 bool loglevel_only = false;
564
20a01d15
SM
565 lttng_dynamic_pointer_array_init(&res.capture_descriptors,
566 destroy_event_expr);
4624dad0
SM
567 state = argpar_state_create(*argc, *argv, event_rule_opt_descrs);
568 if (!state) {
569 ERR("Failed to allocate an argpar state.");
570 goto error;
571 }
572
573 while (true) {
574 enum argpar_state_parse_next_status status;
575
576 ARGPAR_ITEM_DESTROY_AND_RESET(item);
577 status = argpar_state_parse_next(state, &item, &error);
578 if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR) {
579 ERR("%s", error);
580 goto error;
581 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR_UNKNOWN_OPT) {
582 /* Just stop parsing here. */
583 break;
584 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_END) {
585 break;
586 }
587
588 assert(status == ARGPAR_STATE_PARSE_NEXT_STATUS_OK);
589
590 if (item->type == ARGPAR_ITEM_TYPE_OPT) {
591 const struct argpar_item_opt *item_opt =
592 (const struct argpar_item_opt *) item;
593
594 switch (item_opt->descr->id) {
595 /* Domains. */
596 case OPT_USERSPACE:
597 if (!assign_domain_type(&domain_type, LTTNG_DOMAIN_UST)) {
598 goto error;
599 }
600
601 break;
602 case OPT_KERNEL:
603 if (!assign_domain_type(&domain_type, LTTNG_DOMAIN_KERNEL)) {
604 goto error;
605 }
606
607 break;
608 case OPT_LOG4J:
609 if (!assign_domain_type(&domain_type, LTTNG_DOMAIN_LOG4J)) {
610 goto error;
611 }
612
613 break;
614 case OPT_JUL:
615 if (!assign_domain_type(&domain_type, LTTNG_DOMAIN_JUL)) {
616 goto error;
617 }
618
619 break;
620 case OPT_PYTHON:
621 if (!assign_domain_type(&domain_type, LTTNG_DOMAIN_PYTHON)) {
622 goto error;
623 }
624
625 break;
626
627 /* Event rule types */
628 case OPT_FUNCTION:
629 if (!assign_event_rule_type(&event_rule_type,
630 LTTNG_EVENT_RULE_TYPE_KRETPROBE)) {
631 goto error;
632 }
633
634 break;
635 case OPT_PROBE:
636 if (!assign_event_rule_type(&event_rule_type,
f2791161 637 LTTNG_EVENT_RULE_TYPE_KERNEL_PROBE)) {
4624dad0
SM
638 goto error;
639 }
640
641 if (!assign_string(&source, item_opt->arg, "source")) {
642 goto error;
643 }
644
645 break;
646 case OPT_USERSPACE_PROBE:
647 if (!assign_event_rule_type(&event_rule_type,
1f1567a5 648 LTTNG_EVENT_RULE_TYPE_USERSPACE_PROBE)) {
4624dad0
SM
649 goto error;
650 }
651
652 if (!assign_string(&source, item_opt->arg, "source")) {
653 goto error;
654 }
655
656 break;
657 case OPT_SYSCALL:
658 if (!assign_event_rule_type(&event_rule_type,
659 LTTNG_EVENT_RULE_TYPE_SYSCALL)) {
660 goto error;
661 }
662
663 break;
664 case OPT_TRACEPOINT:
665 if (!assign_event_rule_type(&event_rule_type,
666 LTTNG_EVENT_RULE_TYPE_TRACEPOINT)) {
667 goto error;
668 }
669
670 break;
671 case OPT_ALL:
672 all_events = true;
673 break;
674 case OPT_FILTER:
675 if (!assign_string(&filter, item_opt->arg,
676 "--filter/-f")) {
677 goto error;
678 }
679
680 break;
681 case OPT_EXCLUDE:
682 if (!assign_string(&exclude, item_opt->arg,
683 "--exclude/-x")) {
684 goto error;
685 }
686
687 break;
688 case OPT_LOGLEVEL:
689 case OPT_LOGLEVEL_ONLY:
690 if (!assign_string(&loglevel_str, item_opt->arg,
691 "--loglevel/--loglevel-only")) {
692 goto error;
693 }
694
695 loglevel_only = item_opt->descr->id ==
696 OPT_LOGLEVEL_ONLY;
697 break;
20a01d15
SM
698 case OPT_CAPTURE:
699 {
700 int ret;
701 const char *capture_str = item_opt->arg;
702
703 ret = filter_parser_ctx_create_from_filter_expression(
704 capture_str, &parser_ctx);
705 if (ret) {
706 ERR("Failed to parse capture expression `%s`.",
707 capture_str);
708 goto error;
709 }
710
711 event_expr = ir_op_root_to_event_expr(
712 parser_ctx->ir_root,
713 capture_str);
714 if (!event_expr) {
715 /*
716 * ir_op_root_to_event_expr has printed
717 * an error message.
718 */
719 goto error;
720 }
721
722 ret = lttng_dynamic_pointer_array_add_pointer(
723 &res.capture_descriptors,
724 event_expr);
725 if (ret) {
726 goto error;
727 }
728
729 /*
730 * The ownership of event expression was
731 * transferred to the dynamic array.
732 */
733 event_expr = NULL;
734
735 break;
736 }
4624dad0
SM
737 default:
738 abort();
739 }
740 } else {
741 const struct argpar_item_non_opt *item_non_opt =
742 (const struct argpar_item_non_opt *)
743 item;
744
745 /*
746 * Don't accept two non-option arguments/tracepoint
747 * names.
748 */
749 if (tracepoint_name) {
750 ERR("Unexpected argument '%s'",
751 item_non_opt->arg);
752 goto error;
753 }
754
755 tracepoint_name = item_non_opt->arg;
756 }
757 }
758
759 if (event_rule_type == LTTNG_EVENT_RULE_TYPE_UNKNOWN) {
760 event_rule_type = LTTNG_EVENT_RULE_TYPE_TRACEPOINT;
761 }
762
763 /*
764 * Option -a is applicable to event rules of type tracepoint and
765 * syscall, and it is equivalent to using "*" as the tracepoint name.
766 */
767 if (all_events) {
768 switch (event_rule_type) {
769 case LTTNG_EVENT_RULE_TYPE_TRACEPOINT:
770 case LTTNG_EVENT_RULE_TYPE_SYSCALL:
771 break;
772 default:
773 ERR("Can't use -a/--all with %s event rules.",
774 lttng_event_rule_type_str(event_rule_type));
775 goto error;
776 }
777
778 if (tracepoint_name) {
779 ERR("Can't provide a tracepoint name with -a/--all.");
780 goto error;
781 }
782
783 /* In which case, it's equivalent to tracepoint name "*". */
784 tracepoint_name = "*";
785 }
786
787 /*
788 * A tracepoint name (or -a, for the event rule types that accept it)
789 * is required.
790 */
791 if (!tracepoint_name) {
792 ERR("Need to provide either a tracepoint name or -a/--all.");
793 goto error;
794 }
795
796 /*
797 * We don't support multiple tracepoint names for now.
798 */
799 if (strchr(tracepoint_name, ',')) {
800 ERR("Comma separated tracepoint names are not supported.");
801 goto error;
802 }
803
804 /*
805 * Update *argc and *argv so our caller can keep parsing what follows.
806 */
807 consumed_args = argpar_state_get_ingested_orig_args(state);
808 assert(consumed_args >= 0);
809 *argc -= consumed_args;
810 *argv += consumed_args;
811
812 /* Need to specify a domain. */
813 if (domain_type == LTTNG_DOMAIN_NONE) {
814 ERR("Please specify a domain (--kernel/--userspace/--jul/--log4j/--python).");
815 goto error;
816 }
817
818 /* Validate event rule type against domain. */
819 switch (event_rule_type) {
f2791161 820 case LTTNG_EVENT_RULE_TYPE_KERNEL_PROBE:
4624dad0 821 case LTTNG_EVENT_RULE_TYPE_KRETPROBE:
1f1567a5 822 case LTTNG_EVENT_RULE_TYPE_USERSPACE_PROBE:
4624dad0
SM
823 case LTTNG_EVENT_RULE_TYPE_SYSCALL:
824 if (domain_type != LTTNG_DOMAIN_KERNEL) {
825 ERR("Event type not available for user-space tracing.");
826 goto error;
827 }
828 break;
829
830 case LTTNG_EVENT_RULE_TYPE_TRACEPOINT:
831 break;
832
833 default:
834 abort();
835 }
836
837 /*
838 * Adding a filter to a probe, function or userspace-probe would be
839 * denied by the kernel tracer as it's not supported at the moment. We
840 * do an early check here to warn the user.
841 */
842 if (filter && domain_type == LTTNG_DOMAIN_KERNEL) {
843 switch (event_rule_type) {
844 case LTTNG_EVENT_RULE_TYPE_TRACEPOINT:
845 case LTTNG_EVENT_RULE_TYPE_SYSCALL:
846 break;
847 default:
848 ERR("Filter expressions are not supported for %s event rules.",
849 lttng_event_rule_type_str(event_rule_type));
850 goto error;
851 }
852 }
853
854 /* If --exclude/-x was passed, split it into an exclusion list. */
855 if (exclude) {
856 if (domain_type != LTTNG_DOMAIN_UST) {
857 ERR("Event name exclusions are not yet implemented for %s event rules.",
858 get_domain_str(domain_type));
859 goto error;
860 }
861
862
863 if (create_exclusion_list_and_validate(tracepoint_name, exclude,
864 &exclusion_list) != 0) {
865 ERR("Failed to create exclusion list.");
866 goto error;
867 }
868 }
869
870 if (loglevel_str && event_rule_type != LTTNG_EVENT_RULE_TYPE_TRACEPOINT) {
871 ERR("Log levels are only applicable to tracepoint event rules.");
872 goto error;
873 }
874
875 /* Finally, create the event rule object. */
876 switch (event_rule_type) {
877 case LTTNG_EVENT_RULE_TYPE_TRACEPOINT:
878 {
879 enum lttng_event_rule_status event_rule_status;
880
20a01d15
SM
881 res.er = lttng_event_rule_tracepoint_create(domain_type);
882 if (!res.er) {
4624dad0
SM
883 ERR("Failed to create tracepoint event rule.");
884 goto error;
885 }
886
887 /* Set pattern. */
888 event_rule_status = lttng_event_rule_tracepoint_set_pattern(
20a01d15 889 res.er, tracepoint_name);
4624dad0
SM
890 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
891 ERR("Failed to set tracepoint event rule's pattern to '%s'.",
892 tracepoint_name);
893 goto error;
894 }
895
896 /* Set filter. */
897 if (filter) {
898 event_rule_status = lttng_event_rule_tracepoint_set_filter(
20a01d15 899 res.er, filter);
4624dad0
SM
900 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
901 ERR("Failed to set tracepoint event rule's filter to '%s'.",
902 filter);
903 goto error;
904 }
905 }
906
907 /* Set exclusion list. */
908 if (exclusion_list) {
909 int n;
910
911 for (n = 0; exclusion_list[n]; n++) {
912 event_rule_status = lttng_event_rule_tracepoint_add_exclusion(
20a01d15 913 res.er,
4624dad0
SM
914 exclusion_list[n]);
915 if (event_rule_status !=
916 LTTNG_EVENT_RULE_STATUS_OK) {
917 ERR("Failed to set tracepoint exclusion list element '%s'",
918 exclusion_list[n]);
919 goto error;
920 }
921 }
922 }
923
924 if (loglevel_str) {
925 int loglevel;
926
927 if (domain_type == LTTNG_DOMAIN_KERNEL) {
928 ERR("Log levels are not supported by the kernel tracer.");
929 goto error;
930 }
931
932 loglevel = parse_loglevel_string(
933 loglevel_str, domain_type);
934 if (loglevel < 0) {
935 ERR("Failed to parse `%s` as a log level.",
936 loglevel_str);
937 goto error;
938 }
939
940 if (loglevel_only) {
941 event_rule_status = lttng_event_rule_tracepoint_set_log_level(
20a01d15
SM
942 res.er,
943 loglevel);
4624dad0
SM
944 } else {
945 event_rule_status = lttng_event_rule_tracepoint_set_log_level_range_lower_bound(
20a01d15
SM
946 res.er,
947 loglevel);
4624dad0
SM
948 }
949
950 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
951 ERR("Failed to set log level on event fule.");
952 goto error;
953 }
954 }
955
956 break;
957 }
f2791161 958 case LTTNG_EVENT_RULE_TYPE_KERNEL_PROBE:
4624dad0
SM
959 {
960 int ret;
961 enum lttng_event_rule_status event_rule_status;
962
f2791161 963 res.er = lttng_event_rule_kernel_probe_create();
20a01d15 964 if (!res.er) {
4624dad0
SM
965 ERR("Failed to create kprobe event rule.");
966 goto error;
967 }
968
969 ret = parse_kernel_probe_opts(source, &kernel_probe_location);
970 if (ret) {
971 ERR("Failed to parse kernel probe location.");
972 goto error;
973 }
974
f2791161 975 event_rule_status = lttng_event_rule_kernel_probe_set_name(res.er, tracepoint_name);
4624dad0
SM
976 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
977 ERR("Failed to set kprobe event rule's name to '%s'.", tracepoint_name);
978 goto error;
979 }
980
981 assert(kernel_probe_location);
f2791161 982 event_rule_status = lttng_event_rule_kernel_probe_set_location(res.er, kernel_probe_location);
4624dad0
SM
983 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
984 ERR("Failed to set kprobe event rule's location.");
985 goto error;
986 }
987
988 break;
989 }
1f1567a5 990 case LTTNG_EVENT_RULE_TYPE_USERSPACE_PROBE:
4624dad0
SM
991 {
992 int ret;
993 enum lttng_event_rule_status event_rule_status;
994
995 ret = parse_userspace_probe_opts(
996 source, &userspace_probe_location);
997 if (ret) {
998 ERR("Failed to parse user space probe location.");
999 goto error;
1000 }
1001
1f1567a5 1002 res.er = lttng_event_rule_userspace_probe_create();
20a01d15
SM
1003 if (!res.er) {
1004 ERR("Failed to create userspace probe event rule.");
4624dad0
SM
1005 goto error;
1006 }
1007
1f1567a5 1008 event_rule_status = lttng_event_rule_userspace_probe_set_location(
20a01d15 1009 res.er, userspace_probe_location);
4624dad0
SM
1010 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
1011 ERR("Failed to set user space probe event rule's location.");
1012 goto error;
1013 }
1014
1f1567a5 1015 event_rule_status = lttng_event_rule_userspace_probe_set_name(
20a01d15 1016 res.er, tracepoint_name);
4624dad0
SM
1017 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
1018 ERR("Failed to set user space probe event rule's name to '%s'.",
1019 tracepoint_name);
1020 goto error;
1021 }
1022
1023 break;
1024 }
1025 case LTTNG_EVENT_RULE_TYPE_SYSCALL:
1026 {
1027 enum lttng_event_rule_status event_rule_status;
1028
20a01d15
SM
1029 res.er = lttng_event_rule_syscall_create();
1030 if (!res.er) {
4624dad0
SM
1031 ERR("Failed to create syscall event rule.");
1032 goto error;
1033 }
1034
1035 event_rule_status = lttng_event_rule_syscall_set_pattern(
20a01d15 1036 res.er, tracepoint_name);
4624dad0
SM
1037 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
1038 ERR("Failed to set syscall event rule's pattern to '%s'.",
1039 tracepoint_name);
1040 goto error;
1041 }
1042
1043 if (filter) {
1044 event_rule_status = lttng_event_rule_syscall_set_filter(
20a01d15 1045 res.er, filter);
4624dad0
SM
1046 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
1047 ERR("Failed to set syscall event rule's filter to '%s'.",
1048 filter);
1049 goto error;
1050 }
1051 }
1052
1053 break;
1054 }
1055 default:
1056 abort();
1057 goto error;
1058 }
1059
1060 goto end;
1061
1062error:
20a01d15
SM
1063 lttng_event_rule_destroy(res.er);
1064 res.er = NULL;
1065 lttng_dynamic_pointer_array_reset(&res.capture_descriptors);
4624dad0
SM
1066
1067end:
20a01d15
SM
1068 if (parser_ctx) {
1069 filter_parser_ctx_free(parser_ctx);
1070 }
1071
1072 lttng_event_expr_destroy(event_expr);
4624dad0
SM
1073 argpar_item_destroy(item);
1074 free(error);
1075 argpar_state_destroy(state);
1076 free(filter);
1077 free(exclude);
1078 free(loglevel_str);
6e61d0fa 1079 free(source);
4624dad0
SM
1080 strutils_free_null_terminated_array_of_strings(exclusion_list);
1081 lttng_kernel_probe_location_destroy(kernel_probe_location);
1082 lttng_userspace_probe_location_destroy(userspace_probe_location);
20a01d15 1083 return res;
4624dad0
SM
1084}
1085
1086static
1087struct lttng_condition *handle_condition_event(int *argc, const char ***argv)
1088{
20a01d15 1089 struct parse_event_rule_res res;
4624dad0 1090 struct lttng_condition *c;
20a01d15 1091 size_t i;
4624dad0 1092
20a01d15
SM
1093 res = parse_event_rule(argc, argv);
1094 if (!res.er) {
4624dad0 1095 c = NULL;
20a01d15 1096 goto error;
4624dad0
SM
1097 }
1098
d602bd6a 1099 c = lttng_condition_on_event_create(res.er);
20a01d15
SM
1100 lttng_event_rule_destroy(res.er);
1101 res.er = NULL;
4624dad0 1102 if (!c) {
20a01d15
SM
1103 goto error;
1104 }
1105
1106 for (i = 0; i < lttng_dynamic_pointer_array_get_count(&res.capture_descriptors);
1107 i++) {
1108 enum lttng_condition_status status;
1109 struct lttng_event_expr **expr =
1110 lttng_dynamic_array_get_element(
1111 &res.capture_descriptors.array, i);
1112
1113 assert(expr);
1114 assert(*expr);
d602bd6a 1115 status = lttng_condition_on_event_append_capture_descriptor(
20a01d15
SM
1116 c, *expr);
1117 if (status != LTTNG_CONDITION_STATUS_OK) {
81d566c9
JR
1118 if (status == LTTNG_CONDITION_STATUS_UNSUPPORTED) {
1119 ERR("The capture feature is unsupported by the event-rule condition type");
1120 }
1121
20a01d15
SM
1122 goto error;
1123 }
1124
1125 /* Ownership of event expression moved to `c` */
1126 *expr = NULL;
4624dad0
SM
1127 }
1128
20a01d15
SM
1129 goto end;
1130
1131error:
1132 lttng_condition_destroy(c);
1133 c = NULL;
1134
4624dad0 1135end:
20a01d15
SM
1136 lttng_dynamic_pointer_array_reset(&res.capture_descriptors);
1137 lttng_event_rule_destroy(res.er);
4624dad0
SM
1138 return c;
1139}
1140
1141static
1142struct lttng_condition *handle_condition_session_consumed_size(int *argc, const char ***argv)
1143{
1144 struct lttng_condition *cond = NULL;
1145 struct argpar_state *state = NULL;
1146 struct argpar_item *item = NULL;
1147 const char *threshold_arg = NULL;
1148 const char *session_name_arg = NULL;
1149 uint64_t threshold;
1150 char *error = NULL;
1151 enum lttng_condition_status condition_status;
1152
1153 state = argpar_state_create(*argc, *argv, event_rule_opt_descrs);
1154 if (!state) {
1155 ERR("Failed to allocate an argpar state.");
1156 goto error;
1157 }
1158
1159 while (true) {
1160 enum argpar_state_parse_next_status status;
1161
1162 ARGPAR_ITEM_DESTROY_AND_RESET(item);
1163 status = argpar_state_parse_next(state, &item, &error);
1164 if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR) {
1165 ERR("%s", error);
1166 goto error;
1167 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR_UNKNOWN_OPT) {
1168 /* Just stop parsing here. */
1169 break;
1170 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_END) {
1171 break;
1172 }
1173
1174 assert(status == ARGPAR_STATE_PARSE_NEXT_STATUS_OK);
1175
1176 if (item->type == ARGPAR_ITEM_TYPE_OPT) {
1177 const struct argpar_item_opt *item_opt =
1178 (const struct argpar_item_opt *) item;
1179
1180 switch (item_opt->descr->id) {
1181 default:
1182 abort();
1183 }
1184 } else {
1185 const struct argpar_item_non_opt *item_non_opt;
1186
1187 assert(item->type == ARGPAR_ITEM_TYPE_NON_OPT);
1188
1189 item_non_opt = (const struct argpar_item_non_opt *) item;
1190
1191 switch (item_non_opt->non_opt_index) {
1192 case 0:
1193 session_name_arg = item_non_opt->arg;
1194 break;
1195 case 1:
1196 threshold_arg = item_non_opt->arg;
1197 break;
1198 default:
1199 ERR("Unexpected argument `%s`.",
1200 item_non_opt->arg);
1201 goto error;
1202 }
1203 }
1204 }
1205
1206 *argc -= argpar_state_get_ingested_orig_args(state);
1207 *argv += argpar_state_get_ingested_orig_args(state);
1208
1209 if (!session_name_arg) {
1210 ERR("Missing session name argument.");
1211 goto error;
1212 }
1213
1214 if (!threshold_arg) {
1215 ERR("Missing threshold argument.");
1216 goto error;
1217 }
1218
1219 if (utils_parse_size_suffix(threshold_arg, &threshold) != 0) {
1220 ERR("Failed to parse `%s` as a size.", threshold_arg);
1221 goto error;
1222 }
1223
1224 cond = lttng_condition_session_consumed_size_create();
1225 if (!cond) {
1226 ERR("Failed to allocate a session consumed size condition.");
1227 goto error;
1228 }
1229
1230 condition_status = lttng_condition_session_consumed_size_set_session_name(
1231 cond, session_name_arg);
1232 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
1233 ERR("Failed to set session consumed size condition's session name to '%s'.",
1234 session_name_arg);
1235 goto error;
1236 }
1237
1238 condition_status = lttng_condition_session_consumed_size_set_threshold(
1239 cond, threshold);
1240 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
1241 ERR("Failed to set session consumed size condition threshold.");
1242 goto error;
1243 }
1244
1245 goto end;
1246
1247error:
1248 lttng_condition_destroy(cond);
1249 cond = NULL;
1250
1251end:
1252 argpar_state_destroy(state);
1253 argpar_item_destroy(item);
1254 free(error);
1255 return cond;
1256}
1257
1258static
1259struct lttng_condition *handle_condition_buffer_usage_high(int *argc, const char ***argv)
1260{
1261 ERR("High buffer usage threshold conditions are unsupported for the moment.");
1262 return NULL;
1263}
1264
1265static
1266struct lttng_condition *handle_condition_buffer_usage_low(int *argc, const char ***argv)
1267{
1268 ERR("Low buffer usage threshold conditions are unsupported for the moment.");
1269 return NULL;
1270}
1271
1272static
1273struct lttng_condition *handle_condition_session_rotation_ongoing(int *argc, const char ***argv)
1274{
1275 ERR("Session rotation ongoing conditions are unsupported for the moment.");
1276 return NULL;
1277}
1278
1279static
1280struct lttng_condition *handle_condition_session_rotation_completed(int *argc, const char ***argv)
1281{
1282 ERR("Session rotation completed conditions are unsupported for the moment.");
1283 return NULL;
1284}
1285
1286struct condition_descr {
1287 const char *name;
1288 struct lttng_condition *(*handler) (int *argc, const char ***argv);
1289};
1290
1291static const
1292struct condition_descr condition_descrs[] = {
1293 { "on-event", handle_condition_event },
1294 { "on-session-consumed-size", handle_condition_session_consumed_size },
1295 { "on-buffer-usage-high", handle_condition_buffer_usage_high },
1296 { "on-buffer-usage-low", handle_condition_buffer_usage_low },
1297 { "on-session-rotation-ongoing", handle_condition_session_rotation_ongoing },
1298 { "on-session-rotation-completed", handle_condition_session_rotation_completed },
1299};
1300
1301static
1302struct lttng_condition *parse_condition(int *argc, const char ***argv)
1303{
1304 int i;
1305 struct lttng_condition *cond;
1306 const char *condition_name;
1307 const struct condition_descr *descr = NULL;
1308
1309 if (*argc == 0) {
1310 ERR("Missing condition name.");
1311 goto error;
1312 }
1313
1314 condition_name = (*argv)[0];
1315
1316 (*argc)--;
1317 (*argv)++;
1318
1319 for (i = 0; i < ARRAY_SIZE(condition_descrs); i++) {
1320 if (strcmp(condition_name, condition_descrs[i].name) == 0) {
1321 descr = &condition_descrs[i];
1322 break;
1323 }
1324 }
1325
1326 if (!descr) {
1327 ERR("Unknown condition name '%s'", condition_name);
1328 goto error;
1329 }
1330
1331 cond = descr->handler(argc, argv);
1332 if (!cond) {
1333 /* The handler has already printed an error message. */
1334 goto error;
1335 }
1336
1337 goto end;
1338error:
1339 cond = NULL;
1340end:
1341 return cond;
1342}
1343
1344
1345static
1346struct lttng_action *handle_action_notify(int *argc, const char ***argv)
1347{
1348 return lttng_action_notify_create();
1349}
1350
1351static const struct argpar_opt_descr no_opt_descrs[] = {
1352 ARGPAR_OPT_DESCR_SENTINEL
1353};
1354
1355/*
1356 * Generic handler for a kind of action that takes a session name as its sole
1357 * argument.
1358 */
1359
1360static
1361struct lttng_action *handle_action_simple_session(
1362 int *argc, const char ***argv,
1363 struct lttng_action *(*create_action_cb)(void),
1364 enum lttng_action_status (*set_session_name_cb)(struct lttng_action *, const char *),
1365 const char *action_name)
1366{
1367 struct lttng_action *action = NULL;
1368 struct argpar_state *state = NULL;
1369 struct argpar_item *item = NULL;
1370 const char *session_name_arg = NULL;
1371 char *error = NULL;
1372 enum lttng_action_status action_status;
1373
1374 state = argpar_state_create(*argc, *argv, no_opt_descrs);
1375 if (!state) {
1376 ERR("Failed to allocate an argpar state.");
1377 goto error;
1378 }
1379
1380 while (true) {
1381 enum argpar_state_parse_next_status status;
1382 const struct argpar_item_non_opt *item_non_opt;
1383
1384 ARGPAR_ITEM_DESTROY_AND_RESET(item);
1385 status = argpar_state_parse_next(state, &item, &error);
1386 if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR) {
1387 ERR("%s", error);
1388 goto error;
1389 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR_UNKNOWN_OPT) {
1390 /* Just stop parsing here. */
1391 break;
1392 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_END) {
1393 break;
1394 }
1395
1396 assert(status == ARGPAR_STATE_PARSE_NEXT_STATUS_OK);
1397 assert(item->type == ARGPAR_ITEM_TYPE_NON_OPT);
1398
1399 item_non_opt = (const struct argpar_item_non_opt *) item;
1400
1401 switch (item_non_opt->non_opt_index) {
1402 case 0:
1403 session_name_arg = item_non_opt->arg;
1404 break;
1405 default:
1406 ERR("Unexpected argument `%s`.", item_non_opt->arg);
1407 goto error;
1408 }
1409 }
1410
1411 *argc -= argpar_state_get_ingested_orig_args(state);
1412 *argv += argpar_state_get_ingested_orig_args(state);
1413
1414 if (!session_name_arg) {
1415 ERR("Missing session name.");
1416 goto error;
1417 }
1418
1419 action = create_action_cb();
1420 if (!action) {
1421 ERR("Failed to allocate %s session action.", action_name);
1422 goto error;
1423 }
1424
1425 action_status = set_session_name_cb(action, session_name_arg);
1426 if (action_status != LTTNG_ACTION_STATUS_OK) {
1427 ERR("Failed to set action %s session's session name to '%s'.",
1428 action_name, session_name_arg);
1429 goto error;
1430 }
1431
1432 goto end;
1433
1434error:
1435 lttng_action_destroy(action);
1436 action = NULL;
97abbc84 1437 argpar_item_destroy(item);
4624dad0 1438end:
cb1b81ea 1439 free(error);
b78ef509 1440 argpar_state_destroy(state);
4624dad0
SM
1441 return action;
1442}
1443
1444static
1445struct lttng_action *handle_action_start_session(int *argc,
1446 const char ***argv)
1447{
1448 return handle_action_simple_session(argc, argv,
1449 lttng_action_start_session_create,
1450 lttng_action_start_session_set_session_name,
1451 "start");
1452}
1453
1454static
1455struct lttng_action *handle_action_stop_session(int *argc,
1456 const char ***argv)
1457{
1458 return handle_action_simple_session(argc, argv,
1459 lttng_action_stop_session_create,
1460 lttng_action_stop_session_set_session_name,
1461 "stop");
1462}
1463
1464static
1465struct lttng_action *handle_action_rotate_session(int *argc,
1466 const char ***argv)
1467{
1468 return handle_action_simple_session(argc, argv,
1469 lttng_action_rotate_session_create,
1470 lttng_action_rotate_session_set_session_name,
1471 "rotate");
1472}
1473
1474static const struct argpar_opt_descr snapshot_action_opt_descrs[] = {
1475 { OPT_NAME, 'n', "name", true },
1476 { OPT_MAX_SIZE, 'm', "max-size", true },
1477 { OPT_CTRL_URL, '\0', "ctrl-url", true },
1478 { OPT_DATA_URL, '\0', "data-url", true },
1479 { OPT_URL, '\0', "url", true },
1480 { OPT_PATH, '\0', "path", true },
1481 ARGPAR_OPT_DESCR_SENTINEL
1482};
1483
1484static
1485struct lttng_action *handle_action_snapshot_session(int *argc,
1486 const char ***argv)
1487{
1488 struct lttng_action *action = NULL;
1489 struct argpar_state *state = NULL;
1490 struct argpar_item *item = NULL;
1491 const char *session_name_arg = NULL;
1492 char *snapshot_name_arg = NULL;
1493 char *ctrl_url_arg = NULL;
1494 char *data_url_arg = NULL;
1495 char *max_size_arg = NULL;
1496 char *url_arg = NULL;
1497 char *path_arg = NULL;
1498 char *error = NULL;
1499 enum lttng_action_status action_status;
1500 struct lttng_snapshot_output *snapshot_output = NULL;
1501 int ret;
1502 unsigned int locations_specified = 0;
1503
1504 state = argpar_state_create(*argc, *argv, snapshot_action_opt_descrs);
1505 if (!state) {
1506 ERR("Failed to allocate an argpar state.");
1507 goto error;
1508 }
1509
1510 while (true) {
1511 enum argpar_state_parse_next_status status;
1512
1513 ARGPAR_ITEM_DESTROY_AND_RESET(item);
1514 status = argpar_state_parse_next(state, &item, &error);
1515 if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR) {
1516 ERR("%s", error);
1517 goto error;
1518 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR_UNKNOWN_OPT) {
1519 /* Just stop parsing here. */
1520 break;
1521 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_END) {
1522 break;
1523 }
1524
1525 assert(status == ARGPAR_STATE_PARSE_NEXT_STATUS_OK);
1526
1527 if (item->type == ARGPAR_ITEM_TYPE_OPT) {
1528 const struct argpar_item_opt *item_opt =
1529 (const struct argpar_item_opt *) item;
1530
1531 switch (item_opt->descr->id) {
1532 case OPT_NAME:
1533 if (!assign_string(&snapshot_name_arg, item_opt->arg, "--name/-n")) {
1534 goto error;
1535 }
1536
1537 break;
1538 case OPT_MAX_SIZE:
1539 if (!assign_string(&max_size_arg, item_opt->arg, "--max-size/-m")) {
1540 goto error;
1541 }
1542
1543 break;
1544 case OPT_CTRL_URL:
1545 if (!assign_string(&ctrl_url_arg, item_opt->arg, "--ctrl-url")) {
1546 goto error;
1547 }
1548
1549 break;
1550 case OPT_DATA_URL:
1551 if (!assign_string(&data_url_arg, item_opt->arg, "--data-url")) {
1552 goto error;
1553 }
1554
1555 break;
1556 case OPT_URL:
1557 if (!assign_string(&url_arg, item_opt->arg, "--url")) {
1558 goto error;
1559 }
1560
1561 break;
1562 case OPT_PATH:
1563 if (!assign_string(&path_arg, item_opt->arg, "--path")) {
1564 goto error;
1565 }
1566
1567 break;
1568 default:
1569 abort();
1570 }
1571 } else {
1572 const struct argpar_item_non_opt *item_non_opt;
1573
1574 assert(item->type == ARGPAR_ITEM_TYPE_NON_OPT);
1575
1576 item_non_opt = (const struct argpar_item_non_opt *) item;
1577
1578 switch (item_non_opt->non_opt_index) {
1579 case 0:
1580 session_name_arg = item_non_opt->arg;
1581 break;
1582 default:
1583 ERR("Unexpected argument `%s`.",
1584 item_non_opt->arg);
1585 goto error;
1586 }
1587 }
1588 }
1589
1590 *argc -= argpar_state_get_ingested_orig_args(state);
1591 *argv += argpar_state_get_ingested_orig_args(state);
1592
1593 if (!session_name_arg) {
1594 ERR("Missing session name.");
1595 goto error;
1596 }
1597
1598 /* --ctrl-url and --data-url must come in pair. */
1599 if (ctrl_url_arg && !data_url_arg) {
1600 ERR("--ctrl-url is specified, but --data-url is missing.");
1601 goto error;
1602 }
1603
1604 if (!ctrl_url_arg && data_url_arg) {
1605 ERR("--data-url is specified, but --ctrl-url is missing.");
1606 goto error;
1607 }
1608
1609 locations_specified += !!(ctrl_url_arg || data_url_arg);
1610 locations_specified += !!url_arg;
1611 locations_specified += !!path_arg;
1612
1613 /* --ctrl-url/--data-url, --url and --path are mutually exclusive. */
1614 if (locations_specified > 1) {
1615 ERR("The --ctrl-url/--data-url, --url, and --path options can't be used together.");
1616 goto error;
1617 }
1618
1619 /*
1620 * Did the user specify an option that implies using a
1621 * custom/unregistered output?
1622 */
1623 if (url_arg || ctrl_url_arg || path_arg) {
1624 snapshot_output = lttng_snapshot_output_create();
1625 if (!snapshot_output) {
1626 ERR("Failed to allocate a snapshot output.");
1627 goto error;
1628 }
1629 }
1630
1631 action = lttng_action_snapshot_session_create();
1632 if (!action) {
1633 ERR("Failed to allocate snapshot session action.");
1634 goto error;
1635 }
1636
1637 action_status = lttng_action_snapshot_session_set_session_name(
1638 action, session_name_arg);
1639 if (action_status != LTTNG_ACTION_STATUS_OK) {
1640 ERR("Failed to set action snapshot session's session name to '%s'.",
1641 session_name_arg);
1642 goto error;
1643 }
1644
1645 if (snapshot_name_arg) {
1646 if (!snapshot_output) {
1647 ERR("Can't provide a snapshot output name without a snapshot output destination.");
1648 goto error;
1649 }
1650
1651 ret = lttng_snapshot_output_set_name(
1652 snapshot_name_arg, snapshot_output);
1653 if (ret != 0) {
1654 ERR("Failed to set name of snapshot output.");
1655 goto error;
1656 }
1657 }
1658
1659 if (max_size_arg) {
1660 uint64_t max_size;
1661
1662 if (!snapshot_output) {
1663 ERR("Can't provide a snapshot output max size without a snapshot output destination.");
1664 goto error;
1665 }
1666
1667 ret = utils_parse_size_suffix(max_size_arg, &max_size);
1668 if (ret != 0) {
1669 ERR("Failed to parse `%s` as a size.", max_size_arg);
1670 goto error;
1671 }
1672
1673 ret = lttng_snapshot_output_set_size(max_size, snapshot_output);
1674 if (ret != 0) {
1675 ERR("Failed to set snapshot output's max size to %" PRIu64 " bytes.",
1676 max_size);
1677 goto error;
1678 }
1679 }
1680
1681 if (url_arg) {
1682 int num_uris;
1683 struct lttng_uri *uris;
1684
1685 if (!strstr(url_arg, "://")) {
1686 ERR("Failed to parse '%s' as an URL.", url_arg);
1687 goto error;
1688 }
1689
1690 num_uris = uri_parse_str_urls(url_arg, NULL, &uris);
1691 if (num_uris < 1) {
1692 ERR("Failed to parse '%s' as an URL.", url_arg);
1693 goto error;
1694 }
1695
1696 if (uris[0].dtype == LTTNG_DST_PATH) {
1697 ret = lttng_snapshot_output_set_local_path(
1698 uris[0].dst.path, snapshot_output);
1699 free(uris);
1700 if (ret != 0) {
1701 ERR("Failed to assign '%s' as a local destination.",
1702 url_arg);
1703 goto error;
1704 }
1705 } else {
1706 ret = lttng_snapshot_output_set_network_url(
1707 url_arg, snapshot_output);
1708 free(uris);
1709 if (ret != 0) {
1710 ERR("Failed to assign '%s' as a network URL.",
1711 url_arg);
1712 goto error;
1713 }
1714 }
1715 }
1716
1717 if (path_arg) {
1718 ret = lttng_snapshot_output_set_local_path(
1719 path_arg, snapshot_output);
1720 if (ret != 0) {
1721 ERR("Failed to parse '%s' as a local path.", path_arg);
1722 goto error;
1723 }
1724 }
1725
1726 if (ctrl_url_arg) {
1727 /*
1728 * Two argument form, network output with separate control and
1729 * data URLs.
1730 */
1731 ret = lttng_snapshot_output_set_network_urls(
1732 ctrl_url_arg, data_url_arg, snapshot_output);
1733 if (ret != 0) {
1734 ERR("Failed to parse `%s` and `%s` as control and data URLs.",
1735 ctrl_url_arg, data_url_arg);
1736 goto error;
1737 }
1738 }
1739
1740 if (snapshot_output) {
1741 action_status = lttng_action_snapshot_session_set_output(
1742 action, snapshot_output);
1743 if (action_status != LTTNG_ACTION_STATUS_OK) {
1744 ERR("Failed to set snapshot session action's output.");
1745 goto error;
1746 }
1747
1748 /* Ownership of `snapshot_output` has been transferred to the action. */
1749 snapshot_output = NULL;
1750 }
1751
1752 goto end;
1753
1754error:
1755 lttng_action_destroy(action);
1756 action = NULL;
1757 free(error);
1758end:
1759 free(snapshot_name_arg);
1760 free(path_arg);
1761 free(url_arg);
1762 free(ctrl_url_arg);
1763 free(data_url_arg);
1764 free(snapshot_output);
f6b73530 1765 free(max_size_arg);
4624dad0 1766 argpar_state_destroy(state);
97abbc84 1767 argpar_item_destroy(item);
4624dad0
SM
1768 return action;
1769}
1770
1771struct action_descr {
1772 const char *name;
1773 struct lttng_action *(*handler) (int *argc, const char ***argv);
1774};
1775
1776static const
1777struct action_descr action_descrs[] = {
1778 { "notify", handle_action_notify },
1779 { "start-session", handle_action_start_session },
1780 { "stop-session", handle_action_stop_session },
1781 { "rotate-session", handle_action_rotate_session },
1782 { "snapshot-session", handle_action_snapshot_session },
1783};
1784
1785static
1786struct lttng_action *parse_action(int *argc, const char ***argv)
1787{
1788 int i;
1789 struct lttng_action *action;
1790 const char *action_name;
1791 const struct action_descr *descr = NULL;
1792
1793 if (*argc == 0) {
1794 ERR("Missing action name.");
1795 goto error;
1796 }
1797
1798 action_name = (*argv)[0];
1799
1800 (*argc)--;
1801 (*argv)++;
1802
1803 for (i = 0; i < ARRAY_SIZE(action_descrs); i++) {
1804 if (strcmp(action_name, action_descrs[i].name) == 0) {
1805 descr = &action_descrs[i];
1806 break;
1807 }
1808 }
1809
1810 if (!descr) {
1811 ERR("Unknown action name: %s", action_name);
1812 goto error;
1813 }
1814
1815 action = descr->handler(argc, argv);
1816 if (!action) {
1817 /* The handler has already printed an error message. */
1818 goto error;
1819 }
1820
1821 goto end;
1822error:
1823 action = NULL;
1824end:
1825 return action;
1826}
1827
1828static const
1829struct argpar_opt_descr add_trigger_options[] = {
1830 { OPT_HELP, 'h', "help", false },
1831 { OPT_LIST_OPTIONS, '\0', "list-options", false },
1832 { OPT_CONDITION, '\0', "condition", false },
1833 { OPT_ACTION, '\0', "action", false },
1834 { OPT_ID, '\0', "id", true },
1835 { OPT_FIRE_ONCE_AFTER, '\0', "fire-once-after", true },
1836 { OPT_FIRE_EVERY, '\0', "fire-every", true },
1837 { OPT_USER_ID, '\0', "user-id", true },
1838 ARGPAR_OPT_DESCR_SENTINEL,
1839};
1840
1841static
1842void lttng_actions_destructor(void *p)
1843{
1844 struct lttng_action *action = p;
1845
1846 lttng_action_destroy(action);
1847}
1848
1849int cmd_add_trigger(int argc, const char **argv)
1850{
1851 int ret;
1852 int my_argc = argc - 1;
1853 const char **my_argv = argv + 1;
1854 struct lttng_condition *condition = NULL;
1855 struct lttng_dynamic_pointer_array actions;
1856 struct argpar_state *argpar_state = NULL;
1857 struct argpar_item *argpar_item = NULL;
1858 struct lttng_action *action_group = NULL;
1859 struct lttng_action *action = NULL;
1860 struct lttng_trigger *trigger = NULL;
1861 char *error = NULL;
1862 char *id = NULL;
1863 int i;
1864 char *fire_once_after_str = NULL;
1865 char *fire_every_str = NULL;
1866 char *user_id = NULL;
1867
1868 lttng_dynamic_pointer_array_init(&actions, lttng_actions_destructor);
1869
1870 while (true) {
1871 enum argpar_state_parse_next_status status;
1872 const struct argpar_item_opt *item_opt;
1873 int ingested_args;
1874
1875 argpar_state_destroy(argpar_state);
1876 argpar_state = argpar_state_create(my_argc, my_argv,
1877 add_trigger_options);
1878 if (!argpar_state) {
1879 ERR("Failed to create argpar state.");
1880 goto error;
1881 }
1882
1883 ARGPAR_ITEM_DESTROY_AND_RESET(argpar_item);
1884 status = argpar_state_parse_next(argpar_state, &argpar_item, &error);
1885 if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR) {
1886 ERR("%s", error);
1887 goto error;
1888 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR_UNKNOWN_OPT) {
1889 ERR("%s", error);
1890 goto error;
1891 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_END) {
1892 break;
1893 }
1894
1895 assert(status == ARGPAR_STATE_PARSE_NEXT_STATUS_OK);
1896
1897 if (argpar_item->type == ARGPAR_ITEM_TYPE_NON_OPT) {
1898 const struct argpar_item_non_opt *item_non_opt =
1899 (const struct argpar_item_non_opt *)
1900 argpar_item;
1901
1902 ERR("Unexpected argument `%s`.", item_non_opt->arg);
1903 goto error;
1904 }
1905
1906 item_opt = (const struct argpar_item_opt *) argpar_item;
1907
1908 ingested_args = argpar_state_get_ingested_orig_args(
1909 argpar_state);
1910
1911 my_argc -= ingested_args;
1912 my_argv += ingested_args;
1913
1914 switch (item_opt->descr->id) {
1915 case OPT_HELP:
1916 SHOW_HELP();
1917 ret = 0;
1918 goto end;
1919 case OPT_LIST_OPTIONS:
1920 list_cmd_options_argpar(stdout, add_trigger_options);
1921 ret = 0;
1922 goto end;
1923 case OPT_CONDITION:
1924 {
1925 if (condition) {
1926 ERR("A --condition was already given.");
1927 goto error;
1928 }
1929
1930 condition = parse_condition(&my_argc, &my_argv);
1931 if (!condition) {
1932 /*
1933 * An error message was already printed by
1934 * parse_condition.
1935 */
1936 goto error;
1937 }
1938
1939 break;
1940 }
1941 case OPT_ACTION:
1942 {
1943 action = parse_action(&my_argc, &my_argv);
1944 if (!action) {
1945 /*
1946 * An error message was already printed by
1947 * parse_condition.
1948 */
1949 goto error;
1950 }
1951
1952 ret = lttng_dynamic_pointer_array_add_pointer(
1953 &actions, action);
1954 if (ret) {
1955 ERR("Failed to add pointer to pointer array.");
1956 goto error;
1957 }
1958
1959 /* Ownership of the action was transferred to the group. */
1960 action = NULL;
1961
1962 break;
1963 }
1964 case OPT_ID:
1965 {
1966 if (!assign_string(&id, item_opt->arg, "--id")) {
1967 goto error;
1968 }
1969
1970 break;
1971 }
1972 case OPT_FIRE_ONCE_AFTER:
1973 {
1974 if (!assign_string(&fire_once_after_str, item_opt->arg,
1975 "--fire-once-after")) {
1976 goto error;
1977 }
1978
1979 break;
1980 }
1981 case OPT_FIRE_EVERY:
1982 {
1983 if (!assign_string(&fire_every_str, item_opt->arg,
1984 "--fire-every")) {
1985 goto error;
1986 }
1987
1988 break;
1989 }
1990 case OPT_USER_ID:
1991 {
1992 if (!assign_string(&user_id, item_opt->arg,
1993 "--user-id")) {
1994 goto error;
1995 }
1996
1997 break;
1998 }
1999 default:
2000 abort();
2001 }
2002 }
2003
2004 if (!condition) {
2005 ERR("Missing --condition.");
2006 goto error;
2007 }
2008
2009 if (lttng_dynamic_pointer_array_get_count(&actions) == 0) {
2010 ERR("Need at least one --action.");
2011 goto error;
2012 }
2013
2014 if (fire_every_str && fire_once_after_str) {
2015 ERR("Can't specify both --fire-once-after and --fire-every.");
2016 goto error;
2017 }
2018
2019 action_group = lttng_action_group_create();
2020 if (!action_group) {
2021 goto error;
2022 }
2023
2024 for (i = 0; i < lttng_dynamic_pointer_array_get_count(&actions); i++) {
2025 enum lttng_action_status status;
2026
2027 action = lttng_dynamic_pointer_array_steal_pointer(&actions, i);
2028
2029 status = lttng_action_group_add_action(action_group, action);
2030 if (status != LTTNG_ACTION_STATUS_OK) {
2031 goto error;
2032 }
2033
2034 /*
2035 * The `lttng_action_group_add_action()` takes a reference to
2036 * the action. We can destroy ours.
2037 */
2038 lttng_action_destroy(action);
2039 action = NULL;
2040 }
2041
2042 trigger = lttng_trigger_create(condition, action_group);
2043 if (!trigger) {
2044 goto error;
2045 }
2046
2047 if (id) {
2048 enum lttng_trigger_status trigger_status =
2049 lttng_trigger_set_name(trigger, id);
2050
2051 if (trigger_status != LTTNG_TRIGGER_STATUS_OK) {
2052 ERR("Failed to set trigger id.");
2053 goto error;
2054 }
2055 }
2056
2057 if (fire_once_after_str) {
2058 unsigned long long threshold;
2059 enum lttng_trigger_status trigger_status;
2060
2061 if (utils_parse_unsigned_long_long(fire_once_after_str, &threshold) != 0) {
2062 ERR("Failed to parse `%s` as an integer.", fire_once_after_str);
2063 goto error;
2064 }
2065
2066 trigger_status = lttng_trigger_set_firing_policy(trigger,
2067 LTTNG_TRIGGER_FIRING_POLICY_ONCE_AFTER_N,
2068 threshold);
2069 if (trigger_status != LTTNG_TRIGGER_STATUS_OK) {
2070 ERR("Failed to set trigger's policy to `fire once after N`.");
2071 goto error;
2072 }
2073 }
2074
2075 if (fire_every_str) {
2076 unsigned long long threshold;
2077 enum lttng_trigger_status trigger_status;
2078
2079 if (utils_parse_unsigned_long_long(fire_every_str, &threshold) != 0) {
2080 ERR("Failed to parse `%s` as an integer.", fire_every_str);
2081 goto error;
2082 }
2083
2084 trigger_status = lttng_trigger_set_firing_policy(trigger,
2085 LTTNG_TRIGGER_FIRING_POLICY_EVERY_N, threshold);
2086 if (trigger_status != LTTNG_TRIGGER_STATUS_OK) {
2087 ERR("Failed to set trigger's policy to `fire every N`.");
2088 goto error;
2089 }
2090 }
2091
2092 if (user_id) {
2093 enum lttng_trigger_status trigger_status;
2094 char *end;
2095 long long uid;
2096
2097 errno = 0;
2098 uid = strtol(user_id, &end, 10);
2099 if (end == user_id || *end != '\0' || errno != 0) {
2100 ERR("Failed to parse `%s` as a user id.", user_id);
2101 }
2102
2103 trigger_status = lttng_trigger_set_owner_uid(trigger, uid);
2104 if (trigger_status != LTTNG_TRIGGER_STATUS_OK) {
2105 ERR("Failed to set trigger's user identity.");
2106 goto error;
2107 }
2108 }
2109
2110 ret = lttng_register_trigger(trigger);
2111 if (ret) {
2112 ERR("Failed to register trigger: %s.", lttng_strerror(ret));
2113 goto error;
2114 }
2115
2116 MSG("Trigger registered successfully.");
2117
2118 goto end;
2119
2120error:
2121 ret = 1;
2122
2123end:
2124 argpar_state_destroy(argpar_state);
2125 argpar_item_destroy(argpar_item);
2126 lttng_dynamic_pointer_array_reset(&actions);
2127 lttng_condition_destroy(condition);
2128 lttng_action_destroy(action_group);
2129 lttng_action_destroy(action);
2130 lttng_trigger_destroy(trigger);
2131 free(error);
2132 free(id);
2133 free(fire_once_after_str);
2134 free(fire_every_str);
2135 free(user_id);
2136 return ret;
2137}
This page took 0.105959 seconds and 4 git commands to generate.