notify: break out command template expansion to spawn_expand_template()

This commit is contained in:
Daniel Eklöf 2021-01-31 14:40:27 +01:00
parent 4233c806c3
commit 06aba59430
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
3 changed files with 97 additions and 60 deletions

View file

@ -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);
}

80
spawn.c
View file

@ -1,5 +1,6 @@
#include "spawn.h"
#include <string.h>
#include <unistd.h>
#include <errno.h>
@ -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;
}

View file

@ -1,7 +1,13 @@
#pragma once
#include <stdbool.h>
#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);