diff options
author | Steve <sb@npubs.com> | 2006-04-19 18:22:56 +0000 |
---|---|---|
committer | Steve <sb@npubs.com> | 2006-04-19 18:22:56 +0000 |
commit | 3c6697aa59e56937173755474e4ecdee60303d46 (patch) | |
tree | e896d1db38d88a7b4e56a66215227c76ecf047ae /tools/rrdui-cgi.c | |
parent | 677fc07386ed457e4576e437a5d8fd0b3dc31a7d (diff) |
added parse_args function
Diffstat (limited to 'tools/rrdui-cgi.c')
-rw-r--r-- | tools/rrdui-cgi.c | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/tools/rrdui-cgi.c b/tools/rrdui-cgi.c index a2e7407..45dbf83 100644 --- a/tools/rrdui-cgi.c +++ b/tools/rrdui-cgi.c @@ -1,10 +1,17 @@ +/* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING + file accompanying popt source distributions, available from + ftp://ftp.rpm.org/pub/rpm/dist. */ #include <stdlib.h> #include <stdio.h> #include <string.h> #include <err.h> #include <unistd.h> +#include <ctype.h> +#include <errno.h> + +#include "../common/config-parser.h" static char* conf_directory = NULL; static char* work_directory = NULL; @@ -17,6 +24,8 @@ typedef struct _graph int height; int interval; char* category; + const char** options; + const char** commands; struct _graph *next; } @@ -28,6 +37,126 @@ static graph* allgraphs = NULL; * CONFIG PARSING */ +/* *argv should be freed with free() after use */ +int +parse_argv(const char* s, const char*** argvp) +{ + #define GROW_DELTA 5 + const char* src; + char quote = '\0'; + int alloced = GROW_DELTA; + const char** argv = NULL; + const char** argv2; + const char** a; + size_t nb; + char* dst; + int argc = 0; + int buflen; + char* buf; + int i, r = 0; + + argv = malloc (sizeof (*argv) * alloced); + if (!argv) { + errno = ENOMEM; + return -1; + } + + buflen = strlen (s) + 1; + buf = memset (alloca (buflen), 0, buflen); + + argv[argc] = buf; + + for (src = s; r == 0 && *src; src++) { + if (quote == *src) { + quote = '\0'; + } else if (quote != '\0') { + if (*src == '\\') { + src++; + if (!*src) { + r = -1; errno = EINVAL; + continue; + } + if (*src != quote) + *buf++ = '\\'; + } + *buf++ = *src; + } else if (isspace(*src)) { + if (*argv[argc] != '\0') { + buf++, argc++; + if (argc == alloced) { + alloced += GROW_DELTA; + a = realloc (argv, sizeof(*argv) * alloced); + if (!a) { + r = -1; errno = ENOMEM; + continue; + } + argv = a; + } + argv[argc] = buf; + } + } else { + switch (*src) { + case '"': + case '\'': + quote = *src; + break; + case '\\': + src++; + if (!*src) { + r = -1; errno = EINVAL; + continue; + } + default: + *buf++ = *src; + break; + } + } + } + + /* Reallocate the whole thing as one block of memory */ + if (r == 0) { + if (strlen(argv[argc])) + argc++; + + nb = (argc + 1) * sizeof(*argv); + + for (i = 0; i < argc; i++) { + if (argv[i] != NULL) + nb += strlen(argv[i]) + 1; + } + + dst = malloc (nb); + if (dst == NULL) { + free(argv); + errno = ENOMEM; + return -1; + } + + argv2 = (void *) dst; + dst += (argc + 1) * sizeof(*argv); + + for (i = 0; i < argc; i++) { + if (argv[i] == NULL) + continue; + argv2[i] = dst; + dst += strlen(strcpy(dst, argv[i])) + 1; + } + argv2[argc] = NULL; + + if (argvp) { + *argvp = argv2; + } else { + free(argv2); + argv2 = NULL; + } + + r = 0; + } + + free(argv); + return r; +} + int cfg_value(const char* filename, const char* header, const char* name, char* value, void* data) { @@ -66,12 +195,24 @@ int cfg_value(const char* filename, const char* header, const char* name, gr->height = atoi(value); else if (strcmp(name, "width") == 0) gr->width = atoi(value); + else if (strcmp(name, "options") == 0) + { + if (parse_argv(value, &gr->options) != 0) + errx(2, "Invalid 'options' option"); + } + else if (strcmp(name, "commands") == 0) + { + if (parse_argv(value, &gr->commands) != 0) + errx(2, "Invalid 'commands' option"); + } } else if (strcmp(header, "poll") == 0) { if (strcmp(name, "interval") == 0) gr->interval = atoi(value); } + + return 0; } int cfg_error(const char* filename, const char* errmsg, void* data) @@ -90,6 +231,11 @@ freegraphs () for (l = allgraphs; l != NULL; ) { t = l->next; + if (l->options) + free(l->options); + if (l->commands) + free(l->commands); + free(l); l = t; } |