FILE
actions.c
File preview with syntax highlighting.
linux-6.19.14/tools/tracing/rtla/src/actions.c
1// SPDX-License-Identifier: GPL-2.0 2#include <stdlib.h> 3#include <string.h> 4#include <signal.h> 5#include <unistd.h> 6 7#include "actions.h" 8#include "trace.h" 9#include "utils.h" 10 11/* 12 * actions_init - initialize struct actions 13 */ 14void 15actions_init(struct actions *self) 16{ 17 self->size = action_default_size; 18 self->list = calloc(self->size, sizeof(struct action)); 19 self->len = 0; 20 self->continue_flag = false; 21 22 memset(&self->present, 0, sizeof(self->present)); 23 24 /* This has to be set by the user */ 25 self->trace_output_inst = NULL; 26} 27 28/* 29 * actions_destroy - destroy struct actions 30 */ 31void 32actions_destroy(struct actions *self) 33{ 34 /* Free any action-specific data */ 35 for (struct action *action = self->list; action < self->list + self->len; action++) { 36 if (action->type == ACTION_SHELL) 37 free(action->command); 38 if (action->type == ACTION_TRACE_OUTPUT) 39 free(action->trace_output); 40 } 41 42 /* Free action list */ 43 free(self->list); 44} 45 46/* 47 * actions_new - Get pointer to new action 48 */ 49static struct action * 50actions_new(struct actions *self) 51{ 52 if (self->len >= self->size) { 53 self->size *= 2; 54 self->list = realloc(self->list, self->size * sizeof(struct action)); 55 } 56 57 return &self->list[self->len++]; 58} 59 60/* 61 * actions_add_trace_output - add an action to output trace 62 */ 63int 64actions_add_trace_output(struct actions *self, const char *trace_output) 65{ 66 struct action *action = actions_new(self); 67 68 self->present[ACTION_TRACE_OUTPUT] = true; 69 action->type = ACTION_TRACE_OUTPUT; 70 action->trace_output = calloc(strlen(trace_output) + 1, sizeof(char)); 71 if (!action->trace_output) 72 return -1; 73 strcpy(action->trace_output, trace_output); 74 75 return 0; 76} 77 78/* 79 * actions_add_trace_output - add an action to send signal to a process 80 */ 81int 82actions_add_signal(struct actions *self, int signal, int pid) 83{ 84 struct action *action = actions_new(self); 85 86 self->present[ACTION_SIGNAL] = true; 87 action->type = ACTION_SIGNAL; 88 action->signal = signal; 89 action->pid = pid; 90 91 return 0; 92} 93 94/* 95 * actions_add_shell - add an action to execute a shell command 96 */ 97int 98actions_add_shell(struct actions *self, const char *command) 99{ 100 struct action *action = actions_new(self); 101 102 self->present[ACTION_SHELL] = true; 103 action->type = ACTION_SHELL; 104 action->command = calloc(strlen(command) + 1, sizeof(char)); 105 if (!action->command) 106 return -1; 107 strcpy(action->command, command); 108 109 return 0; 110} 111 112/* 113 * actions_add_continue - add an action to resume measurement 114 */ 115int 116actions_add_continue(struct actions *self) 117{ 118 struct action *action = actions_new(self); 119 120 self->present[ACTION_CONTINUE] = true; 121 action->type = ACTION_CONTINUE; 122 123 return 0; 124} 125 126/* 127 * actions_parse - add an action based on text specification 128 */ 129int 130actions_parse(struct actions *self, const char *trigger, const char *tracefn) 131{ 132 enum action_type type = ACTION_NONE; 133 const char *token; 134 char trigger_c[strlen(trigger) + 1]; 135 136 /* For ACTION_SIGNAL */ 137 int signal = 0, pid = 0; 138 139 /* For ACTION_TRACE_OUTPUT */ 140 const char *trace_output; 141 142 strcpy(trigger_c, trigger); 143 token = strtok(trigger_c, ","); 144 if (!token) 145 return -1; 146 147 if (strcmp(token, "trace") == 0) 148 type = ACTION_TRACE_OUTPUT; 149 else if (strcmp(token, "signal") == 0) 150 type = ACTION_SIGNAL; 151 else if (strcmp(token, "shell") == 0) 152 type = ACTION_SHELL; 153 else if (strcmp(token, "continue") == 0) 154 type = ACTION_CONTINUE; 155 else 156 /* Invalid trigger type */ 157 return -1; 158 159 token = strtok(NULL, ","); 160 161 switch (type) { 162 case ACTION_TRACE_OUTPUT: 163 /* Takes no argument */ 164 if (token == NULL) 165 trace_output = tracefn; 166 else { 167 if (strlen(token) > 5 && strncmp(token, "file=", 5) == 0) { 168 trace_output = token + 5; 169 } else { 170 /* Invalid argument */ 171 return -1; 172 } 173 174 token = strtok(NULL, ","); 175 if (token != NULL) 176 /* Only one argument allowed */ 177 return -1; 178 } 179 return actions_add_trace_output(self, trace_output); 180 case ACTION_SIGNAL: 181 /* Takes two arguments, num (signal) and pid */ 182 while (token != NULL) { 183 if (strlen(token) > 4 && strncmp(token, "num=", 4) == 0) { 184 signal = atoi(token + 4); 185 } else if (strlen(token) > 4 && strncmp(token, "pid=", 4) == 0) { 186 if (strncmp(token + 4, "parent", 7) == 0) 187 pid = -1; 188 else 189 pid = atoi(token + 4); 190 } else { 191 /* Invalid argument */ 192 return -1; 193 } 194 195 token = strtok(NULL, ","); 196 } 197 198 if (!signal || !pid) 199 /* Missing argument */ 200 return -1; 201 202 return actions_add_signal(self, signal, pid); 203 case ACTION_SHELL: 204 if (token == NULL) 205 return -1; 206 if (strlen(token) > 8 && strncmp(token, "command=", 8) == 0) 207 return actions_add_shell(self, token + 8); 208 return -1; 209 case ACTION_CONTINUE: 210 /* Takes no argument */ 211 if (token != NULL) 212 return -1; 213 return actions_add_continue(self); 214 default: 215 return -1; 216 } 217} 218 219/* 220 * actions_perform - perform all actions 221 */ 222int 223actions_perform(struct actions *self) 224{ 225 int pid, retval; 226 const struct action *action; 227 228 for (action = self->list; action < self->list + self->len; action++) { 229 switch (action->type) { 230 case ACTION_TRACE_OUTPUT: 231 retval = save_trace_to_file(self->trace_output_inst, action->trace_output); 232 if (retval) { 233 err_msg("Error saving trace\n"); 234 return retval; 235 } 236 break; 237 case ACTION_SIGNAL: 238 if (action->pid == -1) 239 pid = getppid(); 240 else 241 pid = action->pid; 242 retval = kill(pid, action->signal); 243 if (retval) { 244 err_msg("Error sending signal\n"); 245 return retval; 246 } 247 break; 248 case ACTION_SHELL: 249 retval = system(action->command); 250 if (retval) 251 return retval; 252 break; 253 case ACTION_CONTINUE: 254 self->continue_flag = true; 255 return 0; 256 default: 257 break; 258 } 259 } 260 261 return 0; 262}
~/
Read-only file preview.