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