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