diff --git a/meson.build b/meson.build index 36c5807e..e6a5c3d4 100644 --- a/meson.build +++ b/meson.build @@ -155,6 +155,7 @@ executable( 'ime.c', 'ime.h', 'input.c', 'input.h', 'main.c', + 'notify.c', 'notify.h', 'quirks.c', 'quirks.h', 'reaper.c', 'reaper.h', 'render.c', 'render.h', diff --git a/notify.c b/notify.c new file mode 100644 index 00000000..293344ec --- /dev/null +++ b/notify.c @@ -0,0 +1,103 @@ +#include "notify.h" + +#include +#include +#include + +#include +#include + +#define LOG_MODULE "notify" +#define LOG_ENABLE_DBG 0 +#include "log.h" +#include "config.h" +#include "spawn.h" +#include "xmalloc.h" + +void +notify_notify(const struct terminal *term, const char *title, const char *body) +{ + LOG_DBG("notify: title=\"%s\", msg=\"%s\"", title, msg); + + if (title == NULL || body == NULL) + return; + + if (term->conf->notify.argv == NULL) + return; + + size_t argv_size = 0; + for (; term->conf->notify.argv[argv_size] != NULL; argv_size++) + ; + +#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; + } + argv[argv_size] = NULL; + +#undef append + + LOG_DBG("notify command:"); + for (size_t i = 0; i < argv_size; i++) + LOG_DBG(" argv[%zu] = \"%s\"", i, argv[i]); + + /* Redirect stdin to /dev/null, but ignore failure to open */ + int devnull = open("/dev/null", O_RDONLY); + spawn(term->reaper, NULL, argv, devnull, -1, -1); + + if (devnull >= 0) + close(devnull); + + for (size_t i = 0; i < argv_size; i++) + free(argv[i]); + free(argv); +} diff --git a/notify.h b/notify.h new file mode 100644 index 00000000..ce60562f --- /dev/null +++ b/notify.h @@ -0,0 +1,6 @@ +#pragma once + +#include "terminal.h" + +void notify_notify( + const struct terminal *term, const char *title, const char *body); diff --git a/osc.c b/osc.c index 27b15686..d24a4603 100644 --- a/osc.c +++ b/osc.c @@ -3,10 +3,6 @@ #include #include #include -#include - -#include -#include #define LOG_MODULE "osc" #define LOG_ENABLE_DBG 0 @@ -14,9 +10,9 @@ #include "base64.h" #include "config.h" #include "grid.h" +#include "notify.h" #include "render.h" #include "selection.h" -#include "spawn.h" #include "terminal.h" #include "uri.h" #include "vt.h" @@ -408,92 +404,7 @@ osc_notify(struct terminal *term, char *string) const char *title = strtok_r(string, ";", &ctx); const char *msg = strtok_r(NULL, "\x00", &ctx); - LOG_DBG("notify: title=\"%s\", msg=\"%s\"", title, msg); - - /* TODO: move everything below to a separate function, to be able - * to support multiple escape sequences */ - - if (title == NULL || msg == NULL) - return; - - if (term->conf->notify.argv == NULL) - return; - - size_t argv_size = 0; - for (; term->conf->notify.argv[argv_size] != NULL; argv_size++) - ; - -#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(msg, strlen(msg)); - 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; - } - argv[argv_size] = NULL; - -#undef append - - LOG_DBG("notify command:"); - for (size_t i = 0; i < argv_size; i++) - LOG_DBG(" argv[%zu] = \"%s\"", i, argv[i]); - - /* Redirect stdin to /dev/null, but ignore failure to open */ - int devnull = open("/dev/null", O_RDONLY); - spawn(term->reaper, NULL, argv, devnull, -1, -1); - - if (devnull >= 0) - close(devnull); - - for (size_t i = 0; i < argv_size; i++) - free(argv[i]); - free(argv); + notify_notify(term, title, msg); } static void diff --git a/pgo/pgo.c b/pgo/pgo.c index 0dc08f61..7874cc8d 100644 --- a/pgo/pgo.c +++ b/pgo/pgo.c @@ -129,6 +129,11 @@ void cmd_scrollback_down(struct terminal *term, int rows) {} void ime_enable(struct seat *seat) {} void ime_disable(struct seat *seat) {} +void +notify_notify(const struct terminal *term, const char *title, const char *body) +{ +} + int main(int argc, const char *const *argv) {