Merge branch 'collectd-5.7'
[collectd.git] / src / utils_parse_option.c
1 /**
2  * collectd - src/utils_parse_option.c
3  * Copyright (C) 2008       Florian Forster
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  *
23  * Authors:
24  *   Florian octo Forster <octo at collectd.org>
25  **/
26
27 #include "collectd.h"
28
29 #include "utils_parse_option.h"
30
31 int parse_string(char **ret_buffer, char **ret_string) {
32   char *buffer;
33   char *string;
34
35   buffer = *ret_buffer;
36
37   /* Eat up leading spaces. */
38   string = buffer;
39   while (isspace((int)*string))
40     string++;
41   if (*string == 0)
42     return 1;
43
44   /* A quoted string */
45   if (*string == '"') {
46     char *dst;
47
48     string++;
49     if (*string == 0)
50       return 1;
51
52     dst = string;
53     buffer = string;
54     while ((*buffer != '"') && (*buffer != 0)) {
55       /* Un-escape backslashes */
56       if (*buffer == '\\') {
57         buffer++;
58         /* Catch a backslash at the end of buffer */
59         if (*buffer == 0)
60           return -1;
61       }
62       *dst = *buffer;
63       buffer++;
64       dst++;
65     }
66     /* No quote sign has been found */
67     if (*buffer == 0)
68       return -1;
69
70     *dst = 0;
71     dst++;
72     *buffer = 0;
73     buffer++;
74
75     /* Check for trailing spaces. */
76     if ((*buffer != 0) && !isspace((int)*buffer))
77       return -1;
78   } else /* an unquoted string */
79   {
80     buffer = string;
81     while ((*buffer != 0) && !isspace((int)*buffer))
82       buffer++;
83     if (*buffer != 0) {
84       *buffer = 0;
85       buffer++;
86     }
87   }
88
89   /* Eat up trailing spaces */
90   while (isspace((int)*buffer))
91     buffer++;
92
93   *ret_buffer = buffer;
94   *ret_string = string;
95
96   return 0;
97 } /* int parse_string */
98
99 /*
100  * parse_option
101  * ------------
102  *  Parses an ``option'' as used with the unixsock and exec commands. An
103  *  option is of the form:
104  *    name0="value"
105  *    name1="value with \"quotes\""
106  *    name2="value \\ backslash"
107  *  However, if the value does *not* contain a space character, you can skip
108  *  the quotes.
109  */
110 int parse_option(char **ret_buffer, char **ret_key, char **ret_value) {
111   char *buffer;
112   char *key;
113   char *value;
114   int status;
115
116   buffer = *ret_buffer;
117
118   /* Eat up leading spaces */
119   key = buffer;
120   while (isspace((int)*key))
121     key++;
122   if (*key == 0)
123     return 1;
124
125   /* Look for the equal sign */
126   buffer = key;
127   while (isalnum((int)*buffer) || *buffer == '_' || *buffer == ':')
128     buffer++;
129   if ((*buffer != '=') || (buffer == key))
130     return 1;
131   *buffer = 0;
132   buffer++;
133   /* Empty values must be written as "" */
134   if (isspace((int)*buffer) || (*buffer == 0))
135     return -1;
136
137   status = parse_string(&buffer, &value);
138   if (status != 0)
139     return -1;
140
141   /* NB: parse_string will have eaten up all trailing spaces. */
142
143   *ret_buffer = buffer;
144   *ret_key = key;
145   *ret_value = value;
146
147   return 0;
148 } /* int parse_option */