summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve <sb@npubs.com>2006-04-19 18:22:56 +0000
committerSteve <sb@npubs.com>2006-04-19 18:22:56 +0000
commit3c6697aa59e56937173755474e4ecdee60303d46 (patch)
treee896d1db38d88a7b4e56a66215227c76ecf047ae
parent677fc07386ed457e4576e437a5d8fd0b3dc31a7d (diff)
added parse_args function
-rw-r--r--tools/rrdui-cgi.c146
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;
}