summaryrefslogtreecommitdiffstats
path: root/lib/parse_ini.c
diff options
context:
space:
mode:
authorLorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>2025-09-15 16:09:40 +0200
committerGitHub <noreply@github.com>2025-09-15 16:09:40 +0200
commit601a48a63e745817cf2a4c7f3ca526e393dd3fb8 (patch)
treeed011d8f2bfcde8750bca64c0f69407df4bd6444 /lib/parse_ini.c
parent8ef825d85fb4d09c32ca44c545d6eb8d995ddea4 (diff)
parent15ecdb73ce5cda54f824e5a63ee8e801bf16a996 (diff)
downloadmonitoring-plugins-601a48a63e745817cf2a4c7f3ca526e393dd3fb8.tar.gz
Merge pull request #2150 from RincewindsHat/refactor/lib
general refactorin in lib, more local variables, real booleans
Diffstat (limited to 'lib/parse_ini.c')
-rw-r--r--lib/parse_ini.c141
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 */
62static int read_defaults(FILE *f, const char *stanza, np_arg_list **opts); 62static 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 */
65static int add_option(FILE *f, np_arg_list **optlst); 65static 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 */
68static char *default_file(void); 68static 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 */
76static void parse_locator(const char *locator, const char *def_stanza, np_ini_info *i) { 76static 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 */
114np_arg_list *np_get_defaults(const char *locator, const char *default_section) { 115np_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 */
156static int read_defaults(FILE *f, const char *stanza, np_arg_list **opts) { 158static 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 */
243static int add_option(FILE *f, np_arg_list **optlst) { 244static 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
386static char *default_file_in_path(void) { 404static 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;