SoW-2020-0003: Trace Hit Counters
[lttng-tools.git] / src / bin / lttng / commands / list_triggers.c
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 <stdio.h>
9
10 #include "../command.h"
11
12 #include "common/argpar/argpar.h"
13 #include "common/dynamic-array.h"
14 #include "common/mi-lttng.h"
15 /* For lttng_condition_type_str(). */
16 #include "lttng/condition/condition-internal.h"
17 #include "lttng/condition/on-event.h"
18 #include "lttng/condition/on-event-internal.h"
19 /* For lttng_domain_type_str(). */
20 #include "lttng/domain-internal.h"
21 #include "lttng/event-rule/event-rule-internal.h"
22 #include "lttng/event-rule/kernel-probe.h"
23 #include "lttng/event-rule/kernel-probe-internal.h"
24 #include "lttng/event-rule/syscall.h"
25 #include "lttng/event-rule/tracepoint.h"
26 #include "lttng/event-rule/userspace-probe.h"
27 #include "lttng/map-key.h"
28 #include "lttng/map-key-internal.h"
29 #include "lttng/trigger/trigger-internal.h"
30 #include "lttng/kernel-probe.h"
31
32 #ifdef LTTNG_EMBED_HELP
33 static const char help_msg[] =
34 #include <lttng-list-triggers.1.h>
35 ;
36 #endif
37
38 enum {
39 OPT_HELP,
40 OPT_LIST_OPTIONS,
41 };
42
43 static const
44 struct argpar_opt_descr list_trigger_options[] = {
45 { OPT_HELP, 'h', "help", false },
46 { OPT_LIST_OPTIONS, '\0', "list-options", false },
47 ARGPAR_OPT_DESCR_SENTINEL,
48 };
49
50 static
51 void print_event_rule_tracepoint(const struct lttng_event_rule *event_rule)
52 {
53 enum lttng_event_rule_status event_rule_status;
54 enum lttng_domain_type domain_type;
55 const char *pattern;
56 const char *filter;
57 int log_level;
58 const struct lttng_log_level_rule *log_level_rule = NULL;
59 unsigned int exclusions_count;
60 int i;
61
62 event_rule_status = lttng_event_rule_tracepoint_get_pattern(
63 event_rule, &pattern);
64 assert(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK);
65
66 event_rule_status = lttng_event_rule_tracepoint_get_domain_type(
67 event_rule, &domain_type);
68 assert(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK);
69
70 _MSG(" rule: %s (type: tracepoint, domain: %s", pattern,
71 lttng_domain_type_str(domain_type));
72
73 event_rule_status = lttng_event_rule_tracepoint_get_filter(
74 event_rule, &filter);
75 if (event_rule_status == LTTNG_EVENT_RULE_STATUS_OK) {
76 _MSG(", filter: %s", filter);
77 } else {
78 assert(event_rule_status == LTTNG_EVENT_RULE_STATUS_UNSET);
79 }
80
81 event_rule_status = lttng_event_rule_tracepoint_get_log_level_rule(
82 event_rule, &log_level_rule);
83 if (event_rule_status == LTTNG_EVENT_RULE_STATUS_OK) {
84 enum lttng_log_level_rule_status llr_status;
85 const char *log_level_op;
86
87 switch (lttng_log_level_rule_get_type(log_level_rule)) {
88 case LTTNG_LOG_LEVEL_RULE_TYPE_EXACTLY:
89 llr_status = lttng_log_level_rule_exactly_get_level(
90 log_level_rule, &log_level);
91 log_level_op = "==";
92 break;
93 case LTTNG_LOG_LEVEL_RULE_TYPE_AT_LEAST_AS_SEVERE_AS:
94 log_level_op = "<=";
95 llr_status = lttng_log_level_rule_at_least_as_severe_as_get_level(
96 log_level_rule, &log_level);
97 break;
98 default:
99 abort();
100 }
101
102 assert(llr_status == LTTNG_LOG_LEVEL_RULE_STATUS_OK);
103
104 /* TODO: here the raw level value must be printed since the
105 * value could have no known string equivalent, the string
106 * representation is only a "convenience".
107 */
108 _MSG(", log level %s %s", log_level_op,
109 mi_lttng_loglevel_string(
110 log_level, domain_type));
111 } else {
112 assert(event_rule_status == LTTNG_EVENT_RULE_STATUS_UNSET);
113 }
114
115 event_rule_status = lttng_event_rule_tracepoint_get_exclusions_count(
116 event_rule, &exclusions_count);
117 assert(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK);
118 if (exclusions_count > 0) {
119 _MSG(", exclusions: ");
120 for (i = 0; i < exclusions_count; i++) {
121 const char *exclusion;
122
123 event_rule_status = lttng_event_rule_tracepoint_get_exclusion_at_index(
124 event_rule, i, &exclusion);
125 assert(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK);
126
127 _MSG("%s%s", i > 0 ? "," : "", exclusion);
128 }
129 }
130
131 MSG(")");
132 }
133
134 static void print_kernel_probe_location(
135 const struct lttng_kernel_probe_location *location)
136 {
137 enum lttng_kernel_probe_location_status status;
138 switch (lttng_kernel_probe_location_get_type(location)) {
139 case LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS:
140 {
141 uint64_t address;
142
143 status = lttng_kernel_probe_location_address_get_address(
144 location, &address);
145 if (status != LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK) {
146 ERR("Getting kernel probe location address failed.");
147 goto end;
148 }
149
150 _MSG("0x%" PRIx64, address);
151
152 break;
153 }
154 case LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET:
155 {
156 uint64_t offset;
157 const char *symbol_name;
158
159 symbol_name = lttng_kernel_probe_location_symbol_get_name(
160 location);
161 if (!symbol_name) {
162 ERR("Getting kernel probe location symbol name failed.");
163 goto end;
164 }
165
166 status = lttng_kernel_probe_location_symbol_get_offset(
167 location, &offset);
168 if (status != LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK) {
169 ERR("Getting kernel probe location address failed.");
170 goto end;
171 }
172
173 if (offset == 0) {
174 _MSG("%s", symbol_name);
175 } else {
176 _MSG("%s+0x%" PRIx64, symbol_name, offset);
177 }
178
179 break;
180 }
181 default:
182 abort();
183 };
184 end:
185 return;
186 }
187
188 static
189 void print_event_rule_kernel_probe(const struct lttng_event_rule *event_rule)
190 {
191 enum lttng_event_rule_status event_rule_status;
192 const char *name;
193 const struct lttng_kernel_probe_location *location;
194
195 assert(lttng_event_rule_get_type(event_rule) == LTTNG_EVENT_RULE_TYPE_KERNEL_PROBE);
196
197 event_rule_status = lttng_event_rule_kernel_probe_get_event_name(event_rule, &name);
198 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
199 ERR("Failed to get kprobe event rule's name.");
200 goto end;
201 }
202
203 event_rule_status = lttng_event_rule_kernel_probe_get_location(
204 event_rule, &location);
205 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
206 ERR("Failed to get kprobe event rule's location.");
207 goto end;
208 }
209
210 _MSG(" rule: %s (type: probe, location: ", name);
211
212 print_kernel_probe_location(location);
213
214 MSG(")");
215
216 end:
217 return;
218 }
219
220 static
221 void print_event_rule_userspace_probe(const struct lttng_event_rule *event_rule)
222 {
223 enum lttng_event_rule_status event_rule_status;
224 const char *name;
225 const struct lttng_userspace_probe_location *location;
226 enum lttng_userspace_probe_location_type userspace_probe_location_type;
227
228 assert(lttng_event_rule_get_type(event_rule) == LTTNG_EVENT_RULE_TYPE_USERSPACE_PROBE);
229
230 event_rule_status = lttng_event_rule_userspace_probe_get_event_name(event_rule, &name);
231 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
232 ERR("Failed to get uprobe event rule's name.");
233 goto end;
234 }
235
236 event_rule_status = lttng_event_rule_userspace_probe_get_location(
237 event_rule, &location);
238 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
239 ERR("Failed to get uprobe event rule's location.");
240 goto end;
241 }
242
243 _MSG(" rule: %s (type: userspace probe, location: ", name);
244
245 userspace_probe_location_type =
246 lttng_userspace_probe_location_get_type(location);
247
248 switch (userspace_probe_location_type) {
249 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
250 {
251 const char *binary_path, *function_name;
252
253 binary_path = lttng_userspace_probe_location_function_get_binary_path(
254 location);
255 function_name = lttng_userspace_probe_location_function_get_function_name(
256 location);
257
258 _MSG("%s:%s", binary_path, function_name);
259 break;
260 }
261 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
262 _MSG("SDT not implemented yet");
263 break;
264 default:
265 abort();
266 }
267
268 MSG(")");
269
270 end:
271 return;
272 }
273
274 static
275 void print_event_rule_syscall(const struct lttng_event_rule *event_rule)
276 {
277 const char *pattern, *filter;
278 enum lttng_event_rule_status event_rule_status;
279
280 assert(lttng_event_rule_get_type(event_rule) == LTTNG_EVENT_RULE_TYPE_SYSCALL);
281
282 event_rule_status = lttng_event_rule_syscall_get_pattern(
283 event_rule, &pattern);
284 assert(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK);
285
286 _MSG(" rule: %s (type: syscall", pattern);
287
288 event_rule_status = lttng_event_rule_syscall_get_filter(
289 event_rule, &filter);
290 if (event_rule_status == LTTNG_EVENT_RULE_STATUS_OK) {
291 _MSG(", filter: %s", filter);
292 } else {
293 assert(event_rule_status == LTTNG_EVENT_RULE_STATUS_UNSET);
294 }
295
296 MSG(")");
297 }
298
299 static
300 void print_event_rule(const struct lttng_event_rule *event_rule)
301 {
302 const enum lttng_event_rule_type event_rule_type =
303 lttng_event_rule_get_type(event_rule);
304
305 switch (event_rule_type) {
306 case LTTNG_EVENT_RULE_TYPE_TRACEPOINT:
307 print_event_rule_tracepoint(event_rule);
308 break;
309 case LTTNG_EVENT_RULE_TYPE_KERNEL_PROBE:
310 print_event_rule_kernel_probe(event_rule);
311 break;
312 case LTTNG_EVENT_RULE_TYPE_USERSPACE_PROBE:
313 print_event_rule_userspace_probe(event_rule);
314 break;
315 case LTTNG_EVENT_RULE_TYPE_SYSCALL:
316 print_event_rule_syscall(event_rule);
317 break;
318 default:
319 abort();
320 }
321 }
322
323 static
324 void print_one_event_expr(const struct lttng_event_expr *event_expr)
325 {
326 enum lttng_event_expr_type type;
327
328 type = lttng_event_expr_get_type(event_expr);
329
330 switch (type) {
331 case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD: {
332 const char *name;
333
334 name = lttng_event_expr_event_payload_field_get_name(event_expr);
335 _MSG("%s", name);
336
337 break;
338 }
339
340 case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD: {
341 const char *name;
342
343 name = lttng_event_expr_channel_context_field_get_name(event_expr);
344 _MSG("$ctx.%s", name);
345
346 break;
347 }
348
349 case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD: {
350 const char *provider_name;
351 const char *type_name;
352
353 provider_name =
354 lttng_event_expr_app_specific_context_field_get_provider_name(
355 event_expr);
356 type_name =
357 lttng_event_expr_app_specific_context_field_get_type_name(
358 event_expr);
359
360 _MSG("$app.%s:%s", provider_name, type_name);
361
362 break;
363 }
364
365 case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT: {
366 unsigned int index;
367 const struct lttng_event_expr *parent_expr;
368 enum lttng_event_expr_status status;
369
370 parent_expr = lttng_event_expr_array_field_element_get_parent_expr(
371 event_expr);
372 assert(parent_expr != NULL);
373
374 print_one_event_expr(parent_expr);
375
376 status = lttng_event_expr_array_field_element_get_index(
377 event_expr, &index);
378 assert(status == LTTNG_EVENT_EXPR_STATUS_OK);
379
380 _MSG("[%u]", index);
381
382 break;
383 }
384
385 default:
386 abort();
387 }
388 }
389
390 static
391 void print_condition_on_event(const struct lttng_condition *condition)
392 {
393 const struct lttng_event_rule *event_rule;
394 enum lttng_condition_status condition_status;
395 unsigned int cap_desc_count, i;
396 uint64_t error_count;
397
398 condition_status =
399 lttng_condition_on_event_get_rule(condition, &event_rule);
400 assert(condition_status == LTTNG_CONDITION_STATUS_OK);
401
402 print_event_rule(event_rule);
403
404 condition_status
405 = lttng_condition_on_event_get_capture_descriptor_count(
406 condition, &cap_desc_count);
407 assert(condition_status == LTTNG_CONDITION_STATUS_OK);
408
409 error_count = lttng_condition_on_event_get_error_count(condition);
410 MSG(" tracer notifications discarded: %ld", error_count);
411
412 if (cap_desc_count > 0) {
413 MSG(" captures:");
414
415 for (i = 0; i < cap_desc_count; i++) {
416 const struct lttng_event_expr *cap_desc =
417 lttng_condition_on_event_get_capture_descriptor_at_index(
418 condition, i);
419
420 _MSG(" - ");
421 print_one_event_expr(cap_desc);
422 MSG("");
423 }
424 }
425 }
426
427 static
428 void print_map_key(const struct lttng_map_key *key)
429 {
430 unsigned int i, token_count;
431 enum lttng_map_key_status key_status;
432
433 _MSG(" key: `");
434 key_status = lttng_map_key_get_token_count(key, &token_count);
435 assert(key_status == LTTNG_MAP_KEY_STATUS_OK);
436
437 for (i = 0; i < token_count; i++) {
438 const struct lttng_map_key_token *token =
439 lttng_map_key_get_token_at_index(key, i);
440 assert(token);
441
442 switch (token->type) {
443 case LTTNG_MAP_KEY_TOKEN_TYPE_STRING:
444 {
445 const struct lttng_map_key_token_string *str_token;
446 str_token = (typeof(str_token)) token;
447 _MSG("%s", str_token->string);
448 break;
449 }
450 case LTTNG_MAP_KEY_TOKEN_TYPE_VARIABLE:
451 {
452 const struct lttng_map_key_token_variable *var_token;
453 var_token = (typeof(var_token)) token;
454
455 switch (var_token->type) {
456 case LTTNG_MAP_KEY_TOKEN_VARIABLE_TYPE_EVENT_NAME:
457 _MSG("${EVENT_NAME}");
458 break;
459 case LTTNG_MAP_KEY_TOKEN_VARIABLE_TYPE_PROVIDER_NAME:
460 _MSG("${PROVIDER_NAME}");
461 break;
462 default:
463 abort();
464 }
465
466 break;
467 }
468 default:
469 abort();
470 }
471 }
472 MSG("`");
473 }
474
475 static
476 void print_one_incr_value_action(const struct lttng_action *action)
477 {
478 enum lttng_action_status action_status;
479 const char *session_name, *map_name;
480 const struct lttng_map_key *key;
481
482 action_status = lttng_action_incr_value_get_session_name(
483 action, &session_name);
484 assert(action_status == LTTNG_ACTION_STATUS_OK);
485
486 action_status = lttng_action_incr_value_get_map_name(
487 action, &map_name);
488 assert(action_status == LTTNG_ACTION_STATUS_OK);
489
490 action_status = lttng_action_incr_value_get_key(
491 action, &key);
492 assert(action_status == LTTNG_ACTION_STATUS_OK);
493
494 MSG("increment value:");
495 MSG(" session: `%s`", session_name);
496 MSG(" map: `%s`", map_name);
497 print_map_key(key);
498 }
499
500 static
501 void print_one_action(const struct lttng_action *action)
502 {
503 enum lttng_action_type action_type;
504 enum lttng_action_status action_status;
505 const char *value;
506
507 action_type = lttng_action_get_type(action);
508 assert(action_type != LTTNG_ACTION_TYPE_GROUP);
509
510 switch (action_type) {
511 case LTTNG_ACTION_TYPE_INCREMENT_VALUE:
512 print_one_incr_value_action(action);
513 break;
514 case LTTNG_ACTION_TYPE_NOTIFY:
515 MSG("notify");
516 break;
517 case LTTNG_ACTION_TYPE_START_SESSION:
518 action_status = lttng_action_start_session_get_session_name(
519 action, &value);
520 assert(action_status == LTTNG_ACTION_STATUS_OK);
521 MSG("start session `%s`", value);
522 break;
523 case LTTNG_ACTION_TYPE_STOP_SESSION:
524 action_status = lttng_action_stop_session_get_session_name(
525 action, &value);
526 assert(action_status == LTTNG_ACTION_STATUS_OK);
527 MSG("stop session `%s`", value);
528 break;
529 case LTTNG_ACTION_TYPE_ROTATE_SESSION:
530 action_status = lttng_action_rotate_session_get_session_name(
531 action, &value);
532 assert(action_status == LTTNG_ACTION_STATUS_OK);
533 MSG("rotate session `%s`", value);
534 break;
535 case LTTNG_ACTION_TYPE_SNAPSHOT_SESSION:
536 {
537 const struct lttng_snapshot_output *output;
538
539 action_status = lttng_action_snapshot_session_get_session_name(
540 action, &value);
541 assert(action_status == LTTNG_ACTION_STATUS_OK);
542 _MSG("snapshot session `%s`", value);
543
544 action_status = lttng_action_snapshot_session_get_output(
545 action, &output);
546 if (action_status == LTTNG_ACTION_STATUS_OK) {
547 const char *name;
548 uint64_t max_size;
549 const char *ctrl_url, *data_url;
550 bool starts_with_file, starts_with_net, starts_with_net6;
551
552 ctrl_url = lttng_snapshot_output_get_ctrl_url(output);
553 assert(ctrl_url && strlen(ctrl_url) > 0);
554
555 data_url = lttng_snapshot_output_get_data_url(output);
556 assert(data_url);
557
558 starts_with_file = strncmp(ctrl_url, "file://", strlen("file://")) == 0;
559 starts_with_net = strncmp(ctrl_url, "net://", strlen("net://")) == 0;
560 starts_with_net6 = strncmp(ctrl_url, "net6://", strlen("net6://")) == 0;
561
562 if (ctrl_url[0] == '/' || starts_with_file) {
563 if (starts_with_file) {
564 ctrl_url += strlen("file://");
565 }
566
567 _MSG(", path: %s", ctrl_url);
568 } else if (starts_with_net || starts_with_net6) {
569 _MSG(", url: %s", ctrl_url);
570 } else {
571 assert(strlen(data_url) > 0);
572
573 _MSG(", control url: %s, data url: %s", ctrl_url, data_url);
574 }
575
576 name = lttng_snapshot_output_get_name(output);
577 assert(name);
578 if (strlen(name) > 0) {
579 _MSG(", name: %s", name);
580 }
581
582 max_size = lttng_snapshot_output_get_maxsize(output);
583 if (max_size != -1ULL) {
584 _MSG(", max size: %" PRIu64, max_size);
585 }
586 }
587
588 MSG("");
589 break;
590 }
591
592 default:
593 abort();
594 }
595 }
596
597 static
598 void print_one_trigger(const struct lttng_trigger *trigger)
599 {
600 const struct lttng_condition *condition;
601 enum lttng_condition_type condition_type;
602 const struct lttng_action *action;
603 enum lttng_action_type action_type;
604 enum lttng_trigger_status trigger_status;
605 const char *name;
606 enum lttng_trigger_firing_policy firing_policy_type;
607 uint64_t threshold;
608 uid_t trigger_uid;
609
610 trigger_status = lttng_trigger_get_name(trigger, &name);
611 assert(trigger_status == LTTNG_TRIGGER_STATUS_OK);
612
613 trigger_status = lttng_trigger_get_owner_uid(trigger, &trigger_uid);
614 assert(trigger_status == LTTNG_TRIGGER_STATUS_OK);
615
616 MSG("- id: %s", name);
617 MSG(" user id: %d", trigger_uid);
618
619 trigger_status = lttng_trigger_get_firing_policy(
620 trigger, &firing_policy_type, &threshold);
621 if (trigger_status != LTTNG_TRIGGER_STATUS_OK) {
622 ERR("Failed to get trigger's policy.");
623 goto end;
624 }
625
626 switch (firing_policy_type) {
627 case LTTNG_TRIGGER_FIRING_POLICY_EVERY_N:
628 if (threshold > 1) {
629 MSG(" firing policy: after every %" PRIu64 " occurences", threshold);
630 }
631 break;
632 case LTTNG_TRIGGER_FIRING_POLICY_ONCE_AFTER_N:
633 MSG(" firing policy: once after %" PRIu64 " occurences", threshold);
634 break;
635 default:
636 abort();
637 }
638
639 condition = lttng_trigger_get_const_condition(trigger);
640 condition_type = lttng_condition_get_type(condition);
641 MSG(" condition: %s", lttng_condition_type_str(condition_type));
642 switch (condition_type) {
643 case LTTNG_CONDITION_TYPE_ON_EVENT:
644 print_condition_on_event(condition);
645 break;
646 default:
647 MSG(" (condition type not handled in %s)", __func__);
648 break;
649 }
650
651 action = lttng_trigger_get_const_action(trigger);
652 action_type = lttng_action_get_type(action);
653 if (action_type == LTTNG_ACTION_TYPE_GROUP) {
654 unsigned int count, i;
655 enum lttng_action_status action_status;
656
657 MSG(" actions:");
658
659 action_status = lttng_action_group_get_count(action, &count);
660 assert(action_status == LTTNG_ACTION_STATUS_OK);
661
662 for (i = 0; i < count; i++) {
663 const struct lttng_action *subaction =
664 lttng_action_group_get_at_index(
665 action, i);
666
667 _MSG(" ");
668 print_one_action(subaction);
669 }
670 } else {
671 _MSG(" action:");
672 print_one_action(action);
673 }
674
675 end:
676 return;
677 }
678
679 static
680 int compare_triggers_by_name(const void *a, const void *b)
681 {
682 const struct lttng_trigger *trigger_a = *((const struct lttng_trigger **) a);
683 const struct lttng_trigger *trigger_b = *((const struct lttng_trigger **) b);
684 const char *name_a, *name_b;
685 enum lttng_trigger_status trigger_status;
686
687 trigger_status = lttng_trigger_get_name(trigger_a, &name_a);
688 assert(trigger_status == LTTNG_TRIGGER_STATUS_OK);
689
690 trigger_status = lttng_trigger_get_name(trigger_b, &name_b);
691 assert(trigger_status == LTTNG_TRIGGER_STATUS_OK);
692
693 return strcmp(name_a, name_b);
694 }
695
696 int cmd_list_triggers(int argc, const char **argv)
697 {
698 int ret;
699 struct argpar_parse_ret argpar_parse_ret = {};
700 struct lttng_triggers *triggers = NULL;
701 int i;
702 struct lttng_dynamic_pointer_array sorted_triggers;
703 enum lttng_trigger_status trigger_status;
704 unsigned int num_triggers;
705
706 lttng_dynamic_pointer_array_init(&sorted_triggers, NULL);
707
708 argpar_parse_ret = argpar_parse(
709 argc - 1, argv + 1, list_trigger_options, true);
710 if (!argpar_parse_ret.items) {
711 ERR("%s", argpar_parse_ret.error);
712 goto error;
713 }
714
715 for (i = 0; i < argpar_parse_ret.items->n_items; i++) {
716 const struct argpar_item *item =
717 argpar_parse_ret.items->items[i];
718
719 if (item->type == ARGPAR_ITEM_TYPE_OPT) {
720 const struct argpar_item_opt *item_opt =
721 (const struct argpar_item_opt *) item;
722
723 switch (item_opt->descr->id) {
724 case OPT_HELP:
725 SHOW_HELP();
726 ret = 0;
727 goto end;
728
729 case OPT_LIST_OPTIONS:
730 list_cmd_options_argpar(stdout,
731 list_trigger_options);
732 ret = 0;
733 goto end;
734
735 default:
736 abort();
737 }
738
739 } else {
740 const struct argpar_item_non_opt *item_non_opt =
741 (const struct argpar_item_non_opt *) item;
742
743 ERR("Unexpected argument: %s", item_non_opt->arg);
744 }
745 }
746
747 ret = lttng_list_triggers(&triggers);
748 if (ret != LTTNG_OK) {
749 ERR("Error listing triggers: %s.", lttng_strerror(-ret));
750 goto error;
751 }
752
753 trigger_status = lttng_triggers_get_count(triggers, &num_triggers);
754 if (trigger_status != LTTNG_TRIGGER_STATUS_OK) {
755 ERR("Failed to get trigger count.");
756 goto error;
757 }
758
759 for (i = 0; i < num_triggers; i++) {
760 const int add_ret = lttng_dynamic_pointer_array_add_pointer(
761 &sorted_triggers,
762 (void *) lttng_triggers_get_at_index(triggers, i));
763
764 if (add_ret) {
765 ERR("Failed to allocate array of struct lttng_trigger *.");
766 goto error;
767 }
768 }
769
770 qsort(sorted_triggers.array.buffer.data, num_triggers,
771 sizeof(struct lttng_trigger *),
772 compare_triggers_by_name);
773
774 for (i = 0; i < num_triggers; i++) {
775 const struct lttng_trigger *trigger_to_print =
776 (const struct lttng_trigger *)
777 lttng_dynamic_pointer_array_get_pointer(
778 &sorted_triggers, i);
779
780 print_one_trigger(trigger_to_print);
781 }
782
783 ret = 0;
784 goto end;
785
786 error:
787 ret = 1;
788
789 end:
790 argpar_parse_ret_fini(&argpar_parse_ret);
791 lttng_triggers_destroy(triggers);
792 lttng_dynamic_pointer_array_reset(&sorted_triggers);
793
794 return ret;
795 }
This page took 0.046073 seconds and 5 git commands to generate.