diff options
| author | Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> | 2025-09-15 16:09:40 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-09-15 16:09:40 +0200 |
| commit | 601a48a63e745817cf2a4c7f3ca526e393dd3fb8 (patch) | |
| tree | ed011d8f2bfcde8750bca64c0f69407df4bd6444 /lib/parse_ini.c | |
| parent | 8ef825d85fb4d09c32ca44c545d6eb8d995ddea4 (diff) | |
| parent | 15ecdb73ce5cda54f824e5a63ee8e801bf16a996 (diff) | |
| download | monitoring-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.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; |
