From 3567c7b73a193cf64793efe59416321e290de7ba Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Sat, 2 Jan 2016 21:50:29 +0100 Subject: marshal settings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- src/settings.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/settings.h | 21 ++++++++++++++++ 2 files changed, 97 insertions(+) diff --git a/src/settings.c b/src/settings.c index 1eba1cc..0333a41 100644 --- a/src/settings.c +++ b/src/settings.c @@ -244,3 +244,79 @@ fail: exit(1); } + +/** + * Marshal settings into a buffer. + * + * @param buffer The buffer, `NULL` if you want to know the required size. + * @param settings The settings to marshal. + * @return The size of the output. + */ +size_t +marshal_settings(char *buffer, const struct settings *settings) +{ +#define MARSHAL(N, DATUMP) (n += aux = (N), (buf ? (memcpy(buf, DATUMP, aux), buf += aux, 0) : 0)) + + size_t n = 0, i = 0; + size_t aux; + char *buf = buffer; + + if (buffer) i = marshal_settings(NULL, settings); + MARSHAL(sizeof(i), &i); + + MARSHAL(sizeof(*settings), settings); + if (settings->hookpath) + MARSHAL(strlen(settings->hookpath) + 1, settings->hookpath); + if (settings->monitors_arg) + MARSHAL(settings->monitors_n, settings->monitors_arg); + for (i = 0; i < settings->monitors_n; i++) + MARSHAL(strlen(settings->monitors_id[i]) + 1, settings->monitors_id[i]); + + return n; +} + + +/** + * Unmarshal settings from a buffer. + * + * @param buffer The buffer. + * @param settings Output parameter for the settings, will be allocated. + * @return The number of unmarshalled bytes, 0 on error. + */ +size_t +unmarshal_settings(char *buffer, struct settings **settings) +{ +#define UNMARSHAL(N, DATUMP) (aux = (N), memcpy((DATUMP), buf, aux), buf += aux) + + size_t n, aux, i; + struct settings *s = NULL; + struct settings s_; + char *buf = buffer; + int saved_errno; + + UNMARSHAL(sizeof(n), &n); + if (!(s = *settings = malloc(n - sizeof(n)))) return 0; + s->monitors_id = NULL, s->monitors_arg = NULL; + + UNMARSHAL(sizeof(s_), &s_); + if (s_.monitors_n) { + if (!(*s = s_, s->monitors_id = malloc(s_.monitors_n * sizeof(char*)))) goto fail; + if (!(*s = s_, s->monitors_arg = malloc(s_.monitors_n * sizeof(char)))) goto fail; + } + + s->hookpath = buf; + buf = strchr(buf, '\0') + 1; + + UNMARSHAL(s_.monitors_n, s->monitors_arg); + for (i = 0; i < s_.monitors_n; i++) + UNMARSHAL(strlen(buf + 1), s->monitors_id[i]); + + return n; + +fail: + saved_errno = errno; + free(s->monitors_id), free(s->monitors_arg), free(s), *settings = NULL; + errno = saved_errno; + return 0; +} + diff --git a/src/settings.h b/src/settings.h index b1909bb..980c6f6 100644 --- a/src/settings.h +++ b/src/settings.h @@ -91,6 +91,7 @@ struct settings { /** * Pathname to the hook script. + * Do not free this. */ char *hookpath; @@ -122,6 +123,7 @@ struct settings { /** * Values for -d, -e, and -m, in order. + * Do not free its elements. */ char **monitors_id; @@ -144,3 +146,22 @@ struct settings { */ void parse_command_line(int argc, char *argv[], struct settings *settings); + +/** + * Marshal settings into a buffer. + * + * @param param The buffer, `NULL` if you want to know the required size. + * @param settings The settings to marshal. + * @return The size of the output. + */ +size_t marshal_settings(char *buffer, const struct settings *settings); + +/** + * Unmarshal settings from a buffer. + * + * @param buffer The buffer. + * @param settings Output parameter for the settings, will be allocated. + * @return The number of unmarshalled bytes, 0 on error. + */ +size_t unmarshal_settings(char *buffer, struct settings **settings); + -- cgit v1.2.3-70-g09d2