Autotoolization.
authorFlorian Forster <ff@octo.it>
Wed, 16 Jun 2010 15:13:28 +0000 (17:13 +0200)
committerFlorian Forster <octo@leeloo.lan.home.verplant.org>
Wed, 16 Jun 2010 15:13:28 +0000 (17:13 +0200)
68 files changed:
AUTHORS [new file with mode: 0644]
ChangeLog [new file with mode: 0644]
Makefile [deleted file]
Makefile.am [new file with mode: 0644]
NEWS [new file with mode: 0644]
README [new file with mode: 0644]
action_graph.c [deleted file]
action_graph.h [deleted file]
action_list_graphs.c [deleted file]
action_list_graphs.h [deleted file]
aux_types.h [deleted file]
common.c [deleted file]
common.h [deleted file]
configure.ac [new file with mode: 0644]
filesystem.c [deleted file]
filesystem.h [deleted file]
graph.c [deleted file]
graph.h [deleted file]
graph_config.c [deleted file]
graph_config.h [deleted file]
graph_def.c [deleted file]
graph_def.h [deleted file]
graph_ident.c [deleted file]
graph_ident.h [deleted file]
graph_instance.c [deleted file]
graph_instance.h [deleted file]
graph_list.c [deleted file]
graph_list.h [deleted file]
oconfig.c [deleted file]
oconfig.h [deleted file]
parser.y [deleted file]
scanner.l [deleted file]
src/Makefile.am [new file with mode: 0644]
src/action_graph.c [new file with mode: 0644]
src/action_graph.h [new file with mode: 0644]
src/action_list_graphs.c [new file with mode: 0644]
src/action_list_graphs.h [new file with mode: 0644]
src/aux_types.h [new file with mode: 0644]
src/common.c [new file with mode: 0644]
src/common.h [new file with mode: 0644]
src/filesystem.c [new file with mode: 0644]
src/filesystem.h [new file with mode: 0644]
src/graph.c [new file with mode: 0644]
src/graph.h [new file with mode: 0644]
src/graph_config.c [new file with mode: 0644]
src/graph_config.h [new file with mode: 0644]
src/graph_def.c [new file with mode: 0644]
src/graph_def.h [new file with mode: 0644]
src/graph_ident.c [new file with mode: 0644]
src/graph_ident.h [new file with mode: 0644]
src/graph_instance.c [new file with mode: 0644]
src/graph_instance.h [new file with mode: 0644]
src/graph_list.c [new file with mode: 0644]
src/graph_list.h [new file with mode: 0644]
src/main.c [new file with mode: 0644]
src/oconfig.c [new file with mode: 0644]
src/oconfig.h [new file with mode: 0644]
src/parser.y [new file with mode: 0644]
src/scanner.l [new file with mode: 0644]
src/utils_array.c [new file with mode: 0644]
src/utils_array.h [new file with mode: 0644]
src/utils_params.c [new file with mode: 0644]
src/utils_params.h [new file with mode: 0644]
test.fcgi.c [deleted file]
utils_array.c [deleted file]
utils_array.h [deleted file]
utils_params.c [deleted file]
utils_params.h [deleted file]

diff --git a/AUTHORS b/AUTHORS
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/ChangeLog b/ChangeLog
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/Makefile b/Makefile
deleted file mode 100644 (file)
index 356ae57..0000000
--- a/Makefile
+++ /dev/null
@@ -1,54 +0,0 @@
-CC = gcc
-CPPFLAGS = 
-CFLAGS = -Wall -Wextra -O0 -g
-LDFLAGS = 
-LDLIBS = 
-
-all: test.fcgi
-
-clean:
-       rm -f test.cgi
-
-common.o: common.c common.h
-
-filesystem.o: filesystem.c filesystem.h
-
-graph.o: graph.c graph.h
-
-graph_config.o: graph_config.c graph_config.h
-
-graph_def.o: graph_def.c graph_def.h
-
-graph_ident.o: graph_ident.c graph_ident.h
-
-graph_instance.o: graph_instance.c graph_instance.h
-
-graph_list.o: graph_list.c graph_list.h
-
-utils_array.o: utils_array.c utils_array.h
-
-utils_params.o: utils_params.c utils_params.h
-
-action_graph.o: action_graph.c action_graph.h
-
-action_list_graphs.o: action_list_graphs.c action_list_graphs.h
-
-oconfig.o: oconfig.c oconfig.h
-
-scanner.c: scanner.l
-       flex --outfile=scanner.c scanner.l
-
-scanner.o: scanner.c parser.h
-
-parser.c parser.h: parser.y
-       bison --output=parser.c --defines=parser.h parser.y
-
-parser.o: parser.c
-
-test: test.c utils_params.o
-
-test.fcgi: LDLIBS = -lfcgi -lrrd
-test.fcgi: test.fcgi.c common.o filesystem.o graph.o graph_config.o graph_def.o graph_ident.o graph_instance.o graph_list.o utils_array.o utils_params.o action_graph.o action_list_graphs.o scanner.o parser.o oconfig.o
-
-.PHONY: clean
-
diff --git a/Makefile.am b/Makefile.am
new file mode 100644 (file)
index 0000000..af437a6
--- /dev/null
@@ -0,0 +1 @@
+SUBDIRS = src
diff --git a/NEWS b/NEWS
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/action_graph.c b/action_graph.c
deleted file mode 100644 (file)
index a0f257e..0000000
+++ /dev/null
@@ -1,150 +0,0 @@
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <stdint.h>
-#include <inttypes.h>
-#include <dirent.h> /* for PATH_MAX */
-#include <assert.h>
-#include <math.h>
-
-#include <rrd.h>
-
-#include "common.h"
-#include "action_graph.h"
-#include "graph_list.h"
-#include "utils_params.h"
-#include "utils_array.h"
-
-#include <fcgiapp.h>
-#include <fcgi_stdio.h>
-
-static void emulate_graph (int argc, char **argv) /* {{{ */
-{
-  int i;
-
-  printf ("rrdtool \\\n");
-  for (i = 0; i < argc; i++)
-  {
-    if (i < (argc - 1))
-      printf ("  \"%s\" \\\n", argv[i]);
-    else
-      printf ("  \"%s\"\n", argv[i]);
-  }
-} /* }}} void emulate_graph */
-
-static int ag_info_print (rrd_info_t *info) /* {{{ */
-{
-  if (info->type == RD_I_VAL)
-    printf ("[info] %s = %g;\n", info->key, info->value.u_val);
-  else if (info->type == RD_I_CNT)
-    printf ("[info] %s = %lu;\n", info->key, info->value.u_cnt);
-  else if (info->type == RD_I_STR)
-    printf ("[info] %s = %s;\n", info->key, info->value.u_str);
-  else if (info->type == RD_I_INT)
-    printf ("[info] %s = %i;\n", info->key, info->value.u_int);
-  else if (info->type == RD_I_BLO)
-    printf ("[info] %s = [blob, %lu bytes];\n", info->key, info->value.u_blo.size);
-  else
-    printf ("[info] %s = [unknown type %#x];\n", info->key, info->type);
-
-  return (0);
-} /* }}} int ag_info_print */
-
-static int output_graph (rrd_info_t *info) /* {{{ */
-{
-  rrd_info_t *img;
-
-  for (img = info; img != NULL; img = img->next)
-    if ((strcmp ("image", img->key) == 0)
-        && (img->type == RD_I_BLO))
-      break;
-
-  if (img == NULL)
-    return (ENOENT);
-
-  printf ("Content-Type: image/png\n"
-      "Content-Length: %lu\n"
-      "\n",
-      img->value.u_blo.size);
-  fwrite (img->value.u_blo.ptr, img->value.u_blo.size,
-      /* nmemb = */ 1, stdout);
-
-  return (0);
-} /* }}} int output_graph */
-
-#define OUTPUT_ERROR(...) do {             \
-  printf ("Content-Type: text/plain\n\n"); \
-  printf (__VA_ARGS__);                    \
-  return (0);                              \
-} while (0)
-
-int action_graph (void) /* {{{ */
-{
-  str_array_t *args;
-  graph_config_t *cfg;
-  graph_instance_t *inst;
-  rrd_info_t *info;
-  int status;
-
-  cfg = gl_graph_get_selected ();
-  if (cfg == NULL)
-    OUTPUT_ERROR ("gl_graph_get_selected () failed.\n");
-
-  inst = inst_get_selected (cfg);
-  if (inst == NULL)
-    OUTPUT_ERROR ("inst_get_selected (%p) failed.\n", (void *) cfg);
-
-  args = array_create ();
-  if (args == NULL)
-    return (ENOMEM);
-
-  array_append (args, "graph");
-  array_append (args, "-");
-  array_append (args, "--imgformat");
-  array_append (args, "PNG");
-
-  status = inst_get_rrdargs (cfg, inst, args);
-  if (status != 0)
-  {
-    array_destroy (args);
-    OUTPUT_ERROR ("inst_get_rrdargs failed with status %i.\n", status);
-  }
-
-  rrd_clear_error ();
-  info = rrd_graph_v (array_argc (args), array_argv (args));
-  if ((info == NULL) || rrd_test_error ())
-  {
-    printf ("Content-Type: text/plain\n\n");
-    printf ("rrd_graph_v failed: %s\n", rrd_get_error ());
-    emulate_graph (array_argc (args), array_argv (args));
-  }
-  else
-  {
-    int status;
-
-    status = output_graph (info);
-    if (status != 0)
-    {
-      rrd_info_t *ptr;
-
-      printf ("Content-Type: text/plain\n\n");
-      printf ("output_graph failed. Maybe the \"image\" info was not found?\n\n");
-
-      for (ptr = info; ptr != NULL; ptr = ptr->next)
-      {
-        ag_info_print (ptr);
-      }
-    }
-  }
-
-  if (info != NULL)
-    rrd_info_free (info);
-
-  array_destroy (args);
-  args = NULL;
-
-  return (0);
-} /* }}} int action_graph */
-
-/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/action_graph.h b/action_graph.h
deleted file mode 100644 (file)
index 712f398..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef ACTION_GRAPH_H
-#define ACTION_GRAPH_H 1
-
-int action_graph (void);
-
-#endif /* ACTION_GRAPH_H */
-/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/action_list_graphs.c b/action_list_graphs.c
deleted file mode 100644 (file)
index 29e3d8b..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-
-#include "action_list_graphs.h"
-#include "graph.h"
-#include "graph_list.h"
-#include "utils_params.h"
-
-#include <fcgiapp.h>
-#include <fcgi_stdio.h>
-
-static int print_graph_inst_json (__attribute__((unused)) graph_config_t *cfg, /* {{{ */
-    graph_instance_t *inst,
-    void *user_data)
-{
-  _Bool *first;
-  graph_ident_t *ident;
-  char *json;
-
-  first = user_data;
-
-  ident = inst_get_selector (inst);
-  if (ident == NULL)
-    return (-1);
-
-  json = ident_to_json (ident);
-  if (json == NULL)
-  {
-    ident_destroy (ident);
-    return (ENOMEM);
-  }
-
-  if (*first)
-    printf ("%s", json);
-  else
-    printf (",\n%s", json);
-
-  *first = 0;
-
-  ident_destroy (ident);
-  return (0);
-} /* }}} int print_graph_inst_json */
-
-static int print_graph_json (graph_config_t *cfg, /* {{{ */
-    void *user_data)
-{
-  return (gl_graph_instance_get_all (cfg, print_graph_inst_json, user_data));
-} /* }}} int print_graph_json */
-
-static int list_graphs_json (void) /* {{{ */
-{
-  _Bool first = 1;
-
-  printf ("Content-Type: application/json\n\n");
-
-  printf ("[\n");
-  gl_graph_get_all (print_graph_json, /* user_data = */ &first);
-  printf ("\n]");
-
-  return (0);
-} /* }}} int list_graphs_json */
-
-static int print_graph_inst_html (graph_config_t *cfg, /* {{{ */
-    graph_instance_t *inst,
-    __attribute__((unused)) void *user_data)
-{
-  char params[1024];
-  char desc[1024];
-
-  memset (params, 0, sizeof (params));
-  inst_get_params (cfg, inst, params, sizeof (params));
-
-  memset (desc, 0, sizeof (desc));
-  inst_describe (cfg, inst, desc, sizeof (desc));
-
-  printf ("    <li><a href=\"test.fcgi?action=graph;%s\">%s</a></li>\n",
-      params, desc);
-
-  return (0);
-} /* }}} int print_graph_inst_html */
-
-static int print_graph_html (graph_config_t *cfg, /* {{{ */
-    __attribute__((unused)) void *user_data)
-{
-  char buffer[1024];
-
-  memset (buffer, 0, sizeof (buffer));
-  graph_get_title (cfg, buffer, sizeof (buffer));
-
-  printf ("  <li>%s\n  <ul>\n", buffer);
-  gl_graph_instance_get_all (cfg, print_graph_inst_html, /* user_data = */ NULL);
-  printf ("  </ul></li>\n");
-
-  return (0);
-} /* }}} int print_graph_html */
-
-static int list_graphs_html (void) /* {{{ */
-{
-  printf ("Content-Type: text/html\n\n");
-
-  printf ("<ul>\n");
-  gl_graph_get_all (print_graph_html, /* user_data = */ NULL);
-  printf ("</ul>\n");
-
-  return (0);
-} /* }}} int list_graphs_html */
-
-int action_list_graphs (void) /* {{{ */
-{
-  const char *format;
-
-  gl_update ();
-
-  format = param ("format");
-  if (format == NULL)
-    format = "html";
-
-  if (strcmp ("json", format) == 0)
-    return (list_graphs_json ());
-  else
-    return (list_graphs_html ());
-} /* }}} int action_list_graphs */
-
-/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/action_list_graphs.h b/action_list_graphs.h
deleted file mode 100644 (file)
index dd7edf9..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef ACTION_LIST_GRAPHS_H
-#define ACTION_LIST_GRAPHS_H 1
-
-int action_list_graphs (void);
-
-#endif /* ACTION_LIST_GRAPHS_H */
-/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/aux_types.h b/aux_types.h
deleted file mode 100644 (file)
index 25b81ab..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifndef AUX_TYPES_H
-#define AUX_TYPES_H 1
-
-struct statement_list_s
-{
-       oconfig_item_t *statement;
-       int             statement_num;
-};
-typedef struct statement_list_s statement_list_t;
-
-struct argument_list_s
-{
-       oconfig_value_t *argument;
-       int              argument_num;
-};
-typedef struct argument_list_s argument_list_t;
-
-#endif /* AUX_TYPES_H */
diff --git a/common.c b/common.c
deleted file mode 100644 (file)
index 2b6b5eb..0000000
--- a/common.c
+++ /dev/null
@@ -1,193 +0,0 @@
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <inttypes.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <dirent.h>
-#include <assert.h>
-#include <math.h>
-
-#include <rrd.h>
-
-#include "common.h"
-#include "graph_list.h"
-
-#include <fcgiapp.h>
-#include <fcgi_stdio.h>
-
-size_t c_strlcat (char *dst, const char *src, size_t size) /* {{{ */
-{
-  size_t retval;
-  size_t dst_len;
-  size_t src_len;
-
-  dst_len = strlen (dst);
-  src_len = strlen (src);
-  retval = dst_len + src_len;
-
-  if ((dst_len + 1) >= size)
-    return (retval);
-
-  dst  += dst_len;
-  size -= dst_len;
-  assert (size >= 2);
-
-  /* Result will be truncated. */
-  if (src_len >= size)
-    src_len = size - 1;
-
-  memcpy (dst, src, src_len);
-  dst[src_len] = 0;
-
-  return (retval);
-} /* }}} size_t c_strlcat */
-
-int ds_list_from_rrd_file (char *file, /* {{{ */
-    size_t *ret_dses_num, char ***ret_dses)
-{
-  char *rrd_argv[] = { "info", file, NULL };
-  int rrd_argc = (sizeof (rrd_argv) / sizeof (rrd_argv[0])) - 1;
-
-  rrd_info_t *info;
-  rrd_info_t *ptr;
-
-  char **dses = NULL;
-  size_t dses_num = 0;
-
-  info = rrd_info (rrd_argc, rrd_argv);
-  if (info == NULL)
-  {
-    printf ("%s: rrd_info (%s) failed.\n", __func__, file);
-    return (-1);
-  }
-
-  for (ptr = info; ptr != NULL; ptr = ptr->next)
-  {
-    size_t keylen;
-    size_t dslen;
-    char *ds;
-    char **tmp;
-
-    if (strncmp ("ds[", ptr->key, strlen ("ds[")) != 0)
-      continue;
-
-    keylen = strlen (ptr->key);
-    if (keylen < strlen ("ds[?].index"))
-      continue;
-
-    dslen = keylen - strlen ("ds[].index");
-    assert (dslen >= 1);
-
-    if (strcmp ("].index", ptr->key + (strlen ("ds[") + dslen)) != 0)
-      continue;
-
-    ds = malloc (dslen + 1);
-    if (ds == NULL)
-      continue;
-
-    memcpy (ds, ptr->key + strlen ("ds["), dslen);
-    ds[dslen] = 0;
-
-    tmp = realloc (dses, sizeof (*dses) * (dses_num + 1));
-    if (tmp == NULL)
-    {
-      free (ds);
-      continue;
-    }
-    dses = tmp;
-
-    dses[dses_num] = ds;
-    dses_num++;
-  }
-
-  rrd_info_free (info);
-
-  if (dses_num < 1)
-  {
-    assert (dses == NULL);
-    return (ENOENT);
-  }
-
-  *ret_dses_num = dses_num;
-  *ret_dses = dses;
-
-  return (0);
-} /* }}} int ds_list_from_rrd_file */
-
-static int hsv_to_rgb (double *hsv, double *rgb) /* {{{ */
-{
-  double c = hsv[2] * hsv[1];
-  double h = hsv[0] / 60.0;
-  double x = c * (1.0 - fabs (fmod (h, 2.0) - 1));
-  double m = hsv[2] - c;
-
-  rgb[0] = 0.0;
-  rgb[1] = 0.0;
-  rgb[2] = 0.0;
-
-       if ((0.0 <= h) && (h < 1.0)) { rgb[0] = 1.0; rgb[1] = x; rgb[2] = 0.0; }
-  else if ((1.0 <= h) && (h < 2.0)) { rgb[0] = x; rgb[1] = 1.0; rgb[2] = 0.0; }
-  else if ((2.0 <= h) && (h < 3.0)) { rgb[0] = 0.0; rgb[1] = 1.0; rgb[2] = x; }
-  else if ((3.0 <= h) && (h < 4.0)) { rgb[0] = 0.0; rgb[1] = x; rgb[2] = 1.0; }
-  else if ((4.0 <= h) && (h < 5.0)) { rgb[0] = x; rgb[1] = 0.0; rgb[2] = 1.0; }
-  else if ((5.0 <= h) && (h < 6.0)) { rgb[0] = 1.0; rgb[1] = 0.0; rgb[2] = x; }
-
-  rgb[0] += m;
-  rgb[1] += m;
-  rgb[2] += m;
-
-  return (0);
-} /* }}} int hsv_to_rgb */
-
-static uint32_t rgb_to_uint32 (double *rgb) /* {{{ */
-{
-  uint8_t r;
-  uint8_t g;
-  uint8_t b;
-
-  r = (uint8_t) (255.0 * rgb[0]);
-  g = (uint8_t) (255.0 * rgb[1]);
-  b = (uint8_t) (255.0 * rgb[2]);
-
-  return ((((uint32_t) r) << 16)
-      | (((uint32_t) g) << 8)
-      | ((uint32_t) b));
-} /* }}} uint32_t rgb_to_uint32 */
-
-uint32_t get_random_color (void) /* {{{ */
-{
-  double hsv[3] = { 0.0, 1.0, 1.0 };
-  double rgb[3] = { 0.0, 0.0, 0.0 };
-
-  hsv[0] = 360.0 * ((double) rand ()) / (((double) RAND_MAX) + 1.0);
-
-  hsv_to_rgb (hsv, rgb);
-
-  return (rgb_to_uint32 (rgb));
-} /* }}} uint32_t get_random_color */
-
-int print_debug (const char *format, ...) /* {{{ */
-{
-  static _Bool have_header = 0;
-
-  va_list ap;
-  int status;
-
-  if (!have_header)
-  {
-    printf ("Content-Type: text/plain\n\n");
-    have_header = 1;
-  }
-
-  va_start (ap, format);
-  status = vprintf (format, ap);
-  va_end (ap);
-
-  return (status);
-} /* }}} int print_debug */
-
-/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/common.h b/common.h
deleted file mode 100644 (file)
index 2b5662f..0000000
--- a/common.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef COMMON_H
-#define COMMON_H 1
-
-#include <stdint.h>
-#include <inttypes.h>
-
-int print_debug (const char *format, ...)
-  __attribute__((format(printf,1,2)));
-#if 0
-# define DEBUG(...) print_debug (__VA_ARGS__)
-#else
-# define DEBUG(...) /**/
-#endif
-
-size_t c_strlcat (char *dst, const char *src, size_t size);
-#define strlcat c_strlcat
-
-int ds_list_from_rrd_file (char *file,
-    size_t *ret_dses_num, char ***ret_dses);
-
-uint32_t get_random_color (void);
-
-#endif /* COMMON_H */
-/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/configure.ac b/configure.ac
new file mode 100644 (file)
index 0000000..9c8b628
--- /dev/null
@@ -0,0 +1,33 @@
+AC_INIT(collection, 4.0.0)
+AC_CONFIG_SRCDIR(src/main.c)
+AC_CONFIG_HEADERS(src/config.h)
+AM_INIT_AUTOMAKE(dist-bzip2)
+AC_LANG(C)
+
+AC_PREFIX_DEFAULT("/opt/collection4")
+
+#
+# Check for programs/utilities
+#
+AC_PROG_CC
+AC_PROG_CPP
+AC_PROG_INSTALL
+AC_PROG_LEX
+AC_PROG_YACC
+AM_CONDITIONAL(COMPILER_IS_GCC, test "x$GCC" = "xyes")
+
+#
+# Checks for header files.
+#
+AC_HEADER_STDC
+AC_CHECK_HEADERS(stdbool.h sys/types.h sys/socket.h netdb.h)
+
+AC_CHECK_HEADERS(fcgiapp.h fcgi_stdio.h rrd.h, [],
+                [AC_MSG_ERROR(a required header file cannot be found.)])
+
+AC_CHECK_LIB(fcgi, FCGI_Accept, [],
+            [AC_MSG_ERROR(cannot find libfcgi.)])
+AC_CHECK_LIB(rrd_th, rrd_graph_v, [],
+            [AC_MSG_ERROR(cannot find librrd_th.)], [-lm])
+
+AC_OUTPUT(Makefile src/Makefile)
diff --git a/filesystem.c b/filesystem.c
deleted file mode 100644 (file)
index a5eeb81..0000000
+++ /dev/null
@@ -1,297 +0,0 @@
-#include <stdlib.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <limits.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <dirent.h>
-
-#include "filesystem.h"
-
-struct fs_scan_dir_data_s /* {{{ */
-{
-  fs_ident_cb_t callback;
-  void *user_data;
-
-  char *host;
-  char *plugin;
-  char *plugin_instance;
-  char *type;
-  char *type_instance;
-}; /* }}} */
-typedef struct fs_scan_dir_data_s fs_scan_dir_data_t;
-
-typedef int (*callback_type_t)   (const char *type,   void *user_data);
-typedef int (*callback_plugin_t) (const char *plugin, void *user_data);
-typedef int (*callback_host_t)   (const char *host,   void *user_data);
-
-/*
- * Directory and file walking functions
- */
-static int foreach_rrd_file (const char *dir, /* {{{ */
-    int (*callback) (const char *, void *),
-    void *user_data)
-{
-  DIR *dh;
-  struct dirent *entry;
-  int status;
-
-  if (callback == NULL)
-    return (EINVAL);
-
-  dh = opendir (dir);
-  if (dh == NULL)
-    return (errno);
-
-  while ((entry = readdir (dh)) != NULL)
-  {
-    struct stat statbuf;
-    char abspath[PATH_MAX + 1];
-    size_t d_name_len;
-
-    if (entry->d_name[0] == '.')
-      continue;
-
-    d_name_len = strlen (entry->d_name);
-    if (d_name_len <= 4)
-      continue;
-
-    if (strcasecmp (".rrd", entry->d_name + (d_name_len - 4)) != 0)
-      continue;
-
-    snprintf (abspath, sizeof (abspath), "%s/%s", dir, entry->d_name);
-    abspath[sizeof (abspath) - 1] = 0;
-
-    memset (&statbuf, 0, sizeof (statbuf));
-
-    status = stat (abspath, &statbuf);
-    if (status != 0)
-      continue;
-
-    if (!S_ISREG (statbuf.st_mode))
-      continue;
-
-    entry->d_name[d_name_len - 4] = 0;
-
-    status = (*callback) (entry->d_name, user_data);
-    if (status != 0)
-      break;
-  } /* while (readdir) */
-
-  closedir (dh);
-  return (status);
-} /* }}} int foreach_rrd_file */
-
-static int foreach_dir (const char *dir, /* {{{ */
-    int (*callback) (const char *, void *),
-    void *user_data)
-{
-  DIR *dh;
-  struct dirent *entry;
-  int status = 0;
-
-  if (callback == NULL)
-    return (EINVAL);
-
-  dh = opendir (dir);
-  if (dh == NULL)
-    return (errno);
-
-  while ((entry = readdir (dh)) != NULL)
-  {
-    struct stat statbuf;
-    char abspath[PATH_MAX + 1];
-
-    if (entry->d_name[0] == '.')
-      continue;
-
-    snprintf (abspath, sizeof (abspath), "%s/%s", dir, entry->d_name);
-    abspath[sizeof (abspath) - 1] = 0;
-
-    memset (&statbuf, 0, sizeof (statbuf));
-
-    status = stat (abspath, &statbuf);
-    if (status != 0)
-      continue;
-
-    if (!S_ISDIR (statbuf.st_mode))
-      continue;
-
-    status = (*callback) (entry->d_name, user_data);
-    if (status != 0)
-      break;
-  } /* while (readdir) */
-
-  closedir (dh);
-  return (status);
-} /* }}} int foreach_dir */
-
-static int foreach_type (const char *host, const char *plugin, /* {{{ */
-    callback_type_t callback, void *user_data)
-{
-  char abspath[PATH_MAX + 1];
-
-  if ((host == NULL) || (plugin == NULL))
-    return (EINVAL);
-
-  snprintf (abspath, sizeof (abspath), "%s/%s/%s", DATA_DIR, host, plugin);
-  abspath[sizeof (abspath) - 1] = 0;
-
-  return (foreach_rrd_file (abspath, callback, user_data));
-} /* }}} int foreach_type */
-
-static int foreach_plugin (const char *host, /* {{{ */
-    callback_plugin_t callback,
-    void *user_data)
-{
-  char abspath[PATH_MAX + 1];
-
-  if (host == NULL)
-    return (EINVAL);
-
-  snprintf (abspath, sizeof (abspath), "%s/%s", DATA_DIR, host);
-  abspath[sizeof (abspath) - 1] = 0;
-
-  return (foreach_dir (abspath, callback, user_data));
-} /* }}} int foreach_plugin */
-
-static int foreach_host (callback_host_t callback, /* {{{ */
-    void *user_data)
-{
-  return (foreach_dir (DATA_DIR, callback, user_data));
-} /* }}} int foreach_host */
-
-/*
- * Functions building "fs_scan_dir_data_t" and calling the user-supplied
- * callback eventually.
- */
-static int scan_type (const char *type, void *user_data) /* {{{ */
-{
-  fs_scan_dir_data_t *data = user_data;
-  graph_ident_t *ident;
-  int status;
-
-  if ((type == NULL) || (data == NULL))
-    return (EINVAL);
-
-  if ((data->type != NULL) || (data->type_instance != NULL))
-    return (EINVAL);
-
-  data->type = strdup (type);
-  if (data->type == NULL)
-    return (ENOMEM);
-
-  data->type_instance = strchr (data->type, '-');
-  if (data->type_instance != NULL)
-  {
-    *data->type_instance = 0;
-    data->type_instance++;
-  }
-  else
-  {
-    data->type_instance = data->type + strlen (data->type);
-  }
-
-  ident = ident_create (data->host,
-      data->plugin, data->plugin_instance,
-      data->type, data->type_instance);
-  if (ident == NULL)
-  {
-    status = -1;
-  }
-  else
-  {
-    status = (*data->callback) (ident, data->user_data);
-    ident_destroy (ident);
-  }
-
-  free (data->type);
-  data->type = NULL;
-  data->type_instance = NULL;
-
-  return (status);
-} /* }}} int scan_type */
-
-static int scan_plugin (const char *plugin, void *user_data) /* {{{ */
-{
-  fs_scan_dir_data_t *data = user_data;
-  int status;
-
-  if ((plugin == NULL) || (data == NULL))
-    return (EINVAL);
-
-  if ((data->plugin != NULL) || (data->plugin_instance != NULL))
-    return (EINVAL);
-
-  data->plugin = strdup (plugin);
-  if (data->plugin == NULL)
-    return (ENOMEM);
-
-  data->plugin_instance = strchr (data->plugin, '-');
-  if (data->plugin_instance != NULL)
-  {
-    *data->plugin_instance = 0;
-    data->plugin_instance++;
-  }
-  else
-  {
-    data->plugin_instance = data->plugin + strlen (data->plugin);
-  }
-
-  status = foreach_type (data->host, plugin, scan_type, data);
-
-  free (data->plugin);
-  data->plugin = NULL;
-  data->plugin_instance = NULL;
-
-  return (status);
-} /* }}} int scan_plugin */
-
-static int scan_host (const char *host, void *user_data) /* {{{ */
-{
-  fs_scan_dir_data_t *data = user_data;
-  int status;
-
-  if ((host == NULL) || (data == NULL))
-    return (EINVAL);
-
-  if (data->host != NULL)
-    return (EINVAL);
-
-  data->host = strdup (host);
-  if (data->host == NULL)
-    return (ENOMEM);
-
-  status =  foreach_plugin (host, scan_plugin, data);
-
-  free (data->host);
-  data->host = NULL;
-
-  return (status);
-} /* }}} int scan_host */
-
-/*
- * Public function
- */
-int fs_scan (fs_ident_cb_t callback, void *user_data) /* {{{ */
-{
-  fs_scan_dir_data_t data;
-
-  memset (&data, 0, sizeof (data));
-  data.callback = callback;
-  data.user_data = user_data;
-
-  data.host = NULL;
-  data.plugin = NULL;
-  data.plugin_instance = NULL;
-  data.type = NULL;
-  data.type_instance = NULL;
-
-  foreach_host (scan_host, &data);
-
-  return (0);
-} /* }}} int fs_scan */
-
-/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/filesystem.h b/filesystem.h
deleted file mode 100644 (file)
index 9569bc3..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef FILESYSTEM_G
-#define FILESYSTEM_G 1
-
-#include "graph_ident.h"
-
-#define DATA_DIR "/var/lib/collectd/rrd"
-
-typedef int (*fs_ident_cb_t) (const graph_ident_t *ident, void *user_data);
-
-int fs_scan (fs_ident_cb_t callback, void *user_data);
-
-#endif /* FILESYSTEM_G */
-/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/graph.c b/graph.c
deleted file mode 100644 (file)
index 154af77..0000000
--- a/graph.c
+++ /dev/null
@@ -1,290 +0,0 @@
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <inttypes.h>
-#include <string.h>
-#include <time.h>
-#include <errno.h>
-#include <assert.h>
-
-#include "graph.h"
-#include "graph_list.h"
-#include "graph_ident.h"
-#include "graph_def.h"
-#include "graph_config.h"
-#include "common.h"
-#include "filesystem.h"
-#include "utils_params.h"
-
-#include <fcgiapp.h>
-#include <fcgi_stdio.h>
-
-/*
- * Data types
- */
-struct graph_config_s /* {{{ */
-{
-  graph_ident_t *select;
-
-  char *title;
-  char *vertical_label;
-
-  graph_def_t *defs;
-
-  graph_instance_t *instances;
-}; /* }}} struct graph_config_s */
-
-/*
- * Private functions
- */
-static graph_instance_t *graph_find_instance (graph_config_t *cfg, /* {{{ */
-    const graph_ident_t *ident)
-{
-  if ((cfg == NULL) || (ident == NULL))
-    return (NULL);
-
-  return (inst_find_matching (cfg->instances, ident));
-} /* }}} graph_instance_t *graph_find_instance */
-
-/*
- * Config functions
- */
-static graph_ident_t *graph_config_get_selector (const oconfig_item_t *ci) /* {{{ */
-{
-  char *host = NULL;
-  char *plugin = NULL;
-  char *plugin_instance = NULL;
-  char *type = NULL;
-  char *type_instance = NULL;
-  graph_ident_t *ret;
-  int i;
-
-  for (i = 0; i < ci->children_num; i++)
-  {
-    oconfig_item_t *child;
-
-    child = ci->children + i;
-
-    if (strcasecmp ("Host", child->key) == 0)
-      graph_config_get_string (child, &host);
-    else if (strcasecmp ("Plugin", child->key) == 0)
-      graph_config_get_string (child, &plugin);
-    else if (strcasecmp ("PluginInstance", child->key) == 0)
-      graph_config_get_string (child, &plugin_instance);
-    else if (strcasecmp ("Type", child->key) == 0)
-      graph_config_get_string (child, &type);
-    else if (strcasecmp ("TypeInstance", child->key) == 0)
-      graph_config_get_string (child, &type_instance);
-    /* else: ignore all other directives here. */
-  } /* for */
-
-  ret = ident_create (host, plugin, plugin_instance, type, type_instance);
-
-  free (host);
-  free (plugin);
-  free (plugin_instance);
-  free (type);
-  free (type_instance);
-
-  return (ret);
-} /* }}} int graph_config_get_selector */
-
-/*
- * Global functions
- */
-graph_config_t *graph_create (const graph_ident_t *selector) /* {{{ */
-{
-  graph_config_t *cfg;
-
-  cfg = malloc (sizeof (*cfg));
-  if (cfg == NULL)
-    return (NULL);
-  memset (cfg, 0, sizeof (*cfg));
-
-  if (selector != NULL)
-    cfg->select = ident_clone (selector);
-  else
-    cfg->select = NULL;
-
-  cfg->title = NULL;
-  cfg->vertical_label = NULL;
-  cfg->defs = NULL;
-  cfg->instances = NULL;
-
-  return (cfg);
-} /* }}} int graph_create */
-
-void graph_destroy (graph_config_t *cfg) /* {{{ */
-{
-  if (cfg == NULL)
-    return;
-
-  ident_destroy (cfg->select);
-
-  free (cfg->title);
-  free (cfg->vertical_label);
-
-  def_destroy (cfg->defs);
-  inst_destroy (cfg->instances);
-} /* }}} void graph_destroy */
-
-int graph_config_add (const oconfig_item_t *ci) /* {{{ */
-{
-  graph_ident_t *select;
-  graph_config_t *cfg = NULL;
-  int i;
-
-  select = graph_config_get_selector (ci);
-  if (select == NULL)
-    return (EINVAL);
-
-  cfg = graph_create (/* selector = */ NULL);
-  if (cfg == NULL)
-    return (ENOMEM);
-
-  cfg->select = select;
-
-  for (i = 0; i < ci->children_num; i++)
-  {
-    oconfig_item_t *child;
-
-    child = ci->children + i;
-
-    if (strcasecmp ("Title", child->key) == 0)
-      graph_config_get_string (child, &cfg->title);
-    else if (strcasecmp ("VerticalLabel", child->key) == 0)
-      graph_config_get_string (child, &cfg->vertical_label);
-    else if (strcasecmp ("DEF", child->key) == 0)
-      def_config (cfg, child);
-  } /* for */
-
-  gl_add_graph (cfg);
-
-  return (0);
-} /* }}} graph_config_add */
-
-int graph_add_file (graph_config_t *cfg, const graph_ident_t *file) /* {{{ */
-{
-  graph_instance_t *inst;
-
-  inst = graph_find_instance (cfg, file);
-  if (inst == NULL)
-  {
-    inst = inst_create (cfg, file);
-    if (inst == NULL)
-      return (ENOMEM);
-
-    if (cfg->instances == NULL)
-      cfg->instances = inst;
-    else
-      inst_append (cfg->instances, inst);
-  }
-
-  return (inst_add_file (inst, file));
-} /* }}} int graph_add_file */
-
-int graph_get_title (graph_config_t *cfg, /* {{{ */
-    char *buffer, size_t buffer_size)
-{
-  if ((cfg == NULL) || (buffer == NULL) || (buffer_size < 1))
-    return (EINVAL);
-
-  if (cfg->title == NULL)
-    cfg->title = ident_to_string (cfg->select);
-
-  if (cfg->title == NULL)
-    return (ENOMEM);
-
-  strncpy (buffer, cfg->title, buffer_size);
-  buffer[buffer_size - 1] = 0;
-
-  return (0);
-} /* }}} int graph_get_title */
-
-graph_ident_t *graph_get_selector (graph_config_t *cfg) /* {{{ */
-{
-  if (cfg == NULL)
-    return (NULL);
-
-  return (ident_clone (cfg->select));
-} /* }}} graph_ident_t *graph_get_selector */
-
-graph_instance_t *graph_get_instances (graph_config_t *cfg) /* {{{ */
-{
-  if (cfg == NULL)
-    return (NULL);
-
-  return (cfg->instances);
-} /* }}} graph_instance_t *graph_get_instances */
-
-graph_def_t *graph_get_defs (graph_config_t *cfg) /* {{{ */
-{
-  if (cfg == NULL)
-    return (NULL);
-
-  return (cfg->defs);
-} /* }}} graph_def_t *graph_get_defs */
-
-int graph_add_def (graph_config_t *cfg, graph_def_t *def) /* {{{ */
-{
-  if ((cfg == NULL) || (def == NULL))
-    return (EINVAL);
-
-  if (cfg->defs == NULL)
-  {
-    cfg->defs = def;
-    return (0);
-  }
-
-  return (def_append (cfg->defs, def));
-} /* }}} int graph_add_def */
-
-_Bool graph_matches (graph_config_t *cfg, const graph_ident_t *ident) /* {{{ */
-{
-  if ((cfg == NULL) || (ident == NULL))
-    return (0);
-
-  return (ident_matches (cfg->select, ident));
-} /* }}} _Bool graph_matches */
-
-int graph_compare (graph_config_t *cfg, const graph_ident_t *ident) /* {{{ */
-{
-  if ((cfg == NULL) || (ident == NULL))
-    return (0);
-
-  return (ident_compare (cfg->select, ident));
-} /* }}} int graph_compare */
-
-int graph_clear_instances (graph_config_t *cfg) /* {{{ */
-{
-  if (cfg == NULL)
-    return (EINVAL);
-
-  inst_destroy (cfg->instances);
-  cfg->instances = NULL;
-
-  return (0);
-} /* }}} int graph_clear_instances */
-
-int graph_get_rrdargs (graph_config_t *cfg, graph_instance_t *inst, /* {{{ */
-    str_array_t *args)
-{
-  if ((cfg == NULL) || (inst == NULL) || (args == NULL))
-    return (EINVAL);
-
-  if (cfg->title != NULL)
-  {
-    array_append (args, "-t");
-    array_append (args, cfg->title);
-  }
-
-  if (cfg->vertical_label != NULL)
-  {
-    array_append (args, "-v");
-    array_append (args, cfg->vertical_label);
-  }
-
-  return (0);
-} /* }}} int graph_get_rrdargs */
-
-/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/graph.h b/graph.h
deleted file mode 100644 (file)
index 6e9ae07..0000000
--- a/graph.h
+++ /dev/null
@@ -1,48 +0,0 @@
-#ifndef GRAPH_H
-#define GRAPH_H 1
-
-/*
- * Data types
- */
-struct graph_config_s;
-typedef struct graph_config_s graph_config_t;
-
-#include "graph_def.h"
-#include "graph_ident.h"
-#include "graph_instance.h"
-#include "oconfig.h"
-#include "utils_array.h"
-
-/*
- * Functions
- */
-graph_config_t *graph_create (const graph_ident_t *selector);
-
-void graph_destroy (graph_config_t *graph);
-
-int graph_config_add (const oconfig_item_t *ci);
-
-int graph_add_file (graph_config_t *cfg, const graph_ident_t *file);
-
-int graph_get_title (graph_config_t *cfg,
-    char *buffer, size_t buffer_size);
-
-graph_ident_t *graph_get_selector (graph_config_t *cfg);
-
-graph_instance_t *graph_get_instances (graph_config_t *cfg);
-
-graph_def_t *graph_get_defs (graph_config_t *cfg);
-
-int graph_add_def (graph_config_t *cfg, graph_def_t *def);
-
-_Bool graph_matches (graph_config_t *cfg, const graph_ident_t *ident);
-
-int graph_compare (graph_config_t *cfg, const graph_ident_t *ident);
-
-int graph_clear_instances (graph_config_t *cfg);
-
-int graph_get_rrdargs (graph_config_t *cfg, graph_instance_t *inst,
-    str_array_t *args);
-
-#endif /* GRAPH_H */
-/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/graph_config.c b/graph_config.c
deleted file mode 100644 (file)
index 94dd440..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <strings.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <errno.h>
-
-#include "graph_config.h"
-#include "graph_list.h"
-#include "oconfig.h"
-#include "common.h"
-
-#define CONFIG_FILE "/usr/lib/cgi-bin/octo/collection.conf"
-
-time_t last_read_mtime = 0;
-
-static int dispatch_config (const oconfig_item_t *ci) /* {{{ */
-{
-  int i;
-
-  for (i = 0; i < ci->children_num; i++)
-  {
-    oconfig_item_t *child;
-
-    child = ci->children + i;
-    if (strcasecmp ("Graph", child->key) == 0)
-      graph_config_add (child);
-    else
-    {
-      DEBUG ("Unknown config option: %s", child->key);
-    }
-  }
-
-  return (0);
-} /* }}} int dispatch_config */
-
-static int internal_read_config (void) /* {{{ */
-{
-  oconfig_item_t *ci;
-
-  ci = oconfig_parse_file (CONFIG_FILE);
-  if (ci == NULL)
-    return (-1);
-
-  dispatch_config (ci);
-
-  oconfig_free (ci);
-
-  gl_config_submit ();
-
-  return (0);
-} /* }}} int internal_read_config */
-
-static time_t get_config_mtime (void) /* {{{ */
-{
-  struct stat statbuf;
-  int status;
-
-  memset (&statbuf, 0, sizeof (statbuf));
-  status = stat (CONFIG_FILE, &statbuf);
-  if (status != 0)
-    return (0);
-
-  return (statbuf.st_mtime);
-} /* }}} time_t get_config_mtime */
-
-int graph_read_config (void) /* {{{ */
-{
-  time_t mtime;
-
-  mtime = get_config_mtime ();
-
-  if (mtime <= last_read_mtime)
-    return (0);
-
-  internal_read_config ();
-
-  last_read_mtime = mtime;
-
-  return (0);
-} /* }}} int graph_read_config */
-
-int graph_config_get_string (const oconfig_item_t *ci, /* {{{ */
-    char **ret_str)
-{
-  char *tmp;
-
-  if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
-    return (EINVAL);
-
-  tmp = strdup (ci->values[0].value.string);
-  if (tmp == NULL)
-    return (ENOMEM);
-
-  free (*ret_str);
-  *ret_str = tmp;
-
-  return (0);
-} /* }}} int graph_config_get_string */
-
-int graph_config_get_bool (const oconfig_item_t *ci, /* {{{ */
-    _Bool *ret_bool)
-{
-  if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_BOOLEAN))
-    return (EINVAL);
-
-  if (ci->values[0].value.boolean)
-    *ret_bool = 1;
-  else
-    *ret_bool = 0;
-
-  return (0);
-} /* }}} int graph_config_get_bool */
-
-/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/graph_config.h b/graph_config.h
deleted file mode 100644 (file)
index c468eec..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef GRAPH_CONFIG_H
-#define GRAPH_CONFIG_H 1
-
-#include "oconfig.h"
-
-int graph_read_config (void);
-
-int graph_config_get_string (const oconfig_item_t *ci, char **ret_str);
-int graph_config_get_bool (const oconfig_item_t *ci, _Bool *ret_bool);
-
-/* vim: set sw=2 sts=2 et fdm=marker : */
-#endif /* GRAPH_CONFIG_H */
diff --git a/graph_def.c b/graph_def.c
deleted file mode 100644 (file)
index b8e0ce4..0000000
+++ /dev/null
@@ -1,348 +0,0 @@
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-
-#include "graph_def.h"
-#include "graph.h"
-#include "graph_config.h"
-#include "common.h"
-#include "oconfig.h"
-
-#include <fcgiapp.h>
-#include <fcgi_stdio.h>
-
-/*
- * Data structures
- */
-struct graph_def_s
-{
-  graph_ident_t *select;
-
-  char *ds_name;
-  char *legend;
-  uint32_t color;
-  _Bool stack;
-  _Bool area;
-  char *format;
-
-  graph_def_t *next;
-};
-
-/*
- * Private functions
- */
-#define DEF_CONFIG_FIELD(field) \
-static int def_config_##field (const oconfig_item_t *ci, graph_ident_t *ident) \
-{                                                                              \
-  char *tmp = NULL;                                                            \
-  int status = graph_config_get_string (ci, &tmp);                             \
-  if (status != 0)                                                             \
-    return (status);                                                           \
-  ident_set_##field (ident, tmp);                                              \
-  free (tmp);                                                                  \
-  return (0);                                                                  \
-} /* }}} int def_config_field */
-
-DEF_CONFIG_FIELD (host);
-DEF_CONFIG_FIELD (plugin);
-DEF_CONFIG_FIELD (plugin_instance);
-DEF_CONFIG_FIELD (type);
-DEF_CONFIG_FIELD (type_instance);
-
-#undef DEF_CONFIG_FIELD
-
-static int def_config_color (const oconfig_item_t *ci, uint32_t *ret_color) /* {{{ */
-{
-  char *tmp;
-  char *endptr;
-  uint32_t color;
-
-  if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
-    return (EINVAL);
-
-  tmp = ci->values[0].value.string;
-
-  endptr = NULL;
-  errno = 0;
-  color = (uint32_t) strtoul (tmp, &endptr, /* base = */ 16);
-  if ((errno != 0) || (endptr == tmp) || (color > 0x00ffffff))
-    return (EINVAL);
-
-  *ret_color = color;
-
-  return (0);
-} /* }}} int def_config_color */
-
-static graph_def_t *def_config_get_obj (graph_config_t *cfg, /* {{{ */
-    const oconfig_item_t *ci)
-{
-  graph_ident_t *ident;
-  char *ds_name = NULL;
-  graph_def_t *def;
-  int i;
-
-  ident = graph_get_selector (cfg);
-  if (ident == NULL)
-  {
-    fprintf (stderr, "def_config_get_obj: graph_get_selector failed");
-    return (NULL);
-  }
-
-  for (i = 0; i < ci->children_num; i++)
-  {
-    oconfig_item_t *child;
-
-#define HANDLE_FIELD(name,field) \
-    else if (strcasecmp (name, child->key) == 0) \
-      def_config_##field (child, ident)
-
-    child = ci->children + i;
-    if (strcasecmp ("DSName", child->key) == 0)
-      graph_config_get_string (child, &ds_name);
-
-    HANDLE_FIELD ("Host", host);
-    HANDLE_FIELD ("Plugin", plugin);
-    HANDLE_FIELD ("PluginInstance", plugin_instance);
-    HANDLE_FIELD ("Type", type);
-    HANDLE_FIELD ("TypeInstance", type_instance);
-
-#undef HANDLE_FIELD
-  }
-
-  def = def_create (cfg, ident, ds_name);
-  if (def == NULL)
-  {
-    fprintf (stderr, "def_config_get_obj: def_create failed\n");
-    ident_destroy (ident);
-    free (ds_name);
-    return (NULL);
-  }
-
-  ident_destroy (ident);
-  free (ds_name);
-
-  return (def);
-} /* }}} graph_def_t *def_config_get_obj */
-
-/*
- * Public functions
- */
-graph_def_t *def_create (graph_config_t *cfg, graph_ident_t *ident, /* {{{ */
-    const char *ds_name)
-{
-  graph_ident_t *selector;
-  graph_def_t *ret;
-
-  if ((cfg == NULL) || (ident == NULL) || (ds_name == NULL))
-    return (NULL);
-
-  selector = graph_get_selector (cfg);
-  if (selector == NULL)
-    return (NULL);
-
-  ret = malloc (sizeof (*ret));
-  if (ret == NULL)
-  {
-    ident_destroy (selector);
-    return (NULL);
-  }
-  memset (ret, 0, sizeof (*ret));
-  ret->legend = NULL;
-  ret->format = NULL;
-
-  ret->ds_name = strdup (ds_name);
-  if (ret->ds_name == NULL)
-  {
-    ident_destroy (selector);
-    free (ret);
-    return (NULL);
-  }
-
-  ret->color = get_random_color ();
-  ret->next = NULL;
-
-  ret->select = ident_copy_with_selector (selector, ident,
-      IDENT_FLAG_REPLACE_ALL);
-  if (ret->select == NULL)
-  {
-    ident_destroy (selector);
-    free (ret->ds_name);
-    free (ret);
-    return (NULL);
-  }
-
-  ident_destroy (selector);
-  return (ret);
-} /* }}} graph_def_t *def_create */
-
-void def_destroy (graph_def_t *def) /* {{{ */
-{
-  graph_def_t *next;
-
-  if (def == NULL)
-    return;
-
-  next = def->next;
-
-  ident_destroy (def->select);
-
-  free (def->ds_name);
-  free (def->legend);
-  free (def->format);
-
-  free (def);
-
-  def_destroy (next);
-} /* }}} void def_destroy */
-
-int def_config (graph_config_t *cfg, const oconfig_item_t *ci) /* {{{ */
-{
-  graph_def_t *def;
-  int i;
-
-  def = def_config_get_obj (cfg, ci);
-  if (def == NULL)
-    return (EINVAL);
-
-  for (i = 0; i < ci->children_num; i++)
-  {
-    oconfig_item_t *child;
-
-    child = ci->children + i;
-    if (strcasecmp ("Legend", child->key) == 0)
-      graph_config_get_string (child, &def->legend);
-    else if (strcasecmp ("Color", child->key) == 0)
-      def_config_color (child, &def->color);
-    else if (strcasecmp ("Stack", child->key) == 0)
-      graph_config_get_bool (child, &def->stack);
-    else if (strcasecmp ("Area", child->key) == 0)
-      graph_config_get_bool (child, &def->area);
-    else if (strcasecmp ("Format", child->key) == 0)
-      graph_config_get_string (child, &def->format);
-    else
-      fprintf (stderr, "def_config: Ignoring unknown config option \"%s\"",
-          child->key);
-  }
-
-  return (graph_add_def (cfg, def));
-} /* }}} int def_config */
-
-int def_append (graph_def_t *head, graph_def_t *def) /* {{{ */
-{
-  graph_def_t *ptr;
-
-  if ((head == NULL) || (def == NULL))
-    return (EINVAL);
-
-  ptr = head;
-  while (ptr->next != NULL)
-    ptr = ptr->next;
-
-  ptr->next = def;
-
-  return (0);
-} /* }}} int def_append */
-
-graph_def_t *def_search (graph_def_t *head, graph_ident_t *ident, /* {{{ */
-    const char *ds_name)
-{
-  graph_def_t *ptr;
-
-  if ((head == NULL) || (ident == NULL) || (ds_name == NULL))
-    return (NULL);
-
-  for (ptr = head; ptr != NULL; ptr = ptr->next)
-  {
-    if (!ident_matches (ptr->select, ident))
-      continue;
-
-    if (strcmp (ptr->ds_name, ds_name) == 0)
-      return (ptr);
-  }
-
-  return (NULL);
-} /* }}} graph_def_t *def_search */
-
-_Bool def_matches (graph_def_t *def, graph_ident_t *ident) /* {{{ */
-{
-  return (ident_matches (def->select, ident));
-} /* }}} _Bool def_matches */
-
-int def_foreach (graph_def_t *def, def_callback_t callback, /* {{{ */
-    void *user_data)
-{
-  graph_def_t *ptr;
-
-  if ((def == NULL) || (callback == NULL))
-    return (EINVAL);
-
-  for (ptr = def; ptr != NULL; ptr = ptr->next)
-  {
-    int status;
-
-    status = (*callback) (ptr, user_data);
-    if (status != 0)
-      return (status);
-  }
-
-  return (0);
-} /* }}} int def_foreach */
-
-int def_get_rrdargs (graph_def_t *def, graph_ident_t *ident, /* {{{ */
-    str_array_t *args)
-{
-  char *file;
-  int index;
-
-  if ((def == NULL) || (ident == NULL) || (args == NULL))
-    return (EINVAL);
-
-  file = ident_to_file (ident);
-  if (file == NULL)
-  {
-    DEBUG ("gl_ident_get_rrdargs: ident_to_file returned NULL.\n");
-    return (-1);
-  }
-
-  DEBUG ("gl_ident_get_rrdargs: file = %s;\n", file);
-
-  index = array_argc (args);
-
-  /* CDEFs */
-  array_append_format (args, "DEF:def_%04i_min=%s:%s:MIN",
-      index, file, def->ds_name);
-  array_append_format (args, "DEF:def_%04i_avg=%s:%s:AVERAGE",
-      index, file, def->ds_name);
-  array_append_format (args, "DEF:def_%04i_max=%s:%s:MAX",
-      index, file, def->ds_name);
-  /* VDEFs */
-  array_append_format (args, "VDEF:vdef_%04i_min=def_%04i_min,MINIMUM",
-      index, index);
-  array_append_format (args, "VDEF:vdef_%04i_avg=def_%04i_avg,AVERAGE",
-      index, index);
-  array_append_format (args, "VDEF:vdef_%04i_max=def_%04i_max,MAXIMUM",
-      index, index);
-  array_append_format (args, "VDEF:vdef_%04i_lst=def_%04i_avg,LAST",
-      index, index);
-
-  /* Graph part */
-  array_append_format (args, "%s:def_%04i_avg#%06"PRIx32":%s%s",
-      def->area ? "AREA" : "LINE1",
-      index, def->color,
-      (def->legend != NULL) ? def->legend : def->ds_name,
-      def->stack ? ":STACK" : "");
-  array_append_format (args, "GPRINT:vdef_%04i_min:%s min,",
-      index, (def->format != NULL) ? def->format : "%lg");
-  array_append_format (args, "GPRINT:vdef_%04i_avg:%s avg,",
-      index, (def->format != NULL) ? def->format : "%lg");
-  array_append_format (args, "GPRINT:vdef_%04i_max:%s max,",
-      index, (def->format != NULL) ? def->format : "%lg");
-  array_append_format (args, "GPRINT:vdef_%04i_lst:%s last\\l",
-      index, (def->format != NULL) ? def->format : "%lg");
-
-  free (file);
-
-  return (0);
-} /* }}} int def_get_rrdargs */
-
-/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/graph_def.h b/graph_def.h
deleted file mode 100644 (file)
index b2cd228..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-#ifndef GRAPH_DEF_H
-#define GRAPH_DEF_H 1
-
-struct graph_def_s;
-typedef struct graph_def_s graph_def_t;
-
-typedef int (*def_callback_t) (graph_def_t *def,
-    void *user_data);
-
-#include "graph.h"
-#include "graph_ident.h"
-#include "utils_array.h"
-#include "oconfig.h"
-
-graph_def_t *def_create (graph_config_t *cfg, graph_ident_t *ident,
-    const char *ds_name);
-
-void def_destroy (graph_def_t *def);
-
-int def_config (graph_config_t *cfg, const oconfig_item_t *ci);
-
-int def_append (graph_def_t *head, graph_def_t *def);
-
-graph_def_t *def_search (graph_def_t *head, graph_ident_t *ident,
-    const char *ds_name);
-
-_Bool def_matches (graph_def_t *def, graph_ident_t *ident);
-
-int def_foreach (graph_def_t *def, def_callback_t callback, void *user_data);
-
-int def_get_rrdargs (graph_def_t *def, graph_ident_t *ident,
-    str_array_t *args);
-
-/* vim: set sw=2 sts=2 et fdm=marker : */
-#endif
diff --git a/graph_ident.c b/graph_ident.c
deleted file mode 100644 (file)
index b008a56..0000000
+++ /dev/null
@@ -1,455 +0,0 @@
-#include <stdlib.h>
-#include <string.h>
-#include <strings.h>
-#include <errno.h>
-#include <limits.h> /* PATH_MAX */
-
-#include "graph_ident.h"
-#include "common.h"
-#include "filesystem.h"
-
-/*
- * Data types
- */
-struct graph_ident_s /* {{{ */
-{
-  char *host;
-  char *plugin;
-  char *plugin_instance;
-  char *type;
-  char *type_instance;
-}; /* }}} struct graph_ident_s */
-
-/*
- * Private functions
- */
-static char *part_copy_with_selector (const char *selector, /* {{{ */
-    const char *part, unsigned int flags)
-{
-  if ((selector == NULL) || (part == NULL))
-    return (NULL);
-
-  if ((flags & IDENT_FLAG_REPLACE_ANY) && IS_ANY (part))
-    return (NULL);
-
-  if ((flags & IDENT_FLAG_REPLACE_ALL) && IS_ALL (part))
-    return (NULL);
-
-  /* Replace the ANY and ALL flags if requested and if the selecter actually
-   * *is* that flag. */
-  if (IS_ANY (selector))
-  {
-    if (flags & IDENT_FLAG_REPLACE_ANY)
-      return (strdup (part));
-    else
-      return (strdup (selector));
-  }
-
-  if (IS_ALL (selector))
-  {
-    if (flags & IDENT_FLAG_REPLACE_ALL)
-      return (strdup (part));
-    else
-      return (strdup (selector));
-  }
-
-  if (strcmp (selector, part) != 0)
-    return (NULL);
-
-  /* Otherwise (no replacement), return a copy of the selector. */
-  return (strdup (selector));
-} /* }}} char *part_copy_with_selector */
-
-static _Bool part_matches (const char *selector, /* {{{ */
-    const char *part)
-{
-  if ((selector == NULL) && (part == NULL))
-    return (1);
-
-  if (selector == NULL) /* && (part != NULL) */
-    return (0);
-
-  if (IS_ANY(selector) || IS_ALL(selector))
-    return (1);
-
-  if (part == NULL) /* && (selector != NULL) */
-    return (0);
-
-  if (strcmp (selector, part) == 0)
-    return (1);
-
-  return (0);
-} /* }}} _Bool part_matches */
-
-/*
- * Public functions
- */
-graph_ident_t *ident_create (const char *host, /* {{{ */
-    const char *plugin, const char *plugin_instance,
-    const char *type, const char *type_instance)
-{
-  graph_ident_t *ret;
-
-  if ((host == NULL)
-      || (plugin == NULL) || (plugin_instance == NULL)
-      || (type == NULL) || (type_instance == NULL))
-    return (NULL);
-
-  ret = malloc (sizeof (*ret));
-  if (ret == NULL)
-    return (NULL);
-  memset (ret, 0, sizeof (*ret));
-
-  ret->host = NULL;
-  ret->host = NULL;
-  ret->plugin = NULL;
-  ret->plugin_instance = NULL;
-  ret->type = NULL;
-  ret->type_instance = NULL;
-
-#define COPY_PART(p) do {        \
-  ret->p = strdup (p);           \
-  if (ret->p == NULL)            \
-  {                              \
-    free (ret->host);            \
-    free (ret->plugin);          \
-    free (ret->plugin_instance); \
-    free (ret->type);            \
-    free (ret->type_instance);   \
-    free (ret);                  \
-    return (NULL);               \
-  }                              \
-} while (0)
-
-  COPY_PART(host);
-  COPY_PART(plugin);
-  COPY_PART(plugin_instance);
-  COPY_PART(type);
-  COPY_PART(type_instance);
-
-#undef COPY_PART
-
-  return (ret);
-} /* }}} graph_ident_t *ident_create */
-
-graph_ident_t *ident_clone (const graph_ident_t *ident) /* {{{ */
-{
-  return (ident_create (ident->host,
-        ident->plugin, ident->plugin_instance,
-        ident->type, ident->type_instance));
-} /* }}} graph_ident_t *ident_clone */
-
-graph_ident_t *ident_copy_with_selector (const graph_ident_t *selector, /* {{{ */
-    const graph_ident_t *ident, unsigned int flags)
-{
-  graph_ident_t *ret;
-
-  if ((selector == NULL) || (ident == NULL))
-    return (NULL);
-
-  ret = malloc (sizeof (*ret));
-  if (ret == NULL)
-    return (NULL);
-  memset (ret, 0, sizeof (*ret));
-  ret->host = NULL;
-  ret->plugin = NULL;
-  ret->plugin_instance = NULL;
-  ret->type = NULL;
-  ret->type_instance = NULL;
-
-#define COPY_PART(p) do {                                  \
-  ret->p = part_copy_with_selector (selector->p, ident->p, flags); \
-  if (ret->p == NULL)                                      \
-  {                                                        \
-    free (ret->host);                                      \
-    free (ret->plugin);                                    \
-    free (ret->plugin_instance);                           \
-    free (ret->type);                                      \
-    free (ret->type_instance);                             \
-    return (NULL);                                         \
-  }                                                        \
-} while (0)
-
-  COPY_PART (host);
-  COPY_PART (plugin);
-  COPY_PART (plugin_instance);
-  COPY_PART (type);
-  COPY_PART (type_instance);
-
-#undef COPY_PART
-
-  return (ret);
-} /* }}} graph_ident_t *ident_copy_with_selector */
-
-void ident_destroy (graph_ident_t *ident) /* {{{ */
-{
-  if (ident == NULL)
-    return;
-
-  free (ident->host);
-  free (ident->plugin);
-  free (ident->plugin_instance);
-  free (ident->type);
-  free (ident->type_instance);
-
-  free (ident);
-} /* }}} void ident_destroy */
-
-/* ident_get_* methods {{{ */
-const char *ident_get_host (graph_ident_t *ident) /* {{{ */
-{
-  if (ident == NULL)
-    return (NULL);
-
-  return (ident->host);
-} /* }}} char *ident_get_host */
-
-const char *ident_get_plugin (graph_ident_t *ident) /* {{{ */
-{
-  if (ident == NULL)
-    return (NULL);
-
-  return (ident->plugin);
-} /* }}} char *ident_get_plugin */
-
-const char *ident_get_plugin_instance (graph_ident_t *ident) /* {{{ */
-{
-  if (ident == NULL)
-    return (NULL);
-
-  return (ident->plugin_instance);
-} /* }}} char *ident_get_plugin_instance */
-
-const char *ident_get_type (graph_ident_t *ident) /* {{{ */
-{
-  if (ident == NULL)
-    return (NULL);
-
-  return (ident->type);
-} /* }}} char *ident_get_type */
-
-const char *ident_get_type_instance (graph_ident_t *ident) /* {{{ */
-{
-  if (ident == NULL)
-    return (NULL);
-
-  return (ident->type_instance);
-} /* }}} char *ident_get_type_instance */
-/* }}} ident_get_* methods */
-
-/* ident_set_* methods {{{ */
-int ident_set_host (graph_ident_t *ident, const char *host) /* {{{ */
-{
-  char *tmp;
-
-  if ((ident == NULL) || (host == NULL))
-    return (EINVAL);
-
-  tmp = strdup (host);
-  if (tmp == NULL)
-    return (ENOMEM);
-
-  free (ident->host);
-  ident->host = tmp;
-
-  return (0);
-} /* }}} int ident_set_host */
-
-int ident_set_plugin (graph_ident_t *ident, const char *plugin) /* {{{ */
-{
-  char *tmp;
-
-  if ((ident == NULL) || (plugin == NULL))
-    return (EINVAL);
-
-  tmp = strdup (plugin);
-  if (tmp == NULL)
-    return (ENOMEM);
-
-  free (ident->plugin);
-  ident->plugin = tmp;
-
-  return (0);
-} /* }}} int ident_set_plugin */
-
-int ident_set_plugin_instance (graph_ident_t *ident, const char *plugin_instance) /* {{{ */
-{
-  char *tmp;
-
-  if ((ident == NULL) || (plugin_instance == NULL))
-    return (EINVAL);
-
-  tmp = strdup (plugin_instance);
-  if (tmp == NULL)
-    return (ENOMEM);
-
-  free (ident->plugin_instance);
-  ident->plugin_instance = tmp;
-
-  return (0);
-} /* }}} int ident_set_plugin_instance */
-
-int ident_set_type (graph_ident_t *ident, const char *type) /* {{{ */
-{
-  char *tmp;
-
-  if ((ident == NULL) || (type == NULL))
-    return (EINVAL);
-
-  tmp = strdup (type);
-  if (tmp == NULL)
-    return (ENOMEM);
-
-  free (ident->type);
-  ident->type = tmp;
-
-  return (0);
-} /* }}} int ident_set_type */
-
-int ident_set_type_instance (graph_ident_t *ident, const char *type_instance) /* {{{ */
-{
-  char *tmp;
-
-  if ((ident == NULL) || (type_instance == NULL))
-    return (EINVAL);
-
-  tmp = strdup (type_instance);
-  if (tmp == NULL)
-    return (ENOMEM);
-
-  free (ident->type_instance);
-  ident->type_instance = tmp;
-
-  return (0);
-} /* }}} int ident_set_type_instance */
-
-/* }}} ident_set_* methods */
-
-int ident_compare (const graph_ident_t *i0, /* {{{ */
-    const graph_ident_t *i1)
-{
-  int status;
-
-#define COMPARE_PART(p) do {       \
-  status = strcmp (i0->p, i1->p);  \
-  if (status != 0)                 \
-    return (status);               \
-} while (0)
-
-  COMPARE_PART (host);
-  COMPARE_PART (plugin);
-  COMPARE_PART (plugin_instance);
-  COMPARE_PART (type);
-  COMPARE_PART (type_instance);
-
-#undef COMPARE_PART
-
-  return (0);
-} /* }}} int ident_compare */
-
-_Bool ident_matches (const graph_ident_t *selector, /* {{{ */
-    const graph_ident_t *ident)
-{
-  if ((selector == NULL) && (ident == NULL))
-    return (0);
-  else if (selector == NULL)
-    return (-1);
-  else if (ident == NULL)
-    return (1);
-
-  if (!part_matches (selector->host, ident->host))
-    return (0);
-
-  if (!part_matches (selector->plugin, ident->plugin))
-    return (0);
-
-  if (!part_matches (selector->plugin_instance, ident->plugin_instance))
-    return (0);
-
-  if (!part_matches (selector->type, ident->type))
-    return (0);
-
-  if (!part_matches (selector->type_instance, ident->type_instance))
-    return (0);
-
-  return (1);
-} /* }}} _Bool ident_matches */
-
-char *ident_to_string (const graph_ident_t *ident) /* {{{ */
-{
-  char buffer[PATH_MAX];
-
-  buffer[0] = 0;
-
-  strlcat (buffer, ident->host, sizeof (buffer));
-  strlcat (buffer, "/", sizeof (buffer));
-  strlcat (buffer, ident->plugin, sizeof (buffer));
-  if (ident->plugin_instance[0] != 0)
-  {
-    strlcat (buffer, "-", sizeof (buffer));
-    strlcat (buffer, ident->plugin_instance, sizeof (buffer));
-  }
-  strlcat (buffer, "/", sizeof (buffer));
-  strlcat (buffer, ident->type, sizeof (buffer));
-  if (ident->type_instance[0] != 0)
-  {
-    strlcat (buffer, "-", sizeof (buffer));
-    strlcat (buffer, ident->type_instance, sizeof (buffer));
-  }
-
-  return (strdup (buffer));
-} /* }}} char *ident_to_string */
-
-char *ident_to_file (const graph_ident_t *ident) /* {{{ */
-{
-  char buffer[PATH_MAX];
-
-  buffer[0] = 0;
-
-  strlcat (buffer, DATA_DIR, sizeof (buffer));
-  strlcat (buffer, "/", sizeof (buffer));
-
-  strlcat (buffer, ident->host, sizeof (buffer));
-  strlcat (buffer, "/", sizeof (buffer));
-  strlcat (buffer, ident->plugin, sizeof (buffer));
-  if (ident->plugin_instance[0] != 0)
-  {
-    strlcat (buffer, "-", sizeof (buffer));
-    strlcat (buffer, ident->plugin_instance, sizeof (buffer));
-  }
-  strlcat (buffer, "/", sizeof (buffer));
-  strlcat (buffer, ident->type, sizeof (buffer));
-  if (ident->type_instance[0] != 0)
-  {
-    strlcat (buffer, "-", sizeof (buffer));
-    strlcat (buffer, ident->type_instance, sizeof (buffer));
-  }
-
-  strlcat (buffer, ".rrd", sizeof (buffer));
-
-  return (strdup (buffer));
-} /* }}} char *ident_to_file */
-
-char *ident_to_json (const graph_ident_t *ident) /* {{{ */
-{
-  char buffer[4096];
-
-  buffer[0] = 0;
-
-  strlcat (buffer, "{\"host\":\"", sizeof (buffer));
-  strlcat (buffer, ident->host, sizeof (buffer));
-  strlcat (buffer, "\",\"plugin\":\"", sizeof (buffer));
-  strlcat (buffer, ident->plugin, sizeof (buffer));
-  strlcat (buffer, "\",\"plugin_instance\":\"", sizeof (buffer));
-  strlcat (buffer, ident->plugin_instance, sizeof (buffer));
-  strlcat (buffer, "\",\"type\":\"", sizeof (buffer));
-  strlcat (buffer, ident->type, sizeof (buffer));
-  strlcat (buffer, "\",\"type_instance\":\"", sizeof (buffer));
-  strlcat (buffer, ident->type_instance, sizeof (buffer));
-  strlcat (buffer, "\"}", sizeof (buffer));
-
-  return (strdup (buffer));
-} /* }}} char *ident_to_json */
-
-/* vim: set sw=2 sts=2 et fdm=marker : */
-
diff --git a/graph_ident.h b/graph_ident.h
deleted file mode 100644 (file)
index 5107011..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-#ifndef GRAPH_IDENT_H
-#define GRAPH_IDENT_H 1
-
-#define ANY_TOKEN "/any/"
-#define ALL_TOKEN "/all/"
-
-#define IS_ANY(str) (((str) != NULL) && (strcasecmp (ANY_TOKEN, (str)) == 0))
-#define IS_ALL(str) (((str) != NULL) && (strcasecmp (ALL_TOKEN, (str)) == 0))
-
-struct graph_ident_s;
-typedef struct graph_ident_s graph_ident_t;
-
-graph_ident_t *ident_create (const char *host,
-    const char *plugin, const char *plugin_instance,
-    const char *type, const char *type_instance);
-graph_ident_t *ident_clone (const graph_ident_t *ident);
-
-#define IDENT_FLAG_REPLACE_ALL 0x01
-#define IDENT_FLAG_REPLACE_ANY 0x02
-graph_ident_t *ident_copy_with_selector (const graph_ident_t *selector,
-    const graph_ident_t *ident, unsigned int flags);
-
-void ident_destroy (graph_ident_t *ident);
-
-const char *ident_get_host (graph_ident_t *ident);
-const char *ident_get_plugin (graph_ident_t *ident);
-const char *ident_get_plugin_instance (graph_ident_t *ident);
-const char *ident_get_type (graph_ident_t *ident);
-const char *ident_get_type_instance (graph_ident_t *ident);
-
-int ident_set_host (graph_ident_t *ident, const char *host);
-int ident_set_plugin (graph_ident_t *ident, const char *plugin);
-int ident_set_plugin_instance (graph_ident_t *ident,
-    const char *plugin_instance);
-int ident_set_type (graph_ident_t *ident, const char *type);
-int ident_set_type_instance (graph_ident_t *ident,
-    const char *type_instance);
-
-int ident_compare (const graph_ident_t *i0,
-    const graph_ident_t *i1);
-
-_Bool ident_matches (const graph_ident_t *selector,
-               const graph_ident_t *ident);
-
-char *ident_to_string (const graph_ident_t *ident);
-char *ident_to_file (const graph_ident_t *ident);
-char *ident_to_json (const graph_ident_t *ident);
-
-/* vim: set sw=2 sts=2 et fdm=marker : */
-#endif /* GRAPH_IDENT_H */
diff --git a/graph_instance.c b/graph_instance.c
deleted file mode 100644 (file)
index 103be23..0000000
+++ /dev/null
@@ -1,475 +0,0 @@
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-
-#include "graph_instance.h"
-#include "graph_ident.h"
-#include "graph_list.h"
-#include "common.h"
-#include "utils_params.h"
-
-#include <fcgiapp.h>
-#include <fcgi_stdio.h>
-
-struct graph_instance_s /* {{{ */
-{
-  graph_ident_t *select;
-
-  graph_ident_t **files;
-  size_t files_num;
-
-  graph_instance_t *next;
-}; /* }}} struct graph_instance_s */
-
-struct def_callback_data_s
-{
-  graph_instance_t *inst;
-  str_array_t *args;
-};
-typedef struct def_callback_data_s def_callback_data_t;
-
-/*
- * Private functions
- */
-/* Create one DEF for each data source in the file. Called by
- * "inst_get_default_defs" for each file. */
-static graph_def_t *ident_get_default_defs (graph_config_t *cfg, /* {{{ */
-    graph_ident_t *ident, graph_def_t *def_head)
-{
-  graph_def_t *defs = NULL;
-  char *file;
-  char **dses = NULL;
-  size_t dses_num = 0;
-  int status;
-  size_t i;
-
-  if ((cfg == NULL) || (ident == NULL))
-    return (def_head);
-
-  file = ident_to_file (ident);
-  if (file == NULL)
-  {
-    fprintf (stderr, "ident_get_default_defs: ident_to_file failed\n");
-    return (def_head);
-  }
-
-  status = ds_list_from_rrd_file (file, &dses_num, &dses);
-  if (status != 0)
-  {
-    free (file);
-    return (def_head);
-  }
-
-  for (i = 0; i < dses_num; i++)
-  {
-    graph_def_t *def;
-
-    def = def_search (def_head, ident, dses[i]);
-    if (def != NULL)
-      continue;
-
-    def = def_create (cfg, ident, dses[i]);
-    if (def == NULL)
-      continue;
-
-    if (defs == NULL)
-      defs = def;
-    else
-      def_append (defs, def);
-
-    free (dses[i]);
-  }
-
-  free (dses);
-  free (file);
-
-  return (defs);
-} /* }}} int ident_get_default_defs */
-
-/* Create one or more DEFs for each file in the graph instance. The number
- * depends on the number of data sources in each of the files. Called from
- * "inst_get_rrdargs" if no DEFs are available from the configuration.
- * */
-static graph_def_t *inst_get_default_defs (graph_config_t *cfg, /* {{{ */
-    graph_instance_t *inst)
-{
-  graph_def_t *defs = NULL;
-  size_t i;
-
-  if ((cfg == NULL) || (inst == NULL))
-    return (NULL);
-
-  for (i = 0; i < inst->files_num; i++)
-  {
-    graph_def_t *def;
-
-    def = ident_get_default_defs (cfg, inst->files[i], defs);
-    if (def == NULL)
-      continue;
-
-    if (defs == NULL)
-      defs = def;
-    else
-      def_append (defs, def);
-  }
-
-  return (defs);
-} /* }}} graph_def_t *inst_get_default_defs */
-
-/* Called with each DEF in turn. Calls "def_get_rrdargs" with every appropriate
- * file / DEF pair. */
-static int gl_instance_get_rrdargs_cb (graph_def_t *def, void *user_data) /* {{{ */
-{
-  def_callback_data_t *data = user_data;
-  graph_instance_t *inst = data->inst;
-  str_array_t *args = data->args;
-
-  size_t i;
-
-  for (i = 0; i < inst->files_num; i++)
-  {
-    if (!def_matches (def, inst->files[i]))
-      continue;
-
-    def_get_rrdargs (def, inst->files[i], args);
-  }
-
-  return (0);
-} /* }}} int gl_instance_get_rrdargs_cb */
-
-static const char *get_part_from_param (const char *prim_key, /* {{{ */
-    const char *sec_key)
-{
-  const char *val;
-
-  val = param (prim_key);
-  if (val != NULL)
-    return (val);
-  
-  return (param (sec_key));
-} /* }}} const char *get_part_from_param */
-
-/*
- * Public functions
- */
-graph_instance_t *inst_create (graph_config_t *cfg, /* {{{ */
-    const graph_ident_t *ident)
-{
-  graph_instance_t *i;
-  graph_ident_t *selector;
-
-  if ((cfg == NULL) || (ident == NULL))
-    return (NULL);
-
-  i = malloc (sizeof (*i));
-  if (i == NULL)
-    return (NULL);
-  memset (i, 0, sizeof (*i));
-
-  selector = graph_get_selector (cfg);
-  if (selector == NULL)
-  {
-    fprintf (stderr, "inst_create: graph_get_selector failed\n");
-    free (i);
-    return (NULL);
-  }
-
-  i->select = ident_copy_with_selector (selector, ident,
-      IDENT_FLAG_REPLACE_ANY);
-  if (i->select == NULL)
-  {
-    fprintf (stderr, "inst_create: ident_copy_with_selector failed\n");
-    ident_destroy (selector);
-    free (i);
-    return (NULL);
-  }
-
-  ident_destroy (selector);
-
-  i->files = NULL;
-  i->files_num = 0;
-
-  i->next = NULL;
-
-  return (i);
-} /* }}} graph_instance_t *inst_create */
-
-void inst_destroy (graph_instance_t *inst) /* {{{ */
-{
-  graph_instance_t *next;
-  size_t i;
-
-  if (inst == NULL)
-    return;
-
-  next = inst->next;
-
-  ident_destroy (inst->select);
-
-  for (i = 0; i < inst->files_num; i++)
-    ident_destroy (inst->files[i]);
-  free (inst->files);
-
-  free (inst);
-
-  inst_destroy (next);
-} /* }}} void inst_destroy */
-
-int inst_add_file (graph_instance_t *inst, /* {{{ */
-    const graph_ident_t *file)
-{
-  graph_ident_t **tmp;
-
-  tmp = realloc (inst->files, sizeof (*inst->files) * (inst->files_num + 1));
-  if (tmp == NULL)
-    return (ENOMEM);
-  inst->files = tmp;
-
-  inst->files[inst->files_num] = ident_clone (file);
-  if (inst->files[inst->files_num] == NULL)
-    return (ENOMEM);
-
-  inst->files_num++;
-
-  return (0);
-} /* }}} int inst_add_file */
-
-graph_instance_t *inst_get_selected (graph_config_t *cfg) /* {{{ */
-{
-  const char *host = get_part_from_param ("inst_host", "host");
-  const char *plugin = get_part_from_param ("inst_plugin", "plugin");
-  const char *plugin_instance = get_part_from_param ("inst_plugin_instance", "plugin_instance");
-  const char *type = get_part_from_param ("inst_type", "type");
-  const char *type_instance = get_part_from_param ("inst_type_instance", "type_instance");
-  graph_ident_t *ident;
-  graph_instance_t *inst;
-
-  if (cfg == NULL)
-    cfg = gl_graph_get_selected ();
-
-  if (cfg == NULL)
-  {
-    DEBUG ("inst_get_selected: cfg == NULL;\n");
-    return (NULL);
-  }
-
-  if ((host == NULL)
-      || (plugin == NULL) || (plugin_instance == NULL)
-      || (type == NULL) || (type_instance == NULL))
-  {
-    DEBUG ("inst_get_selected: A parameter is NULL.\n");
-    return (NULL);
-  }
-
-  ident = ident_create (host, plugin, plugin_instance, type, type_instance);
-
-  for (inst = graph_get_instances (cfg); inst != NULL; inst = inst->next)
-  {
-    if (ident_compare (ident, inst->select) != 0)
-      continue;
-
-    ident_destroy (ident);
-    return (inst);
-  }
-
-  DEBUG ("inst_get_selected: No match found.\n");
-  ident_destroy (ident);
-  return (NULL);
-} /* }}} graph_instance_t *inst_get_selected */
-
-int inst_get_rrdargs (graph_config_t *cfg, /* {{{ */
-    graph_instance_t *inst,
-    str_array_t *args)
-{
-  def_callback_data_t data = { inst, args };
-  graph_def_t *defs;
-  int status;
-
-  if ((cfg == NULL) || (inst == NULL) || (args == NULL))
-    return (EINVAL);
-
-  status = graph_get_rrdargs (cfg, inst, args);
-  if (status != 0)
-    return (status);
-
-  defs = graph_get_defs (cfg);
-  if (defs == NULL)
-  {
-    defs = inst_get_default_defs (cfg, inst);
-
-    if (defs == NULL)
-      return (-1);
-
-    status = def_foreach (defs, gl_instance_get_rrdargs_cb, &data);
-
-    def_destroy (defs);
-  }
-  else
-  {
-    status = def_foreach (defs, gl_instance_get_rrdargs_cb, &data);
-  }
-
-  return (status);
-} /* }}} int inst_get_rrdargs */
-
-graph_ident_t *inst_get_selector (graph_instance_t *inst) /* {{{ */
-{
-  if (inst == NULL)
-    return (NULL);
-
-  return (ident_clone (inst->select));
-} /* }}} graph_ident_t *inst_get_selector */
-
-int inst_get_params (graph_config_t *cfg, graph_instance_t *inst, /* {{{ */
-    char *buffer, size_t buffer_size)
-{
-  graph_ident_t *cfg_select;
-
-  if ((cfg == NULL) || (inst == NULL)
-      || (buffer == NULL) || (buffer_size < 1))
-    return (EINVAL);
-
-  cfg_select = graph_get_selector (cfg);
-  if (cfg_select == NULL)
-  {
-    fprintf (stderr, "inst_get_params: graph_get_selector failed");
-    return (-1);
-  }
-
-  buffer[0] = 0;
-
-#define COPY_FIELD(field) do {                                  \
-  const char *cfg_f  = ident_get_##field (cfg_select);          \
-  const char *inst_f = ident_get_##field (inst->select);        \
-  if (strcmp (cfg_f, inst_f) == 0)                              \
-  {                                                             \
-    strlcat (buffer, #field, buffer_size);                      \
-    strlcat (buffer, "=", buffer_size);                         \
-    strlcat (buffer, cfg_f, buffer_size);                       \
-  }                                                             \
-  else                                                          \
-  {                                                             \
-    strlcat (buffer, "graph_", buffer_size);                    \
-    strlcat (buffer, #field, buffer_size);                      \
-    strlcat (buffer, "=", buffer_size);                         \
-    strlcat (buffer, cfg_f, buffer_size);                       \
-    strlcat (buffer, ";", buffer_size);                         \
-    strlcat (buffer, "inst_", buffer_size);                     \
-    strlcat (buffer, #field, buffer_size);                      \
-    strlcat (buffer, "=", buffer_size);                         \
-    strlcat (buffer, inst_f, buffer_size);                      \
-  }                                                             \
-} while (0)
-
-  COPY_FIELD(host);
-  strlcat (buffer, ";", buffer_size);
-  COPY_FIELD(plugin);
-  strlcat (buffer, ";", buffer_size);
-  COPY_FIELD(plugin_instance);
-  strlcat (buffer, ";", buffer_size);
-  COPY_FIELD(type);
-  strlcat (buffer, ";", buffer_size);
-  COPY_FIELD(type_instance);
-
-#undef COPY_FIELD
-
-  ident_destroy (cfg_select);
-
-  return (0);
-} /* }}} int inst_get_params */
-
-int inst_append (graph_instance_t *head, graph_instance_t *inst) /* {{{ */
-{
-  graph_instance_t *ptr;
-
-  if ((head == NULL) || (inst == NULL))
-    return (EINVAL);
-
-  ptr = head;
-  while (ptr->next != NULL)
-    ptr = ptr->next;
-
-  ptr->next = inst;
-
-  return (0);
-} /* }}} int inst_append */
-
-int inst_foreach (graph_instance_t *inst, /* {{{ */
-               inst_callback_t cb, void *user_data)
-{
-  graph_instance_t *ptr;
-
-  if ((inst == NULL) || (cb == NULL))
-    return (EINVAL);
-
-  for (ptr = inst; ptr != NULL; ptr = ptr->next)
-  {
-    int status;
-
-    status = (*cb) (ptr, user_data);
-    if (status != 0)
-      return (status);
-  }
-
-  return (0);
-} /* }}} int inst_foreach */
-
-graph_instance_t *inst_find_matching (graph_instance_t *inst, /* {{{ */
-    const graph_ident_t *ident)
-{
-  graph_instance_t *ptr;
-
-  if ((inst == NULL) || (ident == NULL))
-    return (NULL);
-
-  for (ptr = inst; ptr != NULL; ptr = ptr->next)
-    if (ident_matches (ptr->select, ident))
-      return (ptr);
-
-  return (NULL);
-} /* }}} graph_instance_t *inst_find_matching */
-
-int inst_describe (graph_config_t *cfg, graph_instance_t *inst, /* {{{ */
-    char *buffer, size_t buffer_size)
-{
-  graph_ident_t *cfg_select;
-
-  if ((cfg == NULL) || (inst == NULL)
-      || (buffer == NULL) || (buffer_size < 2))
-    return (EINVAL);
-
-  cfg_select = graph_get_selector (cfg);
-  if (cfg_select == NULL)
-  {
-    fprintf (stderr, "inst_describe: graph_get_selector failed\n");
-    return (-1);
-  }
-
-  buffer[0] = 0;
-
-#define CHECK_FIELD(field) do {                                              \
-  if (IS_ANY (ident_get_##field (cfg_select)))                               \
-  {                                                                          \
-    if (buffer[0] != 0)                                                      \
-      strlcat (buffer, "/", buffer_size);                                    \
-    strlcat (buffer, ident_get_##field (inst->select), buffer_size);         \
-  }                                                                          \
-} while (0)
-
-  CHECK_FIELD (host);
-  CHECK_FIELD (plugin);
-  CHECK_FIELD (plugin_instance);
-  CHECK_FIELD (type);
-  CHECK_FIELD (type_instance);
-
-#undef CHECK_FIELD
-
-  if (buffer[0] == 0)
-    strlcat (buffer, "default", buffer_size);
-
-  ident_destroy (cfg_select);
-
-  return (0);
-} /* }}} int inst_describe */
-
-/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/graph_instance.h b/graph_instance.h
deleted file mode 100644 (file)
index b90f984..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-#ifndef GRAPH_INSTANCE_H
-#define GRAPH_INSTANCE_H 1
-
-/*
- * Data types
- */
-struct graph_instance_s;
-typedef struct graph_instance_s graph_instance_t;
-
-typedef int (*inst_callback_t) (graph_instance_t *inst, void *user_data);
-
-#include "graph.h"
-#include "utils_array.h"
-
-/*
- * Callback types
- */
-/*
- * Methods
- */
-graph_instance_t *inst_create (graph_config_t *cfg,
-               const graph_ident_t *ident);
-
-void inst_destroy (graph_instance_t *inst);
-
-int inst_add_file (graph_instance_t *inst, const graph_ident_t *file);
-
-graph_instance_t *inst_get_selected (graph_config_t *cfg);
-
-int inst_get_params (graph_config_t *cfg, graph_instance_t *inst,
-    char *buffer, size_t buffer_size);
-
-int inst_get_rrdargs (graph_config_t *cfg, graph_instance_t *inst,
-    str_array_t *args);
-
-graph_ident_t *inst_get_selector (graph_instance_t *inst);
-
-int inst_append (graph_instance_t *head, graph_instance_t *inst);
-
-int inst_foreach (graph_instance_t *inst,
-               inst_callback_t cb, void *user_data);
-
-graph_instance_t *inst_find_matching (graph_instance_t *inst,
-    const graph_ident_t *ident);
-
-int inst_describe (graph_config_t *cfg, graph_instance_t *inst,
-    char *buffer, size_t buffer_size);
-
-#endif /* GRAPH_INSTANCE_H */
-/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/graph_list.c b/graph_list.c
deleted file mode 100644 (file)
index 965fcba..0000000
+++ /dev/null
@@ -1,287 +0,0 @@
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <inttypes.h>
-#include <string.h>
-#include <time.h>
-#include <errno.h>
-
-#include "graph_list.h"
-#include "graph_ident.h"
-#include "graph_def.h"
-#include "graph_config.h"
-#include "common.h"
-#include "filesystem.h"
-#include "utils_params.h"
-
-#include <fcgiapp.h>
-#include <fcgi_stdio.h>
-
-/*
- * Defines
- */
-#define UPDATE_INTERVAL 10
-
-/*
- * Global variables
- */
-static graph_config_t **gl_active = NULL;
-static size_t gl_active_num = 0;
-
-static graph_config_t **gl_staging = NULL;
-static size_t gl_staging_num = 0;
-
-static time_t gl_last_update = 0;
-
-/*
- * Private functions
- */
-int gl_add_graph_internal (graph_config_t *cfg, /* {{{ */
-    graph_config_t ***gl_array, size_t *gl_array_num)
-{
-  graph_config_t **tmp;
-
-#define ARRAY_PTR  (*gl_array)
-#define ARRAY_SIZE (*gl_array_num)
-
-  if (cfg == NULL)
-    return (EINVAL);
-
-  tmp = realloc (ARRAY_PTR, sizeof (*ARRAY_PTR) * (ARRAY_SIZE + 1));
-  if (tmp == NULL)
-    return (ENOMEM);
-  ARRAY_PTR = tmp;
-
-  ARRAY_PTR[ARRAY_SIZE] = cfg;
-  ARRAY_SIZE++;
-
-#undef ARRAY_SIZE
-#undef ARRAY_PTR
-
-  return (0);
-} /* }}} int gl_add_graph_internal */
-
-static int gl_register_file (const graph_ident_t *file, /* {{{ */
-    __attribute__((unused)) void *user_data)
-{
-  graph_config_t *cfg;
-  int num_graphs = 0;
-  size_t i;
-
-  for (i = 0; i < gl_active_num; i++)
-  {
-    graph_config_t *cfg = gl_active[i];
-    int status;
-
-    if (!graph_matches (cfg, file))
-      continue;
-
-    status = graph_add_file (cfg, file);
-    if (status != 0)
-    {
-      /* report error */;
-    }
-    else
-    {
-      num_graphs++;
-    }
-  }
-
-  if (num_graphs == 0)
-  {
-    cfg = graph_create (file);
-    gl_add_graph_internal (cfg, &gl_active, &gl_active_num);
-    graph_add_file (cfg, file);
-  }
-
-  return (0);
-} /* }}} int gl_register_file */
-
-static const char *get_part_from_param (const char *prim_key, /* {{{ */
-    const char *sec_key)
-{
-  const char *val;
-
-  val = param (prim_key);
-  if (val != NULL)
-    return (val);
-  
-  return (param (sec_key));
-} /* }}} const char *get_part_from_param */
-
-static int gl_clear_instances (void) /* {{{ */
-{
-  size_t i;
-
-  for (i = 0; i < gl_active_num; i++)
-    graph_clear_instances (gl_active[i]);
-
-  return (0);
-} /* }}} int gl_clear_instances */
-
-
-/*
- * Global functions
- */
-int gl_add_graph (graph_config_t *cfg) /* {{{ */
-{
-  return (gl_add_graph_internal (cfg, &gl_staging, &gl_staging_num));
-} /* }}} int gl_add_graph */
-
-int gl_config_submit (void) /* {{{ */
-{
-  graph_config_t **old;
-  size_t old_num;
-  size_t i;
-
-  old = gl_active;
-  old_num = gl_active_num;
-
-  gl_active = gl_staging;
-  gl_active_num = gl_staging_num;
-
-  gl_staging = NULL;
-  gl_staging_num = 0;
-
-  for (i = 0; i < old_num; i++)
-  {
-    graph_destroy (old[i]);
-    old[i] = NULL;
-  }
-  free (old);
-
-  return (0);
-} /* }}} int graph_config_submit */
-
-int gl_graph_get_all (gl_cfg_callback callback, /* {{{ */
-    void *user_data)
-{
-  size_t i;
-
-  if (callback == NULL)
-    return (EINVAL);
-
-  gl_update ();
-
-  for (i = 0; i < gl_active_num; i++)
-  {
-    int status;
-
-    status = (*callback) (gl_active[i], user_data);
-    if (status != 0)
-      return (status);
-  }
-
-  return (0);
-} /* }}} int gl_graph_get_all */
-
-graph_config_t *gl_graph_get_selected (void) /* {{{ */
-{
-  const char *host = get_part_from_param ("graph_host", "host");
-  const char *plugin = get_part_from_param ("graph_plugin", "plugin");
-  const char *plugin_instance = get_part_from_param ("graph_plugin_instance", "plugin_instance");
-  const char *type = get_part_from_param ("graph_type", "type");
-  const char *type_instance = get_part_from_param ("graph_type_instance", "type_instance");
-  graph_ident_t *ident;
-  size_t i;
-
-  if ((host == NULL)
-      || (plugin == NULL) || (plugin_instance == NULL)
-      || (type == NULL) || (type_instance == NULL))
-    return (NULL);
-
-  ident = ident_create (host, plugin, plugin_instance, type, type_instance);
-
-  gl_update ();
-
-  for (i = 0; i < gl_active_num; i++)
-  {
-    if (graph_compare (gl_active[i], ident) != 0)
-      continue;
-
-    ident_destroy (ident);
-    return (gl_active[i]);
-  }
-
-  ident_destroy (ident);
-  return (NULL);
-} /* }}} graph_config_t *gl_graph_get_selected */
-
-/* gl_instance_get_all, gl_graph_instance_get_all {{{ */
-struct gl_inst_callback_data /* {{{ */
-{
-  graph_config_t *cfg;
-  gl_inst_callback callback;
-  void *user_data;
-}; /* }}} struct gl_inst_callback_data */
-
-static int gl_inst_callback_handler (graph_instance_t *inst, /* {{{ */
-    void *user_data)
-{
-  struct gl_inst_callback_data *data = user_data;
-
-  return ((*data->callback) (data->cfg, inst, data->user_data));
-} /* }}} int gl_inst_callback_handler */
-
-int gl_graph_instance_get_all (graph_config_t *cfg, /* {{{ */
-    gl_inst_callback callback, void *user_data)
-{
-  struct gl_inst_callback_data data =
-  {
-    cfg,
-    callback,
-    user_data
-  };
-
-  if ((cfg == NULL) || (callback == NULL))
-    return (EINVAL);
-
-  return (inst_foreach (graph_get_instances (cfg),
-        gl_inst_callback_handler, &data));
-} /* }}} int gl_graph_instance_get_all */
-
-int gl_instance_get_all (gl_inst_callback callback, /* {{{ */
-    void *user_data)
-{
-  size_t i;
-
-  gl_update ();
-
-  for (i = 0; i < gl_active_num; i++)
-  {
-    int status;
-
-    status = gl_graph_instance_get_all (gl_active[i], callback, user_data);
-    if (status != 0)
-      return (status);
-  }
-
-  return (0);
-} /* }}} int gl_instance_get_all */
-/* }}} gl_instance_get_all, gl_graph_instance_get_all */
-
-int gl_update (void) /* {{{ */
-{
-  time_t now;
-  int status;
-
-  /*
-  printf ("Content-Type: text/plain\n\n");
-  */
-
-  now = time (NULL);
-
-  if ((gl_last_update + UPDATE_INTERVAL) >= now)
-    return (0);
-
-  graph_read_config ();
-
-  gl_clear_instances ();
-  status = fs_scan (/* callback = */ gl_register_file, /* user data = */ NULL);
-
-  gl_last_update = now;
-
-  return (status);
-} /* }}} int gl_update */
-
-/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/graph_list.h b/graph_list.h
deleted file mode 100644 (file)
index c17d6fc..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-#ifndef GRAPH_LIST_H
-#define GRAPH_LIST_H 1
-
-#include "graph_instance.h"
-
-/*
- * Callback types
- */
-typedef int (*gl_cfg_callback) (graph_config_t *cfg,
-    void *user_data);
-
-typedef int (*gl_inst_callback) (graph_config_t *cfg,
-    graph_instance_t *inst, void *user_data);
-
-/*
- * Functions
- */
-int gl_add_graph (graph_config_t *cfg);
-
-int gl_config_submit (void);
-
-int gl_graph_get_all (gl_cfg_callback callback,
-    void *user_data);
-
-graph_config_t *gl_graph_get_selected (void);
-
-int gl_graph_instance_get_all (graph_config_t *cfg,
-    gl_inst_callback callback, void *user_data);
-
-int gl_instance_get_all (gl_inst_callback callback,
-    void *user_data);
-
-int gl_update (void);
-
-#endif /* GRAPH_LIST_H */
-/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/oconfig.c b/oconfig.c
deleted file mode 100644 (file)
index b8087dd..0000000
--- a/oconfig.c
+++ /dev/null
@@ -1,217 +0,0 @@
-/**
- * oconfig - src/oconfig.c
- * Copyright (C) 2006,2007  Florian octo Forster <octo at verplant.org>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; only version 2 of the License is applicable.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
-#include <errno.h>
-
-#include "oconfig.h"
-
-extern FILE *yyin;
-
-oconfig_item_t *ci_root;
-const char     *c_file;
-
-static void yyset_in  (FILE *fd)
-{
-  yyin = fd;
-} /* void yyset_in */
-
-oconfig_item_t *oconfig_parse_fh (FILE *fh)
-{
-  int status;
-  oconfig_item_t *ret;
-
-  char file[10];
-
-  yyset_in (fh);
-
-  if (NULL == c_file) {
-    int status;
-
-    status = snprintf (file, sizeof (file), "<fd#%d>", fileno (fh));
-
-    if ((status < 0) || (((size_t) status) >= sizeof (file))) {
-      c_file = "<unknown>";
-    }
-    else {
-      file[sizeof (file) - 1] = '\0';
-      c_file = file;
-    }
-  }
-
-  status = yyparse ();
-  if (status != 0)
-  {
-    fprintf (stderr, "yyparse returned error #%i\n", status);
-    return (NULL);
-  }
-
-  c_file = NULL;
-
-  ret = ci_root;
-  ci_root = NULL;
-  yyset_in ((FILE *) 0);
-
-  return (ret);
-} /* oconfig_item_t *oconfig_parse_fh */
-
-oconfig_item_t *oconfig_parse_file (const char *file)
-{
-  FILE *fh;
-  oconfig_item_t *ret;
-
-  c_file = file;
-
-  fh = fopen (file, "r");
-  if (fh == NULL)
-  {
-    fprintf (stderr, "fopen (%s) failed: %s\n", file, strerror (errno));
-    return (NULL);
-  }
-
-  ret = oconfig_parse_fh (fh);
-  fclose (fh);
-
-  c_file = NULL;
-
-  return (ret);
-} /* oconfig_item_t *oconfig_parse_file */
-
-oconfig_item_t *oconfig_clone (const oconfig_item_t *ci_orig)
-{
-  oconfig_item_t *ci_copy;
-
-  ci_copy = (oconfig_item_t *) malloc (sizeof (*ci_copy));
-  if (ci_copy == NULL)
-  {
-    fprintf (stderr, "malloc failed.\n");
-    return (NULL);
-  }
-  memset (ci_copy, 0, sizeof (*ci_copy));
-  ci_copy->values = NULL;
-  ci_copy->parent = NULL;
-  ci_copy->children = NULL;
-
-  ci_copy->key = strdup (ci_orig->key);
-  if (ci_copy->key == NULL)
-  {
-    fprintf (stderr, "strdup failed.\n");
-    free (ci_copy);
-    return (NULL);
-  }
-
-  if (ci_orig->values_num > 0) /* {{{ */
-  {
-    int i;
-
-    ci_copy->values = (oconfig_value_t *) calloc (ci_orig->values_num,
-       sizeof (*ci_copy->values));
-    if (ci_copy->values == NULL)
-    {
-      fprintf (stderr, "calloc failed.\n");
-      free (ci_copy->key);
-      free (ci_copy);
-      return (NULL);
-    }
-    ci_copy->values_num = ci_orig->values_num;
-
-    for (i = 0; i < ci_copy->values_num; i++)
-    {
-       ci_copy->values[i].type = ci_orig->values[i].type;
-       if (ci_copy->values[i].type == OCONFIG_TYPE_STRING)
-       {
-        ci_copy->values[i].value.string
-          = strdup (ci_orig->values[i].value.string);
-        if (ci_copy->values[i].value.string == NULL)
-        {
-          fprintf (stderr, "strdup failed.\n");
-          oconfig_free (ci_copy);
-          return (NULL);
-        }
-       }
-       else /* ci_copy->values[i].type != OCONFIG_TYPE_STRING) */
-       {
-        ci_copy->values[i].value = ci_orig->values[i].value;
-       }
-    }
-  } /* }}} if (ci_orig->values_num > 0) */
-
-  if (ci_orig->children_num > 0) /* {{{ */
-  {
-    int i;
-
-    ci_copy->children = (oconfig_item_t *) calloc (ci_orig->children_num,
-       sizeof (*ci_copy->children));
-    if (ci_copy->children == NULL)
-    {
-      fprintf (stderr, "calloc failed.\n");
-      oconfig_free (ci_copy);
-      return (NULL);
-    }
-    ci_copy->children_num = ci_orig->children_num;
-
-    for (i = 0; i < ci_copy->children_num; i++)
-    {
-      oconfig_item_t *child;
-      
-      child = oconfig_clone (ci_orig->children + i);
-      if (child == NULL)
-      {
-       oconfig_free (ci_copy);
-       return (NULL);
-      }
-      child->parent = ci_copy;
-      ci_copy->children[i] = *child;
-      free (child);
-    } /* for (i = 0; i < ci_copy->children_num; i++) */
-  } /* }}} if (ci_orig->children_num > 0) */
-
-  return (ci_copy);
-} /* oconfig_item_t *oconfig_clone */
-
-void oconfig_free (oconfig_item_t *ci)
-{
-  int i;
-
-  if (ci == NULL)
-    return;
-
-  if (ci->key != NULL)
-    free (ci->key);
-
-  for (i = 0; i < ci->values_num; i++)
-    if ((ci->values[i].type == OCONFIG_TYPE_STRING)
-        && (NULL != ci->values[i].value.string))
-      free (ci->values[i].value.string);
-
-  if (ci->values != NULL)
-    free (ci->values);
-
-  for (i = 0; i < ci->children_num; i++)
-    oconfig_free (ci->children + i);
-
-  if (ci->children != NULL)
-    free (ci->children);
-}
-
-/*
- * vim:shiftwidth=2:tabstop=8:softtabstop=2:fdm=marker
- */
diff --git a/oconfig.h b/oconfig.h
deleted file mode 100644 (file)
index 70fc623..0000000
--- a/oconfig.h
+++ /dev/null
@@ -1,69 +0,0 @@
-#ifndef OCONFIG_H
-#define OCONFIG_H 1
-
-#include <stdio.h>
-
-/**
- * oconfig - src/oconfig.h
- * Copyright (C) 2006-2009  Florian octo Forster <octo at verplant.org>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; only version 2 of the License is applicable.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
- */
-
-/*
- * Types
- */
-#define OCONFIG_TYPE_STRING  0
-#define OCONFIG_TYPE_NUMBER  1
-#define OCONFIG_TYPE_BOOLEAN 2
-
-struct oconfig_value_s
-{
-  union
-  {
-    char  *string;
-    double number;
-    int    boolean;
-  } value;
-  int type;
-};
-typedef struct oconfig_value_s oconfig_value_t;
-
-struct oconfig_item_s;
-typedef struct oconfig_item_s oconfig_item_t;
-struct oconfig_item_s
-{
-  char            *key;
-  oconfig_value_t *values;
-  int              values_num;
-
-  oconfig_item_t  *parent;
-  oconfig_item_t  *children;
-  int              children_num;
-};
-
-/*
- * Functions
- */
-oconfig_item_t *oconfig_parse_fh (FILE *fh);
-oconfig_item_t *oconfig_parse_file (const char *file);
-
-oconfig_item_t *oconfig_clone (const oconfig_item_t *ci);
-
-void oconfig_free (oconfig_item_t *ci);
-
-/*
- * vim: shiftwidth=2:tabstop=8:softtabstop=2
- */
-#endif /* OCONFIG_H */
diff --git a/parser.y b/parser.y
deleted file mode 100644 (file)
index 5b7aa94..0000000
--- a/parser.y
+++ /dev/null
@@ -1,239 +0,0 @@
-/**
- * oconfig - src/parser.y
- * Copyright (C) 2007,2008  Florian octo Forster <octo at verplant.org>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; only version 2 of the License is applicable.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
- */
-
-%{
-#include <stdlib.h>
-#include <string.h>
-#include "oconfig.h"
-#include "aux_types.h"
-
-static char *unquote (const char *orig);
-static int yyerror (const char *s);
-
-/* Lexer variables */
-extern int yylineno;
-extern char *yytext;
-
-extern oconfig_item_t *ci_root;
-extern char           *c_file;
-%}
-
-%start entire_file
-
-%union {
-       double  number;
-       int     boolean;
-       char   *string;
-       oconfig_value_t  cv;
-       oconfig_item_t   ci;
-       argument_list_t  al;
-       statement_list_t sl;
-}
-
-%token <number> NUMBER
-%token <boolean> BTRUE BFALSE
-%token <string> QUOTED_STRING UNQUOTED_STRING
-%token SLASH OPENBRAC CLOSEBRAC EOL
-
-%type <string> string
-%type <string> identifier
-/* arguments */
-%type <cv> argument
-%type <al> argument_list
-/* blocks */
-%type <ci> block_begin
-%type <ci> block
-%type <string> block_end
-/* statements */
-%type <ci> option
-%type <ci> statement
-%type <sl> statement_list
-%type <ci> entire_file
-
-/* pass an verbose, specific error message to yyerror() */
-%error-verbose
-
-%%
-string:
-       QUOTED_STRING           {$$ = unquote ($1);}
-       | UNQUOTED_STRING       {$$ = strdup ($1);}
-       ;
-
-argument:
-       NUMBER                  {$$.value.number = $1; $$.type = OCONFIG_TYPE_NUMBER;}
-       | BTRUE                 {$$.value.boolean = 1; $$.type = OCONFIG_TYPE_BOOLEAN;}
-       | BFALSE                {$$.value.boolean = 0; $$.type = OCONFIG_TYPE_BOOLEAN;}
-       | string                {$$.value.string = $1; $$.type = OCONFIG_TYPE_STRING;}
-       ;
-
-argument_list:
-       argument_list argument
-       {
-        $$ = $1;
-        $$.argument_num++;
-        $$.argument = realloc ($$.argument, $$.argument_num * sizeof (oconfig_value_t));
-        $$.argument[$$.argument_num-1] = $2;
-       }
-       | argument
-       {
-        $$.argument = malloc (sizeof (oconfig_value_t));
-        $$.argument[0] = $1;
-        $$.argument_num = 1;
-       }
-       ;
-
-identifier:
-       UNQUOTED_STRING                 {$$ = strdup ($1);}
-       ;
-
-option:
-       identifier argument_list EOL
-       {
-        memset (&$$, '\0', sizeof ($$));
-        $$.key = $1;
-        $$.values = $2.argument;
-        $$.values_num = $2.argument_num;
-       }
-       ;
-
-block_begin:
-       OPENBRAC identifier CLOSEBRAC EOL
-       {
-        memset (&$$, '\0', sizeof ($$));
-        $$.key = $2;
-       }
-       |
-       OPENBRAC identifier argument_list CLOSEBRAC EOL
-       {
-        memset (&$$, '\0', sizeof ($$));
-        $$.key = $2;
-        $$.values = $3.argument;
-        $$.values_num = $3.argument_num;
-       }
-       ;
-
-block_end:
-       OPENBRAC SLASH identifier CLOSEBRAC EOL
-       {
-        $$ = $3;
-       }
-       ;
-
-block:
-       block_begin statement_list block_end
-       {
-        if (strcmp ($1.key, $3) != 0)
-        {
-               printf ("block_begin = %s; block_end = %s;\n", $1.key, $3);
-               yyerror ("Block not closed..\n");
-               exit (1);
-        }
-        free ($3); $3 = NULL;
-        $$ = $1;
-        $$.children = $2.statement;
-        $$.children_num = $2.statement_num;
-       }
-       ;
-
-statement:
-       option          {$$ = $1;}
-       | block         {$$ = $1;}
-       | EOL           {$$.values_num = 0;}
-       ;
-
-statement_list:
-       statement_list statement
-       {
-        $$ = $1;
-        if (($2.values_num > 0) || ($2.children_num > 0))
-        {
-                $$.statement_num++;
-                $$.statement = realloc ($$.statement, $$.statement_num * sizeof (oconfig_item_t));
-                $$.statement[$$.statement_num-1] = $2;
-        }
-       }
-       | statement
-       {
-        if (($1.values_num > 0) || ($1.children_num > 0))
-        {
-                $$.statement = malloc (sizeof (oconfig_item_t));
-                $$.statement[0] = $1;
-                $$.statement_num = 1;
-        }
-        else
-        {
-               $$.statement = NULL;
-               $$.statement_num = 0;
-        }
-       }
-       ;
-
-entire_file:
-       statement_list
-       {
-        ci_root = malloc (sizeof (oconfig_item_t));
-        memset (ci_root, '\0', sizeof (oconfig_item_t));
-        ci_root->children = $1.statement;
-        ci_root->children_num = $1.statement_num;
-       }
-       ;
-
-%%
-static int yyerror (const char *s)
-{
-       char *text;
-
-       if (*yytext == '\n')
-               text = "<newline>";
-       else
-               text = yytext;
-
-       fprintf (stderr, "Parse error in file `%s', line %i near `%s': %s\n",
-               c_file, yylineno, text, s);
-       return (-1);
-} /* int yyerror */
-
-static char *unquote (const char *orig)
-{
-       char *ret = strdup (orig);
-       int len;
-       int i;
-
-       if (ret == NULL)
-               return (NULL);
-
-       len = strlen (ret);
-
-       if ((len < 2) || (ret[0] != '"') || (ret[len - 1] != '"'))
-               return (ret);
-
-       len -= 2;
-       memmove (ret, ret + 1, len);
-       ret[len] = '\0';
-
-       for (i = 0; i < len; i++)
-       {
-               if (ret[i] == '\\')
-               {
-                       memmove (ret + i, ret + (i + 1), len - i);
-                       len--;
-               }
-       }
-
-       return (ret);
-} /* char *unquote */
diff --git a/scanner.l b/scanner.l
deleted file mode 100644 (file)
index 9f0cd8e..0000000
--- a/scanner.l
+++ /dev/null
@@ -1,137 +0,0 @@
-/**
- * oconfig - src/scanner.l
- * Copyright (C) 2007  Florian octo Forster <octo at verplant.org>
- * Copyright (C) 2008  Sebastian tokkee Harl <sh at tokkee.org>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; only version 2 of the License is applicable.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
- */
-
-%{
-#include <stdlib.h>
-#include "oconfig.h"
-#include "aux_types.h"
-#include "parser.h"
-
-/* multiline string buffer */
-static char *ml_buffer = NULL;
-static int   ml_pos    = 0;
-static int   ml_len    = 0;
-
-#define ml_free (ml_len - ml_pos)
-
-static void ml_append (char *);
-
-#ifdef yyterminate
-# undef yyterminate
-#endif
-#define yyterminate() \
-       do { free (ml_buffer); ml_buffer = NULL; ml_pos = 0; ml_len = 0; \
-               return YY_NULL; } while (0)
-%}
-%option yylineno
-%option noyywrap
-%x ML
-WHITE_SPACE [\ \t\b]
-NON_WHITE_SPACE [^\ \t\b]
-EOL (\r\n|\n)
-QUOTED_STRING ([^\\"]+|\\.)*
-UNQUOTED_STRING [0-9A-Za-z_]+
-HEX_NUMBER 0[xX][0-9a-fA-F]+
-OCT_NUMBER 0[0-7]+
-DEC_NUMBER [\+\-]?[0-9]+
-FLOAT_NUMBER [\+\-]?[0-9]*\.[0-9]+([eE][\+\-][0-9]+)?
-NUMBER ({FLOAT_NUMBER}|{HEX_NUMBER}|{OCT_NUMBER}|{DEC_NUMBER})
-BOOL_TRUE (true|yes|on)
-BOOL_FALSE (false|no|off)
-COMMENT #.*
-PORT (6(5(5(3[0-5]|[0-2][0-9])|[0-4][0-9][0-9])|[0-4][0-9][0-9][0-9])|[1-5][0-9][0-9][0-9][0-9]|[1-9][0-9]?[0-9]?[0-9]?)
-IP_BYTE (2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])
-IPV4_ADDR {IP_BYTE}\.{IP_BYTE}\.{IP_BYTE}\.{IP_BYTE}(:{PORT})?
-
-%%
-{WHITE_SPACE}          |
-{COMMENT}              {/* ignore */}
-
-\\{EOL}                        {/* continue line */}
-
-{EOL}                  {return (EOL);}
-"/"                    {return (SLASH);}
-"<"                    {return (OPENBRAC);}
-">"                    {return (CLOSEBRAC);}
-{BOOL_TRUE}            {yylval.boolean = 1; return (BTRUE);}
-{BOOL_FALSE}           {yylval.boolean = 0; return (BFALSE);}
-
-{IPV4_ADDR}            {yylval.string = yytext; return (UNQUOTED_STRING);}
-
-{NUMBER}               {yylval.number = strtod (yytext, NULL); return (NUMBER);}
-
-\"{QUOTED_STRING}\"    {yylval.string = yytext; return (QUOTED_STRING);}
-{UNQUOTED_STRING}      {yylval.string = yytext; return (UNQUOTED_STRING);}
-
-\"{QUOTED_STRING}\\{EOL} {
-       int len = strlen (yytext);
-
-       ml_pos = 0;
-
-       /* remove "\\<EOL>" */
-       if ('\r' == yytext[len - 2])
-               len -= 3;
-       else
-               len -= 2;
-       yytext[len] = '\0';
-
-       ml_append (yytext);
-       BEGIN (ML);
-}
-<ML>^{WHITE_SPACE}+ {/* remove leading white-space */}
-<ML>{NON_WHITE_SPACE}{QUOTED_STRING}\\{EOL} {
-       int len = strlen (yytext);
-
-       /* remove "\\<EOL>" */
-       if ('\r' == yytext[len - 2])
-               len -= 3;
-       else
-               len -= 2;
-       yytext[len] = '\0';
-
-       ml_append(yytext);
-}
-<ML>{NON_WHITE_SPACE}{QUOTED_STRING}\" {
-       ml_append(yytext);
-       yylval.string = ml_buffer;
-
-       BEGIN (INITIAL);
-       return (QUOTED_STRING);
-}
-%%
-static void ml_append (char *string)
-{
-       int len = strlen (string);
-       int s;
-
-       if (ml_free <= len) {
-               ml_len += len - ml_free + 1;
-               ml_buffer = (char *)realloc (ml_buffer, ml_len);
-               if (NULL == ml_buffer)
-                       YY_FATAL_ERROR ("out of dynamic memory in ml_append");
-       }
-
-       s = snprintf (ml_buffer + ml_pos, ml_free, "%s", string);
-       if ((0 > s) || (ml_free <= s))
-               YY_FATAL_ERROR ("failed to write to multiline buffer");
-
-       ml_pos += s;
-       return;
-} /* ml_append */
-
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644 (file)
index 0000000..de0cb7e
--- /dev/null
@@ -0,0 +1,25 @@
+AUTOMAKE_OPTIONS = foreign no-dependencies
+
+if COMPILER_IS_GCC
+AM_CFLAGS = -Wall -Wextra
+endif
+AM_YFLAGS = -d
+
+BUILT_SOURCES = parser.h
+
+bin_PROGRAMS = collection.fcgi
+
+collection_fcgi_SOURCES = main.c \
+                         oconfig.c oconfig.h aux_types.h scanner.l parser.y \
+                         action_graph.c action_graph.h \
+                         action_list_graphs.c action_list_graphs.h \
+                         common.c common.h \
+                         filesystem.c filesystem.h \
+                         graph.c graph.h \
+                         graph_config.c graph_config.h \
+                         graph_def.c graph_def.h \
+                         graph_ident.c graph_ident.h \
+                         graph_instance.c graph_instance.h \
+                         graph_list.c graph_list.h \
+                         utils_array.c utils_array.h \
+                         utils_params.c utils_params.h
diff --git a/src/action_graph.c b/src/action_graph.c
new file mode 100644 (file)
index 0000000..a0f257e
--- /dev/null
@@ -0,0 +1,150 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <dirent.h> /* for PATH_MAX */
+#include <assert.h>
+#include <math.h>
+
+#include <rrd.h>
+
+#include "common.h"
+#include "action_graph.h"
+#include "graph_list.h"
+#include "utils_params.h"
+#include "utils_array.h"
+
+#include <fcgiapp.h>
+#include <fcgi_stdio.h>
+
+static void emulate_graph (int argc, char **argv) /* {{{ */
+{
+  int i;
+
+  printf ("rrdtool \\\n");
+  for (i = 0; i < argc; i++)
+  {
+    if (i < (argc - 1))
+      printf ("  \"%s\" \\\n", argv[i]);
+    else
+      printf ("  \"%s\"\n", argv[i]);
+  }
+} /* }}} void emulate_graph */
+
+static int ag_info_print (rrd_info_t *info) /* {{{ */
+{
+  if (info->type == RD_I_VAL)
+    printf ("[info] %s = %g;\n", info->key, info->value.u_val);
+  else if (info->type == RD_I_CNT)
+    printf ("[info] %s = %lu;\n", info->key, info->value.u_cnt);
+  else if (info->type == RD_I_STR)
+    printf ("[info] %s = %s;\n", info->key, info->value.u_str);
+  else if (info->type == RD_I_INT)
+    printf ("[info] %s = %i;\n", info->key, info->value.u_int);
+  else if (info->type == RD_I_BLO)
+    printf ("[info] %s = [blob, %lu bytes];\n", info->key, info->value.u_blo.size);
+  else
+    printf ("[info] %s = [unknown type %#x];\n", info->key, info->type);
+
+  return (0);
+} /* }}} int ag_info_print */
+
+static int output_graph (rrd_info_t *info) /* {{{ */
+{
+  rrd_info_t *img;
+
+  for (img = info; img != NULL; img = img->next)
+    if ((strcmp ("image", img->key) == 0)
+        && (img->type == RD_I_BLO))
+      break;
+
+  if (img == NULL)
+    return (ENOENT);
+
+  printf ("Content-Type: image/png\n"
+      "Content-Length: %lu\n"
+      "\n",
+      img->value.u_blo.size);
+  fwrite (img->value.u_blo.ptr, img->value.u_blo.size,
+      /* nmemb = */ 1, stdout);
+
+  return (0);
+} /* }}} int output_graph */
+
+#define OUTPUT_ERROR(...) do {             \
+  printf ("Content-Type: text/plain\n\n"); \
+  printf (__VA_ARGS__);                    \
+  return (0);                              \
+} while (0)
+
+int action_graph (void) /* {{{ */
+{
+  str_array_t *args;
+  graph_config_t *cfg;
+  graph_instance_t *inst;
+  rrd_info_t *info;
+  int status;
+
+  cfg = gl_graph_get_selected ();
+  if (cfg == NULL)
+    OUTPUT_ERROR ("gl_graph_get_selected () failed.\n");
+
+  inst = inst_get_selected (cfg);
+  if (inst == NULL)
+    OUTPUT_ERROR ("inst_get_selected (%p) failed.\n", (void *) cfg);
+
+  args = array_create ();
+  if (args == NULL)
+    return (ENOMEM);
+
+  array_append (args, "graph");
+  array_append (args, "-");
+  array_append (args, "--imgformat");
+  array_append (args, "PNG");
+
+  status = inst_get_rrdargs (cfg, inst, args);
+  if (status != 0)
+  {
+    array_destroy (args);
+    OUTPUT_ERROR ("inst_get_rrdargs failed with status %i.\n", status);
+  }
+
+  rrd_clear_error ();
+  info = rrd_graph_v (array_argc (args), array_argv (args));
+  if ((info == NULL) || rrd_test_error ())
+  {
+    printf ("Content-Type: text/plain\n\n");
+    printf ("rrd_graph_v failed: %s\n", rrd_get_error ());
+    emulate_graph (array_argc (args), array_argv (args));
+  }
+  else
+  {
+    int status;
+
+    status = output_graph (info);
+    if (status != 0)
+    {
+      rrd_info_t *ptr;
+
+      printf ("Content-Type: text/plain\n\n");
+      printf ("output_graph failed. Maybe the \"image\" info was not found?\n\n");
+
+      for (ptr = info; ptr != NULL; ptr = ptr->next)
+      {
+        ag_info_print (ptr);
+      }
+    }
+  }
+
+  if (info != NULL)
+    rrd_info_free (info);
+
+  array_destroy (args);
+  args = NULL;
+
+  return (0);
+} /* }}} int action_graph */
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/src/action_graph.h b/src/action_graph.h
new file mode 100644 (file)
index 0000000..712f398
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef ACTION_GRAPH_H
+#define ACTION_GRAPH_H 1
+
+int action_graph (void);
+
+#endif /* ACTION_GRAPH_H */
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/src/action_list_graphs.c b/src/action_list_graphs.c
new file mode 100644 (file)
index 0000000..29e3d8b
--- /dev/null
@@ -0,0 +1,126 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include "action_list_graphs.h"
+#include "graph.h"
+#include "graph_list.h"
+#include "utils_params.h"
+
+#include <fcgiapp.h>
+#include <fcgi_stdio.h>
+
+static int print_graph_inst_json (__attribute__((unused)) graph_config_t *cfg, /* {{{ */
+    graph_instance_t *inst,
+    void *user_data)
+{
+  _Bool *first;
+  graph_ident_t *ident;
+  char *json;
+
+  first = user_data;
+
+  ident = inst_get_selector (inst);
+  if (ident == NULL)
+    return (-1);
+
+  json = ident_to_json (ident);
+  if (json == NULL)
+  {
+    ident_destroy (ident);
+    return (ENOMEM);
+  }
+
+  if (*first)
+    printf ("%s", json);
+  else
+    printf (",\n%s", json);
+
+  *first = 0;
+
+  ident_destroy (ident);
+  return (0);
+} /* }}} int print_graph_inst_json */
+
+static int print_graph_json (graph_config_t *cfg, /* {{{ */
+    void *user_data)
+{
+  return (gl_graph_instance_get_all (cfg, print_graph_inst_json, user_data));
+} /* }}} int print_graph_json */
+
+static int list_graphs_json (void) /* {{{ */
+{
+  _Bool first = 1;
+
+  printf ("Content-Type: application/json\n\n");
+
+  printf ("[\n");
+  gl_graph_get_all (print_graph_json, /* user_data = */ &first);
+  printf ("\n]");
+
+  return (0);
+} /* }}} int list_graphs_json */
+
+static int print_graph_inst_html (graph_config_t *cfg, /* {{{ */
+    graph_instance_t *inst,
+    __attribute__((unused)) void *user_data)
+{
+  char params[1024];
+  char desc[1024];
+
+  memset (params, 0, sizeof (params));
+  inst_get_params (cfg, inst, params, sizeof (params));
+
+  memset (desc, 0, sizeof (desc));
+  inst_describe (cfg, inst, desc, sizeof (desc));
+
+  printf ("    <li><a href=\"test.fcgi?action=graph;%s\">%s</a></li>\n",
+      params, desc);
+
+  return (0);
+} /* }}} int print_graph_inst_html */
+
+static int print_graph_html (graph_config_t *cfg, /* {{{ */
+    __attribute__((unused)) void *user_data)
+{
+  char buffer[1024];
+
+  memset (buffer, 0, sizeof (buffer));
+  graph_get_title (cfg, buffer, sizeof (buffer));
+
+  printf ("  <li>%s\n  <ul>\n", buffer);
+  gl_graph_instance_get_all (cfg, print_graph_inst_html, /* user_data = */ NULL);
+  printf ("  </ul></li>\n");
+
+  return (0);
+} /* }}} int print_graph_html */
+
+static int list_graphs_html (void) /* {{{ */
+{
+  printf ("Content-Type: text/html\n\n");
+
+  printf ("<ul>\n");
+  gl_graph_get_all (print_graph_html, /* user_data = */ NULL);
+  printf ("</ul>\n");
+
+  return (0);
+} /* }}} int list_graphs_html */
+
+int action_list_graphs (void) /* {{{ */
+{
+  const char *format;
+
+  gl_update ();
+
+  format = param ("format");
+  if (format == NULL)
+    format = "html";
+
+  if (strcmp ("json", format) == 0)
+    return (list_graphs_json ());
+  else
+    return (list_graphs_html ());
+} /* }}} int action_list_graphs */
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/src/action_list_graphs.h b/src/action_list_graphs.h
new file mode 100644 (file)
index 0000000..dd7edf9
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef ACTION_LIST_GRAPHS_H
+#define ACTION_LIST_GRAPHS_H 1
+
+int action_list_graphs (void);
+
+#endif /* ACTION_LIST_GRAPHS_H */
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/src/aux_types.h b/src/aux_types.h
new file mode 100644 (file)
index 0000000..25b81ab
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef AUX_TYPES_H
+#define AUX_TYPES_H 1
+
+struct statement_list_s
+{
+       oconfig_item_t *statement;
+       int             statement_num;
+};
+typedef struct statement_list_s statement_list_t;
+
+struct argument_list_s
+{
+       oconfig_value_t *argument;
+       int              argument_num;
+};
+typedef struct argument_list_s argument_list_t;
+
+#endif /* AUX_TYPES_H */
diff --git a/src/common.c b/src/common.c
new file mode 100644 (file)
index 0000000..2b6b5eb
--- /dev/null
@@ -0,0 +1,193 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <assert.h>
+#include <math.h>
+
+#include <rrd.h>
+
+#include "common.h"
+#include "graph_list.h"
+
+#include <fcgiapp.h>
+#include <fcgi_stdio.h>
+
+size_t c_strlcat (char *dst, const char *src, size_t size) /* {{{ */
+{
+  size_t retval;
+  size_t dst_len;
+  size_t src_len;
+
+  dst_len = strlen (dst);
+  src_len = strlen (src);
+  retval = dst_len + src_len;
+
+  if ((dst_len + 1) >= size)
+    return (retval);
+
+  dst  += dst_len;
+  size -= dst_len;
+  assert (size >= 2);
+
+  /* Result will be truncated. */
+  if (src_len >= size)
+    src_len = size - 1;
+
+  memcpy (dst, src, src_len);
+  dst[src_len] = 0;
+
+  return (retval);
+} /* }}} size_t c_strlcat */
+
+int ds_list_from_rrd_file (char *file, /* {{{ */
+    size_t *ret_dses_num, char ***ret_dses)
+{
+  char *rrd_argv[] = { "info", file, NULL };
+  int rrd_argc = (sizeof (rrd_argv) / sizeof (rrd_argv[0])) - 1;
+
+  rrd_info_t *info;
+  rrd_info_t *ptr;
+
+  char **dses = NULL;
+  size_t dses_num = 0;
+
+  info = rrd_info (rrd_argc, rrd_argv);
+  if (info == NULL)
+  {
+    printf ("%s: rrd_info (%s) failed.\n", __func__, file);
+    return (-1);
+  }
+
+  for (ptr = info; ptr != NULL; ptr = ptr->next)
+  {
+    size_t keylen;
+    size_t dslen;
+    char *ds;
+    char **tmp;
+
+    if (strncmp ("ds[", ptr->key, strlen ("ds[")) != 0)
+      continue;
+
+    keylen = strlen (ptr->key);
+    if (keylen < strlen ("ds[?].index"))
+      continue;
+
+    dslen = keylen - strlen ("ds[].index");
+    assert (dslen >= 1);
+
+    if (strcmp ("].index", ptr->key + (strlen ("ds[") + dslen)) != 0)
+      continue;
+
+    ds = malloc (dslen + 1);
+    if (ds == NULL)
+      continue;
+
+    memcpy (ds, ptr->key + strlen ("ds["), dslen);
+    ds[dslen] = 0;
+
+    tmp = realloc (dses, sizeof (*dses) * (dses_num + 1));
+    if (tmp == NULL)
+    {
+      free (ds);
+      continue;
+    }
+    dses = tmp;
+
+    dses[dses_num] = ds;
+    dses_num++;
+  }
+
+  rrd_info_free (info);
+
+  if (dses_num < 1)
+  {
+    assert (dses == NULL);
+    return (ENOENT);
+  }
+
+  *ret_dses_num = dses_num;
+  *ret_dses = dses;
+
+  return (0);
+} /* }}} int ds_list_from_rrd_file */
+
+static int hsv_to_rgb (double *hsv, double *rgb) /* {{{ */
+{
+  double c = hsv[2] * hsv[1];
+  double h = hsv[0] / 60.0;
+  double x = c * (1.0 - fabs (fmod (h, 2.0) - 1));
+  double m = hsv[2] - c;
+
+  rgb[0] = 0.0;
+  rgb[1] = 0.0;
+  rgb[2] = 0.0;
+
+       if ((0.0 <= h) && (h < 1.0)) { rgb[0] = 1.0; rgb[1] = x; rgb[2] = 0.0; }
+  else if ((1.0 <= h) && (h < 2.0)) { rgb[0] = x; rgb[1] = 1.0; rgb[2] = 0.0; }
+  else if ((2.0 <= h) && (h < 3.0)) { rgb[0] = 0.0; rgb[1] = 1.0; rgb[2] = x; }
+  else if ((3.0 <= h) && (h < 4.0)) { rgb[0] = 0.0; rgb[1] = x; rgb[2] = 1.0; }
+  else if ((4.0 <= h) && (h < 5.0)) { rgb[0] = x; rgb[1] = 0.0; rgb[2] = 1.0; }
+  else if ((5.0 <= h) && (h < 6.0)) { rgb[0] = 1.0; rgb[1] = 0.0; rgb[2] = x; }
+
+  rgb[0] += m;
+  rgb[1] += m;
+  rgb[2] += m;
+
+  return (0);
+} /* }}} int hsv_to_rgb */
+
+static uint32_t rgb_to_uint32 (double *rgb) /* {{{ */
+{
+  uint8_t r;
+  uint8_t g;
+  uint8_t b;
+
+  r = (uint8_t) (255.0 * rgb[0]);
+  g = (uint8_t) (255.0 * rgb[1]);
+  b = (uint8_t) (255.0 * rgb[2]);
+
+  return ((((uint32_t) r) << 16)
+      | (((uint32_t) g) << 8)
+      | ((uint32_t) b));
+} /* }}} uint32_t rgb_to_uint32 */
+
+uint32_t get_random_color (void) /* {{{ */
+{
+  double hsv[3] = { 0.0, 1.0, 1.0 };
+  double rgb[3] = { 0.0, 0.0, 0.0 };
+
+  hsv[0] = 360.0 * ((double) rand ()) / (((double) RAND_MAX) + 1.0);
+
+  hsv_to_rgb (hsv, rgb);
+
+  return (rgb_to_uint32 (rgb));
+} /* }}} uint32_t get_random_color */
+
+int print_debug (const char *format, ...) /* {{{ */
+{
+  static _Bool have_header = 0;
+
+  va_list ap;
+  int status;
+
+  if (!have_header)
+  {
+    printf ("Content-Type: text/plain\n\n");
+    have_header = 1;
+  }
+
+  va_start (ap, format);
+  status = vprintf (format, ap);
+  va_end (ap);
+
+  return (status);
+} /* }}} int print_debug */
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/src/common.h b/src/common.h
new file mode 100644 (file)
index 0000000..2b5662f
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef COMMON_H
+#define COMMON_H 1
+
+#include <stdint.h>
+#include <inttypes.h>
+
+int print_debug (const char *format, ...)
+  __attribute__((format(printf,1,2)));
+#if 0
+# define DEBUG(...) print_debug (__VA_ARGS__)
+#else
+# define DEBUG(...) /**/
+#endif
+
+size_t c_strlcat (char *dst, const char *src, size_t size);
+#define strlcat c_strlcat
+
+int ds_list_from_rrd_file (char *file,
+    size_t *ret_dses_num, char ***ret_dses);
+
+uint32_t get_random_color (void);
+
+#endif /* COMMON_H */
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/src/filesystem.c b/src/filesystem.c
new file mode 100644 (file)
index 0000000..a5eeb81
--- /dev/null
@@ -0,0 +1,297 @@
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+
+#include "filesystem.h"
+
+struct fs_scan_dir_data_s /* {{{ */
+{
+  fs_ident_cb_t callback;
+  void *user_data;
+
+  char *host;
+  char *plugin;
+  char *plugin_instance;
+  char *type;
+  char *type_instance;
+}; /* }}} */
+typedef struct fs_scan_dir_data_s fs_scan_dir_data_t;
+
+typedef int (*callback_type_t)   (const char *type,   void *user_data);
+typedef int (*callback_plugin_t) (const char *plugin, void *user_data);
+typedef int (*callback_host_t)   (const char *host,   void *user_data);
+
+/*
+ * Directory and file walking functions
+ */
+static int foreach_rrd_file (const char *dir, /* {{{ */
+    int (*callback) (const char *, void *),
+    void *user_data)
+{
+  DIR *dh;
+  struct dirent *entry;
+  int status;
+
+  if (callback == NULL)
+    return (EINVAL);
+
+  dh = opendir (dir);
+  if (dh == NULL)
+    return (errno);
+
+  while ((entry = readdir (dh)) != NULL)
+  {
+    struct stat statbuf;
+    char abspath[PATH_MAX + 1];
+    size_t d_name_len;
+
+    if (entry->d_name[0] == '.')
+      continue;
+
+    d_name_len = strlen (entry->d_name);
+    if (d_name_len <= 4)
+      continue;
+
+    if (strcasecmp (".rrd", entry->d_name + (d_name_len - 4)) != 0)
+      continue;
+
+    snprintf (abspath, sizeof (abspath), "%s/%s", dir, entry->d_name);
+    abspath[sizeof (abspath) - 1] = 0;
+
+    memset (&statbuf, 0, sizeof (statbuf));
+
+    status = stat (abspath, &statbuf);
+    if (status != 0)
+      continue;
+
+    if (!S_ISREG (statbuf.st_mode))
+      continue;
+
+    entry->d_name[d_name_len - 4] = 0;
+
+    status = (*callback) (entry->d_name, user_data);
+    if (status != 0)
+      break;
+  } /* while (readdir) */
+
+  closedir (dh);
+  return (status);
+} /* }}} int foreach_rrd_file */
+
+static int foreach_dir (const char *dir, /* {{{ */
+    int (*callback) (const char *, void *),
+    void *user_data)
+{
+  DIR *dh;
+  struct dirent *entry;
+  int status = 0;
+
+  if (callback == NULL)
+    return (EINVAL);
+
+  dh = opendir (dir);
+  if (dh == NULL)
+    return (errno);
+
+  while ((entry = readdir (dh)) != NULL)
+  {
+    struct stat statbuf;
+    char abspath[PATH_MAX + 1];
+
+    if (entry->d_name[0] == '.')
+      continue;
+
+    snprintf (abspath, sizeof (abspath), "%s/%s", dir, entry->d_name);
+    abspath[sizeof (abspath) - 1] = 0;
+
+    memset (&statbuf, 0, sizeof (statbuf));
+
+    status = stat (abspath, &statbuf);
+    if (status != 0)
+      continue;
+
+    if (!S_ISDIR (statbuf.st_mode))
+      continue;
+
+    status = (*callback) (entry->d_name, user_data);
+    if (status != 0)
+      break;
+  } /* while (readdir) */
+
+  closedir (dh);
+  return (status);
+} /* }}} int foreach_dir */
+
+static int foreach_type (const char *host, const char *plugin, /* {{{ */
+    callback_type_t callback, void *user_data)
+{
+  char abspath[PATH_MAX + 1];
+
+  if ((host == NULL) || (plugin == NULL))
+    return (EINVAL);
+
+  snprintf (abspath, sizeof (abspath), "%s/%s/%s", DATA_DIR, host, plugin);
+  abspath[sizeof (abspath) - 1] = 0;
+
+  return (foreach_rrd_file (abspath, callback, user_data));
+} /* }}} int foreach_type */
+
+static int foreach_plugin (const char *host, /* {{{ */
+    callback_plugin_t callback,
+    void *user_data)
+{
+  char abspath[PATH_MAX + 1];
+
+  if (host == NULL)
+    return (EINVAL);
+
+  snprintf (abspath, sizeof (abspath), "%s/%s", DATA_DIR, host);
+  abspath[sizeof (abspath) - 1] = 0;
+
+  return (foreach_dir (abspath, callback, user_data));
+} /* }}} int foreach_plugin */
+
+static int foreach_host (callback_host_t callback, /* {{{ */
+    void *user_data)
+{
+  return (foreach_dir (DATA_DIR, callback, user_data));
+} /* }}} int foreach_host */
+
+/*
+ * Functions building "fs_scan_dir_data_t" and calling the user-supplied
+ * callback eventually.
+ */
+static int scan_type (const char *type, void *user_data) /* {{{ */
+{
+  fs_scan_dir_data_t *data = user_data;
+  graph_ident_t *ident;
+  int status;
+
+  if ((type == NULL) || (data == NULL))
+    return (EINVAL);
+
+  if ((data->type != NULL) || (data->type_instance != NULL))
+    return (EINVAL);
+
+  data->type = strdup (type);
+  if (data->type == NULL)
+    return (ENOMEM);
+
+  data->type_instance = strchr (data->type, '-');
+  if (data->type_instance != NULL)
+  {
+    *data->type_instance = 0;
+    data->type_instance++;
+  }
+  else
+  {
+    data->type_instance = data->type + strlen (data->type);
+  }
+
+  ident = ident_create (data->host,
+      data->plugin, data->plugin_instance,
+      data->type, data->type_instance);
+  if (ident == NULL)
+  {
+    status = -1;
+  }
+  else
+  {
+    status = (*data->callback) (ident, data->user_data);
+    ident_destroy (ident);
+  }
+
+  free (data->type);
+  data->type = NULL;
+  data->type_instance = NULL;
+
+  return (status);
+} /* }}} int scan_type */
+
+static int scan_plugin (const char *plugin, void *user_data) /* {{{ */
+{
+  fs_scan_dir_data_t *data = user_data;
+  int status;
+
+  if ((plugin == NULL) || (data == NULL))
+    return (EINVAL);
+
+  if ((data->plugin != NULL) || (data->plugin_instance != NULL))
+    return (EINVAL);
+
+  data->plugin = strdup (plugin);
+  if (data->plugin == NULL)
+    return (ENOMEM);
+
+  data->plugin_instance = strchr (data->plugin, '-');
+  if (data->plugin_instance != NULL)
+  {
+    *data->plugin_instance = 0;
+    data->plugin_instance++;
+  }
+  else
+  {
+    data->plugin_instance = data->plugin + strlen (data->plugin);
+  }
+
+  status = foreach_type (data->host, plugin, scan_type, data);
+
+  free (data->plugin);
+  data->plugin = NULL;
+  data->plugin_instance = NULL;
+
+  return (status);
+} /* }}} int scan_plugin */
+
+static int scan_host (const char *host, void *user_data) /* {{{ */
+{
+  fs_scan_dir_data_t *data = user_data;
+  int status;
+
+  if ((host == NULL) || (data == NULL))
+    return (EINVAL);
+
+  if (data->host != NULL)
+    return (EINVAL);
+
+  data->host = strdup (host);
+  if (data->host == NULL)
+    return (ENOMEM);
+
+  status =  foreach_plugin (host, scan_plugin, data);
+
+  free (data->host);
+  data->host = NULL;
+
+  return (status);
+} /* }}} int scan_host */
+
+/*
+ * Public function
+ */
+int fs_scan (fs_ident_cb_t callback, void *user_data) /* {{{ */
+{
+  fs_scan_dir_data_t data;
+
+  memset (&data, 0, sizeof (data));
+  data.callback = callback;
+  data.user_data = user_data;
+
+  data.host = NULL;
+  data.plugin = NULL;
+  data.plugin_instance = NULL;
+  data.type = NULL;
+  data.type_instance = NULL;
+
+  foreach_host (scan_host, &data);
+
+  return (0);
+} /* }}} int fs_scan */
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/src/filesystem.h b/src/filesystem.h
new file mode 100644 (file)
index 0000000..9569bc3
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef FILESYSTEM_G
+#define FILESYSTEM_G 1
+
+#include "graph_ident.h"
+
+#define DATA_DIR "/var/lib/collectd/rrd"
+
+typedef int (*fs_ident_cb_t) (const graph_ident_t *ident, void *user_data);
+
+int fs_scan (fs_ident_cb_t callback, void *user_data);
+
+#endif /* FILESYSTEM_G */
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/src/graph.c b/src/graph.c
new file mode 100644 (file)
index 0000000..154af77
--- /dev/null
@@ -0,0 +1,290 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <string.h>
+#include <time.h>
+#include <errno.h>
+#include <assert.h>
+
+#include "graph.h"
+#include "graph_list.h"
+#include "graph_ident.h"
+#include "graph_def.h"
+#include "graph_config.h"
+#include "common.h"
+#include "filesystem.h"
+#include "utils_params.h"
+
+#include <fcgiapp.h>
+#include <fcgi_stdio.h>
+
+/*
+ * Data types
+ */
+struct graph_config_s /* {{{ */
+{
+  graph_ident_t *select;
+
+  char *title;
+  char *vertical_label;
+
+  graph_def_t *defs;
+
+  graph_instance_t *instances;
+}; /* }}} struct graph_config_s */
+
+/*
+ * Private functions
+ */
+static graph_instance_t *graph_find_instance (graph_config_t *cfg, /* {{{ */
+    const graph_ident_t *ident)
+{
+  if ((cfg == NULL) || (ident == NULL))
+    return (NULL);
+
+  return (inst_find_matching (cfg->instances, ident));
+} /* }}} graph_instance_t *graph_find_instance */
+
+/*
+ * Config functions
+ */
+static graph_ident_t *graph_config_get_selector (const oconfig_item_t *ci) /* {{{ */
+{
+  char *host = NULL;
+  char *plugin = NULL;
+  char *plugin_instance = NULL;
+  char *type = NULL;
+  char *type_instance = NULL;
+  graph_ident_t *ret;
+  int i;
+
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child;
+
+    child = ci->children + i;
+
+    if (strcasecmp ("Host", child->key) == 0)
+      graph_config_get_string (child, &host);
+    else if (strcasecmp ("Plugin", child->key) == 0)
+      graph_config_get_string (child, &plugin);
+    else if (strcasecmp ("PluginInstance", child->key) == 0)
+      graph_config_get_string (child, &plugin_instance);
+    else if (strcasecmp ("Type", child->key) == 0)
+      graph_config_get_string (child, &type);
+    else if (strcasecmp ("TypeInstance", child->key) == 0)
+      graph_config_get_string (child, &type_instance);
+    /* else: ignore all other directives here. */
+  } /* for */
+
+  ret = ident_create (host, plugin, plugin_instance, type, type_instance);
+
+  free (host);
+  free (plugin);
+  free (plugin_instance);
+  free (type);
+  free (type_instance);
+
+  return (ret);
+} /* }}} int graph_config_get_selector */
+
+/*
+ * Global functions
+ */
+graph_config_t *graph_create (const graph_ident_t *selector) /* {{{ */
+{
+  graph_config_t *cfg;
+
+  cfg = malloc (sizeof (*cfg));
+  if (cfg == NULL)
+    return (NULL);
+  memset (cfg, 0, sizeof (*cfg));
+
+  if (selector != NULL)
+    cfg->select = ident_clone (selector);
+  else
+    cfg->select = NULL;
+
+  cfg->title = NULL;
+  cfg->vertical_label = NULL;
+  cfg->defs = NULL;
+  cfg->instances = NULL;
+
+  return (cfg);
+} /* }}} int graph_create */
+
+void graph_destroy (graph_config_t *cfg) /* {{{ */
+{
+  if (cfg == NULL)
+    return;
+
+  ident_destroy (cfg->select);
+
+  free (cfg->title);
+  free (cfg->vertical_label);
+
+  def_destroy (cfg->defs);
+  inst_destroy (cfg->instances);
+} /* }}} void graph_destroy */
+
+int graph_config_add (const oconfig_item_t *ci) /* {{{ */
+{
+  graph_ident_t *select;
+  graph_config_t *cfg = NULL;
+  int i;
+
+  select = graph_config_get_selector (ci);
+  if (select == NULL)
+    return (EINVAL);
+
+  cfg = graph_create (/* selector = */ NULL);
+  if (cfg == NULL)
+    return (ENOMEM);
+
+  cfg->select = select;
+
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child;
+
+    child = ci->children + i;
+
+    if (strcasecmp ("Title", child->key) == 0)
+      graph_config_get_string (child, &cfg->title);
+    else if (strcasecmp ("VerticalLabel", child->key) == 0)
+      graph_config_get_string (child, &cfg->vertical_label);
+    else if (strcasecmp ("DEF", child->key) == 0)
+      def_config (cfg, child);
+  } /* for */
+
+  gl_add_graph (cfg);
+
+  return (0);
+} /* }}} graph_config_add */
+
+int graph_add_file (graph_config_t *cfg, const graph_ident_t *file) /* {{{ */
+{
+  graph_instance_t *inst;
+
+  inst = graph_find_instance (cfg, file);
+  if (inst == NULL)
+  {
+    inst = inst_create (cfg, file);
+    if (inst == NULL)
+      return (ENOMEM);
+
+    if (cfg->instances == NULL)
+      cfg->instances = inst;
+    else
+      inst_append (cfg->instances, inst);
+  }
+
+  return (inst_add_file (inst, file));
+} /* }}} int graph_add_file */
+
+int graph_get_title (graph_config_t *cfg, /* {{{ */
+    char *buffer, size_t buffer_size)
+{
+  if ((cfg == NULL) || (buffer == NULL) || (buffer_size < 1))
+    return (EINVAL);
+
+  if (cfg->title == NULL)
+    cfg->title = ident_to_string (cfg->select);
+
+  if (cfg->title == NULL)
+    return (ENOMEM);
+
+  strncpy (buffer, cfg->title, buffer_size);
+  buffer[buffer_size - 1] = 0;
+
+  return (0);
+} /* }}} int graph_get_title */
+
+graph_ident_t *graph_get_selector (graph_config_t *cfg) /* {{{ */
+{
+  if (cfg == NULL)
+    return (NULL);
+
+  return (ident_clone (cfg->select));
+} /* }}} graph_ident_t *graph_get_selector */
+
+graph_instance_t *graph_get_instances (graph_config_t *cfg) /* {{{ */
+{
+  if (cfg == NULL)
+    return (NULL);
+
+  return (cfg->instances);
+} /* }}} graph_instance_t *graph_get_instances */
+
+graph_def_t *graph_get_defs (graph_config_t *cfg) /* {{{ */
+{
+  if (cfg == NULL)
+    return (NULL);
+
+  return (cfg->defs);
+} /* }}} graph_def_t *graph_get_defs */
+
+int graph_add_def (graph_config_t *cfg, graph_def_t *def) /* {{{ */
+{
+  if ((cfg == NULL) || (def == NULL))
+    return (EINVAL);
+
+  if (cfg->defs == NULL)
+  {
+    cfg->defs = def;
+    return (0);
+  }
+
+  return (def_append (cfg->defs, def));
+} /* }}} int graph_add_def */
+
+_Bool graph_matches (graph_config_t *cfg, const graph_ident_t *ident) /* {{{ */
+{
+  if ((cfg == NULL) || (ident == NULL))
+    return (0);
+
+  return (ident_matches (cfg->select, ident));
+} /* }}} _Bool graph_matches */
+
+int graph_compare (graph_config_t *cfg, const graph_ident_t *ident) /* {{{ */
+{
+  if ((cfg == NULL) || (ident == NULL))
+    return (0);
+
+  return (ident_compare (cfg->select, ident));
+} /* }}} int graph_compare */
+
+int graph_clear_instances (graph_config_t *cfg) /* {{{ */
+{
+  if (cfg == NULL)
+    return (EINVAL);
+
+  inst_destroy (cfg->instances);
+  cfg->instances = NULL;
+
+  return (0);
+} /* }}} int graph_clear_instances */
+
+int graph_get_rrdargs (graph_config_t *cfg, graph_instance_t *inst, /* {{{ */
+    str_array_t *args)
+{
+  if ((cfg == NULL) || (inst == NULL) || (args == NULL))
+    return (EINVAL);
+
+  if (cfg->title != NULL)
+  {
+    array_append (args, "-t");
+    array_append (args, cfg->title);
+  }
+
+  if (cfg->vertical_label != NULL)
+  {
+    array_append (args, "-v");
+    array_append (args, cfg->vertical_label);
+  }
+
+  return (0);
+} /* }}} int graph_get_rrdargs */
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/src/graph.h b/src/graph.h
new file mode 100644 (file)
index 0000000..6e9ae07
--- /dev/null
@@ -0,0 +1,48 @@
+#ifndef GRAPH_H
+#define GRAPH_H 1
+
+/*
+ * Data types
+ */
+struct graph_config_s;
+typedef struct graph_config_s graph_config_t;
+
+#include "graph_def.h"
+#include "graph_ident.h"
+#include "graph_instance.h"
+#include "oconfig.h"
+#include "utils_array.h"
+
+/*
+ * Functions
+ */
+graph_config_t *graph_create (const graph_ident_t *selector);
+
+void graph_destroy (graph_config_t *graph);
+
+int graph_config_add (const oconfig_item_t *ci);
+
+int graph_add_file (graph_config_t *cfg, const graph_ident_t *file);
+
+int graph_get_title (graph_config_t *cfg,
+    char *buffer, size_t buffer_size);
+
+graph_ident_t *graph_get_selector (graph_config_t *cfg);
+
+graph_instance_t *graph_get_instances (graph_config_t *cfg);
+
+graph_def_t *graph_get_defs (graph_config_t *cfg);
+
+int graph_add_def (graph_config_t *cfg, graph_def_t *def);
+
+_Bool graph_matches (graph_config_t *cfg, const graph_ident_t *ident);
+
+int graph_compare (graph_config_t *cfg, const graph_ident_t *ident);
+
+int graph_clear_instances (graph_config_t *cfg);
+
+int graph_get_rrdargs (graph_config_t *cfg, graph_instance_t *inst,
+    str_array_t *args);
+
+#endif /* GRAPH_H */
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/src/graph_config.c b/src/graph_config.c
new file mode 100644 (file)
index 0000000..94dd440
--- /dev/null
@@ -0,0 +1,116 @@
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <strings.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+#include "graph_config.h"
+#include "graph_list.h"
+#include "oconfig.h"
+#include "common.h"
+
+#define CONFIG_FILE "/usr/lib/cgi-bin/octo/collection.conf"
+
+time_t last_read_mtime = 0;
+
+static int dispatch_config (const oconfig_item_t *ci) /* {{{ */
+{
+  int i;
+
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child;
+
+    child = ci->children + i;
+    if (strcasecmp ("Graph", child->key) == 0)
+      graph_config_add (child);
+    else
+    {
+      DEBUG ("Unknown config option: %s", child->key);
+    }
+  }
+
+  return (0);
+} /* }}} int dispatch_config */
+
+static int internal_read_config (void) /* {{{ */
+{
+  oconfig_item_t *ci;
+
+  ci = oconfig_parse_file (CONFIG_FILE);
+  if (ci == NULL)
+    return (-1);
+
+  dispatch_config (ci);
+
+  oconfig_free (ci);
+
+  gl_config_submit ();
+
+  return (0);
+} /* }}} int internal_read_config */
+
+static time_t get_config_mtime (void) /* {{{ */
+{
+  struct stat statbuf;
+  int status;
+
+  memset (&statbuf, 0, sizeof (statbuf));
+  status = stat (CONFIG_FILE, &statbuf);
+  if (status != 0)
+    return (0);
+
+  return (statbuf.st_mtime);
+} /* }}} time_t get_config_mtime */
+
+int graph_read_config (void) /* {{{ */
+{
+  time_t mtime;
+
+  mtime = get_config_mtime ();
+
+  if (mtime <= last_read_mtime)
+    return (0);
+
+  internal_read_config ();
+
+  last_read_mtime = mtime;
+
+  return (0);
+} /* }}} int graph_read_config */
+
+int graph_config_get_string (const oconfig_item_t *ci, /* {{{ */
+    char **ret_str)
+{
+  char *tmp;
+
+  if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
+    return (EINVAL);
+
+  tmp = strdup (ci->values[0].value.string);
+  if (tmp == NULL)
+    return (ENOMEM);
+
+  free (*ret_str);
+  *ret_str = tmp;
+
+  return (0);
+} /* }}} int graph_config_get_string */
+
+int graph_config_get_bool (const oconfig_item_t *ci, /* {{{ */
+    _Bool *ret_bool)
+{
+  if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_BOOLEAN))
+    return (EINVAL);
+
+  if (ci->values[0].value.boolean)
+    *ret_bool = 1;
+  else
+    *ret_bool = 0;
+
+  return (0);
+} /* }}} int graph_config_get_bool */
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/src/graph_config.h b/src/graph_config.h
new file mode 100644 (file)
index 0000000..c468eec
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef GRAPH_CONFIG_H
+#define GRAPH_CONFIG_H 1
+
+#include "oconfig.h"
+
+int graph_read_config (void);
+
+int graph_config_get_string (const oconfig_item_t *ci, char **ret_str);
+int graph_config_get_bool (const oconfig_item_t *ci, _Bool *ret_bool);
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
+#endif /* GRAPH_CONFIG_H */
diff --git a/src/graph_def.c b/src/graph_def.c
new file mode 100644 (file)
index 0000000..b8e0ce4
--- /dev/null
@@ -0,0 +1,348 @@
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "graph_def.h"
+#include "graph.h"
+#include "graph_config.h"
+#include "common.h"
+#include "oconfig.h"
+
+#include <fcgiapp.h>
+#include <fcgi_stdio.h>
+
+/*
+ * Data structures
+ */
+struct graph_def_s
+{
+  graph_ident_t *select;
+
+  char *ds_name;
+  char *legend;
+  uint32_t color;
+  _Bool stack;
+  _Bool area;
+  char *format;
+
+  graph_def_t *next;
+};
+
+/*
+ * Private functions
+ */
+#define DEF_CONFIG_FIELD(field) \
+static int def_config_##field (const oconfig_item_t *ci, graph_ident_t *ident) \
+{                                                                              \
+  char *tmp = NULL;                                                            \
+  int status = graph_config_get_string (ci, &tmp);                             \
+  if (status != 0)                                                             \
+    return (status);                                                           \
+  ident_set_##field (ident, tmp);                                              \
+  free (tmp);                                                                  \
+  return (0);                                                                  \
+} /* }}} int def_config_field */
+
+DEF_CONFIG_FIELD (host);
+DEF_CONFIG_FIELD (plugin);
+DEF_CONFIG_FIELD (plugin_instance);
+DEF_CONFIG_FIELD (type);
+DEF_CONFIG_FIELD (type_instance);
+
+#undef DEF_CONFIG_FIELD
+
+static int def_config_color (const oconfig_item_t *ci, uint32_t *ret_color) /* {{{ */
+{
+  char *tmp;
+  char *endptr;
+  uint32_t color;
+
+  if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
+    return (EINVAL);
+
+  tmp = ci->values[0].value.string;
+
+  endptr = NULL;
+  errno = 0;
+  color = (uint32_t) strtoul (tmp, &endptr, /* base = */ 16);
+  if ((errno != 0) || (endptr == tmp) || (color > 0x00ffffff))
+    return (EINVAL);
+
+  *ret_color = color;
+
+  return (0);
+} /* }}} int def_config_color */
+
+static graph_def_t *def_config_get_obj (graph_config_t *cfg, /* {{{ */
+    const oconfig_item_t *ci)
+{
+  graph_ident_t *ident;
+  char *ds_name = NULL;
+  graph_def_t *def;
+  int i;
+
+  ident = graph_get_selector (cfg);
+  if (ident == NULL)
+  {
+    fprintf (stderr, "def_config_get_obj: graph_get_selector failed");
+    return (NULL);
+  }
+
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child;
+
+#define HANDLE_FIELD(name,field) \
+    else if (strcasecmp (name, child->key) == 0) \
+      def_config_##field (child, ident)
+
+    child = ci->children + i;
+    if (strcasecmp ("DSName", child->key) == 0)
+      graph_config_get_string (child, &ds_name);
+
+    HANDLE_FIELD ("Host", host);
+    HANDLE_FIELD ("Plugin", plugin);
+    HANDLE_FIELD ("PluginInstance", plugin_instance);
+    HANDLE_FIELD ("Type", type);
+    HANDLE_FIELD ("TypeInstance", type_instance);
+
+#undef HANDLE_FIELD
+  }
+
+  def = def_create (cfg, ident, ds_name);
+  if (def == NULL)
+  {
+    fprintf (stderr, "def_config_get_obj: def_create failed\n");
+    ident_destroy (ident);
+    free (ds_name);
+    return (NULL);
+  }
+
+  ident_destroy (ident);
+  free (ds_name);
+
+  return (def);
+} /* }}} graph_def_t *def_config_get_obj */
+
+/*
+ * Public functions
+ */
+graph_def_t *def_create (graph_config_t *cfg, graph_ident_t *ident, /* {{{ */
+    const char *ds_name)
+{
+  graph_ident_t *selector;
+  graph_def_t *ret;
+
+  if ((cfg == NULL) || (ident == NULL) || (ds_name == NULL))
+    return (NULL);
+
+  selector = graph_get_selector (cfg);
+  if (selector == NULL)
+    return (NULL);
+
+  ret = malloc (sizeof (*ret));
+  if (ret == NULL)
+  {
+    ident_destroy (selector);
+    return (NULL);
+  }
+  memset (ret, 0, sizeof (*ret));
+  ret->legend = NULL;
+  ret->format = NULL;
+
+  ret->ds_name = strdup (ds_name);
+  if (ret->ds_name == NULL)
+  {
+    ident_destroy (selector);
+    free (ret);
+    return (NULL);
+  }
+
+  ret->color = get_random_color ();
+  ret->next = NULL;
+
+  ret->select = ident_copy_with_selector (selector, ident,
+      IDENT_FLAG_REPLACE_ALL);
+  if (ret->select == NULL)
+  {
+    ident_destroy (selector);
+    free (ret->ds_name);
+    free (ret);
+    return (NULL);
+  }
+
+  ident_destroy (selector);
+  return (ret);
+} /* }}} graph_def_t *def_create */
+
+void def_destroy (graph_def_t *def) /* {{{ */
+{
+  graph_def_t *next;
+
+  if (def == NULL)
+    return;
+
+  next = def->next;
+
+  ident_destroy (def->select);
+
+  free (def->ds_name);
+  free (def->legend);
+  free (def->format);
+
+  free (def);
+
+  def_destroy (next);
+} /* }}} void def_destroy */
+
+int def_config (graph_config_t *cfg, const oconfig_item_t *ci) /* {{{ */
+{
+  graph_def_t *def;
+  int i;
+
+  def = def_config_get_obj (cfg, ci);
+  if (def == NULL)
+    return (EINVAL);
+
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child;
+
+    child = ci->children + i;
+    if (strcasecmp ("Legend", child->key) == 0)
+      graph_config_get_string (child, &def->legend);
+    else if (strcasecmp ("Color", child->key) == 0)
+      def_config_color (child, &def->color);
+    else if (strcasecmp ("Stack", child->key) == 0)
+      graph_config_get_bool (child, &def->stack);
+    else if (strcasecmp ("Area", child->key) == 0)
+      graph_config_get_bool (child, &def->area);
+    else if (strcasecmp ("Format", child->key) == 0)
+      graph_config_get_string (child, &def->format);
+    else
+      fprintf (stderr, "def_config: Ignoring unknown config option \"%s\"",
+          child->key);
+  }
+
+  return (graph_add_def (cfg, def));
+} /* }}} int def_config */
+
+int def_append (graph_def_t *head, graph_def_t *def) /* {{{ */
+{
+  graph_def_t *ptr;
+
+  if ((head == NULL) || (def == NULL))
+    return (EINVAL);
+
+  ptr = head;
+  while (ptr->next != NULL)
+    ptr = ptr->next;
+
+  ptr->next = def;
+
+  return (0);
+} /* }}} int def_append */
+
+graph_def_t *def_search (graph_def_t *head, graph_ident_t *ident, /* {{{ */
+    const char *ds_name)
+{
+  graph_def_t *ptr;
+
+  if ((head == NULL) || (ident == NULL) || (ds_name == NULL))
+    return (NULL);
+
+  for (ptr = head; ptr != NULL; ptr = ptr->next)
+  {
+    if (!ident_matches (ptr->select, ident))
+      continue;
+
+    if (strcmp (ptr->ds_name, ds_name) == 0)
+      return (ptr);
+  }
+
+  return (NULL);
+} /* }}} graph_def_t *def_search */
+
+_Bool def_matches (graph_def_t *def, graph_ident_t *ident) /* {{{ */
+{
+  return (ident_matches (def->select, ident));
+} /* }}} _Bool def_matches */
+
+int def_foreach (graph_def_t *def, def_callback_t callback, /* {{{ */
+    void *user_data)
+{
+  graph_def_t *ptr;
+
+  if ((def == NULL) || (callback == NULL))
+    return (EINVAL);
+
+  for (ptr = def; ptr != NULL; ptr = ptr->next)
+  {
+    int status;
+
+    status = (*callback) (ptr, user_data);
+    if (status != 0)
+      return (status);
+  }
+
+  return (0);
+} /* }}} int def_foreach */
+
+int def_get_rrdargs (graph_def_t *def, graph_ident_t *ident, /* {{{ */
+    str_array_t *args)
+{
+  char *file;
+  int index;
+
+  if ((def == NULL) || (ident == NULL) || (args == NULL))
+    return (EINVAL);
+
+  file = ident_to_file (ident);
+  if (file == NULL)
+  {
+    DEBUG ("gl_ident_get_rrdargs: ident_to_file returned NULL.\n");
+    return (-1);
+  }
+
+  DEBUG ("gl_ident_get_rrdargs: file = %s;\n", file);
+
+  index = array_argc (args);
+
+  /* CDEFs */
+  array_append_format (args, "DEF:def_%04i_min=%s:%s:MIN",
+      index, file, def->ds_name);
+  array_append_format (args, "DEF:def_%04i_avg=%s:%s:AVERAGE",
+      index, file, def->ds_name);
+  array_append_format (args, "DEF:def_%04i_max=%s:%s:MAX",
+      index, file, def->ds_name);
+  /* VDEFs */
+  array_append_format (args, "VDEF:vdef_%04i_min=def_%04i_min,MINIMUM",
+      index, index);
+  array_append_format (args, "VDEF:vdef_%04i_avg=def_%04i_avg,AVERAGE",
+      index, index);
+  array_append_format (args, "VDEF:vdef_%04i_max=def_%04i_max,MAXIMUM",
+      index, index);
+  array_append_format (args, "VDEF:vdef_%04i_lst=def_%04i_avg,LAST",
+      index, index);
+
+  /* Graph part */
+  array_append_format (args, "%s:def_%04i_avg#%06"PRIx32":%s%s",
+      def->area ? "AREA" : "LINE1",
+      index, def->color,
+      (def->legend != NULL) ? def->legend : def->ds_name,
+      def->stack ? ":STACK" : "");
+  array_append_format (args, "GPRINT:vdef_%04i_min:%s min,",
+      index, (def->format != NULL) ? def->format : "%lg");
+  array_append_format (args, "GPRINT:vdef_%04i_avg:%s avg,",
+      index, (def->format != NULL) ? def->format : "%lg");
+  array_append_format (args, "GPRINT:vdef_%04i_max:%s max,",
+      index, (def->format != NULL) ? def->format : "%lg");
+  array_append_format (args, "GPRINT:vdef_%04i_lst:%s last\\l",
+      index, (def->format != NULL) ? def->format : "%lg");
+
+  free (file);
+
+  return (0);
+} /* }}} int def_get_rrdargs */
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/src/graph_def.h b/src/graph_def.h
new file mode 100644 (file)
index 0000000..b2cd228
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef GRAPH_DEF_H
+#define GRAPH_DEF_H 1
+
+struct graph_def_s;
+typedef struct graph_def_s graph_def_t;
+
+typedef int (*def_callback_t) (graph_def_t *def,
+    void *user_data);
+
+#include "graph.h"
+#include "graph_ident.h"
+#include "utils_array.h"
+#include "oconfig.h"
+
+graph_def_t *def_create (graph_config_t *cfg, graph_ident_t *ident,
+    const char *ds_name);
+
+void def_destroy (graph_def_t *def);
+
+int def_config (graph_config_t *cfg, const oconfig_item_t *ci);
+
+int def_append (graph_def_t *head, graph_def_t *def);
+
+graph_def_t *def_search (graph_def_t *head, graph_ident_t *ident,
+    const char *ds_name);
+
+_Bool def_matches (graph_def_t *def, graph_ident_t *ident);
+
+int def_foreach (graph_def_t *def, def_callback_t callback, void *user_data);
+
+int def_get_rrdargs (graph_def_t *def, graph_ident_t *ident,
+    str_array_t *args);
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
+#endif
diff --git a/src/graph_ident.c b/src/graph_ident.c
new file mode 100644 (file)
index 0000000..b008a56
--- /dev/null
@@ -0,0 +1,455 @@
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <errno.h>
+#include <limits.h> /* PATH_MAX */
+
+#include "graph_ident.h"
+#include "common.h"
+#include "filesystem.h"
+
+/*
+ * Data types
+ */
+struct graph_ident_s /* {{{ */
+{
+  char *host;
+  char *plugin;
+  char *plugin_instance;
+  char *type;
+  char *type_instance;
+}; /* }}} struct graph_ident_s */
+
+/*
+ * Private functions
+ */
+static char *part_copy_with_selector (const char *selector, /* {{{ */
+    const char *part, unsigned int flags)
+{
+  if ((selector == NULL) || (part == NULL))
+    return (NULL);
+
+  if ((flags & IDENT_FLAG_REPLACE_ANY) && IS_ANY (part))
+    return (NULL);
+
+  if ((flags & IDENT_FLAG_REPLACE_ALL) && IS_ALL (part))
+    return (NULL);
+
+  /* Replace the ANY and ALL flags if requested and if the selecter actually
+   * *is* that flag. */
+  if (IS_ANY (selector))
+  {
+    if (flags & IDENT_FLAG_REPLACE_ANY)
+      return (strdup (part));
+    else
+      return (strdup (selector));
+  }
+
+  if (IS_ALL (selector))
+  {
+    if (flags & IDENT_FLAG_REPLACE_ALL)
+      return (strdup (part));
+    else
+      return (strdup (selector));
+  }
+
+  if (strcmp (selector, part) != 0)
+    return (NULL);
+
+  /* Otherwise (no replacement), return a copy of the selector. */
+  return (strdup (selector));
+} /* }}} char *part_copy_with_selector */
+
+static _Bool part_matches (const char *selector, /* {{{ */
+    const char *part)
+{
+  if ((selector == NULL) && (part == NULL))
+    return (1);
+
+  if (selector == NULL) /* && (part != NULL) */
+    return (0);
+
+  if (IS_ANY(selector) || IS_ALL(selector))
+    return (1);
+
+  if (part == NULL) /* && (selector != NULL) */
+    return (0);
+
+  if (strcmp (selector, part) == 0)
+    return (1);
+
+  return (0);
+} /* }}} _Bool part_matches */
+
+/*
+ * Public functions
+ */
+graph_ident_t *ident_create (const char *host, /* {{{ */
+    const char *plugin, const char *plugin_instance,
+    const char *type, const char *type_instance)
+{
+  graph_ident_t *ret;
+
+  if ((host == NULL)
+      || (plugin == NULL) || (plugin_instance == NULL)
+      || (type == NULL) || (type_instance == NULL))
+    return (NULL);
+
+  ret = malloc (sizeof (*ret));
+  if (ret == NULL)
+    return (NULL);
+  memset (ret, 0, sizeof (*ret));
+
+  ret->host = NULL;
+  ret->host = NULL;
+  ret->plugin = NULL;
+  ret->plugin_instance = NULL;
+  ret->type = NULL;
+  ret->type_instance = NULL;
+
+#define COPY_PART(p) do {        \
+  ret->p = strdup (p);           \
+  if (ret->p == NULL)            \
+  {                              \
+    free (ret->host);            \
+    free (ret->plugin);          \
+    free (ret->plugin_instance); \
+    free (ret->type);            \
+    free (ret->type_instance);   \
+    free (ret);                  \
+    return (NULL);               \
+  }                              \
+} while (0)
+
+  COPY_PART(host);
+  COPY_PART(plugin);
+  COPY_PART(plugin_instance);
+  COPY_PART(type);
+  COPY_PART(type_instance);
+
+#undef COPY_PART
+
+  return (ret);
+} /* }}} graph_ident_t *ident_create */
+
+graph_ident_t *ident_clone (const graph_ident_t *ident) /* {{{ */
+{
+  return (ident_create (ident->host,
+        ident->plugin, ident->plugin_instance,
+        ident->type, ident->type_instance));
+} /* }}} graph_ident_t *ident_clone */
+
+graph_ident_t *ident_copy_with_selector (const graph_ident_t *selector, /* {{{ */
+    const graph_ident_t *ident, unsigned int flags)
+{
+  graph_ident_t *ret;
+
+  if ((selector == NULL) || (ident == NULL))
+    return (NULL);
+
+  ret = malloc (sizeof (*ret));
+  if (ret == NULL)
+    return (NULL);
+  memset (ret, 0, sizeof (*ret));
+  ret->host = NULL;
+  ret->plugin = NULL;
+  ret->plugin_instance = NULL;
+  ret->type = NULL;
+  ret->type_instance = NULL;
+
+#define COPY_PART(p) do {                                  \
+  ret->p = part_copy_with_selector (selector->p, ident->p, flags); \
+  if (ret->p == NULL)                                      \
+  {                                                        \
+    free (ret->host);                                      \
+    free (ret->plugin);                                    \
+    free (ret->plugin_instance);                           \
+    free (ret->type);                                      \
+    free (ret->type_instance);                             \
+    return (NULL);                                         \
+  }                                                        \
+} while (0)
+
+  COPY_PART (host);
+  COPY_PART (plugin);
+  COPY_PART (plugin_instance);
+  COPY_PART (type);
+  COPY_PART (type_instance);
+
+#undef COPY_PART
+
+  return (ret);
+} /* }}} graph_ident_t *ident_copy_with_selector */
+
+void ident_destroy (graph_ident_t *ident) /* {{{ */
+{
+  if (ident == NULL)
+    return;
+
+  free (ident->host);
+  free (ident->plugin);
+  free (ident->plugin_instance);
+  free (ident->type);
+  free (ident->type_instance);
+
+  free (ident);
+} /* }}} void ident_destroy */
+
+/* ident_get_* methods {{{ */
+const char *ident_get_host (graph_ident_t *ident) /* {{{ */
+{
+  if (ident == NULL)
+    return (NULL);
+
+  return (ident->host);
+} /* }}} char *ident_get_host */
+
+const char *ident_get_plugin (graph_ident_t *ident) /* {{{ */
+{
+  if (ident == NULL)
+    return (NULL);
+
+  return (ident->plugin);
+} /* }}} char *ident_get_plugin */
+
+const char *ident_get_plugin_instance (graph_ident_t *ident) /* {{{ */
+{
+  if (ident == NULL)
+    return (NULL);
+
+  return (ident->plugin_instance);
+} /* }}} char *ident_get_plugin_instance */
+
+const char *ident_get_type (graph_ident_t *ident) /* {{{ */
+{
+  if (ident == NULL)
+    return (NULL);
+
+  return (ident->type);
+} /* }}} char *ident_get_type */
+
+const char *ident_get_type_instance (graph_ident_t *ident) /* {{{ */
+{
+  if (ident == NULL)
+    return (NULL);
+
+  return (ident->type_instance);
+} /* }}} char *ident_get_type_instance */
+/* }}} ident_get_* methods */
+
+/* ident_set_* methods {{{ */
+int ident_set_host (graph_ident_t *ident, const char *host) /* {{{ */
+{
+  char *tmp;
+
+  if ((ident == NULL) || (host == NULL))
+    return (EINVAL);
+
+  tmp = strdup (host);
+  if (tmp == NULL)
+    return (ENOMEM);
+
+  free (ident->host);
+  ident->host = tmp;
+
+  return (0);
+} /* }}} int ident_set_host */
+
+int ident_set_plugin (graph_ident_t *ident, const char *plugin) /* {{{ */
+{
+  char *tmp;
+
+  if ((ident == NULL) || (plugin == NULL))
+    return (EINVAL);
+
+  tmp = strdup (plugin);
+  if (tmp == NULL)
+    return (ENOMEM);
+
+  free (ident->plugin);
+  ident->plugin = tmp;
+
+  return (0);
+} /* }}} int ident_set_plugin */
+
+int ident_set_plugin_instance (graph_ident_t *ident, const char *plugin_instance) /* {{{ */
+{
+  char *tmp;
+
+  if ((ident == NULL) || (plugin_instance == NULL))
+    return (EINVAL);
+
+  tmp = strdup (plugin_instance);
+  if (tmp == NULL)
+    return (ENOMEM);
+
+  free (ident->plugin_instance);
+  ident->plugin_instance = tmp;
+
+  return (0);
+} /* }}} int ident_set_plugin_instance */
+
+int ident_set_type (graph_ident_t *ident, const char *type) /* {{{ */
+{
+  char *tmp;
+
+  if ((ident == NULL) || (type == NULL))
+    return (EINVAL);
+
+  tmp = strdup (type);
+  if (tmp == NULL)
+    return (ENOMEM);
+
+  free (ident->type);
+  ident->type = tmp;
+
+  return (0);
+} /* }}} int ident_set_type */
+
+int ident_set_type_instance (graph_ident_t *ident, const char *type_instance) /* {{{ */
+{
+  char *tmp;
+
+  if ((ident == NULL) || (type_instance == NULL))
+    return (EINVAL);
+
+  tmp = strdup (type_instance);
+  if (tmp == NULL)
+    return (ENOMEM);
+
+  free (ident->type_instance);
+  ident->type_instance = tmp;
+
+  return (0);
+} /* }}} int ident_set_type_instance */
+
+/* }}} ident_set_* methods */
+
+int ident_compare (const graph_ident_t *i0, /* {{{ */
+    const graph_ident_t *i1)
+{
+  int status;
+
+#define COMPARE_PART(p) do {       \
+  status = strcmp (i0->p, i1->p);  \
+  if (status != 0)                 \
+    return (status);               \
+} while (0)
+
+  COMPARE_PART (host);
+  COMPARE_PART (plugin);
+  COMPARE_PART (plugin_instance);
+  COMPARE_PART (type);
+  COMPARE_PART (type_instance);
+
+#undef COMPARE_PART
+
+  return (0);
+} /* }}} int ident_compare */
+
+_Bool ident_matches (const graph_ident_t *selector, /* {{{ */
+    const graph_ident_t *ident)
+{
+  if ((selector == NULL) && (ident == NULL))
+    return (0);
+  else if (selector == NULL)
+    return (-1);
+  else if (ident == NULL)
+    return (1);
+
+  if (!part_matches (selector->host, ident->host))
+    return (0);
+
+  if (!part_matches (selector->plugin, ident->plugin))
+    return (0);
+
+  if (!part_matches (selector->plugin_instance, ident->plugin_instance))
+    return (0);
+
+  if (!part_matches (selector->type, ident->type))
+    return (0);
+
+  if (!part_matches (selector->type_instance, ident->type_instance))
+    return (0);
+
+  return (1);
+} /* }}} _Bool ident_matches */
+
+char *ident_to_string (const graph_ident_t *ident) /* {{{ */
+{
+  char buffer[PATH_MAX];
+
+  buffer[0] = 0;
+
+  strlcat (buffer, ident->host, sizeof (buffer));
+  strlcat (buffer, "/", sizeof (buffer));
+  strlcat (buffer, ident->plugin, sizeof (buffer));
+  if (ident->plugin_instance[0] != 0)
+  {
+    strlcat (buffer, "-", sizeof (buffer));
+    strlcat (buffer, ident->plugin_instance, sizeof (buffer));
+  }
+  strlcat (buffer, "/", sizeof (buffer));
+  strlcat (buffer, ident->type, sizeof (buffer));
+  if (ident->type_instance[0] != 0)
+  {
+    strlcat (buffer, "-", sizeof (buffer));
+    strlcat (buffer, ident->type_instance, sizeof (buffer));
+  }
+
+  return (strdup (buffer));
+} /* }}} char *ident_to_string */
+
+char *ident_to_file (const graph_ident_t *ident) /* {{{ */
+{
+  char buffer[PATH_MAX];
+
+  buffer[0] = 0;
+
+  strlcat (buffer, DATA_DIR, sizeof (buffer));
+  strlcat (buffer, "/", sizeof (buffer));
+
+  strlcat (buffer, ident->host, sizeof (buffer));
+  strlcat (buffer, "/", sizeof (buffer));
+  strlcat (buffer, ident->plugin, sizeof (buffer));
+  if (ident->plugin_instance[0] != 0)
+  {
+    strlcat (buffer, "-", sizeof (buffer));
+    strlcat (buffer, ident->plugin_instance, sizeof (buffer));
+  }
+  strlcat (buffer, "/", sizeof (buffer));
+  strlcat (buffer, ident->type, sizeof (buffer));
+  if (ident->type_instance[0] != 0)
+  {
+    strlcat (buffer, "-", sizeof (buffer));
+    strlcat (buffer, ident->type_instance, sizeof (buffer));
+  }
+
+  strlcat (buffer, ".rrd", sizeof (buffer));
+
+  return (strdup (buffer));
+} /* }}} char *ident_to_file */
+
+char *ident_to_json (const graph_ident_t *ident) /* {{{ */
+{
+  char buffer[4096];
+
+  buffer[0] = 0;
+
+  strlcat (buffer, "{\"host\":\"", sizeof (buffer));
+  strlcat (buffer, ident->host, sizeof (buffer));
+  strlcat (buffer, "\",\"plugin\":\"", sizeof (buffer));
+  strlcat (buffer, ident->plugin, sizeof (buffer));
+  strlcat (buffer, "\",\"plugin_instance\":\"", sizeof (buffer));
+  strlcat (buffer, ident->plugin_instance, sizeof (buffer));
+  strlcat (buffer, "\",\"type\":\"", sizeof (buffer));
+  strlcat (buffer, ident->type, sizeof (buffer));
+  strlcat (buffer, "\",\"type_instance\":\"", sizeof (buffer));
+  strlcat (buffer, ident->type_instance, sizeof (buffer));
+  strlcat (buffer, "\"}", sizeof (buffer));
+
+  return (strdup (buffer));
+} /* }}} char *ident_to_json */
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
+
diff --git a/src/graph_ident.h b/src/graph_ident.h
new file mode 100644 (file)
index 0000000..5107011
--- /dev/null
@@ -0,0 +1,50 @@
+#ifndef GRAPH_IDENT_H
+#define GRAPH_IDENT_H 1
+
+#define ANY_TOKEN "/any/"
+#define ALL_TOKEN "/all/"
+
+#define IS_ANY(str) (((str) != NULL) && (strcasecmp (ANY_TOKEN, (str)) == 0))
+#define IS_ALL(str) (((str) != NULL) && (strcasecmp (ALL_TOKEN, (str)) == 0))
+
+struct graph_ident_s;
+typedef struct graph_ident_s graph_ident_t;
+
+graph_ident_t *ident_create (const char *host,
+    const char *plugin, const char *plugin_instance,
+    const char *type, const char *type_instance);
+graph_ident_t *ident_clone (const graph_ident_t *ident);
+
+#define IDENT_FLAG_REPLACE_ALL 0x01
+#define IDENT_FLAG_REPLACE_ANY 0x02
+graph_ident_t *ident_copy_with_selector (const graph_ident_t *selector,
+    const graph_ident_t *ident, unsigned int flags);
+
+void ident_destroy (graph_ident_t *ident);
+
+const char *ident_get_host (graph_ident_t *ident);
+const char *ident_get_plugin (graph_ident_t *ident);
+const char *ident_get_plugin_instance (graph_ident_t *ident);
+const char *ident_get_type (graph_ident_t *ident);
+const char *ident_get_type_instance (graph_ident_t *ident);
+
+int ident_set_host (graph_ident_t *ident, const char *host);
+int ident_set_plugin (graph_ident_t *ident, const char *plugin);
+int ident_set_plugin_instance (graph_ident_t *ident,
+    const char *plugin_instance);
+int ident_set_type (graph_ident_t *ident, const char *type);
+int ident_set_type_instance (graph_ident_t *ident,
+    const char *type_instance);
+
+int ident_compare (const graph_ident_t *i0,
+    const graph_ident_t *i1);
+
+_Bool ident_matches (const graph_ident_t *selector,
+               const graph_ident_t *ident);
+
+char *ident_to_string (const graph_ident_t *ident);
+char *ident_to_file (const graph_ident_t *ident);
+char *ident_to_json (const graph_ident_t *ident);
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
+#endif /* GRAPH_IDENT_H */
diff --git a/src/graph_instance.c b/src/graph_instance.c
new file mode 100644 (file)
index 0000000..103be23
--- /dev/null
@@ -0,0 +1,475 @@
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "graph_instance.h"
+#include "graph_ident.h"
+#include "graph_list.h"
+#include "common.h"
+#include "utils_params.h"
+
+#include <fcgiapp.h>
+#include <fcgi_stdio.h>
+
+struct graph_instance_s /* {{{ */
+{
+  graph_ident_t *select;
+
+  graph_ident_t **files;
+  size_t files_num;
+
+  graph_instance_t *next;
+}; /* }}} struct graph_instance_s */
+
+struct def_callback_data_s
+{
+  graph_instance_t *inst;
+  str_array_t *args;
+};
+typedef struct def_callback_data_s def_callback_data_t;
+
+/*
+ * Private functions
+ */
+/* Create one DEF for each data source in the file. Called by
+ * "inst_get_default_defs" for each file. */
+static graph_def_t *ident_get_default_defs (graph_config_t *cfg, /* {{{ */
+    graph_ident_t *ident, graph_def_t *def_head)
+{
+  graph_def_t *defs = NULL;
+  char *file;
+  char **dses = NULL;
+  size_t dses_num = 0;
+  int status;
+  size_t i;
+
+  if ((cfg == NULL) || (ident == NULL))
+    return (def_head);
+
+  file = ident_to_file (ident);
+  if (file == NULL)
+  {
+    fprintf (stderr, "ident_get_default_defs: ident_to_file failed\n");
+    return (def_head);
+  }
+
+  status = ds_list_from_rrd_file (file, &dses_num, &dses);
+  if (status != 0)
+  {
+    free (file);
+    return (def_head);
+  }
+
+  for (i = 0; i < dses_num; i++)
+  {
+    graph_def_t *def;
+
+    def = def_search (def_head, ident, dses[i]);
+    if (def != NULL)
+      continue;
+
+    def = def_create (cfg, ident, dses[i]);
+    if (def == NULL)
+      continue;
+
+    if (defs == NULL)
+      defs = def;
+    else
+      def_append (defs, def);
+
+    free (dses[i]);
+  }
+
+  free (dses);
+  free (file);
+
+  return (defs);
+} /* }}} int ident_get_default_defs */
+
+/* Create one or more DEFs for each file in the graph instance. The number
+ * depends on the number of data sources in each of the files. Called from
+ * "inst_get_rrdargs" if no DEFs are available from the configuration.
+ * */
+static graph_def_t *inst_get_default_defs (graph_config_t *cfg, /* {{{ */
+    graph_instance_t *inst)
+{
+  graph_def_t *defs = NULL;
+  size_t i;
+
+  if ((cfg == NULL) || (inst == NULL))
+    return (NULL);
+
+  for (i = 0; i < inst->files_num; i++)
+  {
+    graph_def_t *def;
+
+    def = ident_get_default_defs (cfg, inst->files[i], defs);
+    if (def == NULL)
+      continue;
+
+    if (defs == NULL)
+      defs = def;
+    else
+      def_append (defs, def);
+  }
+
+  return (defs);
+} /* }}} graph_def_t *inst_get_default_defs */
+
+/* Called with each DEF in turn. Calls "def_get_rrdargs" with every appropriate
+ * file / DEF pair. */
+static int gl_instance_get_rrdargs_cb (graph_def_t *def, void *user_data) /* {{{ */
+{
+  def_callback_data_t *data = user_data;
+  graph_instance_t *inst = data->inst;
+  str_array_t *args = data->args;
+
+  size_t i;
+
+  for (i = 0; i < inst->files_num; i++)
+  {
+    if (!def_matches (def, inst->files[i]))
+      continue;
+
+    def_get_rrdargs (def, inst->files[i], args);
+  }
+
+  return (0);
+} /* }}} int gl_instance_get_rrdargs_cb */
+
+static const char *get_part_from_param (const char *prim_key, /* {{{ */
+    const char *sec_key)
+{
+  const char *val;
+
+  val = param (prim_key);
+  if (val != NULL)
+    return (val);
+  
+  return (param (sec_key));
+} /* }}} const char *get_part_from_param */
+
+/*
+ * Public functions
+ */
+graph_instance_t *inst_create (graph_config_t *cfg, /* {{{ */
+    const graph_ident_t *ident)
+{
+  graph_instance_t *i;
+  graph_ident_t *selector;
+
+  if ((cfg == NULL) || (ident == NULL))
+    return (NULL);
+
+  i = malloc (sizeof (*i));
+  if (i == NULL)
+    return (NULL);
+  memset (i, 0, sizeof (*i));
+
+  selector = graph_get_selector (cfg);
+  if (selector == NULL)
+  {
+    fprintf (stderr, "inst_create: graph_get_selector failed\n");
+    free (i);
+    return (NULL);
+  }
+
+  i->select = ident_copy_with_selector (selector, ident,
+      IDENT_FLAG_REPLACE_ANY);
+  if (i->select == NULL)
+  {
+    fprintf (stderr, "inst_create: ident_copy_with_selector failed\n");
+    ident_destroy (selector);
+    free (i);
+    return (NULL);
+  }
+
+  ident_destroy (selector);
+
+  i->files = NULL;
+  i->files_num = 0;
+
+  i->next = NULL;
+
+  return (i);
+} /* }}} graph_instance_t *inst_create */
+
+void inst_destroy (graph_instance_t *inst) /* {{{ */
+{
+  graph_instance_t *next;
+  size_t i;
+
+  if (inst == NULL)
+    return;
+
+  next = inst->next;
+
+  ident_destroy (inst->select);
+
+  for (i = 0; i < inst->files_num; i++)
+    ident_destroy (inst->files[i]);
+  free (inst->files);
+
+  free (inst);
+
+  inst_destroy (next);
+} /* }}} void inst_destroy */
+
+int inst_add_file (graph_instance_t *inst, /* {{{ */
+    const graph_ident_t *file)
+{
+  graph_ident_t **tmp;
+
+  tmp = realloc (inst->files, sizeof (*inst->files) * (inst->files_num + 1));
+  if (tmp == NULL)
+    return (ENOMEM);
+  inst->files = tmp;
+
+  inst->files[inst->files_num] = ident_clone (file);
+  if (inst->files[inst->files_num] == NULL)
+    return (ENOMEM);
+
+  inst->files_num++;
+
+  return (0);
+} /* }}} int inst_add_file */
+
+graph_instance_t *inst_get_selected (graph_config_t *cfg) /* {{{ */
+{
+  const char *host = get_part_from_param ("inst_host", "host");
+  const char *plugin = get_part_from_param ("inst_plugin", "plugin");
+  const char *plugin_instance = get_part_from_param ("inst_plugin_instance", "plugin_instance");
+  const char *type = get_part_from_param ("inst_type", "type");
+  const char *type_instance = get_part_from_param ("inst_type_instance", "type_instance");
+  graph_ident_t *ident;
+  graph_instance_t *inst;
+
+  if (cfg == NULL)
+    cfg = gl_graph_get_selected ();
+
+  if (cfg == NULL)
+  {
+    DEBUG ("inst_get_selected: cfg == NULL;\n");
+    return (NULL);
+  }
+
+  if ((host == NULL)
+      || (plugin == NULL) || (plugin_instance == NULL)
+      || (type == NULL) || (type_instance == NULL))
+  {
+    DEBUG ("inst_get_selected: A parameter is NULL.\n");
+    return (NULL);
+  }
+
+  ident = ident_create (host, plugin, plugin_instance, type, type_instance);
+
+  for (inst = graph_get_instances (cfg); inst != NULL; inst = inst->next)
+  {
+    if (ident_compare (ident, inst->select) != 0)
+      continue;
+
+    ident_destroy (ident);
+    return (inst);
+  }
+
+  DEBUG ("inst_get_selected: No match found.\n");
+  ident_destroy (ident);
+  return (NULL);
+} /* }}} graph_instance_t *inst_get_selected */
+
+int inst_get_rrdargs (graph_config_t *cfg, /* {{{ */
+    graph_instance_t *inst,
+    str_array_t *args)
+{
+  def_callback_data_t data = { inst, args };
+  graph_def_t *defs;
+  int status;
+
+  if ((cfg == NULL) || (inst == NULL) || (args == NULL))
+    return (EINVAL);
+
+  status = graph_get_rrdargs (cfg, inst, args);
+  if (status != 0)
+    return (status);
+
+  defs = graph_get_defs (cfg);
+  if (defs == NULL)
+  {
+    defs = inst_get_default_defs (cfg, inst);
+
+    if (defs == NULL)
+      return (-1);
+
+    status = def_foreach (defs, gl_instance_get_rrdargs_cb, &data);
+
+    def_destroy (defs);
+  }
+  else
+  {
+    status = def_foreach (defs, gl_instance_get_rrdargs_cb, &data);
+  }
+
+  return (status);
+} /* }}} int inst_get_rrdargs */
+
+graph_ident_t *inst_get_selector (graph_instance_t *inst) /* {{{ */
+{
+  if (inst == NULL)
+    return (NULL);
+
+  return (ident_clone (inst->select));
+} /* }}} graph_ident_t *inst_get_selector */
+
+int inst_get_params (graph_config_t *cfg, graph_instance_t *inst, /* {{{ */
+    char *buffer, size_t buffer_size)
+{
+  graph_ident_t *cfg_select;
+
+  if ((cfg == NULL) || (inst == NULL)
+      || (buffer == NULL) || (buffer_size < 1))
+    return (EINVAL);
+
+  cfg_select = graph_get_selector (cfg);
+  if (cfg_select == NULL)
+  {
+    fprintf (stderr, "inst_get_params: graph_get_selector failed");
+    return (-1);
+  }
+
+  buffer[0] = 0;
+
+#define COPY_FIELD(field) do {                                  \
+  const char *cfg_f  = ident_get_##field (cfg_select);          \
+  const char *inst_f = ident_get_##field (inst->select);        \
+  if (strcmp (cfg_f, inst_f) == 0)                              \
+  {                                                             \
+    strlcat (buffer, #field, buffer_size);                      \
+    strlcat (buffer, "=", buffer_size);                         \
+    strlcat (buffer, cfg_f, buffer_size);                       \
+  }                                                             \
+  else                                                          \
+  {                                                             \
+    strlcat (buffer, "graph_", buffer_size);                    \
+    strlcat (buffer, #field, buffer_size);                      \
+    strlcat (buffer, "=", buffer_size);                         \
+    strlcat (buffer, cfg_f, buffer_size);                       \
+    strlcat (buffer, ";", buffer_size);                         \
+    strlcat (buffer, "inst_", buffer_size);                     \
+    strlcat (buffer, #field, buffer_size);                      \
+    strlcat (buffer, "=", buffer_size);                         \
+    strlcat (buffer, inst_f, buffer_size);                      \
+  }                                                             \
+} while (0)
+
+  COPY_FIELD(host);
+  strlcat (buffer, ";", buffer_size);
+  COPY_FIELD(plugin);
+  strlcat (buffer, ";", buffer_size);
+  COPY_FIELD(plugin_instance);
+  strlcat (buffer, ";", buffer_size);
+  COPY_FIELD(type);
+  strlcat (buffer, ";", buffer_size);
+  COPY_FIELD(type_instance);
+
+#undef COPY_FIELD
+
+  ident_destroy (cfg_select);
+
+  return (0);
+} /* }}} int inst_get_params */
+
+int inst_append (graph_instance_t *head, graph_instance_t *inst) /* {{{ */
+{
+  graph_instance_t *ptr;
+
+  if ((head == NULL) || (inst == NULL))
+    return (EINVAL);
+
+  ptr = head;
+  while (ptr->next != NULL)
+    ptr = ptr->next;
+
+  ptr->next = inst;
+
+  return (0);
+} /* }}} int inst_append */
+
+int inst_foreach (graph_instance_t *inst, /* {{{ */
+               inst_callback_t cb, void *user_data)
+{
+  graph_instance_t *ptr;
+
+  if ((inst == NULL) || (cb == NULL))
+    return (EINVAL);
+
+  for (ptr = inst; ptr != NULL; ptr = ptr->next)
+  {
+    int status;
+
+    status = (*cb) (ptr, user_data);
+    if (status != 0)
+      return (status);
+  }
+
+  return (0);
+} /* }}} int inst_foreach */
+
+graph_instance_t *inst_find_matching (graph_instance_t *inst, /* {{{ */
+    const graph_ident_t *ident)
+{
+  graph_instance_t *ptr;
+
+  if ((inst == NULL) || (ident == NULL))
+    return (NULL);
+
+  for (ptr = inst; ptr != NULL; ptr = ptr->next)
+    if (ident_matches (ptr->select, ident))
+      return (ptr);
+
+  return (NULL);
+} /* }}} graph_instance_t *inst_find_matching */
+
+int inst_describe (graph_config_t *cfg, graph_instance_t *inst, /* {{{ */
+    char *buffer, size_t buffer_size)
+{
+  graph_ident_t *cfg_select;
+
+  if ((cfg == NULL) || (inst == NULL)
+      || (buffer == NULL) || (buffer_size < 2))
+    return (EINVAL);
+
+  cfg_select = graph_get_selector (cfg);
+  if (cfg_select == NULL)
+  {
+    fprintf (stderr, "inst_describe: graph_get_selector failed\n");
+    return (-1);
+  }
+
+  buffer[0] = 0;
+
+#define CHECK_FIELD(field) do {                                              \
+  if (IS_ANY (ident_get_##field (cfg_select)))                               \
+  {                                                                          \
+    if (buffer[0] != 0)                                                      \
+      strlcat (buffer, "/", buffer_size);                                    \
+    strlcat (buffer, ident_get_##field (inst->select), buffer_size);         \
+  }                                                                          \
+} while (0)
+
+  CHECK_FIELD (host);
+  CHECK_FIELD (plugin);
+  CHECK_FIELD (plugin_instance);
+  CHECK_FIELD (type);
+  CHECK_FIELD (type_instance);
+
+#undef CHECK_FIELD
+
+  if (buffer[0] == 0)
+    strlcat (buffer, "default", buffer_size);
+
+  ident_destroy (cfg_select);
+
+  return (0);
+} /* }}} int inst_describe */
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/src/graph_instance.h b/src/graph_instance.h
new file mode 100644 (file)
index 0000000..b90f984
--- /dev/null
@@ -0,0 +1,50 @@
+#ifndef GRAPH_INSTANCE_H
+#define GRAPH_INSTANCE_H 1
+
+/*
+ * Data types
+ */
+struct graph_instance_s;
+typedef struct graph_instance_s graph_instance_t;
+
+typedef int (*inst_callback_t) (graph_instance_t *inst, void *user_data);
+
+#include "graph.h"
+#include "utils_array.h"
+
+/*
+ * Callback types
+ */
+/*
+ * Methods
+ */
+graph_instance_t *inst_create (graph_config_t *cfg,
+               const graph_ident_t *ident);
+
+void inst_destroy (graph_instance_t *inst);
+
+int inst_add_file (graph_instance_t *inst, const graph_ident_t *file);
+
+graph_instance_t *inst_get_selected (graph_config_t *cfg);
+
+int inst_get_params (graph_config_t *cfg, graph_instance_t *inst,
+    char *buffer, size_t buffer_size);
+
+int inst_get_rrdargs (graph_config_t *cfg, graph_instance_t *inst,
+    str_array_t *args);
+
+graph_ident_t *inst_get_selector (graph_instance_t *inst);
+
+int inst_append (graph_instance_t *head, graph_instance_t *inst);
+
+int inst_foreach (graph_instance_t *inst,
+               inst_callback_t cb, void *user_data);
+
+graph_instance_t *inst_find_matching (graph_instance_t *inst,
+    const graph_ident_t *ident);
+
+int inst_describe (graph_config_t *cfg, graph_instance_t *inst,
+    char *buffer, size_t buffer_size);
+
+#endif /* GRAPH_INSTANCE_H */
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/src/graph_list.c b/src/graph_list.c
new file mode 100644 (file)
index 0000000..965fcba
--- /dev/null
@@ -0,0 +1,287 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <string.h>
+#include <time.h>
+#include <errno.h>
+
+#include "graph_list.h"
+#include "graph_ident.h"
+#include "graph_def.h"
+#include "graph_config.h"
+#include "common.h"
+#include "filesystem.h"
+#include "utils_params.h"
+
+#include <fcgiapp.h>
+#include <fcgi_stdio.h>
+
+/*
+ * Defines
+ */
+#define UPDATE_INTERVAL 10
+
+/*
+ * Global variables
+ */
+static graph_config_t **gl_active = NULL;
+static size_t gl_active_num = 0;
+
+static graph_config_t **gl_staging = NULL;
+static size_t gl_staging_num = 0;
+
+static time_t gl_last_update = 0;
+
+/*
+ * Private functions
+ */
+int gl_add_graph_internal (graph_config_t *cfg, /* {{{ */
+    graph_config_t ***gl_array, size_t *gl_array_num)
+{
+  graph_config_t **tmp;
+
+#define ARRAY_PTR  (*gl_array)
+#define ARRAY_SIZE (*gl_array_num)
+
+  if (cfg == NULL)
+    return (EINVAL);
+
+  tmp = realloc (ARRAY_PTR, sizeof (*ARRAY_PTR) * (ARRAY_SIZE + 1));
+  if (tmp == NULL)
+    return (ENOMEM);
+  ARRAY_PTR = tmp;
+
+  ARRAY_PTR[ARRAY_SIZE] = cfg;
+  ARRAY_SIZE++;
+
+#undef ARRAY_SIZE
+#undef ARRAY_PTR
+
+  return (0);
+} /* }}} int gl_add_graph_internal */
+
+static int gl_register_file (const graph_ident_t *file, /* {{{ */
+    __attribute__((unused)) void *user_data)
+{
+  graph_config_t *cfg;
+  int num_graphs = 0;
+  size_t i;
+
+  for (i = 0; i < gl_active_num; i++)
+  {
+    graph_config_t *cfg = gl_active[i];
+    int status;
+
+    if (!graph_matches (cfg, file))
+      continue;
+
+    status = graph_add_file (cfg, file);
+    if (status != 0)
+    {
+      /* report error */;
+    }
+    else
+    {
+      num_graphs++;
+    }
+  }
+
+  if (num_graphs == 0)
+  {
+    cfg = graph_create (file);
+    gl_add_graph_internal (cfg, &gl_active, &gl_active_num);
+    graph_add_file (cfg, file);
+  }
+
+  return (0);
+} /* }}} int gl_register_file */
+
+static const char *get_part_from_param (const char *prim_key, /* {{{ */
+    const char *sec_key)
+{
+  const char *val;
+
+  val = param (prim_key);
+  if (val != NULL)
+    return (val);
+  
+  return (param (sec_key));
+} /* }}} const char *get_part_from_param */
+
+static int gl_clear_instances (void) /* {{{ */
+{
+  size_t i;
+
+  for (i = 0; i < gl_active_num; i++)
+    graph_clear_instances (gl_active[i]);
+
+  return (0);
+} /* }}} int gl_clear_instances */
+
+
+/*
+ * Global functions
+ */
+int gl_add_graph (graph_config_t *cfg) /* {{{ */
+{
+  return (gl_add_graph_internal (cfg, &gl_staging, &gl_staging_num));
+} /* }}} int gl_add_graph */
+
+int gl_config_submit (void) /* {{{ */
+{
+  graph_config_t **old;
+  size_t old_num;
+  size_t i;
+
+  old = gl_active;
+  old_num = gl_active_num;
+
+  gl_active = gl_staging;
+  gl_active_num = gl_staging_num;
+
+  gl_staging = NULL;
+  gl_staging_num = 0;
+
+  for (i = 0; i < old_num; i++)
+  {
+    graph_destroy (old[i]);
+    old[i] = NULL;
+  }
+  free (old);
+
+  return (0);
+} /* }}} int graph_config_submit */
+
+int gl_graph_get_all (gl_cfg_callback callback, /* {{{ */
+    void *user_data)
+{
+  size_t i;
+
+  if (callback == NULL)
+    return (EINVAL);
+
+  gl_update ();
+
+  for (i = 0; i < gl_active_num; i++)
+  {
+    int status;
+
+    status = (*callback) (gl_active[i], user_data);
+    if (status != 0)
+      return (status);
+  }
+
+  return (0);
+} /* }}} int gl_graph_get_all */
+
+graph_config_t *gl_graph_get_selected (void) /* {{{ */
+{
+  const char *host = get_part_from_param ("graph_host", "host");
+  const char *plugin = get_part_from_param ("graph_plugin", "plugin");
+  const char *plugin_instance = get_part_from_param ("graph_plugin_instance", "plugin_instance");
+  const char *type = get_part_from_param ("graph_type", "type");
+  const char *type_instance = get_part_from_param ("graph_type_instance", "type_instance");
+  graph_ident_t *ident;
+  size_t i;
+
+  if ((host == NULL)
+      || (plugin == NULL) || (plugin_instance == NULL)
+      || (type == NULL) || (type_instance == NULL))
+    return (NULL);
+
+  ident = ident_create (host, plugin, plugin_instance, type, type_instance);
+
+  gl_update ();
+
+  for (i = 0; i < gl_active_num; i++)
+  {
+    if (graph_compare (gl_active[i], ident) != 0)
+      continue;
+
+    ident_destroy (ident);
+    return (gl_active[i]);
+  }
+
+  ident_destroy (ident);
+  return (NULL);
+} /* }}} graph_config_t *gl_graph_get_selected */
+
+/* gl_instance_get_all, gl_graph_instance_get_all {{{ */
+struct gl_inst_callback_data /* {{{ */
+{
+  graph_config_t *cfg;
+  gl_inst_callback callback;
+  void *user_data;
+}; /* }}} struct gl_inst_callback_data */
+
+static int gl_inst_callback_handler (graph_instance_t *inst, /* {{{ */
+    void *user_data)
+{
+  struct gl_inst_callback_data *data = user_data;
+
+  return ((*data->callback) (data->cfg, inst, data->user_data));
+} /* }}} int gl_inst_callback_handler */
+
+int gl_graph_instance_get_all (graph_config_t *cfg, /* {{{ */
+    gl_inst_callback callback, void *user_data)
+{
+  struct gl_inst_callback_data data =
+  {
+    cfg,
+    callback,
+    user_data
+  };
+
+  if ((cfg == NULL) || (callback == NULL))
+    return (EINVAL);
+
+  return (inst_foreach (graph_get_instances (cfg),
+        gl_inst_callback_handler, &data));
+} /* }}} int gl_graph_instance_get_all */
+
+int gl_instance_get_all (gl_inst_callback callback, /* {{{ */
+    void *user_data)
+{
+  size_t i;
+
+  gl_update ();
+
+  for (i = 0; i < gl_active_num; i++)
+  {
+    int status;
+
+    status = gl_graph_instance_get_all (gl_active[i], callback, user_data);
+    if (status != 0)
+      return (status);
+  }
+
+  return (0);
+} /* }}} int gl_instance_get_all */
+/* }}} gl_instance_get_all, gl_graph_instance_get_all */
+
+int gl_update (void) /* {{{ */
+{
+  time_t now;
+  int status;
+
+  /*
+  printf ("Content-Type: text/plain\n\n");
+  */
+
+  now = time (NULL);
+
+  if ((gl_last_update + UPDATE_INTERVAL) >= now)
+    return (0);
+
+  graph_read_config ();
+
+  gl_clear_instances ();
+  status = fs_scan (/* callback = */ gl_register_file, /* user data = */ NULL);
+
+  gl_last_update = now;
+
+  return (status);
+} /* }}} int gl_update */
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/src/graph_list.h b/src/graph_list.h
new file mode 100644 (file)
index 0000000..c17d6fc
--- /dev/null
@@ -0,0 +1,36 @@
+#ifndef GRAPH_LIST_H
+#define GRAPH_LIST_H 1
+
+#include "graph_instance.h"
+
+/*
+ * Callback types
+ */
+typedef int (*gl_cfg_callback) (graph_config_t *cfg,
+    void *user_data);
+
+typedef int (*gl_inst_callback) (graph_config_t *cfg,
+    graph_instance_t *inst, void *user_data);
+
+/*
+ * Functions
+ */
+int gl_add_graph (graph_config_t *cfg);
+
+int gl_config_submit (void);
+
+int gl_graph_get_all (gl_cfg_callback callback,
+    void *user_data);
+
+graph_config_t *gl_graph_get_selected (void);
+
+int gl_graph_instance_get_all (graph_config_t *cfg,
+    gl_inst_callback callback, void *user_data);
+
+int gl_instance_get_all (gl_inst_callback callback,
+    void *user_data);
+
+int gl_update (void);
+
+#endif /* GRAPH_LIST_H */
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/src/main.c b/src/main.c
new file mode 100644 (file)
index 0000000..097c55c
--- /dev/null
@@ -0,0 +1,112 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <dirent.h>
+
+#include "common.h"
+#include "graph_list.h"
+#include "utils_params.h"
+
+#include "action_graph.h"
+#include "action_list_graphs.h"
+
+/* Include this last, so the macro magic of <fcgi_stdio.h> doesn't interfere
+ * with our own header files. */
+#include <fcgiapp.h>
+#include <fcgi_stdio.h>
+
+struct action_s
+{
+  const char *name;
+  int (*callback) (void);
+};
+typedef struct action_s action_t;
+
+static int action_usage (void);
+
+static const action_t actions[] =
+{
+  { "graph",       action_graph },
+  { "list_graphs", action_list_graphs },
+  { "usage",       action_usage }
+};
+static const size_t actions_num = sizeof (actions) / sizeof (actions[0]);
+
+
+static int action_usage (void) /* {{{ */
+{
+  size_t i;
+
+  printf ("Content-Type: text/plain\n\n");
+
+  printf ("Usage:\n"
+      "\n"
+      "  Available actions:\n"
+      "\n");
+
+  for (i = 0; i < actions_num; i++)
+    printf ("  * %s\n", actions[i].name);
+
+  printf ("\n");
+
+  return (0);
+} /* }}} int action_usage */
+
+static int handle_request (void) /* {{{ */
+{
+  const char *action;
+
+  param_init ();
+
+  action = param ("action");
+  if (action == NULL)
+  {
+    return (action_usage ());
+  }
+  else
+  {
+    size_t i;
+
+    for (i = 0; i < actions_num; i++)
+    {
+      if (strcmp (action, actions[i].name) == 0)
+        return ((*actions[i].callback) ());
+    }
+
+    return (action_usage ());
+  }
+} /* }}} int handle_request */
+
+static int run (void) /* {{{ */
+{
+  while (FCGI_Accept() >= 0)
+  {
+    handle_request ();
+    param_finish ();
+  }
+
+  return (0);
+} /* }}} int run */
+
+int main (int argc, char **argv) /* {{{ */
+{
+  int status;
+
+  argc = 0;
+  argv = NULL;
+
+  if (FCGX_IsCGI ())
+    status = handle_request ();
+  else
+    status = run ();
+
+  exit ((status == 0) ? EXIT_SUCCESS : EXIT_FAILURE);
+} /* }}} int main */
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/src/oconfig.c b/src/oconfig.c
new file mode 100644 (file)
index 0000000..79eec36
--- /dev/null
@@ -0,0 +1,218 @@
+/**
+ * oconfig - src/oconfig.c
+ * Copyright (C) 2006,2007  Florian octo Forster <octo at verplant.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "oconfig.h"
+
+extern FILE *yyin;
+int yyparse (void);
+
+oconfig_item_t *ci_root;
+const char     *c_file;
+
+static void yyset_in  (FILE *fd)
+{
+  yyin = fd;
+} /* void yyset_in */
+
+oconfig_item_t *oconfig_parse_fh (FILE *fh)
+{
+  int status;
+  oconfig_item_t *ret;
+
+  char file[10];
+
+  yyset_in (fh);
+
+  if (NULL == c_file) {
+    int status;
+
+    status = snprintf (file, sizeof (file), "<fd#%d>", fileno (fh));
+
+    if ((status < 0) || (((size_t) status) >= sizeof (file))) {
+      c_file = "<unknown>";
+    }
+    else {
+      file[sizeof (file) - 1] = '\0';
+      c_file = file;
+    }
+  }
+
+  status = yyparse ();
+  if (status != 0)
+  {
+    fprintf (stderr, "yyparse returned error #%i\n", status);
+    return (NULL);
+  }
+
+  c_file = NULL;
+
+  ret = ci_root;
+  ci_root = NULL;
+  yyset_in ((FILE *) 0);
+
+  return (ret);
+} /* oconfig_item_t *oconfig_parse_fh */
+
+oconfig_item_t *oconfig_parse_file (const char *file)
+{
+  FILE *fh;
+  oconfig_item_t *ret;
+
+  c_file = file;
+
+  fh = fopen (file, "r");
+  if (fh == NULL)
+  {
+    fprintf (stderr, "fopen (%s) failed: %s\n", file, strerror (errno));
+    return (NULL);
+  }
+
+  ret = oconfig_parse_fh (fh);
+  fclose (fh);
+
+  c_file = NULL;
+
+  return (ret);
+} /* oconfig_item_t *oconfig_parse_file */
+
+oconfig_item_t *oconfig_clone (const oconfig_item_t *ci_orig)
+{
+  oconfig_item_t *ci_copy;
+
+  ci_copy = (oconfig_item_t *) malloc (sizeof (*ci_copy));
+  if (ci_copy == NULL)
+  {
+    fprintf (stderr, "malloc failed.\n");
+    return (NULL);
+  }
+  memset (ci_copy, 0, sizeof (*ci_copy));
+  ci_copy->values = NULL;
+  ci_copy->parent = NULL;
+  ci_copy->children = NULL;
+
+  ci_copy->key = strdup (ci_orig->key);
+  if (ci_copy->key == NULL)
+  {
+    fprintf (stderr, "strdup failed.\n");
+    free (ci_copy);
+    return (NULL);
+  }
+
+  if (ci_orig->values_num > 0) /* {{{ */
+  {
+    int i;
+
+    ci_copy->values = (oconfig_value_t *) calloc (ci_orig->values_num,
+       sizeof (*ci_copy->values));
+    if (ci_copy->values == NULL)
+    {
+      fprintf (stderr, "calloc failed.\n");
+      free (ci_copy->key);
+      free (ci_copy);
+      return (NULL);
+    }
+    ci_copy->values_num = ci_orig->values_num;
+
+    for (i = 0; i < ci_copy->values_num; i++)
+    {
+       ci_copy->values[i].type = ci_orig->values[i].type;
+       if (ci_copy->values[i].type == OCONFIG_TYPE_STRING)
+       {
+        ci_copy->values[i].value.string
+          = strdup (ci_orig->values[i].value.string);
+        if (ci_copy->values[i].value.string == NULL)
+        {
+          fprintf (stderr, "strdup failed.\n");
+          oconfig_free (ci_copy);
+          return (NULL);
+        }
+       }
+       else /* ci_copy->values[i].type != OCONFIG_TYPE_STRING) */
+       {
+        ci_copy->values[i].value = ci_orig->values[i].value;
+       }
+    }
+  } /* }}} if (ci_orig->values_num > 0) */
+
+  if (ci_orig->children_num > 0) /* {{{ */
+  {
+    int i;
+
+    ci_copy->children = (oconfig_item_t *) calloc (ci_orig->children_num,
+       sizeof (*ci_copy->children));
+    if (ci_copy->children == NULL)
+    {
+      fprintf (stderr, "calloc failed.\n");
+      oconfig_free (ci_copy);
+      return (NULL);
+    }
+    ci_copy->children_num = ci_orig->children_num;
+
+    for (i = 0; i < ci_copy->children_num; i++)
+    {
+      oconfig_item_t *child;
+      
+      child = oconfig_clone (ci_orig->children + i);
+      if (child == NULL)
+      {
+       oconfig_free (ci_copy);
+       return (NULL);
+      }
+      child->parent = ci_copy;
+      ci_copy->children[i] = *child;
+      free (child);
+    } /* for (i = 0; i < ci_copy->children_num; i++) */
+  } /* }}} if (ci_orig->children_num > 0) */
+
+  return (ci_copy);
+} /* oconfig_item_t *oconfig_clone */
+
+void oconfig_free (oconfig_item_t *ci)
+{
+  int i;
+
+  if (ci == NULL)
+    return;
+
+  if (ci->key != NULL)
+    free (ci->key);
+
+  for (i = 0; i < ci->values_num; i++)
+    if ((ci->values[i].type == OCONFIG_TYPE_STRING)
+        && (NULL != ci->values[i].value.string))
+      free (ci->values[i].value.string);
+
+  if (ci->values != NULL)
+    free (ci->values);
+
+  for (i = 0; i < ci->children_num; i++)
+    oconfig_free (ci->children + i);
+
+  if (ci->children != NULL)
+    free (ci->children);
+}
+
+/*
+ * vim:shiftwidth=2:tabstop=8:softtabstop=2:fdm=marker
+ */
diff --git a/src/oconfig.h b/src/oconfig.h
new file mode 100644 (file)
index 0000000..70fc623
--- /dev/null
@@ -0,0 +1,69 @@
+#ifndef OCONFIG_H
+#define OCONFIG_H 1
+
+#include <stdio.h>
+
+/**
+ * oconfig - src/oconfig.h
+ * Copyright (C) 2006-2009  Florian octo Forster <octo at verplant.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+/*
+ * Types
+ */
+#define OCONFIG_TYPE_STRING  0
+#define OCONFIG_TYPE_NUMBER  1
+#define OCONFIG_TYPE_BOOLEAN 2
+
+struct oconfig_value_s
+{
+  union
+  {
+    char  *string;
+    double number;
+    int    boolean;
+  } value;
+  int type;
+};
+typedef struct oconfig_value_s oconfig_value_t;
+
+struct oconfig_item_s;
+typedef struct oconfig_item_s oconfig_item_t;
+struct oconfig_item_s
+{
+  char            *key;
+  oconfig_value_t *values;
+  int              values_num;
+
+  oconfig_item_t  *parent;
+  oconfig_item_t  *children;
+  int              children_num;
+};
+
+/*
+ * Functions
+ */
+oconfig_item_t *oconfig_parse_fh (FILE *fh);
+oconfig_item_t *oconfig_parse_file (const char *file);
+
+oconfig_item_t *oconfig_clone (const oconfig_item_t *ci);
+
+void oconfig_free (oconfig_item_t *ci);
+
+/*
+ * vim: shiftwidth=2:tabstop=8:softtabstop=2
+ */
+#endif /* OCONFIG_H */
diff --git a/src/parser.y b/src/parser.y
new file mode 100644 (file)
index 0000000..5b7aa94
--- /dev/null
@@ -0,0 +1,239 @@
+/**
+ * oconfig - src/parser.y
+ * Copyright (C) 2007,2008  Florian octo Forster <octo at verplant.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+%{
+#include <stdlib.h>
+#include <string.h>
+#include "oconfig.h"
+#include "aux_types.h"
+
+static char *unquote (const char *orig);
+static int yyerror (const char *s);
+
+/* Lexer variables */
+extern int yylineno;
+extern char *yytext;
+
+extern oconfig_item_t *ci_root;
+extern char           *c_file;
+%}
+
+%start entire_file
+
+%union {
+       double  number;
+       int     boolean;
+       char   *string;
+       oconfig_value_t  cv;
+       oconfig_item_t   ci;
+       argument_list_t  al;
+       statement_list_t sl;
+}
+
+%token <number> NUMBER
+%token <boolean> BTRUE BFALSE
+%token <string> QUOTED_STRING UNQUOTED_STRING
+%token SLASH OPENBRAC CLOSEBRAC EOL
+
+%type <string> string
+%type <string> identifier
+/* arguments */
+%type <cv> argument
+%type <al> argument_list
+/* blocks */
+%type <ci> block_begin
+%type <ci> block
+%type <string> block_end
+/* statements */
+%type <ci> option
+%type <ci> statement
+%type <sl> statement_list
+%type <ci> entire_file
+
+/* pass an verbose, specific error message to yyerror() */
+%error-verbose
+
+%%
+string:
+       QUOTED_STRING           {$$ = unquote ($1);}
+       | UNQUOTED_STRING       {$$ = strdup ($1);}
+       ;
+
+argument:
+       NUMBER                  {$$.value.number = $1; $$.type = OCONFIG_TYPE_NUMBER;}
+       | BTRUE                 {$$.value.boolean = 1; $$.type = OCONFIG_TYPE_BOOLEAN;}
+       | BFALSE                {$$.value.boolean = 0; $$.type = OCONFIG_TYPE_BOOLEAN;}
+       | string                {$$.value.string = $1; $$.type = OCONFIG_TYPE_STRING;}
+       ;
+
+argument_list:
+       argument_list argument
+       {
+        $$ = $1;
+        $$.argument_num++;
+        $$.argument = realloc ($$.argument, $$.argument_num * sizeof (oconfig_value_t));
+        $$.argument[$$.argument_num-1] = $2;
+       }
+       | argument
+       {
+        $$.argument = malloc (sizeof (oconfig_value_t));
+        $$.argument[0] = $1;
+        $$.argument_num = 1;
+       }
+       ;
+
+identifier:
+       UNQUOTED_STRING                 {$$ = strdup ($1);}
+       ;
+
+option:
+       identifier argument_list EOL
+       {
+        memset (&$$, '\0', sizeof ($$));
+        $$.key = $1;
+        $$.values = $2.argument;
+        $$.values_num = $2.argument_num;
+       }
+       ;
+
+block_begin:
+       OPENBRAC identifier CLOSEBRAC EOL
+       {
+        memset (&$$, '\0', sizeof ($$));
+        $$.key = $2;
+       }
+       |
+       OPENBRAC identifier argument_list CLOSEBRAC EOL
+       {
+        memset (&$$, '\0', sizeof ($$));
+        $$.key = $2;
+        $$.values = $3.argument;
+        $$.values_num = $3.argument_num;
+       }
+       ;
+
+block_end:
+       OPENBRAC SLASH identifier CLOSEBRAC EOL
+       {
+        $$ = $3;
+       }
+       ;
+
+block:
+       block_begin statement_list block_end
+       {
+        if (strcmp ($1.key, $3) != 0)
+        {
+               printf ("block_begin = %s; block_end = %s;\n", $1.key, $3);
+               yyerror ("Block not closed..\n");
+               exit (1);
+        }
+        free ($3); $3 = NULL;
+        $$ = $1;
+        $$.children = $2.statement;
+        $$.children_num = $2.statement_num;
+       }
+       ;
+
+statement:
+       option          {$$ = $1;}
+       | block         {$$ = $1;}
+       | EOL           {$$.values_num = 0;}
+       ;
+
+statement_list:
+       statement_list statement
+       {
+        $$ = $1;
+        if (($2.values_num > 0) || ($2.children_num > 0))
+        {
+                $$.statement_num++;
+                $$.statement = realloc ($$.statement, $$.statement_num * sizeof (oconfig_item_t));
+                $$.statement[$$.statement_num-1] = $2;
+        }
+       }
+       | statement
+       {
+        if (($1.values_num > 0) || ($1.children_num > 0))
+        {
+                $$.statement = malloc (sizeof (oconfig_item_t));
+                $$.statement[0] = $1;
+                $$.statement_num = 1;
+        }
+        else
+        {
+               $$.statement = NULL;
+               $$.statement_num = 0;
+        }
+       }
+       ;
+
+entire_file:
+       statement_list
+       {
+        ci_root = malloc (sizeof (oconfig_item_t));
+        memset (ci_root, '\0', sizeof (oconfig_item_t));
+        ci_root->children = $1.statement;
+        ci_root->children_num = $1.statement_num;
+       }
+       ;
+
+%%
+static int yyerror (const char *s)
+{
+       char *text;
+
+       if (*yytext == '\n')
+               text = "<newline>";
+       else
+               text = yytext;
+
+       fprintf (stderr, "Parse error in file `%s', line %i near `%s': %s\n",
+               c_file, yylineno, text, s);
+       return (-1);
+} /* int yyerror */
+
+static char *unquote (const char *orig)
+{
+       char *ret = strdup (orig);
+       int len;
+       int i;
+
+       if (ret == NULL)
+               return (NULL);
+
+       len = strlen (ret);
+
+       if ((len < 2) || (ret[0] != '"') || (ret[len - 1] != '"'))
+               return (ret);
+
+       len -= 2;
+       memmove (ret, ret + 1, len);
+       ret[len] = '\0';
+
+       for (i = 0; i < len; i++)
+       {
+               if (ret[i] == '\\')
+               {
+                       memmove (ret + i, ret + (i + 1), len - i);
+                       len--;
+               }
+       }
+
+       return (ret);
+} /* char *unquote */
diff --git a/src/scanner.l b/src/scanner.l
new file mode 100644 (file)
index 0000000..9f0cd8e
--- /dev/null
@@ -0,0 +1,137 @@
+/**
+ * oconfig - src/scanner.l
+ * Copyright (C) 2007  Florian octo Forster <octo at verplant.org>
+ * Copyright (C) 2008  Sebastian tokkee Harl <sh at tokkee.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+%{
+#include <stdlib.h>
+#include "oconfig.h"
+#include "aux_types.h"
+#include "parser.h"
+
+/* multiline string buffer */
+static char *ml_buffer = NULL;
+static int   ml_pos    = 0;
+static int   ml_len    = 0;
+
+#define ml_free (ml_len - ml_pos)
+
+static void ml_append (char *);
+
+#ifdef yyterminate
+# undef yyterminate
+#endif
+#define yyterminate() \
+       do { free (ml_buffer); ml_buffer = NULL; ml_pos = 0; ml_len = 0; \
+               return YY_NULL; } while (0)
+%}
+%option yylineno
+%option noyywrap
+%x ML
+WHITE_SPACE [\ \t\b]
+NON_WHITE_SPACE [^\ \t\b]
+EOL (\r\n|\n)
+QUOTED_STRING ([^\\"]+|\\.)*
+UNQUOTED_STRING [0-9A-Za-z_]+
+HEX_NUMBER 0[xX][0-9a-fA-F]+
+OCT_NUMBER 0[0-7]+
+DEC_NUMBER [\+\-]?[0-9]+
+FLOAT_NUMBER [\+\-]?[0-9]*\.[0-9]+([eE][\+\-][0-9]+)?
+NUMBER ({FLOAT_NUMBER}|{HEX_NUMBER}|{OCT_NUMBER}|{DEC_NUMBER})
+BOOL_TRUE (true|yes|on)
+BOOL_FALSE (false|no|off)
+COMMENT #.*
+PORT (6(5(5(3[0-5]|[0-2][0-9])|[0-4][0-9][0-9])|[0-4][0-9][0-9][0-9])|[1-5][0-9][0-9][0-9][0-9]|[1-9][0-9]?[0-9]?[0-9]?)
+IP_BYTE (2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])
+IPV4_ADDR {IP_BYTE}\.{IP_BYTE}\.{IP_BYTE}\.{IP_BYTE}(:{PORT})?
+
+%%
+{WHITE_SPACE}          |
+{COMMENT}              {/* ignore */}
+
+\\{EOL}                        {/* continue line */}
+
+{EOL}                  {return (EOL);}
+"/"                    {return (SLASH);}
+"<"                    {return (OPENBRAC);}
+">"                    {return (CLOSEBRAC);}
+{BOOL_TRUE}            {yylval.boolean = 1; return (BTRUE);}
+{BOOL_FALSE}           {yylval.boolean = 0; return (BFALSE);}
+
+{IPV4_ADDR}            {yylval.string = yytext; return (UNQUOTED_STRING);}
+
+{NUMBER}               {yylval.number = strtod (yytext, NULL); return (NUMBER);}
+
+\"{QUOTED_STRING}\"    {yylval.string = yytext; return (QUOTED_STRING);}
+{UNQUOTED_STRING}      {yylval.string = yytext; return (UNQUOTED_STRING);}
+
+\"{QUOTED_STRING}\\{EOL} {
+       int len = strlen (yytext);
+
+       ml_pos = 0;
+
+       /* remove "\\<EOL>" */
+       if ('\r' == yytext[len - 2])
+               len -= 3;
+       else
+               len -= 2;
+       yytext[len] = '\0';
+
+       ml_append (yytext);
+       BEGIN (ML);
+}
+<ML>^{WHITE_SPACE}+ {/* remove leading white-space */}
+<ML>{NON_WHITE_SPACE}{QUOTED_STRING}\\{EOL} {
+       int len = strlen (yytext);
+
+       /* remove "\\<EOL>" */
+       if ('\r' == yytext[len - 2])
+               len -= 3;
+       else
+               len -= 2;
+       yytext[len] = '\0';
+
+       ml_append(yytext);
+}
+<ML>{NON_WHITE_SPACE}{QUOTED_STRING}\" {
+       ml_append(yytext);
+       yylval.string = ml_buffer;
+
+       BEGIN (INITIAL);
+       return (QUOTED_STRING);
+}
+%%
+static void ml_append (char *string)
+{
+       int len = strlen (string);
+       int s;
+
+       if (ml_free <= len) {
+               ml_len += len - ml_free + 1;
+               ml_buffer = (char *)realloc (ml_buffer, ml_len);
+               if (NULL == ml_buffer)
+                       YY_FATAL_ERROR ("out of dynamic memory in ml_append");
+       }
+
+       s = snprintf (ml_buffer + ml_pos, ml_free, "%s", string);
+       if ((0 > s) || (ml_free <= s))
+               YY_FATAL_ERROR ("failed to write to multiline buffer");
+
+       ml_pos += s;
+       return;
+} /* ml_append */
+
diff --git a/src/utils_array.c b/src/utils_array.c
new file mode 100644 (file)
index 0000000..5aaabbc
--- /dev/null
@@ -0,0 +1,95 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+
+#include "utils_array.h"
+
+struct str_array_s
+{
+  char **ptr;
+  size_t size;
+};
+
+str_array_t *array_create (void) /* {{{ */
+{
+  str_array_t *a;
+
+  a = malloc (sizeof (*a));
+  if (a == NULL)
+    return (NULL);
+
+  memset (a, 0, sizeof (*a));
+  a->ptr = NULL;
+  a->size = 0;
+
+  return (a);
+} /* }}} str_array_t *array_create */
+
+void array_destroy (str_array_t *a) /* {{{ */
+{
+  if (a == NULL)
+    return;
+
+  free (a->ptr);
+  a->ptr = NULL;
+  a->size = 0;
+
+  free (a);
+} /* }}} void array_destroy */
+
+int array_append (str_array_t *a, const char *entry) /* {{{ */
+{
+  char **ptr;
+
+  if ((entry == NULL) || (a == NULL))
+    return (EINVAL);
+
+  ptr = realloc (a->ptr, sizeof (*a->ptr) * (a->size + 1));
+  if (ptr == NULL)
+    return (ENOMEM);
+  a->ptr = ptr;
+  ptr = a->ptr + a->size;
+
+  *ptr = strdup (entry);
+  if (*ptr == NULL)
+    return (ENOMEM);
+
+  a->size++;
+  return (0);
+} /* }}} int array_append */
+
+int array_append_format (str_array_t *a, const char *format, ...) /* {{{ */
+{
+  char buffer[1024];
+  va_list ap;
+  int status;
+
+  va_start (ap, format);
+  status = vsnprintf (buffer, sizeof (buffer), format, ap);
+  va_end(ap);
+
+  if ((status < 0) || (((size_t) status) >= sizeof (buffer)))
+    return (ENOMEM);
+
+  return (array_append (a, buffer));
+} /* }}} int array_append_format */
+
+int array_argc (str_array_t *a) /* {{{ */
+{
+  if (a == NULL)
+    return (-1);
+
+  return ((int) a->size);
+} /* }}} int array_argc */
+
+char **array_argv (str_array_t *a) /* {{{ */
+{
+  if ((a == NULL) || (a->size == 0))
+    return (NULL);
+
+  return (a->ptr);
+} /* }}} char **array_argv */
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/src/utils_array.h b/src/utils_array.h
new file mode 100644 (file)
index 0000000..917bea9
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef UTILS_ARRAY_H
+#define UTILS_ARRAY_H 1
+
+struct str_array_s;
+typedef struct str_array_s str_array_t;
+
+str_array_t *array_create (void);
+void array_destroy (str_array_t *a);
+int array_append (str_array_t *a, const char *entry);
+int array_append_format (str_array_t *a, const char *format, ...)
+  __attribute__((format(printf,2,3)));
+
+int array_argc (str_array_t *);
+char **array_argv (str_array_t *);
+
+#endif /* UTILS_ARRAY_H */
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/src/utils_params.c b/src/utils_params.c
new file mode 100644 (file)
index 0000000..6e5dc89
--- /dev/null
@@ -0,0 +1,259 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include "utils_params.h"
+
+struct parameter_s
+{
+  char *key;
+  char *value;
+};
+typedef struct parameter_s parameter_t;
+
+static parameter_t *parameters = NULL;
+static size_t parameters_num = 0;
+static _Bool parameters_init = 0;
+
+static int parameter_add (const char *key, const char *value) /* {{{ */
+{
+  parameter_t *ptr;
+
+  if (value == NULL)
+    return (EINVAL);
+
+  ptr = realloc (parameters, sizeof (*parameters) * (parameters_num + 1));
+  if (ptr == NULL)
+    return (ENOMEM);
+  parameters = ptr;
+
+  ptr = parameters + parameters_num;
+  if (key == NULL)
+  {
+    ptr->key = NULL;
+  }
+  else
+  {
+    ptr->key = strdup (key);
+    if (ptr->key == NULL)
+      return (ENOMEM);
+  }
+
+  ptr->value = strdup (value);
+  if (ptr->value == NULL)
+  {
+    free (ptr->key);
+    return (ENOMEM);
+  }
+
+  parameters_num++;
+  return (0);
+} /* }}} int parameter_add */
+
+static char *parameter_lookup (const char *key) /* {{{ */
+{
+  size_t i;
+
+  for (i = 0; i < parameters_num; i++)
+  {
+    if ((key == NULL) && (parameters[i].key == NULL))
+      return (parameters[i].value);
+    else if ((key != NULL) && (parameters[i].key != NULL)
+        && (strcmp (key, parameters[i].key) == 0))
+      return (parameters[i].value);
+  }
+
+  return (NULL);
+} /* }}} char *parameter_lookup */
+
+static char *uri_unescape (char *string) /* {{{ */
+{
+  char *in;
+  char *out;
+
+  if (string == NULL)
+    return (NULL);
+
+  in = string;
+  out = string;
+
+  while (*in != 0)
+  {
+    if (*in == '+')
+    {
+      *out = ' ';
+    }
+    else if ((in[0] == '%')
+        && isxdigit ((int) in[1]) && isxdigit ((int) in[2]))
+    {
+      char tmpstr[3];
+      char *endptr;
+      long value;
+
+      tmpstr[0] = in[1];
+      tmpstr[1] = in[2];
+      tmpstr[2] = 0;
+
+      errno = 0;
+      endptr = NULL;
+      value = strtol (tmpstr, &endptr, /* base = */ 16);
+      if ((endptr == tmpstr) || (errno != 0))
+      {
+        *out = '?';
+      }
+      else
+      {
+        *out = (char) value;
+      }
+
+      in += 2;
+    }
+    else
+    {
+      *out = *in;
+    }
+
+    in++;
+    out++;
+  } /* while (*in != 0) */
+
+  *out = 0;
+  return (string);
+} /* }}} char *uri_unescape */
+
+static int parse_keyval (char *keyval) /* {{{ */
+{
+  char *key;
+  char *val;
+
+  val = strchr (keyval, '=');
+  if (val == NULL)
+  {
+    key = NULL;
+    val = keyval;
+  }
+  else
+  {
+    key = keyval;
+    *val = 0;
+    val++;
+  }
+
+  parameter_add (uri_unescape (key), uri_unescape (val));
+
+  return (0);
+} /* }}} int parse_keyval */
+
+static int parse_query_string (char *query_string) /* {{{ */
+{
+  char *dummy;
+  char *keyval;
+
+  if (query_string == NULL)
+    return (EINVAL);
+
+  dummy = query_string;
+  while ((keyval = strtok (dummy, ";&")) != NULL)
+  {
+    dummy = NULL;
+    parse_keyval (keyval);
+  }
+
+  return (0);
+} /* }}} int parse_query_string */
+
+int param_init (void) /* {{{ */
+{
+  const char *query_string;
+  char *copy;
+  int status;
+
+  if (parameters_init)
+    return (0);
+
+  query_string = getenv ("QUERY_STRING");
+  if (query_string == NULL)
+    return (ENOENT);
+
+  copy = strdup (query_string);
+  if (copy == NULL)
+    return (ENOMEM);
+
+  status = parse_query_string (copy);
+  free (copy);
+
+  parameters_init = 1;
+
+  return (status);
+} /* }}} int param_init */
+
+void param_finish (void) /* {{{ */
+{
+  size_t i;
+
+  if (!parameters_init)
+    return;
+
+  for (i = 0; i < parameters_num; i++)
+  {
+    free (parameters[i].key);
+    free (parameters[i].value);
+  }
+  free (parameters);
+
+  parameters = NULL;
+  parameters_num = 0;
+  parameters_init = 0;
+} /* }}} void param_finish */
+
+const char *param (const char *key) /* {{{ */
+{
+  param_init ();
+
+  return (parameter_lookup (key));
+} /* }}} const char *param */
+
+int uri_escape (char *dst, const char *src, size_t size) /* {{{ */
+{
+  size_t in;
+  size_t out;
+
+  in = 0;
+  out = 0;
+  while (42)
+  {
+    if (src[in] == 0)
+    {
+      dst[out] = 0;
+      return (0);
+    }
+    else if ((src[in] < 32)
+        || (src[in] == '&')
+        || (src[in] == ';')
+        || (src[in] >= 128))
+    {
+      char esc[4];
+
+      if ((size - out) < 4)
+        break;
+      
+      snprintf (esc, sizeof (esc), "%%%02x", (unsigned int) src[in]);
+      dst[out] = esc[0];
+      dst[out+1] = esc[1];
+      dst[out+2] = esc[2];
+
+      out += 3;
+      in++;
+    }
+    else
+    {
+      dst[out] = src[in];
+      out++;
+      in++;
+    }
+  } /* while (42) */
+} /* }}} int uri_escape */
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/src/utils_params.h b/src/utils_params.h
new file mode 100644 (file)
index 0000000..3c7ea0a
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef UTILS_PARAMS_H
+#define UTILS_PARAMS_H 1
+
+int param_init (void);
+void param_finish (void);
+
+const char *param (const char *key);
+
+int uri_escape (char *dst, const char *src, size_t size);
+
+#endif /* UTILS_PARAMS_H */
diff --git a/test.fcgi.c b/test.fcgi.c
deleted file mode 100644 (file)
index 097c55c..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <strings.h>
-#include <errno.h>
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <dirent.h>
-
-#include "common.h"
-#include "graph_list.h"
-#include "utils_params.h"
-
-#include "action_graph.h"
-#include "action_list_graphs.h"
-
-/* Include this last, so the macro magic of <fcgi_stdio.h> doesn't interfere
- * with our own header files. */
-#include <fcgiapp.h>
-#include <fcgi_stdio.h>
-
-struct action_s
-{
-  const char *name;
-  int (*callback) (void);
-};
-typedef struct action_s action_t;
-
-static int action_usage (void);
-
-static const action_t actions[] =
-{
-  { "graph",       action_graph },
-  { "list_graphs", action_list_graphs },
-  { "usage",       action_usage }
-};
-static const size_t actions_num = sizeof (actions) / sizeof (actions[0]);
-
-
-static int action_usage (void) /* {{{ */
-{
-  size_t i;
-
-  printf ("Content-Type: text/plain\n\n");
-
-  printf ("Usage:\n"
-      "\n"
-      "  Available actions:\n"
-      "\n");
-
-  for (i = 0; i < actions_num; i++)
-    printf ("  * %s\n", actions[i].name);
-
-  printf ("\n");
-
-  return (0);
-} /* }}} int action_usage */
-
-static int handle_request (void) /* {{{ */
-{
-  const char *action;
-
-  param_init ();
-
-  action = param ("action");
-  if (action == NULL)
-  {
-    return (action_usage ());
-  }
-  else
-  {
-    size_t i;
-
-    for (i = 0; i < actions_num; i++)
-    {
-      if (strcmp (action, actions[i].name) == 0)
-        return ((*actions[i].callback) ());
-    }
-
-    return (action_usage ());
-  }
-} /* }}} int handle_request */
-
-static int run (void) /* {{{ */
-{
-  while (FCGI_Accept() >= 0)
-  {
-    handle_request ();
-    param_finish ();
-  }
-
-  return (0);
-} /* }}} int run */
-
-int main (int argc, char **argv) /* {{{ */
-{
-  int status;
-
-  argc = 0;
-  argv = NULL;
-
-  if (FCGX_IsCGI ())
-    status = handle_request ();
-  else
-    status = run ();
-
-  exit ((status == 0) ? EXIT_SUCCESS : EXIT_FAILURE);
-} /* }}} int main */
-
-/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/utils_array.c b/utils_array.c
deleted file mode 100644 (file)
index 5aaabbc..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <string.h>
-#include <errno.h>
-
-#include "utils_array.h"
-
-struct str_array_s
-{
-  char **ptr;
-  size_t size;
-};
-
-str_array_t *array_create (void) /* {{{ */
-{
-  str_array_t *a;
-
-  a = malloc (sizeof (*a));
-  if (a == NULL)
-    return (NULL);
-
-  memset (a, 0, sizeof (*a));
-  a->ptr = NULL;
-  a->size = 0;
-
-  return (a);
-} /* }}} str_array_t *array_create */
-
-void array_destroy (str_array_t *a) /* {{{ */
-{
-  if (a == NULL)
-    return;
-
-  free (a->ptr);
-  a->ptr = NULL;
-  a->size = 0;
-
-  free (a);
-} /* }}} void array_destroy */
-
-int array_append (str_array_t *a, const char *entry) /* {{{ */
-{
-  char **ptr;
-
-  if ((entry == NULL) || (a == NULL))
-    return (EINVAL);
-
-  ptr = realloc (a->ptr, sizeof (*a->ptr) * (a->size + 1));
-  if (ptr == NULL)
-    return (ENOMEM);
-  a->ptr = ptr;
-  ptr = a->ptr + a->size;
-
-  *ptr = strdup (entry);
-  if (*ptr == NULL)
-    return (ENOMEM);
-
-  a->size++;
-  return (0);
-} /* }}} int array_append */
-
-int array_append_format (str_array_t *a, const char *format, ...) /* {{{ */
-{
-  char buffer[1024];
-  va_list ap;
-  int status;
-
-  va_start (ap, format);
-  status = vsnprintf (buffer, sizeof (buffer), format, ap);
-  va_end(ap);
-
-  if ((status < 0) || (((size_t) status) >= sizeof (buffer)))
-    return (ENOMEM);
-
-  return (array_append (a, buffer));
-} /* }}} int array_append_format */
-
-int array_argc (str_array_t *a) /* {{{ */
-{
-  if (a == NULL)
-    return (-1);
-
-  return ((int) a->size);
-} /* }}} int array_argc */
-
-char **array_argv (str_array_t *a) /* {{{ */
-{
-  if ((a == NULL) || (a->size == 0))
-    return (NULL);
-
-  return (a->ptr);
-} /* }}} char **array_argv */
-
-/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/utils_array.h b/utils_array.h
deleted file mode 100644 (file)
index 917bea9..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef UTILS_ARRAY_H
-#define UTILS_ARRAY_H 1
-
-struct str_array_s;
-typedef struct str_array_s str_array_t;
-
-str_array_t *array_create (void);
-void array_destroy (str_array_t *a);
-int array_append (str_array_t *a, const char *entry);
-int array_append_format (str_array_t *a, const char *format, ...)
-  __attribute__((format(printf,2,3)));
-
-int array_argc (str_array_t *);
-char **array_argv (str_array_t *);
-
-#endif /* UTILS_ARRAY_H */
-/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/utils_params.c b/utils_params.c
deleted file mode 100644 (file)
index 6e5dc89..0000000
+++ /dev/null
@@ -1,259 +0,0 @@
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <errno.h>
-
-#include "utils_params.h"
-
-struct parameter_s
-{
-  char *key;
-  char *value;
-};
-typedef struct parameter_s parameter_t;
-
-static parameter_t *parameters = NULL;
-static size_t parameters_num = 0;
-static _Bool parameters_init = 0;
-
-static int parameter_add (const char *key, const char *value) /* {{{ */
-{
-  parameter_t *ptr;
-
-  if (value == NULL)
-    return (EINVAL);
-
-  ptr = realloc (parameters, sizeof (*parameters) * (parameters_num + 1));
-  if (ptr == NULL)
-    return (ENOMEM);
-  parameters = ptr;
-
-  ptr = parameters + parameters_num;
-  if (key == NULL)
-  {
-    ptr->key = NULL;
-  }
-  else
-  {
-    ptr->key = strdup (key);
-    if (ptr->key == NULL)
-      return (ENOMEM);
-  }
-
-  ptr->value = strdup (value);
-  if (ptr->value == NULL)
-  {
-    free (ptr->key);
-    return (ENOMEM);
-  }
-
-  parameters_num++;
-  return (0);
-} /* }}} int parameter_add */
-
-static char *parameter_lookup (const char *key) /* {{{ */
-{
-  size_t i;
-
-  for (i = 0; i < parameters_num; i++)
-  {
-    if ((key == NULL) && (parameters[i].key == NULL))
-      return (parameters[i].value);
-    else if ((key != NULL) && (parameters[i].key != NULL)
-        && (strcmp (key, parameters[i].key) == 0))
-      return (parameters[i].value);
-  }
-
-  return (NULL);
-} /* }}} char *parameter_lookup */
-
-static char *uri_unescape (char *string) /* {{{ */
-{
-  char *in;
-  char *out;
-
-  if (string == NULL)
-    return (NULL);
-
-  in = string;
-  out = string;
-
-  while (*in != 0)
-  {
-    if (*in == '+')
-    {
-      *out = ' ';
-    }
-    else if ((in[0] == '%')
-        && isxdigit ((int) in[1]) && isxdigit ((int) in[2]))
-    {
-      char tmpstr[3];
-      char *endptr;
-      long value;
-
-      tmpstr[0] = in[1];
-      tmpstr[1] = in[2];
-      tmpstr[2] = 0;
-
-      errno = 0;
-      endptr = NULL;
-      value = strtol (tmpstr, &endptr, /* base = */ 16);
-      if ((endptr == tmpstr) || (errno != 0))
-      {
-        *out = '?';
-      }
-      else
-      {
-        *out = (char) value;
-      }
-
-      in += 2;
-    }
-    else
-    {
-      *out = *in;
-    }
-
-    in++;
-    out++;
-  } /* while (*in != 0) */
-
-  *out = 0;
-  return (string);
-} /* }}} char *uri_unescape */
-
-static int parse_keyval (char *keyval) /* {{{ */
-{
-  char *key;
-  char *val;
-
-  val = strchr (keyval, '=');
-  if (val == NULL)
-  {
-    key = NULL;
-    val = keyval;
-  }
-  else
-  {
-    key = keyval;
-    *val = 0;
-    val++;
-  }
-
-  parameter_add (uri_unescape (key), uri_unescape (val));
-
-  return (0);
-} /* }}} int parse_keyval */
-
-static int parse_query_string (char *query_string) /* {{{ */
-{
-  char *dummy;
-  char *keyval;
-
-  if (query_string == NULL)
-    return (EINVAL);
-
-  dummy = query_string;
-  while ((keyval = strtok (dummy, ";&")) != NULL)
-  {
-    dummy = NULL;
-    parse_keyval (keyval);
-  }
-
-  return (0);
-} /* }}} int parse_query_string */
-
-int param_init (void) /* {{{ */
-{
-  const char *query_string;
-  char *copy;
-  int status;
-
-  if (parameters_init)
-    return (0);
-
-  query_string = getenv ("QUERY_STRING");
-  if (query_string == NULL)
-    return (ENOENT);
-
-  copy = strdup (query_string);
-  if (copy == NULL)
-    return (ENOMEM);
-
-  status = parse_query_string (copy);
-  free (copy);
-
-  parameters_init = 1;
-
-  return (status);
-} /* }}} int param_init */
-
-void param_finish (void) /* {{{ */
-{
-  size_t i;
-
-  if (!parameters_init)
-    return;
-
-  for (i = 0; i < parameters_num; i++)
-  {
-    free (parameters[i].key);
-    free (parameters[i].value);
-  }
-  free (parameters);
-
-  parameters = NULL;
-  parameters_num = 0;
-  parameters_init = 0;
-} /* }}} void param_finish */
-
-const char *param (const char *key) /* {{{ */
-{
-  param_init ();
-
-  return (parameter_lookup (key));
-} /* }}} const char *param */
-
-int uri_escape (char *dst, const char *src, size_t size) /* {{{ */
-{
-  size_t in;
-  size_t out;
-
-  in = 0;
-  out = 0;
-  while (42)
-  {
-    if (src[in] == 0)
-    {
-      dst[out] = 0;
-      return (0);
-    }
-    else if ((src[in] < 32)
-        || (src[in] == '&')
-        || (src[in] == ';')
-        || (src[in] >= 128))
-    {
-      char esc[4];
-
-      if ((size - out) < 4)
-        break;
-      
-      snprintf (esc, sizeof (esc), "%%%02x", (unsigned int) src[in]);
-      dst[out] = esc[0];
-      dst[out+1] = esc[1];
-      dst[out+2] = esc[2];
-
-      out += 3;
-      in++;
-    }
-    else
-    {
-      dst[out] = src[in];
-      out++;
-      in++;
-    }
-  } /* while (42) */
-} /* }}} int uri_escape */
-
-/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/utils_params.h b/utils_params.h
deleted file mode 100644 (file)
index 3c7ea0a..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef UTILS_PARAMS_H
-#define UTILS_PARAMS_H 1
-
-int param_init (void);
-void param_finish (void);
-
-const char *param (const char *key);
-
-int uri_escape (char *dst, const char *src, size_t size);
-
-#endif /* UTILS_PARAMS_H */