1 // SPDX-License-Identifier: LGPL-2.1
2 /*
3 * Copyright (C) 2015 Red Hat Inc, Steven Rostedt <[email protected]>
4 *
5 */
6
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <ctype.h>
10
11 #include "trace-cmd-private.h"
12 #include "trace-cmd-local.h"
13 #include "event-utils.h"
14
tracecmd_create_event_hook(const char * arg)15 struct hook_list *tracecmd_create_event_hook(const char *arg)
16 {
17 struct hook_list *hook;
18 char *system = NULL;
19 char *event;
20 char *match;
21 char *flags = NULL;
22 char *pid = NULL;
23 char *str;
24 char *tok;
25 int index;
26 int ch;
27 int i;
28
29 hook = malloc(sizeof(*hook));
30 if (!hook)
31 return NULL;
32 memset(hook, 0, sizeof(*hook));
33
34 str = strdup(arg);
35 if (!str) {
36 free(hook);
37 return NULL;
38 }
39
40 hook->str = str;
41 hook->hook = arg;
42
43 /*
44 * Hooks are in the form of:
45 * [<start_system>:]<start_event>,<start_match>[,<start_pid>]/
46 * [<end_system>:]<end_event>,<end_match>[,<flags>]
47 *
48 * Where start_system, start_pid, end_system, and flags are all
49 * optional.
50 *
51 * Flags are (case insensitive):
52 * P - pinned to cpu (wont migrate)
53 * G - global, not hooked to task - currently ignored.
54 * S - save stacks for this event.
55 */
56 tok = strtok(str, ":,");
57 if (!tok)
58 goto invalid_tok;
59
60 /* See what the token was from the original arg */
61 index = strlen(tok);
62 if (arg[index] == ':') {
63 /* this is a system, the next token must be ',' */
64 system = tok;
65 tok = strtok(NULL, ",");
66 if (!tok)
67 goto invalid_tok;
68 }
69 event = tok;
70
71 tok = strtok(NULL, ",/");
72 if (!tok)
73 goto invalid_tok;
74 match = tok;
75 index = strlen(tok) + tok - str;
76 if (arg[index] == ',') {
77 tok = strtok(NULL, "/");
78 if (!tok)
79 goto invalid_tok;
80 pid = tok;
81 }
82
83 hook->start_system = system;
84 hook->start_event = event;
85 hook->start_match = match;
86 hook->pid = pid;
87
88 /* Now process the end event */
89 system = NULL;
90
91 tok = strtok(NULL, ":,");
92 if (!tok)
93 goto invalid_tok;
94
95 /* See what the token was from the original arg */
96 index = tok - str + strlen(tok);
97 if (arg[index] == ':') {
98 /* this is a system, the next token must be ',' */
99 system = tok;
100 tok = strtok(NULL, ",");
101 if (!tok)
102 goto invalid_tok;
103 }
104 event = tok;
105
106 tok = strtok(NULL, ",");
107 if (!tok)
108 goto invalid_tok;
109 match = tok;
110 index = strlen(tok) + tok - str;
111 if (arg[index] == ',') {
112 tok = strtok(NULL, "");
113 if (!tok)
114 goto invalid_tok;
115 flags = tok;
116 }
117
118 hook->end_system = system;
119 hook->end_event = event;
120 hook->end_match = match;
121 hook->migrate = 1;
122 if (flags) {
123 for (i = 0; flags[i]; i++) {
124 ch = tolower(flags[i]);
125 switch (ch) {
126 case 'p':
127 hook->migrate = 0;
128 break;
129 case 'g':
130 hook->global = 1;
131 break;
132 case 's':
133 hook->stack = 1;
134 break;
135 default:
136 tracecmd_warning("unknown flag %c", flags[i]);
137 }
138 }
139 }
140
141 printf("start %s:%s:%s (%s) end %s:%s:%s (%s)\n",
142 hook->start_system,
143 hook->start_event,
144 hook->start_match,
145 hook->pid,
146 hook->end_system,
147 hook->end_event,
148 hook->end_match,
149 flags);
150 return hook;
151
152 invalid_tok:
153 tracecmd_warning("Invalid hook format '%s'", arg);
154 return NULL;
155 }
156
tracecmd_free_hooks(struct hook_list * hooks)157 void tracecmd_free_hooks(struct hook_list *hooks)
158 {
159 struct hook_list *hook;
160
161 while (hooks) {
162 hook = hooks;
163 hooks = hooks->next;
164
165 free(hook->str);
166 free(hook);
167 }
168 }
169