From: Florian Forster Date: Wed, 16 Jun 2010 15:13:28 +0000 (+0200) Subject: Autotoolization. X-Git-Tag: v4.0.0~248 X-Git-Url: https://git.octo.it/?p=collection4.git;a=commitdiff_plain;h=0ab3085f89e64eecd67d3179ea87f0463e918a10 Autotoolization. --- diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..e69de29 diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..e69de29 diff --git a/Makefile b/Makefile deleted file mode 100644 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 index 0000000..af437a6 --- /dev/null +++ b/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = src diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..e69de29 diff --git a/README b/README new file mode 100644 index 0000000..e69de29 diff --git a/action_graph.c b/action_graph.c deleted file mode 100644 index a0f257e..0000000 --- a/action_graph.c +++ /dev/null @@ -1,150 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include /* for PATH_MAX */ -#include -#include - -#include - -#include "common.h" -#include "action_graph.h" -#include "graph_list.h" -#include "utils_params.h" -#include "utils_array.h" - -#include -#include - -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 index 712f398..0000000 --- a/action_graph.h +++ /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 index 29e3d8b..0000000 --- a/action_list_graphs.c +++ /dev/null @@ -1,126 +0,0 @@ -#include -#include -#include -#include - -#include "action_list_graphs.h" -#include "graph.h" -#include "graph_list.h" -#include "utils_params.h" - -#include -#include - -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 ("
  • %s
  • \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 ("
  • %s\n
      \n", buffer); - gl_graph_instance_get_all (cfg, print_graph_inst_html, /* user_data = */ NULL); - printf ("
  • \n"); - - return (0); -} /* }}} int print_graph_html */ - -static int list_graphs_html (void) /* {{{ */ -{ - printf ("Content-Type: text/html\n\n"); - - printf ("
      \n"); - gl_graph_get_all (print_graph_html, /* user_data = */ NULL); - printf ("
    \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 index dd7edf9..0000000 --- a/action_list_graphs.h +++ /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 index 25b81ab..0000000 --- a/aux_types.h +++ /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 index 2b6b5eb..0000000 --- a/common.c +++ /dev/null @@ -1,193 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "common.h" -#include "graph_list.h" - -#include -#include - -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 index 2b5662f..0000000 --- a/common.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef COMMON_H -#define COMMON_H 1 - -#include -#include - -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 index 0000000..9c8b628 --- /dev/null +++ b/configure.ac @@ -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 index a5eeb81..0000000 --- a/filesystem.c +++ /dev/null @@ -1,297 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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 index 9569bc3..0000000 --- a/filesystem.h +++ /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 index 154af77..0000000 --- a/graph.c +++ /dev/null @@ -1,290 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#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 -#include - -/* - * 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 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 index 94dd440..0000000 --- a/graph_config.c +++ /dev/null @@ -1,116 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#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 index c468eec..0000000 --- a/graph_config.h +++ /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 index b8e0ce4..0000000 --- a/graph_def.c +++ /dev/null @@ -1,348 +0,0 @@ -#include -#include -#include - -#include "graph_def.h" -#include "graph.h" -#include "graph_config.h" -#include "common.h" -#include "oconfig.h" - -#include -#include - -/* - * 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 index b2cd228..0000000 --- a/graph_def.h +++ /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 index b008a56..0000000 --- a/graph_ident.c +++ /dev/null @@ -1,455 +0,0 @@ -#include -#include -#include -#include -#include /* 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 index 5107011..0000000 --- a/graph_ident.h +++ /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 index 103be23..0000000 --- a/graph_instance.c +++ /dev/null @@ -1,475 +0,0 @@ -#include -#include -#include - -#include "graph_instance.h" -#include "graph_ident.h" -#include "graph_list.h" -#include "common.h" -#include "utils_params.h" - -#include -#include - -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 index b90f984..0000000 --- a/graph_instance.h +++ /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 index 965fcba..0000000 --- a/graph_list.c +++ /dev/null @@ -1,287 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#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 -#include - -/* - * 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 index c17d6fc..0000000 --- a/graph_list.h +++ /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 index b8087dd..0000000 --- a/oconfig.c +++ /dev/null @@ -1,217 +0,0 @@ -/** - * oconfig - src/oconfig.c - * Copyright (C) 2006,2007 Florian octo Forster - * - * 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 -#include -#include -#include -#include - -#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), "", fileno (fh)); - - if ((status < 0) || (((size_t) status) >= sizeof (file))) { - c_file = ""; - } - 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 index 70fc623..0000000 --- a/oconfig.h +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef OCONFIG_H -#define OCONFIG_H 1 - -#include - -/** - * oconfig - src/oconfig.h - * Copyright (C) 2006-2009 Florian octo Forster - * - * 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 index 5b7aa94..0000000 --- a/parser.y +++ /dev/null @@ -1,239 +0,0 @@ -/** - * oconfig - src/parser.y - * Copyright (C) 2007,2008 Florian octo Forster - * - * 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 -#include -#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 -%token BTRUE BFALSE -%token QUOTED_STRING UNQUOTED_STRING -%token SLASH OPENBRAC CLOSEBRAC EOL - -%type string -%type identifier -/* arguments */ -%type argument -%type argument_list -/* blocks */ -%type block_begin -%type block -%type block_end -/* statements */ -%type option -%type statement -%type statement_list -%type 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 = ""; - 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 index 9f0cd8e..0000000 --- a/scanner.l +++ /dev/null @@ -1,137 +0,0 @@ -/** - * oconfig - src/scanner.l - * Copyright (C) 2007 Florian octo Forster - * Copyright (C) 2008 Sebastian tokkee Harl - * - * 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 -#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 "\\" */ - if ('\r' == yytext[len - 2]) - len -= 3; - else - len -= 2; - yytext[len] = '\0'; - - ml_append (yytext); - BEGIN (ML); -} -^{WHITE_SPACE}+ {/* remove leading white-space */} -{NON_WHITE_SPACE}{QUOTED_STRING}\\{EOL} { - int len = strlen (yytext); - - /* remove "\\" */ - if ('\r' == yytext[len - 2]) - len -= 3; - else - len -= 2; - yytext[len] = '\0'; - - ml_append(yytext); -} -{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 index 0000000..de0cb7e --- /dev/null +++ b/src/Makefile.am @@ -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 index 0000000..a0f257e --- /dev/null +++ b/src/action_graph.c @@ -0,0 +1,150 @@ +#include +#include +#include +#include +#include +#include +#include /* for PATH_MAX */ +#include +#include + +#include + +#include "common.h" +#include "action_graph.h" +#include "graph_list.h" +#include "utils_params.h" +#include "utils_array.h" + +#include +#include + +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 index 0000000..712f398 --- /dev/null +++ b/src/action_graph.h @@ -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 index 0000000..29e3d8b --- /dev/null +++ b/src/action_list_graphs.c @@ -0,0 +1,126 @@ +#include +#include +#include +#include + +#include "action_list_graphs.h" +#include "graph.h" +#include "graph_list.h" +#include "utils_params.h" + +#include +#include + +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 ("
  • %s
  • \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 ("
  • %s\n
      \n", buffer); + gl_graph_instance_get_all (cfg, print_graph_inst_html, /* user_data = */ NULL); + printf ("
  • \n"); + + return (0); +} /* }}} int print_graph_html */ + +static int list_graphs_html (void) /* {{{ */ +{ + printf ("Content-Type: text/html\n\n"); + + printf ("
      \n"); + gl_graph_get_all (print_graph_html, /* user_data = */ NULL); + printf ("
    \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 index 0000000..dd7edf9 --- /dev/null +++ b/src/action_list_graphs.h @@ -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 index 0000000..25b81ab --- /dev/null +++ b/src/aux_types.h @@ -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 index 0000000..2b6b5eb --- /dev/null +++ b/src/common.c @@ -0,0 +1,193 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "common.h" +#include "graph_list.h" + +#include +#include + +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 index 0000000..2b5662f --- /dev/null +++ b/src/common.h @@ -0,0 +1,24 @@ +#ifndef COMMON_H +#define COMMON_H 1 + +#include +#include + +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 index 0000000..a5eeb81 --- /dev/null +++ b/src/filesystem.c @@ -0,0 +1,297 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 index 0000000..9569bc3 --- /dev/null +++ b/src/filesystem.h @@ -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 index 0000000..154af77 --- /dev/null +++ b/src/graph.c @@ -0,0 +1,290 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#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 +#include + +/* + * 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 index 0000000..6e9ae07 --- /dev/null +++ b/src/graph.h @@ -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 index 0000000..94dd440 --- /dev/null +++ b/src/graph_config.c @@ -0,0 +1,116 @@ +#include +#include +#include +#include +#include +#include +#include + +#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 index 0000000..c468eec --- /dev/null +++ b/src/graph_config.h @@ -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 index 0000000..b8e0ce4 --- /dev/null +++ b/src/graph_def.c @@ -0,0 +1,348 @@ +#include +#include +#include + +#include "graph_def.h" +#include "graph.h" +#include "graph_config.h" +#include "common.h" +#include "oconfig.h" + +#include +#include + +/* + * 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 index 0000000..b2cd228 --- /dev/null +++ b/src/graph_def.h @@ -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 index 0000000..b008a56 --- /dev/null +++ b/src/graph_ident.c @@ -0,0 +1,455 @@ +#include +#include +#include +#include +#include /* 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 index 0000000..5107011 --- /dev/null +++ b/src/graph_ident.h @@ -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 index 0000000..103be23 --- /dev/null +++ b/src/graph_instance.c @@ -0,0 +1,475 @@ +#include +#include +#include + +#include "graph_instance.h" +#include "graph_ident.h" +#include "graph_list.h" +#include "common.h" +#include "utils_params.h" + +#include +#include + +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 index 0000000..b90f984 --- /dev/null +++ b/src/graph_instance.h @@ -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 index 0000000..965fcba --- /dev/null +++ b/src/graph_list.c @@ -0,0 +1,287 @@ +#include +#include +#include +#include +#include +#include +#include + +#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 +#include + +/* + * 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 index 0000000..c17d6fc --- /dev/null +++ b/src/graph_list.h @@ -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 index 0000000..097c55c --- /dev/null +++ b/src/main.c @@ -0,0 +1,112 @@ +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#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 doesn't interfere + * with our own header files. */ +#include +#include + +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 index 0000000..79eec36 --- /dev/null +++ b/src/oconfig.c @@ -0,0 +1,218 @@ +/** + * oconfig - src/oconfig.c + * Copyright (C) 2006,2007 Florian octo Forster + * + * 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 +#include +#include +#include +#include + +#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), "", fileno (fh)); + + if ((status < 0) || (((size_t) status) >= sizeof (file))) { + c_file = ""; + } + 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 index 0000000..70fc623 --- /dev/null +++ b/src/oconfig.h @@ -0,0 +1,69 @@ +#ifndef OCONFIG_H +#define OCONFIG_H 1 + +#include + +/** + * oconfig - src/oconfig.h + * Copyright (C) 2006-2009 Florian octo Forster + * + * 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 index 0000000..5b7aa94 --- /dev/null +++ b/src/parser.y @@ -0,0 +1,239 @@ +/** + * oconfig - src/parser.y + * Copyright (C) 2007,2008 Florian octo Forster + * + * 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 +#include +#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 +%token BTRUE BFALSE +%token QUOTED_STRING UNQUOTED_STRING +%token SLASH OPENBRAC CLOSEBRAC EOL + +%type string +%type identifier +/* arguments */ +%type argument +%type argument_list +/* blocks */ +%type block_begin +%type block +%type block_end +/* statements */ +%type option +%type statement +%type statement_list +%type 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 = ""; + 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 index 0000000..9f0cd8e --- /dev/null +++ b/src/scanner.l @@ -0,0 +1,137 @@ +/** + * oconfig - src/scanner.l + * Copyright (C) 2007 Florian octo Forster + * Copyright (C) 2008 Sebastian tokkee Harl + * + * 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 +#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 "\\" */ + if ('\r' == yytext[len - 2]) + len -= 3; + else + len -= 2; + yytext[len] = '\0'; + + ml_append (yytext); + BEGIN (ML); +} +^{WHITE_SPACE}+ {/* remove leading white-space */} +{NON_WHITE_SPACE}{QUOTED_STRING}\\{EOL} { + int len = strlen (yytext); + + /* remove "\\" */ + if ('\r' == yytext[len - 2]) + len -= 3; + else + len -= 2; + yytext[len] = '\0'; + + ml_append(yytext); +} +{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 index 0000000..5aaabbc --- /dev/null +++ b/src/utils_array.c @@ -0,0 +1,95 @@ +#include +#include +#include +#include +#include + +#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 index 0000000..917bea9 --- /dev/null +++ b/src/utils_array.h @@ -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 index 0000000..6e5dc89 --- /dev/null +++ b/src/utils_params.c @@ -0,0 +1,259 @@ +#include +#include +#include +#include +#include + +#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 index 0000000..3c7ea0a --- /dev/null +++ b/src/utils_params.h @@ -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 index 097c55c..0000000 --- a/test.fcgi.c +++ /dev/null @@ -1,112 +0,0 @@ -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#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 doesn't interfere - * with our own header files. */ -#include -#include - -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 index 5aaabbc..0000000 --- a/utils_array.c +++ /dev/null @@ -1,95 +0,0 @@ -#include -#include -#include -#include -#include - -#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 index 917bea9..0000000 --- a/utils_array.h +++ /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 index 6e5dc89..0000000 --- a/utils_params.c +++ /dev/null @@ -1,259 +0,0 @@ -#include -#include -#include -#include -#include - -#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 index 3c7ea0a..0000000 --- a/utils_params.h +++ /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 */