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