src/utils_parse_option.c: Check for the terminating null-byte, too.
[collectd.git] / src / utils_parse_option.c
1 /**
2  * collectd - src/utils_parse_option.c
3  * Copyright (C) 2008  Florian Forster
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License as published by the
7  * Free Software Foundation; only version 2 of the License is applicable.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
17  *
18  * Author:
19  *   Florian octo Forster <octo at verplant.org>
20  **/
21
22 #include "collectd.h"
23 #include "common.h"
24 #include "plugin.h"
25 #include "utils_parse_option.h"
26
27 /*
28  * parse_option
29  * ------------
30  *  Parses an ``option'' as used with the unixsock and exec commands. An
31  *  option is of the form:
32  *    name0="value"
33  *    name1="value with \"quotes\""
34  *    name2="value \\ backslash"
35  *  However, if the value does *not* contain a space character, you can skip
36  *  the quotes.
37  */
38 int parse_option (char **ret_buffer, char **ret_key, char **ret_value)
39 {
40   char *buffer;
41   char *key;
42   char *value;
43
44   buffer = *ret_buffer;
45
46   /* Eat up leading spaces */
47   key = buffer;
48   while (isspace ((int) *key))
49     key++;
50   if (*key == 0)
51     return (1);
52
53   /* Look for the equal sign */
54   value = key;
55   while (isalnum ((int) *value))
56     value++;
57   if ((*value != '=') || (value == key))
58     return (1);
59   *value = 0;
60   value++;
61   /* Empty values must be written as "" */
62   if (isspace ((int) *value) || (*value == 0))
63     return (-1);
64
65   /* A quoted value */
66   if (*value == '"')
67   {
68     char *dst;
69
70     value++;
71     if (*value == 0)
72       return (-1);
73
74     dst = value;
75     buffer = value;
76     while ((*buffer != '"') && (*buffer != 0))
77     {
78       /* Un-escape backslashes */
79       if (*buffer == '\\')
80       {
81         buffer++;
82         /* Catch a backslash at the end of buffer */
83         if (*buffer == 0)
84           return (-1);
85       }
86       *dst = *buffer;
87       buffer++;
88       dst++;
89     }
90     /* No quote sign has been found */
91     if (*buffer == 0)
92       return (-1);
93     *buffer = 0;
94     buffer++;
95
96     /* Check for trailing spaces. */
97     if ((*buffer != 0) && !isspace ((int) *buffer))
98       return (-1);
99   }
100   else /* an unquoted value */
101   {
102     buffer = value;
103     while ((*buffer != 0) && !isspace ((int) *buffer))
104       buffer++;
105     if (*buffer != 0)
106     {
107       *buffer = 0;
108       buffer++;
109     }
110   }
111
112   /* Eat up trailing spaces */
113   while (isspace ((int) *buffer))
114     buffer++;
115
116   *ret_buffer = buffer;
117   *ret_key = key;
118   *ret_value = value;
119
120   return (0);
121 } /* int parse_option */
122
123 /* vim: set sw=2 ts=8 tw=78 et : */