summaryrefslogtreecommitdiffstats
path: root/lib/parse_ini.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/parse_ini.c')
-rw-r--r--lib/parse_ini.c159
1 files changed, 72 insertions, 87 deletions
diff --git a/lib/parse_ini.c b/lib/parse_ini.c
index 0cc864ae..1289aae2 100644
--- a/lib/parse_ini.c
+++ b/lib/parse_ini.c
@@ -1,25 +1,25 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring Plugins parse_ini library 3 * Monitoring Plugins parse_ini library
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2007 Monitoring Plugins Development Team 6 * Copyright (c) 2007 - 2024 Monitoring Plugins Development Team
7* 7 *
8* This program is free software: you can redistribute it and/or modify 8 * This program is free software: you can redistribute it and/or modify
9* it under the terms of the GNU General Public License as published by 9 * it under the terms of the GNU General Public License as published by
10* the Free Software Foundation, either version 3 of the License, or 10 * the Free Software Foundation, either version 3 of the License, or
11* (at your option) any later version. 11 * (at your option) any later version.
12* 12 *
13* This program is distributed in the hope that it will be useful, 13 * This program is distributed in the hope that it will be useful,
14* but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16* GNU General Public License for more details. 16 * GNU General Public License for more details.
17* 17 *
18* You should have received a copy of the GNU General Public License 18 * You should have received a copy of the GNU General Public License
19* along with this program. If not, see <http://www.gnu.org/licenses/>. 19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20* 20 *
21* 21 *
22*****************************************************************************/ 22 *****************************************************************************/
23 23
24#include "common.h" 24#include "common.h"
25#include "idpriv.h" 25#include "idpriv.h"
@@ -36,34 +36,24 @@
36 */ 36 */
37typedef struct { 37typedef struct {
38 char *file; 38 char *file;
39 bool file_string_on_heap;
39 char *stanza; 40 char *stanza;
40} np_ini_info; 41} np_ini_info;
41 42
42static char *default_ini_file_names[] = { 43static char *default_ini_file_names[] = {"monitoring-plugins.ini", "plugins.ini", "nagios-plugins.ini", NULL};
43 "monitoring-plugins.ini",
44 "plugins.ini",
45 "nagios-plugins.ini",
46 NULL
47};
48 44
49static char *default_ini_path_names[] = { 45static char *default_ini_path_names[] = {
50 "/usr/local/etc/monitoring-plugins/monitoring-plugins.ini", 46 "/usr/local/etc/monitoring-plugins/monitoring-plugins.ini", "/usr/local/etc/monitoring-plugins.ini",
51 "/usr/local/etc/monitoring-plugins.ini", 47 "/etc/monitoring-plugins/monitoring-plugins.ini", "/etc/monitoring-plugins.ini",
52 "/etc/monitoring-plugins/monitoring-plugins.ini",
53 "/etc/monitoring-plugins.ini",
54 /* deprecated path names (for backward compatibility): */ 48 /* deprecated path names (for backward compatibility): */
55 "/etc/nagios/plugins.ini", 49 "/etc/nagios/plugins.ini", "/usr/local/nagios/etc/plugins.ini", "/usr/local/etc/nagios/plugins.ini", "/etc/opt/nagios/plugins.ini",
56 "/usr/local/nagios/etc/plugins.ini", 50 "/etc/nagios-plugins.ini", "/usr/local/etc/nagios-plugins.ini", "/etc/opt/nagios-plugins.ini", NULL};
57 "/usr/local/etc/nagios/plugins.ini",
58 "/etc/opt/nagios/plugins.ini",
59 "/etc/nagios-plugins.ini",
60 "/usr/local/etc/nagios-plugins.ini",
61 "/etc/opt/nagios-plugins.ini",
62 NULL
63};
64 51
65/* eat all characters from a FILE pointer until n is encountered */ 52/* eat all characters from a FILE pointer until n is encountered */
66#define GOBBLE_TO(f, c, n) do { (c)=fgetc((f)); } while((c)!=EOF && (c)!=(n)) 53#define GOBBLE_TO(f, c, n) \
54 do { \
55 (c) = fgetc((f)); \
56 } while ((c) != EOF && (c) != (n))
67 57
68/* internal function that returns the constructed defaults options */ 58/* internal function that returns the constructed defaults options */
69static int read_defaults(FILE *f, const char *stanza, np_arg_list **opts); 59static int read_defaults(FILE *f, const char *stanza, np_arg_list **opts);
@@ -80,9 +70,7 @@ static char *default_file_in_path(void);
80 * [stanza][@filename] 70 * [stanza][@filename]
81 * into its separate parts. 71 * into its separate parts.
82 */ 72 */
83static void 73static void parse_locator(const char *locator, const char *def_stanza, np_ini_info *i) {
84parse_locator(const char *locator, const char *def_stanza, np_ini_info *i)
85{
86 size_t locator_len = 0, stanza_len = 0; 74 size_t locator_len = 0, stanza_len = 0;
87 75
88 /* if locator is NULL we'll use default values */ 76 /* if locator is NULL we'll use default values */
@@ -95,54 +83,55 @@ parse_locator(const char *locator, const char *def_stanza, np_ini_info *i)
95 i->stanza = malloc(sizeof(char) * (stanza_len + 1)); 83 i->stanza = malloc(sizeof(char) * (stanza_len + 1));
96 strncpy(i->stanza, locator, stanza_len); 84 strncpy(i->stanza, locator, stanza_len);
97 i->stanza[stanza_len] = '\0'; 85 i->stanza[stanza_len] = '\0';
98 } else /* otherwise we use the default stanza */ 86 } else { /* otherwise we use the default stanza */
99 i->stanza = strdup(def_stanza); 87 i->stanza = strdup(def_stanza);
88 }
100 89
101 if (i->stanza == NULL) 90 if (i->stanza == NULL)
102 die(STATE_UNKNOWN, _("malloc() failed!\n")); 91 die(STATE_UNKNOWN, _("malloc() failed!\n"));
103 92
104 /* check whether there's an @file part */ 93 /* check whether there's an @file part */
105 i->file = stanza_len == locator_len 94 if (stanza_len == locator_len) {
106 ? default_file() 95 i->file = default_file();
107 : strdup(&(locator[stanza_len + 1])); 96 i->file_string_on_heap = false;
97 } else {
98 i->file = strdup(&(locator[stanza_len + 1]));
99 i->file_string_on_heap = true;
100 }
101
108 if (i->file == NULL || i->file[0] == '\0') 102 if (i->file == NULL || i->file[0] == '\0')
109 die(STATE_UNKNOWN, 103 die(STATE_UNKNOWN, _("Cannot find config file in any standard location.\n"));
110 _("Cannot find config file in any standard location.\n"));
111} 104}
112 105
113/* 106/*
114 * This is the externally visible function used by extra_opts. 107 * This is the externally visible function used by extra_opts.
115 */ 108 */
116np_arg_list * 109np_arg_list *np_get_defaults(const char *locator, const char *default_section) {
117np_get_defaults(const char *locator, const char *default_section)
118{
119 FILE *inifile = NULL; 110 FILE *inifile = NULL;
120 np_arg_list *defaults = NULL; 111 np_arg_list *defaults = NULL;
121 np_ini_info i; 112 np_ini_info i;
122 int is_suid_plugin = mp_suid(); 113 int is_suid_plugin = mp_suid();
123 114
124 if (is_suid_plugin && idpriv_temp_drop() == -1) 115 if (is_suid_plugin && idpriv_temp_drop() == -1)
125 die(STATE_UNKNOWN, _("Cannot drop privileges: %s\n"), 116 die(STATE_UNKNOWN, _("Cannot drop privileges: %s\n"), strerror(errno));
126 strerror(errno));
127 117
128 parse_locator(locator, default_section, &i); 118 parse_locator(locator, default_section, &i);
129 inifile = strcmp(i.file, "-") == 0 ? stdin : fopen(i.file, "r"); 119 inifile = strcmp(i.file, "-") == 0 ? stdin : fopen(i.file, "r");
130 120
131 if (inifile == NULL) 121 if (inifile == NULL)
132 die(STATE_UNKNOWN, _("Can't read config file: %s\n"), 122 die(STATE_UNKNOWN, _("Can't read config file: %s\n"), strerror(errno));
133 strerror(errno));
134 if (!read_defaults(inifile, i.stanza, &defaults)) 123 if (!read_defaults(inifile, i.stanza, &defaults))
135 die(STATE_UNKNOWN, 124 die(STATE_UNKNOWN, _("Invalid section '%s' in config file '%s'\n"), i.stanza, i.file);
136 _("Invalid section '%s' in config file '%s'\n"), i.stanza, 125
137 i.file); 126 if (i.file_string_on_heap) {
127 free(i.file);
128 }
138 129
139 free(i.file);
140 if (inifile != stdin) 130 if (inifile != stdin)
141 fclose(inifile); 131 fclose(inifile);
142 free(i.stanza); 132 free(i.stanza);
143 if (is_suid_plugin && idpriv_temp_restore() == -1) 133 if (is_suid_plugin && idpriv_temp_restore() == -1)
144 die(STATE_UNKNOWN, _("Cannot restore privileges: %s\n"), 134 die(STATE_UNKNOWN, _("Cannot restore privileges: %s\n"), strerror(errno));
145 strerror(errno));
146 135
147 return defaults; 136 return defaults;
148} 137}
@@ -154,13 +143,15 @@ np_get_defaults(const char *locator, const char *default_section)
154 * be extra careful about user-supplied input (i.e. avoiding possible 143 * be extra careful about user-supplied input (i.e. avoiding possible
155 * format string vulnerabilities, etc). 144 * format string vulnerabilities, etc).
156 */ 145 */
157static int 146static int read_defaults(FILE *f, const char *stanza, np_arg_list **opts) {
158read_defaults(FILE *f, const char *stanza, np_arg_list **opts)
159{
160 int c = 0; 147 int c = 0;
161 bool status = false; 148 bool status = false;
162 size_t i, stanza_len; 149 size_t i, stanza_len;
163 enum { NOSTANZA, WRONGSTANZA, RIGHTSTANZA } stanzastate = NOSTANZA; 150 enum {
151 NOSTANZA,
152 WRONGSTANZA,
153 RIGHTSTANZA
154 } stanzastate = NOSTANZA;
164 155
165 stanza_len = strlen(stanza); 156 stanza_len = strlen(stanza);
166 157
@@ -207,8 +198,7 @@ read_defaults(FILE *f, const char *stanza, np_arg_list **opts)
207 * we're dealing with a config error 198 * we're dealing with a config error
208 */ 199 */
209 case NOSTANZA: 200 case NOSTANZA:
210 die(STATE_UNKNOWN, "%s\n", 201 die(STATE_UNKNOWN, "%s\n", _("Config file error"));
211 _("Config file error"));
212 /* we're in a stanza, but for a different plugin */ 202 /* we're in a stanza, but for a different plugin */
213 case WRONGSTANZA: 203 case WRONGSTANZA:
214 GOBBLE_TO(f, c, '\n'); 204 GOBBLE_TO(f, c, '\n');
@@ -217,8 +207,7 @@ read_defaults(FILE *f, const char *stanza, np_arg_list **opts)
217 case RIGHTSTANZA: 207 case RIGHTSTANZA:
218 ungetc(c, f); 208 ungetc(c, f);
219 if (add_option(f, opts)) { 209 if (add_option(f, opts)) {
220 die(STATE_UNKNOWN, "%s\n", 210 die(STATE_UNKNOWN, "%s\n", _("Config file error"));
221 _("Config file error"));
222 } 211 }
223 status = true; 212 status = true;
224 break; 213 break;
@@ -236,9 +225,7 @@ read_defaults(FILE *f, const char *stanza, np_arg_list **opts)
236 * --option[=value] 225 * --option[=value]
237 * appending it to the linked list optbuf. 226 * appending it to the linked list optbuf.
238 */ 227 */
239static int 228static int add_option(FILE *f, np_arg_list **optlst) {
240add_option(FILE *f, np_arg_list **optlst)
241{
242 np_arg_list *opttmp = *optlst, *optnew; 229 np_arg_list *opttmp = *optlst, *optnew;
243 char *linebuf = NULL, *lineend = NULL, *optptr = NULL, *optend = NULL; 230 char *linebuf = NULL, *lineend = NULL, *optptr = NULL, *optend = NULL;
244 char *eqptr = NULL, *valptr = NULL, *valend = NULL; 231 char *eqptr = NULL, *valptr = NULL, *valend = NULL;
@@ -285,8 +272,7 @@ add_option(FILE *f, np_arg_list **optlst)
285 if (optptr == eqptr) 272 if (optptr == eqptr)
286 die(STATE_UNKNOWN, "%s\n", _("Config file error")); 273 die(STATE_UNKNOWN, "%s\n", _("Config file error"));
287 /* continue from '=' to start of value or EOL */ 274 /* continue from '=' to start of value or EOL */
288 for (valptr = eqptr + 1; valptr < lineend && isspace(*valptr); 275 for (valptr = eqptr + 1; valptr < lineend && isspace(*valptr); valptr++)
289 valptr++)
290 continue; 276 continue;
291 /* continue to the end of value */ 277 /* continue to the end of value */
292 for (valend = valptr; valend < lineend; valend++) 278 for (valend = valptr; valend < lineend; valend++)
@@ -355,23 +341,22 @@ add_option(FILE *f, np_arg_list **optlst)
355 return 0; 341 return 0;
356} 342}
357 343
358static char * 344static char *default_file(void) {
359default_file(void) 345 char *ini_file;
360{
361 char **p, *ini_file;
362 346
363 if ((ini_file = getenv("MP_CONFIG_FILE")) != NULL || 347 if ((ini_file = getenv("MP_CONFIG_FILE")) != NULL || (ini_file = default_file_in_path()) != NULL) {
364 (ini_file = default_file_in_path()) != NULL)
365 return ini_file; 348 return ini_file;
366 for (p = default_ini_path_names; *p != NULL; p++) 349 }
367 if (access(*p, F_OK) == 0) 350
351 for (char **p = default_ini_path_names; *p != NULL; p++) {
352 if (access(*p, F_OK) == 0) {
368 return *p; 353 return *p;
354 }
355 }
369 return NULL; 356 return NULL;
370} 357}
371 358
372static char * 359static char *default_file_in_path(void) {
373default_file_in_path(void)
374{
375 char *config_path, **file; 360 char *config_path, **file;
376 char *dir, *ini_file, *tokens; 361 char *dir, *ini_file, *tokens;
377 362