|
8 | 8 | #include <glib-unix.h> |
9 | 9 | #include <stdio.h> |
10 | 10 | #include <stdlib.h> |
| 11 | +#include <string.h> |
| 12 | +#include <errno.h> |
| 13 | +#include <limits.h> |
11 | 14 | #ifdef __linux__ |
12 | 15 | #include <linux/limits.h> |
13 | 16 | #endif |
@@ -57,6 +60,9 @@ char *opt_sdnotify_socket = NULL; |
57 | 60 | gboolean opt_full_attach_path = FALSE; |
58 | 61 | char *opt_seccomp_notify_socket = NULL; |
59 | 62 | char *opt_seccomp_notify_plugins = NULL; |
| 63 | +gchar **opt_timer_command = NULL; |
| 64 | +gchar **opt_timer_command_argument = NULL; |
| 65 | +GPtrArray *timer_command_entries = NULL; |
60 | 66 | GOptionEntry opt_entries[] = { |
61 | 67 | {"api-version", 0, 0, G_OPTION_ARG_NONE, &opt_api_version, "Conmon API version to use", NULL}, |
62 | 68 | {"bundle", 'b', 0, G_OPTION_ARG_STRING, &opt_bundle_path, "Location of the OCI Bundle path", NULL}, |
@@ -117,6 +123,10 @@ GOptionEntry opt_entries[] = { |
117 | 123 | "Path to the socket where the seccomp notification fd is received", NULL}, |
118 | 124 | {"seccomp-notify-plugins", 0, 0, G_OPTION_ARG_STRING, &opt_seccomp_notify_plugins, |
119 | 125 | "Plugins to use for managing the seccomp notifications", NULL}, |
| 126 | + {"timer-command", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_timer_command, |
| 127 | + "Execute COMMAND every SECONDS. Format: ID:SECONDS:COMMAND. Can be specified multiple times", NULL}, |
| 128 | + {"timer-command-argument", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_timer_command_argument, |
| 129 | + "Add an argument to timer-command with ID. Format: ID:ARGUMENT. Can be specified multiple times", NULL}, |
120 | 130 | {NULL, 0, 0, 0, NULL, NULL, NULL}}; |
121 | 131 |
|
122 | 132 |
|
@@ -205,4 +215,113 @@ void process_cli() |
205 | 215 | if (opt_no_container_partial_message && !logging_is_journald_enabled()) { |
206 | 216 | nwarnf("--no-container-partial-message has no effect without journald log driver"); |
207 | 217 | } |
| 218 | + |
| 219 | + /* Parse timer-command entries with ID-based arguments */ |
| 220 | + if (opt_timer_command || opt_timer_command_argument) { |
| 221 | + timer_command_entries = g_ptr_array_new_with_free_func(g_free); |
| 222 | + |
| 223 | + /* Parse timer-command commands first */ |
| 224 | + if (opt_timer_command) { |
| 225 | + for (int i = 0; opt_timer_command[i] != NULL; i++) { |
| 226 | + char *entry = g_strdup(opt_timer_command[i]); |
| 227 | + char *first_colon = strchr(entry, ':'); |
| 228 | + if (!first_colon) { |
| 229 | + nexitf("Invalid timer-command format '%s'. Expected ID:SECONDS:COMMAND", opt_timer_command[i]); |
| 230 | + } |
| 231 | + |
| 232 | + *first_colon = '\0'; |
| 233 | + char *second_colon = strchr(first_colon + 1, ':'); |
| 234 | + if (!second_colon) { |
| 235 | + nexitf("Invalid timer-command format '%s'. Expected ID:SECONDS:COMMAND", opt_timer_command[i]); |
| 236 | + } |
| 237 | + |
| 238 | + *second_colon = '\0'; |
| 239 | + |
| 240 | + char *id_str = entry; |
| 241 | + char *interval_str = first_colon + 1; |
| 242 | + char *command = second_colon + 1; |
| 243 | + |
| 244 | + /* Parse ID */ |
| 245 | + char *endptr; |
| 246 | + errno = 0; |
| 247 | + long id_long = strtol(id_str, &endptr, 10); |
| 248 | + if (errno != 0 || endptr == id_str || *endptr != '\0' || id_long < 0 || id_long > INT_MAX) { |
| 249 | + nexitf("Invalid timer-command ID '%s' in '%s'", id_str, opt_timer_command[i]); |
| 250 | + } |
| 251 | + int id = (int)id_long; |
| 252 | + |
| 253 | + /* Require incremental IDs starting from 0 */ |
| 254 | + int expected_id = i; |
| 255 | + if (id != expected_id) { |
| 256 | + nexitf("Timer-command IDs must be incremental starting from 0. Expected %d, got %d", expected_id, |
| 257 | + id); |
| 258 | + } |
| 259 | + |
| 260 | + /* Parse interval */ |
| 261 | + errno = 0; |
| 262 | + long interval_long = strtol(interval_str, &endptr, 10); |
| 263 | + if (errno != 0 || endptr == interval_str || *endptr != '\0' || interval_long <= 0 |
| 264 | + || interval_long > INT_MAX) { |
| 265 | + nexitf("Invalid timer-command interval '%s' in '%s'", interval_str, opt_timer_command[i]); |
| 266 | + } |
| 267 | + int interval = (int)interval_long; |
| 268 | + |
| 269 | + if (*command == '\0') { |
| 270 | + nexitf("Empty timer-command command in '%s'", opt_timer_command[i]); |
| 271 | + } |
| 272 | + |
| 273 | + timer_command_entry_t *cc_entry = g_malloc(sizeof(timer_command_entry_t)); |
| 274 | + cc_entry->id = id; |
| 275 | + cc_entry->interval = interval; |
| 276 | + cc_entry->args = g_malloc(sizeof(gchar *) * 2); |
| 277 | + cc_entry->args[0] = g_strdup(command); |
| 278 | + cc_entry->args[1] = NULL; |
| 279 | + |
| 280 | + g_ptr_array_add(timer_command_entries, cc_entry); |
| 281 | + |
| 282 | + ndebugf("Added timer-command: ID=%d, %d seconds, command: %s", id, interval, command); |
| 283 | + g_free(entry); |
| 284 | + } |
| 285 | + } |
| 286 | + |
| 287 | + if (opt_timer_command_argument) { |
| 288 | + for (int i = 0; opt_timer_command_argument[i] != NULL; i++) { |
| 289 | + char *entry = g_strdup(opt_timer_command_argument[i]); |
| 290 | + char *colon = strchr(entry, ':'); |
| 291 | + if (!colon) { |
| 292 | + nexitf("Invalid timer-command-argument format '%s'. Expected ID:ARGUMENT", |
| 293 | + opt_timer_command_argument[i]); |
| 294 | + } |
| 295 | + |
| 296 | + *colon = '\0'; |
| 297 | + char *id_str = entry; |
| 298 | + char *argument = colon + 1; |
| 299 | + |
| 300 | + /* Parse ID */ |
| 301 | + char *endptr; |
| 302 | + errno = 0; |
| 303 | + long id_long = strtol(id_str, &endptr, 10); |
| 304 | + if (errno != 0 || endptr == id_str || *endptr != '\0' || id_long < 0 || id_long > INT_MAX) { |
| 305 | + nexitf("Invalid timer-command ID '%s' in argument '%s'", id_str, opt_timer_command_argument[i]); |
| 306 | + } |
| 307 | + int id = (int)id_long; |
| 308 | + |
| 309 | + if (id < 0 || id >= (int)timer_command_entries->len) { |
| 310 | + nexitf("Timer-command ID %d not found for argument '%s'", id, argument); |
| 311 | + } |
| 312 | + timer_command_entry_t *target_entry = g_ptr_array_index(timer_command_entries, id); |
| 313 | + |
| 314 | + int arg_count = 0; |
| 315 | + while (target_entry->args[arg_count]) |
| 316 | + arg_count++; |
| 317 | + |
| 318 | + target_entry->args = g_realloc(target_entry->args, sizeof(gchar *) * (arg_count + 2)); |
| 319 | + target_entry->args[arg_count] = g_strdup(argument); |
| 320 | + target_entry->args[arg_count + 1] = NULL; |
| 321 | + |
| 322 | + ndebugf("Added argument '%s' to timer-command ID %d", argument, id); |
| 323 | + g_free(entry); |
| 324 | + } |
| 325 | + } |
| 326 | + } |
208 | 327 | } |
0 commit comments