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