{GPL, other}: Relicense to MIT license.
[collectd.git] / src / utils_parse_option.c
index 06e9f28..0ee4c79 100644 (file)
@@ -1,22 +1,27 @@
 /**
  * collectd - src/utils_parse_option.c
- * Copyright (C) 2008  Florian Forster
+ * 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.
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
  *
- * 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.
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
  *
- * 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
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
  *
- * Author:
- *   Florian octo Forster <octo at verplant.org>
+ * Authors:
+ *   Florian octo Forster <octo at collectd.org>
  **/
 
 #include "collectd.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)
+int parse_string (char **ret_buffer, char **ret_string)
 {
   char *buffer;
-  char *key;
-  char *value;
+  char *string;
 
   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))
+  /* Eat up leading spaces. */
+  string = buffer;
+  while (isspace ((int) *string))
+    string++;
+  if (*string == 0)
     return (1);
-  *value = 0;
-  value++;
-  /* Empty values must be written as "" */
-  if (isspace ((int) *value) || (*value == 0))
-    return (-1);
 
-  /* A quoted value */
-  if (*value == '"')
+  /* A quoted string */
+  if (*string == '"')
   {
     char *dst;
 
-    value++;
-    if (*value == 0)
-      return (-1);
+    string++;
+    if (*string == 0)
+      return (1);
 
-    dst = value;
-    buffer = value;
+    dst = string;
+    buffer = string;
     while ((*buffer != '"') && (*buffer != 0))
     {
       /* Un-escape backslashes */
@@ -90,6 +71,9 @@ int parse_option (char **ret_buffer, char **ret_key, char **ret_value)
     /* No quote sign has been found */
     if (*buffer == 0)
       return (-1);
+
+    *dst = 0;
+    dst++;
     *buffer = 0;
     buffer++;
 
@@ -97,10 +81,10 @@ int parse_option (char **ret_buffer, char **ret_key, char **ret_value)
     if ((*buffer != 0) && !isspace ((int) *buffer))
       return (-1);
   }
-  else /* an unquoted value */
+  else /* an unquoted string */
   {
-    buffer = value;
-    while (!isspace ((int) *buffer))
+    buffer = string;
+    while ((*buffer != 0) && !isspace ((int) *buffer))
       buffer++;
     if (*buffer != 0)
     {
@@ -108,16 +92,118 @@ int parse_option (char **ret_buffer, char **ret_key, char **ret_value)
       buffer++;
     }
   }
-
+  
   /* Eat up trailing spaces */
   while (isspace ((int) *buffer))
     buffer++;
 
   *ret_buffer = buffer;
+  *ret_string = string;
+
+  return (0);
+} /* int parse_string */
+
+/*
+ * 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;
+  int status;
+
+  buffer = *ret_buffer;
+
+  /* Eat up leading spaces */
+  key = buffer;
+  while (isspace ((int) *key))
+    key++;
+  if (*key == 0)
+    return (1);
+
+  /* Look for the equal sign */
+  buffer = key;
+  while (isalnum ((int) *buffer) || *buffer == '_')
+    buffer++;
+  if ((*buffer != '=') || (buffer == key))
+    return (1);
+  *buffer = 0;
+  buffer++;
+  /* Empty values must be written as "" */
+  if (isspace ((int) *buffer) || (*buffer == 0))
+    return (-1);
+
+  status = parse_string (&buffer, &value);
+  if (status != 0)
+    return (-1);
+
+  /* NB: parse_string will have eaten up all trailing spaces. */
+
+  *ret_buffer = buffer;
   *ret_key = key;
   *ret_value = value;
 
   return (0);
 } /* int parse_option */
 
+int escape_string (char *buffer, size_t buffer_size)
+{
+  char *temp;
+  size_t i;
+  size_t j;
+
+  /* Check if we need to escape at all first */
+  temp = strpbrk (buffer, " \t\"\\");
+  if (temp == NULL)
+    return (0);
+
+  temp = (char *) malloc (buffer_size);
+  if (temp == NULL)
+    return (-1);
+  memset (temp, 0, buffer_size);
+
+  temp[0] = '"';
+  j = 1;
+
+  for (i = 0; i < buffer_size; i++)
+  {
+    if (buffer[i] == 0)
+    {
+      break;
+    }
+    else if ((buffer[i] == '"') || (buffer[i] == '\\'))
+    {
+      if (j > (buffer_size - 4))
+        break;
+      temp[j] = '\\';
+      temp[j + 1] = buffer[i];
+      j += 2;
+    }
+    else
+    {
+      if (j > (buffer_size - 3))
+        break;
+      temp[j] = buffer[i];
+      j++;
+    }
+  }
+
+  assert ((j + 1) < buffer_size);
+  temp[j] = '"';
+  temp[j + 1] = 0;
+
+  sstrncpy (buffer, temp, buffer_size);
+  sfree (temp);
+  return (0);
+} /* int escape_string */
+
 /* vim: set sw=2 ts=8 tw=78 et : */