diff options
Diffstat (limited to 'lib/parse_ini.c')
| -rw-r--r-- | lib/parse_ini.c | 342 |
1 files changed, 182 insertions, 160 deletions
diff --git a/lib/parse_ini.c b/lib/parse_ini.c index 09c0dc4f..db337622 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" |
| @@ -40,37 +40,29 @@ typedef struct { | |||
| 40 | char *stanza; | 40 | char *stanza; |
| 41 | } np_ini_info; | 41 | } np_ini_info; |
| 42 | 42 | ||
| 43 | static char *default_ini_file_names[] = { | 43 | static char *default_ini_file_names[] = {"monitoring-plugins.ini", "plugins.ini", |
| 44 | "monitoring-plugins.ini", | 44 | "nagios-plugins.ini", NULL}; |
| 45 | "plugins.ini", | ||
| 46 | "nagios-plugins.ini", | ||
| 47 | NULL | ||
| 48 | }; | ||
| 49 | 45 | ||
| 50 | static char *default_ini_path_names[] = { | 46 | static char *default_ini_path_names[] = { |
| 51 | "/usr/local/etc/monitoring-plugins/monitoring-plugins.ini", | 47 | "/usr/local/etc/monitoring-plugins/monitoring-plugins.ini", |
| 52 | "/usr/local/etc/monitoring-plugins.ini", | 48 | "/usr/local/etc/monitoring-plugins.ini", "/etc/monitoring-plugins/monitoring-plugins.ini", |
| 53 | "/etc/monitoring-plugins/monitoring-plugins.ini", | ||
| 54 | "/etc/monitoring-plugins.ini", | 49 | "/etc/monitoring-plugins.ini", |
| 55 | /* deprecated path names (for backward compatibility): */ | 50 | /* deprecated path names (for backward compatibility): */ |
| 56 | "/etc/nagios/plugins.ini", | 51 | "/etc/nagios/plugins.ini", "/usr/local/nagios/etc/plugins.ini", |
| 57 | "/usr/local/nagios/etc/plugins.ini", | 52 | "/usr/local/etc/nagios/plugins.ini", "/etc/opt/nagios/plugins.ini", "/etc/nagios-plugins.ini", |
| 58 | "/usr/local/etc/nagios/plugins.ini", | 53 | "/usr/local/etc/nagios-plugins.ini", "/etc/opt/nagios-plugins.ini", NULL}; |
| 59 | "/etc/opt/nagios/plugins.ini", | ||
| 60 | "/etc/nagios-plugins.ini", | ||
| 61 | "/usr/local/etc/nagios-plugins.ini", | ||
| 62 | "/etc/opt/nagios-plugins.ini", | ||
| 63 | NULL | ||
| 64 | }; | ||
| 65 | 54 | ||
| 66 | /* eat all characters from a FILE pointer until n is encountered */ | 55 | /* eat all characters from a FILE pointer until n is encountered */ |
| 67 | #define GOBBLE_TO(f, c, n) do { (c)=fgetc((f)); } while((c)!=EOF && (c)!=(n)) | 56 | #define GOBBLE_TO(f, c, n) \ |
| 57 | do { \ | ||
| 58 | (c) = fgetc((f)); \ | ||
| 59 | } while ((c) != EOF && (c) != (n)) | ||
| 68 | 60 | ||
| 69 | /* internal function that returns the constructed defaults options */ | 61 | /* internal function that returns the constructed defaults options */ |
| 70 | 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); |
| 71 | 63 | ||
| 72 | /* internal function that converts a single line into options format */ | 64 | /* internal function that converts a single line into options format */ |
| 73 | static int add_option(FILE *f, np_arg_list **optlst); | 65 | static int add_option(FILE *filePointer, np_arg_list **optlst); |
| 74 | 66 | ||
| 75 | /* internal functions to find default file */ | 67 | /* internal functions to find default file */ |
| 76 | static char *default_file(void); | 68 | static char *default_file(void); |
| @@ -81,10 +73,9 @@ static char *default_file_in_path(void); | |||
| 81 | * [stanza][@filename] | 73 | * [stanza][@filename] |
| 82 | * into its separate parts. | 74 | * into its separate parts. |
| 83 | */ | 75 | */ |
| 84 | static void | 76 | static void parse_locator(const char *locator, const char *def_stanza, np_ini_info *i) { |
| 85 | parse_locator(const char *locator, const char *def_stanza, np_ini_info *i) | 77 | size_t locator_len = 0; |
| 86 | { | 78 | size_t stanza_len = 0; |
| 87 | size_t locator_len = 0, stanza_len = 0; | ||
| 88 | 79 | ||
| 89 | /* if locator is NULL we'll use default values */ | 80 | /* if locator is NULL we'll use default values */ |
| 90 | if (locator != NULL) { | 81 | if (locator != NULL) { |
| @@ -96,63 +87,63 @@ parse_locator(const char *locator, const char *def_stanza, np_ini_info *i) | |||
| 96 | i->stanza = malloc(sizeof(char) * (stanza_len + 1)); | 87 | i->stanza = malloc(sizeof(char) * (stanza_len + 1)); |
| 97 | strncpy(i->stanza, locator, stanza_len); | 88 | strncpy(i->stanza, locator, stanza_len); |
| 98 | i->stanza[stanza_len] = '\0'; | 89 | i->stanza[stanza_len] = '\0'; |
| 99 | } else {/* otherwise we use the default stanza */ | 90 | } else { /* otherwise we use the default stanza */ |
| 100 | i->stanza = strdup(def_stanza); | 91 | i->stanza = strdup(def_stanza); |
| 101 | } | 92 | } |
| 102 | 93 | ||
| 103 | if (i->stanza == NULL) | 94 | if (i->stanza == NULL) { |
| 104 | die(STATE_UNKNOWN, _("malloc() failed!\n")); | 95 | die(STATE_UNKNOWN, _("malloc() failed!\n")); |
| 96 | } | ||
| 105 | 97 | ||
| 106 | /* check whether there's an @file part */ | 98 | /* check whether there's an @file part */ |
| 107 | if (stanza_len == locator_len) { | 99 | if (stanza_len == locator_len) { |
| 108 | i->file = default_file(); | 100 | i->file = default_file(); |
| 109 | i->file_string_on_heap = false; | 101 | i->file_string_on_heap = false; |
| 110 | } else { | 102 | } else { |
| 111 | i->file = strdup(&(locator[stanza_len + 1])); | 103 | i->file = strdup(&(locator[stanza_len + 1])); |
| 112 | i->file_string_on_heap = true; | 104 | i->file_string_on_heap = true; |
| 113 | } | 105 | } |
| 114 | 106 | ||
| 115 | if (i->file == NULL || i->file[0] == '\0') | 107 | if (i->file == NULL || i->file[0] == '\0') { |
| 116 | die(STATE_UNKNOWN, | 108 | die(STATE_UNKNOWN, _("Cannot find config file in any standard location.\n")); |
| 117 | _("Cannot find config file in any standard location.\n")); | 109 | } |
| 118 | } | 110 | } |
| 119 | 111 | ||
| 120 | /* | 112 | /* |
| 121 | * This is the externally visible function used by extra_opts. | 113 | * This is the externally visible function used by extra_opts. |
| 122 | */ | 114 | */ |
| 123 | np_arg_list * | 115 | np_arg_list *np_get_defaults(const char *locator, const char *default_section) { |
| 124 | np_get_defaults(const char *locator, const char *default_section) | ||
| 125 | { | ||
| 126 | FILE *inifile = NULL; | ||
| 127 | np_arg_list *defaults = NULL; | ||
| 128 | np_ini_info i; | ||
| 129 | int is_suid_plugin = mp_suid(); | 116 | int is_suid_plugin = mp_suid(); |
| 130 | 117 | ||
| 131 | if (is_suid_plugin && idpriv_temp_drop() == -1) | 118 | if (is_suid_plugin && idpriv_temp_drop() == -1) { |
| 132 | die(STATE_UNKNOWN, _("Cannot drop privileges: %s\n"), | 119 | die(STATE_UNKNOWN, _("Cannot drop privileges: %s\n"), strerror(errno)); |
| 133 | strerror(errno)); | 120 | } |
| 121 | |||
| 122 | FILE *inifile = NULL; | ||
| 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"); | ||
| 134 | 126 | ||
| 135 | parse_locator(locator, default_section, &i); | 127 | if (inifile == NULL) { |
| 136 | inifile = strcmp(i.file, "-") == 0 ? stdin : fopen(i.file, "r"); | 128 | die(STATE_UNKNOWN, _("Can't read config file: %s\n"), strerror(errno)); |
| 129 | } | ||
| 137 | 130 | ||
| 138 | if (inifile == NULL) | 131 | np_arg_list *defaults = NULL; |
| 139 | die(STATE_UNKNOWN, _("Can't read config file: %s\n"), | 132 | if (!read_defaults(inifile, ini_info.stanza, &defaults)) { |
| 140 | strerror(errno)); | 133 | die(STATE_UNKNOWN, _("Invalid section '%s' in config file '%s'\n"), ini_info.stanza, ini_info.file); |
| 141 | if (!read_defaults(inifile, i.stanza, &defaults)) | 134 | } |
| 142 | die(STATE_UNKNOWN, | ||
| 143 | _("Invalid section '%s' in config file '%s'\n"), i.stanza, | ||
| 144 | i.file); | ||
| 145 | 135 | ||
| 146 | if (i.file_string_on_heap) { | 136 | if (ini_info.file_string_on_heap) { |
| 147 | free(i.file); | 137 | free(ini_info.file); |
| 148 | } | 138 | } |
| 149 | 139 | ||
| 150 | if (inifile != stdin) | 140 | if (inifile != stdin) { |
| 151 | fclose(inifile); | 141 | fclose(inifile); |
| 152 | free(i.stanza); | 142 | } |
| 153 | if (is_suid_plugin && idpriv_temp_restore() == -1) | 143 | free(ini_info.stanza); |
| 154 | die(STATE_UNKNOWN, _("Cannot restore privileges: %s\n"), | 144 | if (is_suid_plugin && idpriv_temp_restore() == -1) { |
| 155 | strerror(errno)); | 145 | die(STATE_UNKNOWN, _("Cannot restore privileges: %s\n"), strerror(errno)); |
| 146 | } | ||
| 156 | 147 | ||
| 157 | return defaults; | 148 | return defaults; |
| 158 | } | 149 | } |
| @@ -164,52 +155,58 @@ np_get_defaults(const char *locator, const char *default_section) | |||
| 164 | * be extra careful about user-supplied input (i.e. avoiding possible | 155 | * be extra careful about user-supplied input (i.e. avoiding possible |
| 165 | * format string vulnerabilities, etc). | 156 | * format string vulnerabilities, etc). |
| 166 | */ | 157 | */ |
| 167 | static int | 158 | static bool read_defaults(FILE *defaults_file, const char *stanza, np_arg_list **opts) { |
| 168 | read_defaults(FILE *f, const char *stanza, np_arg_list **opts) | ||
| 169 | { | ||
| 170 | int c = 0; | ||
| 171 | bool status = false; | 159 | bool status = false; |
| 172 | size_t i, stanza_len; | 160 | enum { |
| 173 | enum { NOSTANZA, WRONGSTANZA, RIGHTSTANZA } stanzastate = NOSTANZA; | 161 | NOSTANZA, |
| 162 | WRONGSTANZA, | ||
| 163 | RIGHTSTANZA | ||
| 164 | } stanzastate = NOSTANZA; | ||
| 174 | 165 | ||
| 175 | stanza_len = strlen(stanza); | 166 | size_t stanza_len = strlen(stanza); |
| 176 | 167 | ||
| 177 | /* our little stanza-parsing state machine */ | 168 | /* our little stanza-parsing state machine */ |
| 178 | while ((c = fgetc(f)) != EOF) { | 169 | int current_char = 0; |
| 170 | while ((current_char = fgetc(defaults_file)) != EOF) { | ||
| 179 | /* gobble up leading whitespace */ | 171 | /* gobble up leading whitespace */ |
| 180 | if (isspace(c)) | 172 | if (isspace(current_char)) { |
| 181 | continue; | 173 | continue; |
| 182 | switch (c) { | 174 | } |
| 175 | switch (current_char) { | ||
| 183 | /* globble up comment lines */ | 176 | /* globble up comment lines */ |
| 184 | case ';': | 177 | case ';': |
| 185 | case '#': | 178 | case '#': |
| 186 | GOBBLE_TO(f, c, '\n'); | 179 | GOBBLE_TO(defaults_file, current_char, '\n'); |
| 187 | break; | 180 | break; |
| 188 | /* start of a stanza, check to see if it matches */ | 181 | /* start of a stanza, check to see if it matches */ |
| 189 | case '[': | 182 | case '[': { |
| 190 | stanzastate = WRONGSTANZA; | 183 | stanzastate = WRONGSTANZA; |
| 184 | size_t i; | ||
| 191 | for (i = 0; i < stanza_len; i++) { | 185 | for (i = 0; i < stanza_len; i++) { |
| 192 | c = fgetc(f); | 186 | current_char = fgetc(defaults_file); |
| 193 | /* strip leading whitespace */ | 187 | /* strip leading whitespace */ |
| 194 | if (i == 0) | 188 | if (i == 0) { |
| 195 | for (; isspace(c); c = fgetc(f)) | 189 | for (; isspace(current_char); current_char = fgetc(defaults_file)) { |
| 196 | continue; | 190 | } |
| 191 | } | ||
| 197 | /* nope, read to the end of the line */ | 192 | /* nope, read to the end of the line */ |
| 198 | if (c != stanza[i]) { | 193 | if (current_char != stanza[i]) { |
| 199 | GOBBLE_TO(f, c, '\n'); | 194 | GOBBLE_TO(defaults_file, current_char, '\n'); |
| 200 | break; | 195 | break; |
| 201 | } | 196 | } |
| 202 | } | 197 | } |
| 198 | |||
| 203 | /* if it matched up to here and the next char is ']'... */ | 199 | /* if it matched up to here and the next char is ']'... */ |
| 204 | if (i == stanza_len) { | 200 | if (i == stanza_len) { |
| 205 | c = fgetc(f); | 201 | current_char = fgetc(defaults_file); |
| 206 | /* strip trailing whitespace */ | 202 | /* strip trailing whitespace */ |
| 207 | for (; isspace(c); c = fgetc(f)) | 203 | for (; isspace(current_char); current_char = fgetc(defaults_file)) { |
| 208 | continue; | 204 | } |
| 209 | if (c == ']') | 205 | if (current_char == ']') { |
| 210 | stanzastate = RIGHTSTANZA; | 206 | stanzastate = RIGHTSTANZA; |
| 207 | } | ||
| 211 | } | 208 | } |
| 212 | break; | 209 | } break; |
| 213 | /* 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 */ |
| 214 | default: | 211 | default: |
| 215 | switch (stanzastate) { | 212 | switch (stanzastate) { |
| @@ -217,18 +214,16 @@ read_defaults(FILE *f, const char *stanza, np_arg_list **opts) | |||
| 217 | * we're dealing with a config error | 214 | * we're dealing with a config error |
| 218 | */ | 215 | */ |
| 219 | case NOSTANZA: | 216 | case NOSTANZA: |
| 220 | die(STATE_UNKNOWN, "%s\n", | 217 | die(STATE_UNKNOWN, "%s\n", _("Config file error")); |
| 221 | _("Config file error")); | ||
| 222 | /* we're in a stanza, but for a different plugin */ | 218 | /* we're in a stanza, but for a different plugin */ |
| 223 | case WRONGSTANZA: | 219 | case WRONGSTANZA: |
| 224 | GOBBLE_TO(f, c, '\n'); | 220 | GOBBLE_TO(defaults_file, current_char, '\n'); |
| 225 | break; | 221 | break; |
| 226 | /* okay, this is where we start taking the config */ | 222 | /* okay, this is where we start taking the config */ |
| 227 | case RIGHTSTANZA: | 223 | case RIGHTSTANZA: |
| 228 | ungetc(c, f); | 224 | ungetc(current_char, defaults_file); |
| 229 | if (add_option(f, opts)) { | 225 | if (add_option(defaults_file, opts)) { |
| 230 | die(STATE_UNKNOWN, "%s\n", | 226 | die(STATE_UNKNOWN, "%s\n", _("Config file error")); |
| 231 | _("Config file error")); | ||
| 232 | } | 227 | } |
| 233 | status = true; | 228 | status = true; |
| 234 | break; | 229 | break; |
| @@ -246,15 +241,12 @@ read_defaults(FILE *f, const char *stanza, np_arg_list **opts) | |||
| 246 | * --option[=value] | 241 | * --option[=value] |
| 247 | * appending it to the linked list optbuf. | 242 | * appending it to the linked list optbuf. |
| 248 | */ | 243 | */ |
| 249 | static int | 244 | static int add_option(FILE *filePointer, np_arg_list **optlst) { |
| 250 | add_option(FILE *f, np_arg_list **optlst) | 245 | char *linebuf = NULL; |
| 251 | { | 246 | bool done_reading = false; |
| 252 | np_arg_list *opttmp = *optlst, *optnew; | 247 | const size_t read_sz = 8; |
| 253 | char *linebuf = NULL, *lineend = NULL, *optptr = NULL, *optend = NULL; | 248 | size_t linebuf_sz = 0; |
| 254 | char *eqptr = NULL, *valptr = NULL, *valend = NULL; | 249 | size_t read_pos = 0; |
| 255 | short done_reading = 0, equals = 0, value = 0; | ||
| 256 | size_t cfg_len = 0, read_sz = 8, linebuf_sz = 0, read_pos = 0; | ||
| 257 | size_t opt_len = 0, val_len = 0; | ||
| 258 | 250 | ||
| 259 | /* read one line from the file */ | 251 | /* read one line from the file */ |
| 260 | while (!done_reading) { | 252 | while (!done_reading) { |
| @@ -262,75 +254,101 @@ add_option(FILE *f, np_arg_list **optlst) | |||
| 262 | if (linebuf == NULL || read_pos + read_sz >= linebuf_sz) { | 254 | if (linebuf == NULL || read_pos + read_sz >= linebuf_sz) { |
| 263 | linebuf_sz = linebuf_sz > 0 ? linebuf_sz << 1 : read_sz; | 255 | linebuf_sz = linebuf_sz > 0 ? linebuf_sz << 1 : read_sz; |
| 264 | linebuf = realloc(linebuf, linebuf_sz); | 256 | linebuf = realloc(linebuf, linebuf_sz); |
| 265 | if (linebuf == NULL) | 257 | if (linebuf == NULL) { |
| 266 | die(STATE_UNKNOWN, _("malloc() failed!\n")); | 258 | die(STATE_UNKNOWN, _("malloc() failed!\n")); |
| 259 | } | ||
| 267 | } | 260 | } |
| 268 | if (fgets(&linebuf[read_pos], (int)read_sz, f) == NULL) | 261 | |
| 269 | done_reading = 1; | 262 | if (fgets(&linebuf[read_pos], (int)read_sz, filePointer) == NULL) { |
| 270 | else { | 263 | done_reading = true; |
| 264 | } else { | ||
| 271 | read_pos = strlen(linebuf); | 265 | read_pos = strlen(linebuf); |
| 272 | if (linebuf[read_pos - 1] == '\n') { | 266 | if (linebuf[read_pos - 1] == '\n') { |
| 273 | linebuf[--read_pos] = '\0'; | 267 | linebuf[--read_pos] = '\0'; |
| 274 | done_reading = 1; | 268 | done_reading = true; |
| 275 | } | 269 | } |
| 276 | } | 270 | } |
| 277 | } | 271 | } |
| 278 | lineend = &linebuf[read_pos]; | 272 | |
| 273 | char *lineend = &linebuf[read_pos]; | ||
| 279 | /* 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 :/ */ |
| 280 | 275 | ||
| 281 | /* skip leading whitespace */ | 276 | /* skip leading whitespace */ |
| 282 | for (optptr = linebuf; optptr < lineend && isspace(*optptr); optptr++) | 277 | char *optptr = NULL; |
| 283 | continue; | 278 | for (optptr = linebuf; optptr < lineend && isspace(*optptr); optptr++) { |
| 279 | } | ||
| 280 | |||
| 284 | /* 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; | ||
| 285 | for (eqptr = optptr; eqptr < lineend && *eqptr != '='; eqptr++) { | 284 | for (eqptr = optptr; eqptr < lineend && *eqptr != '='; eqptr++) { |
| 286 | if (isspace(*eqptr) && optend == NULL) | 285 | if (isspace(*eqptr) && optend == NULL) { |
| 287 | optend = eqptr; | 286 | optend = eqptr; |
| 288 | else | 287 | } else { |
| 289 | optend = NULL; | 288 | optend = NULL; |
| 289 | } | ||
| 290 | } | 290 | } |
| 291 | if (optend == NULL) | 291 | |
| 292 | if (optend == NULL) { | ||
| 292 | optend = eqptr; | 293 | optend = eqptr; |
| 294 | } | ||
| 295 | |||
| 293 | --optend; | 296 | --optend; |
| 297 | |||
| 294 | /* ^[[:space:]]*=foo is a syntax error */ | 298 | /* ^[[:space:]]*=foo is a syntax error */ |
| 295 | if (optptr == eqptr) | 299 | if (optptr == eqptr) { |
| 296 | die(STATE_UNKNOWN, "%s\n", _("Config file error")); | 300 | die(STATE_UNKNOWN, "%s\n", _("Config file error")); |
| 301 | } | ||
| 302 | |||
| 297 | /* continue from '=' to start of value or EOL */ | 303 | /* continue from '=' to start of value or EOL */ |
| 298 | for (valptr = eqptr + 1; valptr < lineend && isspace(*valptr); | 304 | char *valptr = NULL; |
| 299 | valptr++) | 305 | for (valptr = eqptr + 1; valptr < lineend && isspace(*valptr); valptr++) { |
| 300 | continue; | 306 | } |
| 307 | |||
| 301 | /* continue to the end of value */ | 308 | /* continue to the end of value */ |
| 302 | for (valend = valptr; valend < lineend; valend++) | 309 | char *valend = NULL; |
| 303 | continue; | 310 | for (valend = valptr; valend < lineend; valend++) { |
| 311 | } | ||
| 312 | |||
| 304 | --valend; | 313 | --valend; |
| 314 | |||
| 305 | /* finally trim off trailing spaces */ | 315 | /* finally trim off trailing spaces */ |
| 306 | for (; isspace(*valend); valend--) | 316 | for (; isspace(*valend); valend--) { |
| 307 | continue; | 317 | } |
| 318 | |||
| 308 | /* calculate the length of "--foo" */ | 319 | /* calculate the length of "--foo" */ |
| 309 | opt_len = (size_t)(1 + optend - optptr); | 320 | size_t opt_len = (size_t)(1 + optend - optptr); |
| 310 | /* 1-character params needs only one dash */ | 321 | /* 1-character params needs only one dash */ |
| 311 | if (opt_len == 1) | 322 | size_t cfg_len = 0; |
| 323 | if (opt_len == 1) { | ||
| 312 | cfg_len = 1 + (opt_len); | 324 | cfg_len = 1 + (opt_len); |
| 313 | else | 325 | } else { |
| 314 | cfg_len = 2 + (opt_len); | 326 | cfg_len = 2 + (opt_len); |
| 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")); |
| 346 | } | ||
| 329 | 347 | ||
| 330 | /* 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 |
| 331 | * element and set the argument... | 349 | * element and set the argument... |
| 332 | */ | 350 | */ |
| 333 | optnew = malloc(sizeof(np_arg_list)); | 351 | np_arg_list *optnew = malloc(sizeof(np_arg_list)); |
| 334 | optnew->next = NULL; | 352 | optnew->next = NULL; |
| 335 | 353 | ||
| 336 | read_pos = 0; | 354 | read_pos = 0; |
| @@ -353,11 +371,13 @@ add_option(FILE *f, np_arg_list **optlst) | |||
| 353 | optnew->arg[read_pos] = '\0'; | 371 | optnew->arg[read_pos] = '\0'; |
| 354 | 372 | ||
| 355 | /* ...and put that to the end of the list */ | 373 | /* ...and put that to the end of the list */ |
| 356 | if (*optlst == NULL) | 374 | if (*optlst == NULL) { |
| 357 | *optlst = optnew; | 375 | *optlst = optnew; |
| 358 | else { | 376 | } else { |
| 359 | while (opttmp->next != NULL) | 377 | np_arg_list *opttmp = *optlst; |
| 378 | while (opttmp->next != NULL) { | ||
| 360 | opttmp = opttmp->next; | 379 | opttmp = opttmp->next; |
| 380 | } | ||
| 361 | opttmp->next = optnew; | 381 | opttmp->next = optnew; |
| 362 | } | 382 | } |
| 363 | 383 | ||
| @@ -365,13 +385,11 @@ add_option(FILE *f, np_arg_list **optlst) | |||
| 365 | return 0; | 385 | return 0; |
| 366 | } | 386 | } |
| 367 | 387 | ||
| 368 | static char * | 388 | static char *default_file(void) { |
| 369 | default_file(void) | 389 | char *ini_file; |
| 370 | { | ||
| 371 | char *ini_file; | ||
| 372 | 390 | ||
| 373 | if ((ini_file = getenv("MP_CONFIG_FILE")) != NULL || | 391 | if ((ini_file = getenv("MP_CONFIG_FILE")) != NULL || |
| 374 | (ini_file = default_file_in_path()) != NULL) { | 392 | (ini_file = default_file_in_path()) != NULL) { |
| 375 | return ini_file; | 393 | return ini_file; |
| 376 | } | 394 | } |
| 377 | 395 | ||
| @@ -383,22 +401,26 @@ default_file(void) | |||
| 383 | return NULL; | 401 | return NULL; |
| 384 | } | 402 | } |
| 385 | 403 | ||
| 386 | static char * | 404 | static char *default_file_in_path(void) { |
| 387 | default_file_in_path(void) | 405 | char *config_path; |
| 388 | { | 406 | char **file; |
| 389 | char *config_path, **file; | 407 | char *dir; |
| 390 | char *dir, *ini_file, *tokens; | 408 | char *ini_file; |
| 409 | char *tokens; | ||
| 391 | 410 | ||
| 392 | if ((config_path = getenv("NAGIOS_CONFIG_PATH")) == NULL) | 411 | if ((config_path = getenv("NAGIOS_CONFIG_PATH")) == NULL) { |
| 393 | return NULL; | 412 | return NULL; |
| 413 | } | ||
| 394 | /* shall we spit out a warning that NAGIOS_CONFIG_PATH is deprecated? */ | 414 | /* shall we spit out a warning that NAGIOS_CONFIG_PATH is deprecated? */ |
| 395 | 415 | ||
| 396 | if ((tokens = strdup(config_path)) == NULL) | 416 | if ((tokens = strdup(config_path)) == NULL) { |
| 397 | die(STATE_UNKNOWN, "%s\n", _("Insufficient Memory")); | 417 | die(STATE_UNKNOWN, "%s\n", _("Insufficient Memory")); |
| 418 | } | ||
| 398 | for (dir = strtok(tokens, ":"); dir != NULL; dir = strtok(NULL, ":")) { | 419 | for (dir = strtok(tokens, ":"); dir != NULL; dir = strtok(NULL, ":")) { |
| 399 | for (file = default_ini_file_names; *file != NULL; file++) { | 420 | for (file = default_ini_file_names; *file != NULL; file++) { |
| 400 | if ((asprintf(&ini_file, "%s/%s", dir, *file)) < 0) | 421 | if ((asprintf(&ini_file, "%s/%s", dir, *file)) < 0) { |
| 401 | die(STATE_UNKNOWN, "%s\n", _("Insufficient Memory")); | 422 | die(STATE_UNKNOWN, "%s\n", _("Insufficient Memory")); |
| 423 | } | ||
| 402 | if (access(ini_file, F_OK) == 0) { | 424 | if (access(ini_file, F_OK) == 0) { |
| 403 | free(tokens); | 425 | free(tokens); |
| 404 | return ini_file; | 426 | return ini_file; |
