diff options
author | Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> | 2025-09-15 14:06:55 +0200 |
---|---|---|
committer | Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> | 2025-09-15 14:06:55 +0200 |
commit | f855c5b5bbbc6d5436741fd8108be64825a3c76b (patch) | |
tree | 0ee1242bc21dc75a12fae03a5bb211fe10c89625 /lib/parse_ini.c | |
parent | 8ef825d85fb4d09c32ca44c545d6eb8d995ddea4 (diff) | |
download | monitoring-plugins-f855c5b5bbbc6d5436741fd8108be64825a3c76b.tar.gz |
general refactorin in lib, more local variables, real booleans
Diffstat (limited to 'lib/parse_ini.c')
-rw-r--r-- | lib/parse_ini.c | 141 |
1 files changed, 81 insertions, 60 deletions
diff --git a/lib/parse_ini.c b/lib/parse_ini.c index 4c3c1b93..db337622 100644 --- a/lib/parse_ini.c +++ b/lib/parse_ini.c | |||
@@ -59,10 +59,10 @@ static char *default_ini_path_names[] = { | |||
59 | } while ((c) != EOF && (c) != (n)) | 59 | } while ((c) != EOF && (c) != (n)) |
60 | 60 | ||
61 | /* internal function that returns the constructed defaults options */ | 61 | /* internal function that returns the constructed defaults options */ |
62 | static int read_defaults(FILE *f, const char *stanza, np_arg_list **opts); | 62 | static bool read_defaults(FILE *defaults_file, const char *stanza, np_arg_list **opts); |
63 | 63 | ||
64 | /* internal function that converts a single line into options format */ | 64 | /* internal function that converts a single line into options format */ |
65 | static int add_option(FILE *f, np_arg_list **optlst); | 65 | static int add_option(FILE *filePointer, np_arg_list **optlst); |
66 | 66 | ||
67 | /* internal functions to find default file */ | 67 | /* internal functions to find default file */ |
68 | static char *default_file(void); | 68 | static char *default_file(void); |
@@ -74,7 +74,8 @@ static char *default_file_in_path(void); | |||
74 | * into its separate parts. | 74 | * into its separate parts. |
75 | */ | 75 | */ |
76 | static void parse_locator(const char *locator, const char *def_stanza, np_ini_info *i) { | 76 | static void parse_locator(const char *locator, const char *def_stanza, np_ini_info *i) { |
77 | size_t locator_len = 0, stanza_len = 0; | 77 | size_t locator_len = 0; |
78 | size_t stanza_len = 0; | ||
78 | 79 | ||
79 | /* if locator is NULL we'll use default values */ | 80 | /* if locator is NULL we'll use default values */ |
80 | if (locator != NULL) { | 81 | if (locator != NULL) { |
@@ -112,33 +113,34 @@ static void parse_locator(const char *locator, const char *def_stanza, np_ini_in | |||
112 | * This is the externally visible function used by extra_opts. | 113 | * This is the externally visible function used by extra_opts. |
113 | */ | 114 | */ |
114 | np_arg_list *np_get_defaults(const char *locator, const char *default_section) { | 115 | np_arg_list *np_get_defaults(const char *locator, const char *default_section) { |
115 | FILE *inifile = NULL; | ||
116 | np_arg_list *defaults = NULL; | ||
117 | np_ini_info i; | ||
118 | int is_suid_plugin = mp_suid(); | 116 | int is_suid_plugin = mp_suid(); |
119 | 117 | ||
120 | if (is_suid_plugin && idpriv_temp_drop() == -1) { | 118 | if (is_suid_plugin && idpriv_temp_drop() == -1) { |
121 | die(STATE_UNKNOWN, _("Cannot drop privileges: %s\n"), strerror(errno)); | 119 | die(STATE_UNKNOWN, _("Cannot drop privileges: %s\n"), strerror(errno)); |
122 | } | 120 | } |
123 | 121 | ||
124 | parse_locator(locator, default_section, &i); | 122 | FILE *inifile = NULL; |
125 | inifile = strcmp(i.file, "-") == 0 ? stdin : fopen(i.file, "r"); | 123 | np_ini_info ini_info; |
124 | parse_locator(locator, default_section, &ini_info); | ||
125 | inifile = strcmp(ini_info.file, "-") == 0 ? stdin : fopen(ini_info.file, "r"); | ||
126 | 126 | ||
127 | if (inifile == NULL) { | 127 | if (inifile == NULL) { |
128 | die(STATE_UNKNOWN, _("Can't read config file: %s\n"), strerror(errno)); | 128 | die(STATE_UNKNOWN, _("Can't read config file: %s\n"), strerror(errno)); |
129 | } | 129 | } |
130 | if (!read_defaults(inifile, i.stanza, &defaults)) { | 130 | |
131 | die(STATE_UNKNOWN, _("Invalid section '%s' in config file '%s'\n"), i.stanza, i.file); | 131 | np_arg_list *defaults = NULL; |
132 | if (!read_defaults(inifile, ini_info.stanza, &defaults)) { | ||
133 | die(STATE_UNKNOWN, _("Invalid section '%s' in config file '%s'\n"), ini_info.stanza, ini_info.file); | ||
132 | } | 134 | } |
133 | 135 | ||
134 | if (i.file_string_on_heap) { | 136 | if (ini_info.file_string_on_heap) { |
135 | free(i.file); | 137 | free(ini_info.file); |
136 | } | 138 | } |
137 | 139 | ||
138 | if (inifile != stdin) { | 140 | if (inifile != stdin) { |
139 | fclose(inifile); | 141 | fclose(inifile); |
140 | } | 142 | } |
141 | free(i.stanza); | 143 | free(ini_info.stanza); |
142 | if (is_suid_plugin && idpriv_temp_restore() == -1) { | 144 | if (is_suid_plugin && idpriv_temp_restore() == -1) { |
143 | die(STATE_UNKNOWN, _("Cannot restore privileges: %s\n"), strerror(errno)); | 145 | die(STATE_UNKNOWN, _("Cannot restore privileges: %s\n"), strerror(errno)); |
144 | } | 146 | } |
@@ -153,59 +155,58 @@ np_arg_list *np_get_defaults(const char *locator, const char *default_section) { | |||
153 | * be extra careful about user-supplied input (i.e. avoiding possible | 155 | * be extra careful about user-supplied input (i.e. avoiding possible |
154 | * format string vulnerabilities, etc). | 156 | * format string vulnerabilities, etc). |
155 | */ | 157 | */ |
156 | static int read_defaults(FILE *f, const char *stanza, np_arg_list **opts) { | 158 | static bool read_defaults(FILE *defaults_file, const char *stanza, np_arg_list **opts) { |
157 | int c = 0; | ||
158 | bool status = false; | 159 | bool status = false; |
159 | size_t i, stanza_len; | ||
160 | enum { | 160 | enum { |
161 | NOSTANZA, | 161 | NOSTANZA, |
162 | WRONGSTANZA, | 162 | WRONGSTANZA, |
163 | RIGHTSTANZA | 163 | RIGHTSTANZA |
164 | } stanzastate = NOSTANZA; | 164 | } stanzastate = NOSTANZA; |
165 | 165 | ||
166 | stanza_len = strlen(stanza); | 166 | size_t stanza_len = strlen(stanza); |
167 | 167 | ||
168 | /* our little stanza-parsing state machine */ | 168 | /* our little stanza-parsing state machine */ |
169 | while ((c = fgetc(f)) != EOF) { | 169 | int current_char = 0; |
170 | while ((current_char = fgetc(defaults_file)) != EOF) { | ||
170 | /* gobble up leading whitespace */ | 171 | /* gobble up leading whitespace */ |
171 | if (isspace(c)) { | 172 | if (isspace(current_char)) { |
172 | continue; | 173 | continue; |
173 | } | 174 | } |
174 | switch (c) { | 175 | switch (current_char) { |
175 | /* globble up comment lines */ | 176 | /* globble up comment lines */ |
176 | case ';': | 177 | case ';': |
177 | case '#': | 178 | case '#': |
178 | GOBBLE_TO(f, c, '\n'); | 179 | GOBBLE_TO(defaults_file, current_char, '\n'); |
179 | break; | 180 | break; |
180 | /* start of a stanza, check to see if it matches */ | 181 | /* start of a stanza, check to see if it matches */ |
181 | case '[': | 182 | case '[': { |
182 | stanzastate = WRONGSTANZA; | 183 | stanzastate = WRONGSTANZA; |
184 | size_t i; | ||
183 | for (i = 0; i < stanza_len; i++) { | 185 | for (i = 0; i < stanza_len; i++) { |
184 | c = fgetc(f); | 186 | current_char = fgetc(defaults_file); |
185 | /* strip leading whitespace */ | 187 | /* strip leading whitespace */ |
186 | if (i == 0) { | 188 | if (i == 0) { |
187 | for (; isspace(c); c = fgetc(f)) { | 189 | for (; isspace(current_char); current_char = fgetc(defaults_file)) { |
188 | continue; | ||
189 | } | 190 | } |
190 | } | 191 | } |
191 | /* nope, read to the end of the line */ | 192 | /* nope, read to the end of the line */ |
192 | if (c != stanza[i]) { | 193 | if (current_char != stanza[i]) { |
193 | GOBBLE_TO(f, c, '\n'); | 194 | GOBBLE_TO(defaults_file, current_char, '\n'); |
194 | break; | 195 | break; |
195 | } | 196 | } |
196 | } | 197 | } |
198 | |||
197 | /* if it matched up to here and the next char is ']'... */ | 199 | /* if it matched up to here and the next char is ']'... */ |
198 | if (i == stanza_len) { | 200 | if (i == stanza_len) { |
199 | c = fgetc(f); | 201 | current_char = fgetc(defaults_file); |
200 | /* strip trailing whitespace */ | 202 | /* strip trailing whitespace */ |
201 | for (; isspace(c); c = fgetc(f)) { | 203 | for (; isspace(current_char); current_char = fgetc(defaults_file)) { |
202 | continue; | ||
203 | } | 204 | } |
204 | if (c == ']') { | 205 | if (current_char == ']') { |
205 | stanzastate = RIGHTSTANZA; | 206 | stanzastate = RIGHTSTANZA; |
206 | } | 207 | } |
207 | } | 208 | } |
208 | break; | 209 | } break; |
209 | /* otherwise, we're in the body of a stanza or a parse error */ | 210 | /* otherwise, we're in the body of a stanza or a parse error */ |
210 | default: | 211 | default: |
211 | switch (stanzastate) { | 212 | switch (stanzastate) { |
@@ -216,12 +217,12 @@ static int read_defaults(FILE *f, const char *stanza, np_arg_list **opts) { | |||
216 | die(STATE_UNKNOWN, "%s\n", _("Config file error")); | 217 | die(STATE_UNKNOWN, "%s\n", _("Config file error")); |
217 | /* we're in a stanza, but for a different plugin */ | 218 | /* we're in a stanza, but for a different plugin */ |
218 | case WRONGSTANZA: | 219 | case WRONGSTANZA: |
219 | GOBBLE_TO(f, c, '\n'); | 220 | GOBBLE_TO(defaults_file, current_char, '\n'); |
220 | break; | 221 | break; |
221 | /* okay, this is where we start taking the config */ | 222 | /* okay, this is where we start taking the config */ |
222 | case RIGHTSTANZA: | 223 | case RIGHTSTANZA: |
223 | ungetc(c, f); | 224 | ungetc(current_char, defaults_file); |
224 | if (add_option(f, opts)) { | 225 | if (add_option(defaults_file, opts)) { |
225 | die(STATE_UNKNOWN, "%s\n", _("Config file error")); | 226 | die(STATE_UNKNOWN, "%s\n", _("Config file error")); |
226 | } | 227 | } |
227 | status = true; | 228 | status = true; |
@@ -240,13 +241,12 @@ static int read_defaults(FILE *f, const char *stanza, np_arg_list **opts) { | |||
240 | * --option[=value] | 241 | * --option[=value] |
241 | * appending it to the linked list optbuf. | 242 | * appending it to the linked list optbuf. |
242 | */ | 243 | */ |
243 | static int add_option(FILE *f, np_arg_list **optlst) { | 244 | static int add_option(FILE *filePointer, np_arg_list **optlst) { |
244 | np_arg_list *opttmp = *optlst, *optnew; | 245 | char *linebuf = NULL; |
245 | char *linebuf = NULL, *lineend = NULL, *optptr = NULL, *optend = NULL; | 246 | bool done_reading = false; |
246 | char *eqptr = NULL, *valptr = NULL, *valend = NULL; | 247 | const size_t read_sz = 8; |
247 | short done_reading = 0, equals = 0, value = 0; | 248 | size_t linebuf_sz = 0; |
248 | size_t cfg_len = 0, read_sz = 8, linebuf_sz = 0, read_pos = 0; | 249 | size_t read_pos = 0; |
249 | size_t opt_len = 0, val_len = 0; | ||
250 | 250 | ||
251 | /* read one line from the file */ | 251 | /* read one line from the file */ |
252 | while (!done_reading) { | 252 | while (!done_reading) { |
@@ -258,24 +258,29 @@ static int add_option(FILE *f, np_arg_list **optlst) { | |||
258 | die(STATE_UNKNOWN, _("malloc() failed!\n")); | 258 | die(STATE_UNKNOWN, _("malloc() failed!\n")); |
259 | } | 259 | } |
260 | } | 260 | } |
261 | if (fgets(&linebuf[read_pos], (int)read_sz, f) == NULL) { | 261 | |
262 | done_reading = 1; | 262 | if (fgets(&linebuf[read_pos], (int)read_sz, filePointer) == NULL) { |
263 | done_reading = true; | ||
263 | } else { | 264 | } else { |
264 | read_pos = strlen(linebuf); | 265 | read_pos = strlen(linebuf); |
265 | if (linebuf[read_pos - 1] == '\n') { | 266 | if (linebuf[read_pos - 1] == '\n') { |
266 | linebuf[--read_pos] = '\0'; | 267 | linebuf[--read_pos] = '\0'; |
267 | done_reading = 1; | 268 | done_reading = true; |
268 | } | 269 | } |
269 | } | 270 | } |
270 | } | 271 | } |
271 | lineend = &linebuf[read_pos]; | 272 | |
273 | char *lineend = &linebuf[read_pos]; | ||
272 | /* all that to read one line, isn't C fun? :) now comes the parsing :/ */ | 274 | /* all that to read one line, isn't C fun? :) now comes the parsing :/ */ |
273 | 275 | ||
274 | /* skip leading whitespace */ | 276 | /* skip leading whitespace */ |
277 | char *optptr = NULL; | ||
275 | for (optptr = linebuf; optptr < lineend && isspace(*optptr); optptr++) { | 278 | for (optptr = linebuf; optptr < lineend && isspace(*optptr); optptr++) { |
276 | continue; | ||
277 | } | 279 | } |
280 | |||
278 | /* continue to '=' or EOL, watching for spaces that might precede it */ | 281 | /* continue to '=' or EOL, watching for spaces that might precede it */ |
282 | char *eqptr = NULL; | ||
283 | char *optend = NULL; | ||
279 | for (eqptr = optptr; eqptr < lineend && *eqptr != '='; eqptr++) { | 284 | for (eqptr = optptr; eqptr < lineend && *eqptr != '='; eqptr++) { |
280 | if (isspace(*eqptr) && optend == NULL) { | 285 | if (isspace(*eqptr) && optend == NULL) { |
281 | optend = eqptr; | 286 | optend = eqptr; |
@@ -283,55 +288,67 @@ static int add_option(FILE *f, np_arg_list **optlst) { | |||
283 | optend = NULL; | 288 | optend = NULL; |
284 | } | 289 | } |
285 | } | 290 | } |
291 | |||
286 | if (optend == NULL) { | 292 | if (optend == NULL) { |
287 | optend = eqptr; | 293 | optend = eqptr; |
288 | } | 294 | } |
295 | |||
289 | --optend; | 296 | --optend; |
297 | |||
290 | /* ^[[:space:]]*=foo is a syntax error */ | 298 | /* ^[[:space:]]*=foo is a syntax error */ |
291 | if (optptr == eqptr) { | 299 | if (optptr == eqptr) { |
292 | die(STATE_UNKNOWN, "%s\n", _("Config file error")); | 300 | die(STATE_UNKNOWN, "%s\n", _("Config file error")); |
293 | } | 301 | } |
302 | |||
294 | /* continue from '=' to start of value or EOL */ | 303 | /* continue from '=' to start of value or EOL */ |
304 | char *valptr = NULL; | ||
295 | for (valptr = eqptr + 1; valptr < lineend && isspace(*valptr); valptr++) { | 305 | for (valptr = eqptr + 1; valptr < lineend && isspace(*valptr); valptr++) { |
296 | continue; | ||
297 | } | 306 | } |
307 | |||
298 | /* continue to the end of value */ | 308 | /* continue to the end of value */ |
309 | char *valend = NULL; | ||
299 | for (valend = valptr; valend < lineend; valend++) { | 310 | for (valend = valptr; valend < lineend; valend++) { |
300 | continue; | ||
301 | } | 311 | } |
312 | |||
302 | --valend; | 313 | --valend; |
314 | |||
303 | /* finally trim off trailing spaces */ | 315 | /* finally trim off trailing spaces */ |
304 | for (; isspace(*valend); valend--) { | 316 | for (; isspace(*valend); valend--) { |
305 | continue; | ||
306 | } | 317 | } |
318 | |||
307 | /* calculate the length of "--foo" */ | 319 | /* calculate the length of "--foo" */ |
308 | opt_len = (size_t)(1 + optend - optptr); | 320 | size_t opt_len = (size_t)(1 + optend - optptr); |
309 | /* 1-character params needs only one dash */ | 321 | /* 1-character params needs only one dash */ |
322 | size_t cfg_len = 0; | ||
310 | if (opt_len == 1) { | 323 | if (opt_len == 1) { |
311 | cfg_len = 1 + (opt_len); | 324 | cfg_len = 1 + (opt_len); |
312 | } else { | 325 | } else { |
313 | cfg_len = 2 + (opt_len); | 326 | cfg_len = 2 + (opt_len); |
314 | } | 327 | } |
328 | |||
329 | size_t val_len = 0; | ||
330 | bool equals = false; | ||
331 | bool value = false; | ||
315 | /* if valptr<lineend then we have to also allocate space for "=bar" */ | 332 | /* if valptr<lineend then we have to also allocate space for "=bar" */ |
316 | if (valptr < lineend) { | 333 | if (valptr < lineend) { |
317 | equals = value = 1; | 334 | equals = value = true; |
318 | val_len = (size_t)(1 + valend - valptr); | 335 | val_len = (size_t)(1 + valend - valptr); |
319 | cfg_len += 1 + val_len; | 336 | cfg_len += 1 + val_len; |
320 | } | 337 | } else if (valptr == lineend) { |
321 | /* if valptr==valend then we have "=" but no "bar" */ | 338 | /* if valptr==valend then we have "=" but no "bar" */ |
322 | else if (valptr == lineend) { | 339 | equals = true; |
323 | equals = 1; | ||
324 | cfg_len += 1; | 340 | cfg_len += 1; |
325 | } | 341 | } |
342 | |||
326 | /* a line with no equal sign isn't valid */ | 343 | /* a line with no equal sign isn't valid */ |
327 | if (equals == 0) { | 344 | if (!equals) { |
328 | die(STATE_UNKNOWN, "%s\n", _("Config file error")); | 345 | die(STATE_UNKNOWN, "%s\n", _("Config file error")); |
329 | } | 346 | } |
330 | 347 | ||
331 | /* okay, now we have all the info we need, so we create a new np_arg_list | 348 | /* okay, now we have all the info we need, so we create a new np_arg_list |
332 | * element and set the argument... | 349 | * element and set the argument... |
333 | */ | 350 | */ |
334 | optnew = malloc(sizeof(np_arg_list)); | 351 | np_arg_list *optnew = malloc(sizeof(np_arg_list)); |
335 | optnew->next = NULL; | 352 | optnew->next = NULL; |
336 | 353 | ||
337 | read_pos = 0; | 354 | read_pos = 0; |
@@ -357,6 +374,7 @@ static int add_option(FILE *f, np_arg_list **optlst) { | |||
357 | if (*optlst == NULL) { | 374 | if (*optlst == NULL) { |
358 | *optlst = optnew; | 375 | *optlst = optnew; |
359 | } else { | 376 | } else { |
377 | np_arg_list *opttmp = *optlst; | ||
360 | while (opttmp->next != NULL) { | 378 | while (opttmp->next != NULL) { |
361 | opttmp = opttmp->next; | 379 | opttmp = opttmp->next; |
362 | } | 380 | } |
@@ -384,8 +402,11 @@ static char *default_file(void) { | |||
384 | } | 402 | } |
385 | 403 | ||
386 | static char *default_file_in_path(void) { | 404 | static char *default_file_in_path(void) { |
387 | char *config_path, **file; | 405 | char *config_path; |
388 | char *dir, *ini_file, *tokens; | 406 | char **file; |
407 | char *dir; | ||
408 | char *ini_file; | ||
409 | char *tokens; | ||
389 | 410 | ||
390 | if ((config_path = getenv("NAGIOS_CONFIG_PATH")) == NULL) { | 411 | if ((config_path = getenv("NAGIOS_CONFIG_PATH")) == NULL) { |
391 | return NULL; | 412 | return NULL; |