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