From 06aba59430bdb1ad5058ef513eeb91416057d1db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 31 Jan 2021 14:40:27 +0100 Subject: [PATCH] notify: break out command template expansion to spawn_expand_template() --- notify.c | 71 ++++++++----------------------------------------- spawn.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ spawn.h | 6 +++++ 3 files changed, 97 insertions(+), 60 deletions(-) diff --git a/notify.c b/notify.c index b8480d68..3f36e904 100644 --- a/notify.c +++ b/notify.c @@ -30,69 +30,20 @@ notify_notify(const struct terminal *term, const char *title, const char *body) if (term->conf->notify.argv == NULL) return; - size_t argv_size = 0; - for (; term->conf->notify.argv[argv_size] != NULL; argv_size++) - ; + char **argv = NULL; + size_t argc = 0; -#define append(s, n) \ - do { \ - expanded = xrealloc(expanded, len + (n) + 1); \ - memcpy(&expanded[len], s, n); \ - len += n; \ - expanded[len] = '\0'; \ - } while (0) - - char **argv = malloc((argv_size + 1) * sizeof(argv[0])); - - /* Expand ${title} and ${body} */ - for (size_t i = 0; i < argv_size; i++) { - size_t len = 0; - char *expanded = NULL; - - char *start = NULL; - char *last_end = term->conf->notify.argv[i]; - - while ((start = strstr(last_end, "${")) != NULL) { - /* Append everything from the last template's end to this - * one's beginning */ - append(last_end, start - last_end); - - /* Find end of template */ - start += 2; - char *end = strstr(start, "}"); - - if (end == NULL) { - /* Ensure final append() copies the unclosed '${' */ - last_end = start - 2; - LOG_WARN("notify: unclosed template: %s", last_end); - break; - } - - /* Expand template */ - if (strncmp(start, "title", end - start) == 0) - append(title, strlen(title)); - else if (strncmp(start, "body", end - start) == 0) - append(body, strlen(body)); - else { - /* Unrecognized template - append it as-is */ - start -= 2; - append(start, end + 1 - start); - LOG_WARN("notify: unrecognized template: %.*s", - (int)(end + 1 - start), start); - } - - last_end = end + 1;; - } - - append(last_end, term->conf->notify.argv[i] + strlen(term->conf->notify.argv[i]) - last_end); - argv[i] = expanded; + if (!spawn_expand_template( + &term->conf->notify, 2, + (const char *[]){"title", "body"}, + (const char *[]){title, body}, + &argc, &argv)) + { + return; } - argv[argv_size] = NULL; - -#undef append LOG_DBG("notify command:"); - for (size_t i = 0; i < argv_size; i++) + for (size_t i = 0; i < argc; i++) LOG_DBG(" argv[%zu] = \"%s\"", i, argv[i]); /* Redirect stdin to /dev/null, but ignore failure to open */ @@ -102,7 +53,7 @@ notify_notify(const struct terminal *term, const char *title, const char *body) if (devnull >= 0) close(devnull); - for (size_t i = 0; i < argv_size; i++) + for (size_t i = 0; i < argc; i++) free(argv[i]); free(argv); } diff --git a/spawn.c b/spawn.c index fbcf0952..e9fb2f96 100644 --- a/spawn.c +++ b/spawn.c @@ -1,5 +1,6 @@ #include "spawn.h" +#include #include #include @@ -11,6 +12,7 @@ #define LOG_ENABLE_DBG 0 #include "log.h" #include "debug.h" +#include "xmalloc.h" bool spawn(struct reaper *reaper, const char *cwd, char *const argv[], @@ -74,3 +76,81 @@ err: close(pipe_fds[1]); return false; } + +bool +spawn_expand_template(const struct config_spawn_template *template, + size_t key_count, + const char *key_names[static key_count], + const char *key_values[static key_count], + size_t *argc, char ***argv) +{ + *argc = 0; + *argv = NULL; + + for (; template->argv[*argc] != NULL; (*argc)++) + ; + +#define append(s, n) \ + do { \ + expanded = xrealloc(expanded, len + (n) + 1); \ + memcpy(&expanded[len], s, n); \ + len += n; \ + expanded[len] = '\0'; \ + } while (0) + + *argv = malloc((*argc + 1) * sizeof((*argv)[0])); + + /* Expand the provided keys */ + for (size_t i = 0; i < *argc; i++) { + size_t len = 0; + char *expanded = NULL; + + char *start = NULL; + char *last_end = template->argv[i]; + + while ((start = strstr(last_end, "${")) != NULL) { + /* Append everything from the last template's end to this + * one's beginning */ + append(last_end, start - last_end); + + /* Find end of template */ + start += 2; + char *end = strstr(start, "}"); + + if (end == NULL) { + /* Ensure final append() copies the unclosed '${' */ + last_end = start - 2; + LOG_WARN("notify: unclosed template: %s", last_end); + break; + } + + /* Expand template */ + bool valid_key = false; + for (size_t j = 0; j < key_count; j++) { + if (strncmp(start, key_names[j], end - start) != 0) + continue; + + append(key_values[j], strlen(key_values[j])); + valid_key = true; + break; + } + + if (!valid_key) { + /* Unrecognized template - append it as-is */ + start -= 2; + append(start, end + 1 - start); + LOG_WARN("notify: unrecognized template: %.*s", + (int)(end + 1 - start), start); + } + + last_end = end + 1; + } + + append(last_end, template->argv[i] + strlen(template->argv[i]) - last_end); + (*argv)[i] = expanded; + } + (*argv)[*argc] = NULL; + +#undef append + return true; +} diff --git a/spawn.h b/spawn.h index 2ab645a8..c6f9582e 100644 --- a/spawn.h +++ b/spawn.h @@ -1,7 +1,13 @@ #pragma once #include +#include "config.h" #include "reaper.h" bool spawn(struct reaper *reaper, const char *cwd, char *const argv[], int stdin_fd, int stdout_fd, int stderr_fd); + +bool spawn_expand_template( + const struct config_spawn_template *template, + size_t key_count, const char *key_names[static key_count], + const char *key_values[static key_count], size_t *argc, char ***argv);