From 56e6004336aeb3a7e92e8418430217c42feb2515 Mon Sep 17 00:00:00 2001 From: David Oberhollenzer Date: Wed, 4 Apr 2018 14:03:23 +0200 Subject: Simplifiy service file syntax Signed-off-by: David Oberhollenzer --- lib/include/util.h | 16 +----- lib/src/rdsvc.c | 158 +++++++++++++++++++++++++++++++++++------------------ lib/src/splitkv.c | 143 +++++++++++++++--------------------------------- 3 files changed, 152 insertions(+), 165 deletions(-) (limited to 'lib') diff --git a/lib/include/util.h b/lib/include/util.h index e99be3b..0ed7002 100644 --- a/lib/include/util.h +++ b/lib/include/util.h @@ -68,20 +68,10 @@ typedef struct { char *rdline(int fd, int argc, const char *const *argv); /* - Split a line of the shape "key = value" into key and value part. - - The key can contain alphanumeric characters and can be padded with - spaces or tabs. - - The value can be either a sequence of alphanumeric characters, period - or underscore OR a string in quotation marks. For strings, the - quotation marks are removed and escape sequences are processed. - - The value may also be padded with spaces or tabs but the line may not - contain anything else after the value, except for spaces, tabs or - the '#' symbol which is interpreted as start of a comment. + Remove double quotes ('"') from a string and substitute escape + sequences in between double quotes. */ -int splitkv(char *line, char **key, char **value); +int unescape(char *src); /* Search through an array of enum_map_t entries to resolve a string to diff --git a/lib/src/rdsvc.c b/lib/src/rdsvc.c index b186cd9..04cf30f 100644 --- a/lib/src/rdsvc.c +++ b/lib/src/rdsvc.c @@ -28,10 +28,21 @@ #include "service.h" #include "util.h" +static int try_unescape(char *arg, const char *filename, size_t lineno) +{ + if (unescape(arg)) { + fprintf(stderr, "%s: %zu: malformed string constant\n", + filename, lineno); + return -1; + } + return 0; +} + static int svc_desc(service_t *svc, char *arg, const char *filename, size_t lineno) { - (void)filename; (void)lineno; + if (try_unescape(arg, filename, lineno)) + return -1; svc->desc = arg; return 0; } @@ -39,7 +50,8 @@ static int svc_desc(service_t *svc, char *arg, static int svc_tty(service_t *svc, char *arg, const char *filename, size_t lineno) { - (void)filename; (void)lineno; + if (try_unescape(arg, filename, lineno)) + return -1; svc->ctty = arg; return 0; } @@ -63,8 +75,12 @@ static int svc_exec(service_t *svc, char *arg, static int svc_before(service_t *svc, char *arg, const char *filename, size_t lineno) { - char **new = realloc(svc->before, - sizeof(char*) * (svc->num_before + 1)); + char **new; + + if (try_unescape(arg, filename, lineno)) + return -1; + + new = realloc(svc->before, sizeof(char*) * (svc->num_before + 1)); if (new == NULL) { fprintf(stderr, "%s: %zu: out of memory\n", filename, lineno); @@ -80,7 +96,12 @@ static int svc_before(service_t *svc, char *arg, static int svc_after(service_t *svc, char *arg, const char *filename, size_t lineno) { - char **new = realloc(svc->after, sizeof(char*) * (svc->num_after + 1)); + char **new; + + if (try_unescape(arg, filename, lineno)) + return -1; + + new = realloc(svc->after, sizeof(char*) * (svc->num_after + 1)); if (new == NULL) { fprintf(stderr, "%s: %zu: out of memory\n", filename, lineno); @@ -96,7 +117,22 @@ static int svc_after(service_t *svc, char *arg, static int svc_type(service_t *svc, char *arg, const char *filename, size_t lineno) { - int type = svc_type_from_string(arg); + char *extra; + int type; + + if (try_unescape(arg, filename, lineno)) + return -1; + + for (extra = arg; *extra != ' ' && *extra != '\0'; ++extra) + ; + + if (*extra == ' ') { + *(extra++) = '\0'; + } else { + extra = NULL; + } + + type = svc_type_from_string(arg); if (type == -1) { fprintf(stderr, "%s: %zu: unknown service type '%s'\n", @@ -104,15 +140,51 @@ static int svc_type(service_t *svc, char *arg, return -1; } + if (extra != NULL) { + switch (type) { + case SVC_RESPAWN: + if (strncmp(extra, "limit ", 6) != 0) + goto fail_limit; + extra += 6; + + svc->rspwn_limit = 0; + + if (!isdigit(*extra)) + goto fail_limit; + + while (isdigit(*extra)) { + svc->rspwn_limit *= 10; + svc->rspwn_limit += *(extra++) - '0'; + } + + if (*extra != '\0') + goto fail_limit; + break; + default: + fprintf(stderr, "%s: %zu: unexpected extra arguments " + "for type '%s'\n", filename, lineno, arg); + return -1; + } + } + svc->type = type; free(arg); return 0; +fail_limit: + fprintf(stderr, "%s: %zu: expected 'limit ' after 'respawn'\n", + filename, lineno); + return -1; } static int svc_target(service_t *svc, char *arg, const char *filename, size_t lineno) { - int target = svc_target_from_string(arg); + int target; + + if (try_unescape(arg, filename, lineno)) + return -1; + + target = svc_target_from_string(arg); if (target == -1) { fprintf(stderr, "%s: %zu: unknown service target '%s'\n", @@ -125,33 +197,6 @@ static int svc_target(service_t *svc, char *arg, return 0; } -static int svc_rspwn_limit(service_t *svc, char *arg, - const char *filename, size_t lineno) -{ - const char *ptr; - - svc->rspwn_limit = 0; - - if (!isdigit(*arg)) - goto fail; - - for (ptr = arg; isdigit(*ptr); ++ptr) - svc->rspwn_limit = svc->rspwn_limit * 10 + (*ptr - '0'); - - if (*ptr != '\0') - goto fail; - - free(arg); - return 0; -fail: - fprintf(stderr, - "%s: %zu: expected numeric argument for respawn limit\n", - filename, lineno); - free(arg); - return -1; -} - - static const struct { const char *key; @@ -165,7 +210,6 @@ static const struct { { "tty", svc_tty }, { "before", svc_before }, { "after", svc_after }, - { "respawn_limit", svc_rspwn_limit }, }; @@ -239,27 +283,26 @@ service_t *rdsvc(int dirfd, const char *filename) goto fail; } - if (splitkv(line, &key, &value)) { - if (key == NULL) { - fprintf(stderr, - "%s: %zu: expected = \n", - filename, lineno); - } else if (value == NULL) { - fprintf(stderr, - "%s: %zu: expected value after %s\n", - filename, lineno, key); - } else { - fprintf(stderr, - "%s: %zu: unexpected arguments " - "after key-value pair\n", - filename, lineno); + if (!strlen(line)) { + free(line); + continue; + } + + key = value = line; + + while (*value != ' ' && *value != '\0') { + if (!isalpha(*value)) { + fprintf(stderr, "%s: %zu: unexpected '%c' in " + "keyword\n", filename, lineno, *value); + goto fail_line; } - goto fail; + ++value; } - if (key == NULL) { - free(line); - continue; + if (*value == ' ') { + *(value++) = '\0'; + } else { + value = NULL; } for (i = 0; i < ARRAY_SIZE(svc_params); ++i) { @@ -268,7 +311,14 @@ service_t *rdsvc(int dirfd, const char *filename) } if (i >= ARRAY_SIZE(svc_params)) { - fprintf(stderr, "%s: %zu: unknown parameter '%s'\n", + fprintf(stderr, "%s: %zu: unknown keyword '%s'\n", + filename, lineno, key); + goto fail_line; + } + + if (value == NULL) { + fprintf(stderr, + "%s: %zu: expected argument after '%s'\n", filename, lineno, key); goto fail_line; } diff --git a/lib/src/splitkv.c b/lib/src/splitkv.c index b1ef8d3..3631ea8 100644 --- a/lib/src/splitkv.c +++ b/lib/src/splitkv.c @@ -19,13 +19,6 @@ #include "util.h" -static char *skpspc(char *ptr) -{ - while (*ptr == ' ' || *ptr == '\t') - ++ptr; - return ptr; -} - static int xdigit(int x) { if (isupper(x)) @@ -35,107 +28,61 @@ static int xdigit(int x) return x - '0'; } -static char *parse_str(char *src) +int unescape(char *src) { char *dst = src; int c; for (;;) { - c = *(src++); - - switch (c) { - case '\\': - c = *(src++); + while (*src != '"' && *src != '\0') + *(dst++) = *(src++); - switch (c) { - case 'a': c = '\a'; break; - case 'b': c = '\b'; break; - case 'f': c = '\f'; break; - case 'n': c = '\n'; break; - case 't': c = '\t'; break; - case '\\': break; - case '"': break; - case 'x': - c = 0; - if (isxdigit(*src)) - c = (c << 4) | xdigit(*(src++)); - if (isxdigit(*src)) - c = (c << 4) | xdigit(*(src++)); - break; - case '0': - c = 0; - if (isdigit(*src) && *src < '8') - c = (c << 3) | (*(src++) - '0'); - if (isdigit(*src) && *src < '8') - c = (c << 3) | (*(src++) - '0'); - if (isdigit(*src) && *src < '8') - c = (c << 3) | (*(src++) - '0'); - break; - default: - return NULL; - } + if (*src == '\0') break; - case '"': - *(dst++) = '\0'; - goto out; - } - - *(dst++) = c; - } -out: - return src; -} - -int splitkv(char *line, char **key, char **value) -{ - *key = NULL; - *value = NULL; - - line = skpspc(line); - - if (*line == '#' || *line == '\0') - return 0; - if (!isalpha(*line)) - return -1; - - *key = line; - - while (isalnum(*line)) - ++line; - - if (*line == ' ' || *line == '\t') { - *(line++) = '\0'; - line = skpspc(line); - } - - if (*line != '=') - return -1; - - *(line++) = '\0'; - line = skpspc(line); - - if (*line == '"') { - ++line; - *value = line; - - line = parse_str(line); - } else if (isalnum(*line)) { - *value = line; - - while (isalnum(*line) || *line == '.' || *line == '_') - ++line; + ++src; + + while ((c = *(src++)) != '"') { + if (c == '\0') + return -1; + + if (c == '\\') { + c = *(src++); + + switch (c) { + case 'a': c = '\a'; break; + case 'b': c = '\b'; break; + case 'f': c = '\f'; break; + case 'n': c = '\n'; break; + case 't': c = '\t'; break; + case '\\': + case '"': + break; + case 'x': + c = 0; + if (isxdigit(*src)) + c = (c<<4) | xdigit(*(src++)); + if (isxdigit(*src)) + c = (c<<4) | xdigit(*(src++)); + break; + case '0': + c = 0; + if (isdigit(*src) && *src < '8') + c = (c<<3) | (*(src++) - '0'); + if (isdigit(*src) && *src < '8') + c = (c<<3) | (*(src++) - '0'); + if (isdigit(*src) && *src < '8') + c = (c<<3) | (*(src++) - '0'); + break; + default: + return -1; + } + } - if (*line != '\0') - *(line++) = '\0'; - } else { - return -1; + *(dst++) = c; + } } - line = skpspc(line); - - if (*line != '\0' && *line != '#') - return -1; - + *(dst++) = '\0'; return 0; } -- cgit v1.2.3