summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 9d682b2)
raw | patch | inline | side by side (parent: 9d682b2)
author | Florian Forster <octo@noris.net> | |
Thu, 21 Aug 2008 07:26:21 +0000 (09:26 +0200) | ||
committer | Florian Forster <octo@noris.net> | |
Thu, 21 Aug 2008 07:26:21 +0000 (09:26 +0200) |
Due to a bug in the parsing of the FLUSH command, identifiers which
contained spaces would not be accepted. This patch introduces
src/utils_parse_option.[ch], which strips off an option in the form of
name="value" from the beginning of a buffer (removing leading and
trailing spaces) and returns the values found.
The Collectd::Unixsock module is updated to automatically quote
identifiers when necessary.
Many other commands may be effected by this bug, too. They'll be fixed
soon.
contained spaces would not be accepted. This patch introduces
src/utils_parse_option.[ch], which strips off an option in the form of
name="value" from the beginning of a buffer (removing leading and
trailing spaces) and returns the values found.
The Collectd::Unixsock module is updated to automatically quote
identifiers when necessary.
Many other commands may be effected by this bug, too. They'll be fixed
soon.
bindings/perl/Collectd/Unixsock.pm | patch | blob | history | |
src/Makefile.am | patch | blob | history | |
src/unixsock.c | patch | blob | history | |
src/utils_cmd_flush.c | patch | blob | history | |
src/utils_cmd_flush.h | patch | blob | history | |
src/utils_parse_option.c | [new file with mode: 0644] | patch | blob |
src/utils_parse_option.h | [new file with mode: 0644] | patch | blob |
index af274a588e5eed3a8d7503b72326c318ae13eb1a..da144e6e4b4fd95967d7f2d85eeaaf3175c5759b 100644 (file)
{
return;
}
+ if ($ident_str =~ m/ /)
+ {
+ $ident_str =~ s#\\#\\\\#g;
+ $ident_str =~ s#"#\\"#g;
+ $ident_str = "\"$ident_str\"";
+ }
$msg .= " identifier=$ident_str";
}
diff --git a/src/Makefile.am b/src/Makefile.am
index f0ad3cb4c5f2a321381f7b30d6193ea28598ec30..acc53054512b861e3594a7098a493abec2d20c6f 100644 (file)
--- a/src/Makefile.am
+++ b/src/Makefile.am
if BUILD_PLUGIN_UNIXSOCK
pkglib_LTLIBRARIES += unixsock.la
unixsock_la_SOURCES = unixsock.c \
+ utils_parse_option.h utils_parse_option.c \
utils_cmd_flush.h utils_cmd_flush.c \
utils_cmd_getval.h utils_cmd_getval.c \
utils_cmd_listval.h utils_cmd_listval.c \
diff --git a/src/unixsock.c b/src/unixsock.c
index d34b91fae204d9ac43e885c5895db4c37448005e..c2e1f302d67fc2f59aca6e5155f963f5d8f05ad5 100644 (file)
--- a/src/unixsock.c
+++ b/src/unixsock.c
{
int fd;
FILE *fhin, *fhout;
- char buffer[1024];
- char *fields[128];
- int fields_num;
fd = *((int *) arg);
free (arg);
while (42)
{
- int len;
+ char buffer[1024];
+ char buffer_copy[1024];
+ char *fields[128];
+ int fields_num;
+ int len;
errno = 0;
if (fgets (buffer, sizeof (buffer), fhin) == NULL)
if (len == 0)
continue;
- DEBUG ("fgets -> buffer = %s; len = %i;", buffer, len);
+ sstrncpy (buffer_copy, buffer, sizeof (buffer_copy));
- fields_num = strsplit (buffer, fields,
+ fields_num = strsplit (buffer_copy, fields,
sizeof (fields) / sizeof (fields[0]));
if (fields_num < 1)
}
else if (strcasecmp (fields[0], "flush") == 0)
{
- handle_flush (fhout, fields, fields_num);
+ handle_flush (fhout, buffer);
}
else
{
diff --git a/src/utils_cmd_flush.c b/src/utils_cmd_flush.c
index 7feaac28c556b6a74b10af845082c7342926722f..74807b84395901d44935cdab9760edd740cdf2f7 100644 (file)
--- a/src/utils_cmd_flush.c
+++ b/src/utils_cmd_flush.c
#include "collectd.h"
#include "common.h"
#include "plugin.h"
+#include "utils_parse_option.h"
#define print_to_socket(fh, ...) \
if (fprintf (fh, __VA_ARGS__) < 0) { \
return (0);
} /* int add_to_array */
-int handle_flush (FILE *fh, char **fields, int fields_num)
+int handle_flush (FILE *fh, char *buffer)
{
int success = 0;
int error = 0;
int i;
- for (i = 1; i < fields_num; i++)
+ if ((fh == NULL) || (buffer == NULL))
+ return (-1);
+
+ DEBUG ("utils_cmd_flush: handle_flush (fh = %p, buffer = %s);",
+ (void *) fh, buffer);
+
+ if (strncasecmp ("FLUSH", buffer, strlen ("FLUSH")) != 0)
{
- char *option = fields[i];
- int status = 0;
+ print_to_socket (fh, "-1 Cannot parse command.\n");
+ return (-1);
+ }
+ buffer += strlen ("FLUSH");
- if (strncasecmp ("plugin=", option, strlen ("plugin=")) == 0)
+ while (*buffer != 0)
+ {
+ char *opt_key;
+ char *opt_value;
+ int status;
+
+ opt_key = NULL;
+ opt_value = NULL;
+ status = parse_option (&buffer, &opt_key, &opt_value);
+ if (status != 0)
{
- char *plugin;
-
- plugin = option + strlen ("plugin=");
- add_to_array (&plugins, &plugins_num, plugin);
+ print_to_socket (fh, "-1 Parsing options failed.\n");
+ sfree (plugins);
+ sfree (identifiers);
+ return (-1);
}
- else if (strncasecmp ("identifier=", option, strlen ("identifier=")) == 0)
- {
- char *identifier;
- identifier = option + strlen ("identifier=");
- add_to_array (&identifiers, &identifiers_num, identifier);
+ if (strcasecmp ("plugin", opt_key) == 0)
+ {
+ add_to_array (&plugins, &plugins_num, opt_value);
}
- else if (strncasecmp ("timeout=", option, strlen ("timeout=")) == 0)
+ else if (strcasecmp ("identifier", opt_key) == 0)
{
- char *endptr = NULL;
- char *value = option + strlen ("timeout=");
-
+ add_to_array (&identifiers, &identifiers_num, opt_value);
+ }
+ else if (strcasecmp ("timeout", opt_key) == 0)
+ {
+ char *endptr;
+
errno = 0;
- timeout = strtol (value, &endptr, 0);
-
- if ((endptr == value) || (0 != errno))
- status = -1;
- else if (0 >= timeout)
+ endptr = NULL;
+ timeout = strtol (opt_value, &endptr, 0);
+
+ if ((endptr == opt_value) || (errno != 0))
+ {
+ print_to_socket (fh, "-1 Invalid value for option `timeout': "
+ "%s\n", opt_value);
+ sfree (plugins);
+ sfree (identifiers);
+ return (-1);
+ }
+ else if (timeout <= 0)
timeout = -1;
}
else
- status = -1;
-
- if (status != 0)
{
- print_to_socket (fh, "-1 Cannot parse option %s\n", option);
+ print_to_socket (fh, "-1 Cannot parse option %s\n", opt_key);
+ sfree (plugins);
+ sfree (identifiers);
return (-1);
}
- }
+ } /* while (*buffer != 0) */
/* Add NULL entries for `any plugin' and/or `any value' if nothing was
* specified. */
print_to_socket (fh, "0 Done\n");
}
+ sfree (plugins);
+ sfree (identifiers);
return (0);
} /* int handle_flush */
diff --git a/src/utils_cmd_flush.h b/src/utils_cmd_flush.h
index 334f0862f5df284154ff4649431b1bc11633b294..dccafd1534255307701d030a82b706cbbacf797d 100644 (file)
--- a/src/utils_cmd_flush.h
+++ b/src/utils_cmd_flush.h
#ifndef UTILS_CMD_FLUSH_H
#define UTILS_CMD_FLUSH_H 1
-int handle_flush (FILE *fh, char **fields, int fields_num);
+int handle_flush (FILE *fh, char *buffer);
#endif /* UTILS_CMD_FLUSH_H */
diff --git a/src/utils_parse_option.c b/src/utils_parse_option.c
--- /dev/null
+++ b/src/utils_parse_option.c
@@ -0,0 +1,123 @@
+/**
+ * collectd - src/utils_parse_option.c
+ * Copyright (C) 2008 Florian 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
+ *
+ * Author:
+ * Florian octo Forster <octo at verplant.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "utils_parse_option.h"
+
+/*
+ * parse_option
+ * ------------
+ * Parses an ``option'' as used with the unixsock and exec commands. An
+ * option is of the form:
+ * name0="value"
+ * name1="value with \"quotes\""
+ * name2="value \\ backslash"
+ * However, if the value does *not* contain a space character, you can skip
+ * the quotes.
+ */
+int parse_option (char **ret_buffer, char **ret_key, char **ret_value)
+{
+ char *buffer;
+ char *key;
+ char *value;
+
+ buffer = *ret_buffer;
+
+ /* Eat up leading spaces */
+ key = buffer;
+ while (isspace ((int) *key))
+ key++;
+ if (*key == 0)
+ return (1);
+
+ /* Look for the equal sign */
+ value = key;
+ while (isalnum ((int) *value))
+ value++;
+ if ((*value != '=') || (value == key))
+ return (1);
+ *value = 0;
+ value++;
+ /* Empty values must be written as "" */
+ if (isspace ((int) *value) || (*value == 0))
+ return (-1);
+
+ /* A quoted value */
+ if (*value == '"')
+ {
+ char *dst;
+
+ value++;
+ if (*value == 0)
+ return (-1);
+
+ dst = value;
+ buffer = value;
+ while ((*buffer != '"') && (*buffer != 0))
+ {
+ /* Un-escape backslashes */
+ if (*buffer == '\\')
+ {
+ buffer++;
+ /* Catch a backslash at the end of buffer */
+ if (*buffer == 0)
+ return (-1);
+ }
+ *dst = *buffer;
+ buffer++;
+ dst++;
+ }
+ /* No quote sign has been found */
+ if (*buffer == 0)
+ return (-1);
+ *buffer = 0;
+ buffer++;
+
+ /* Check for trailing spaces. */
+ if ((*buffer != 0) && !isspace ((int) *buffer))
+ return (-1);
+ }
+ else /* an unquoted value */
+ {
+ buffer = value;
+ while (!isspace ((int) *buffer))
+ buffer++;
+ if (*buffer != 0)
+ {
+ *buffer = 0;
+ buffer++;
+ }
+ }
+
+ /* Eat up trailing spaces */
+ while (isspace ((int) *buffer))
+ buffer++;
+
+ *ret_buffer = buffer;
+ *ret_key = key;
+ *ret_value = value;
+
+ return (0);
+} /* int parse_option */
+
+/* vim: set sw=2 ts=8 tw=78 et : */
diff --git a/src/utils_parse_option.h b/src/utils_parse_option.h
--- /dev/null
+++ b/src/utils_parse_option.h
@@ -0,0 +1,29 @@
+/**
+ * collectd - src/utils_parse_option.h
+ * Copyright (C) 2008 Florian 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
+ *
+ * Author:
+ * Florian octo Forster <octo at verplant.org>
+ **/
+
+#ifndef UTILS_PARSE_OPTION
+#define UTILS_PARSE_OPTION 1
+
+int parse_option (char **ret_buffer, char **ret_key, char **ret_value);
+
+#endif /* UTILS_PARSE_OPTION */
+
+/* vim: set sw=2 ts=8 tw=78 et : */