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