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.c346
1 files changed, 191 insertions, 155 deletions
diff --git a/lib/parse_ini.c b/lib/parse_ini.c
index 51ad2c17..a5b3d306 100644
--- a/lib/parse_ini.c
+++ b/lib/parse_ini.c
@@ -24,8 +24,8 @@
24#include "common.h" 24#include "common.h"
25#include "utils_base.h" 25#include "utils_base.h"
26#include "parse_ini.h" 26#include "parse_ini.h"
27#include <ctype.h>
28 27
28#include <ctype.h>
29#include <sys/types.h> 29#include <sys/types.h>
30#include <sys/stat.h> 30#include <sys/stat.h>
31#include <unistd.h> 31#include <unistd.h>
@@ -64,63 +64,71 @@ static char *default_ini_path_names[] = {
64 64
65/* internal function that returns the constructed defaults options */ 65/* internal function that returns the constructed defaults options */
66static int read_defaults(FILE *f, const char *stanza, np_arg_list **opts); 66static int read_defaults(FILE *f, const char *stanza, np_arg_list **opts);
67
67/* internal function that converts a single line into options format */ 68/* internal function that converts a single line into options format */
68static int add_option(FILE *f, np_arg_list **optlst); 69static int add_option(FILE *f, np_arg_list **optlst);
70
69/* internal function to find default file */ 71/* internal function to find default file */
70static char* default_file(void); 72static char *default_file(void);
71 73
72/* parse_locator decomposes a string of the form 74/* parse_locator decomposes a string of the form
73 * [stanza][@filename] 75 * [stanza][@filename]
74 * into its seperate parts 76 * into its seperate parts
75 */ 77 */
76static void parse_locator(const char *locator, const char *def_stanza, np_ini_info *i){ 78static void
77 size_t locator_len=0, stanza_len=0; 79parse_locator(const char *locator, const char *def_stanza, np_ini_info *i)
80{
81 size_t locator_len = 0, stanza_len = 0;
78 82
79 /* if locator is NULL we'll use default values */ 83 /* if locator is NULL we'll use default values */
80 if(locator){ 84 if (locator != NULL) {
81 locator_len=strlen(locator); 85 locator_len = strlen(locator);
82 stanza_len=strcspn(locator, "@"); 86 stanza_len = strcspn(locator, "@");
83 } 87 }
84 /* if a non-default stanza is provided */ 88 /* if a non-default stanza is provided */
85 if(stanza_len>0){ 89 if (stanza_len > 0) {
86 i->stanza=(char*)malloc(sizeof(char)*(stanza_len+1)); 90 i->stanza = malloc(sizeof(char) * (stanza_len + 1));
87 strncpy(i->stanza, locator, stanza_len); 91 strncpy(i->stanza, locator, stanza_len);
88 i->stanza[stanza_len]='\0'; 92 i->stanza[stanza_len] = '\0';
89 } else { /* otherwise we use the default stanza */ 93 } else /* otherwise we use the default stanza */
90 i->stanza=strdup(def_stanza); 94 i->stanza = strdup(def_stanza);
91 } 95
92 if(i->stanza==NULL){ 96 if (i->stanza == NULL)
93 die(STATE_UNKNOWN, _("malloc() failed!\n")); 97 die(STATE_UNKNOWN, _("malloc() failed!\n"));
94 } 98
95 /* if there is no @file part */ 99 /* check whether there's an @file part */
96 if(stanza_len==locator_len){ 100 i->file = stanza_len == locator_len
97 i->file=default_file(); 101 ? default_file()
98 } else { 102 : strdup(&(locator[stanza_len + 1]));
99 i->file=strdup(&(locator[stanza_len+1])); 103 if (i->file == NULL || i->file[0] == '\0')
100 } 104 die(STATE_UNKNOWN,
101 if(i->file==NULL || i->file[0]=='\0'){ 105 _("Cannot find config file in any standard location.\n"));
102 die(STATE_UNKNOWN, _("Cannot find config file in any standard location.\n"));
103 }
104} 106}
105 107
106/* this is the externally visible function used by extra_opts */ 108/* this is the externally visible function used by extra_opts */
107np_arg_list* np_get_defaults(const char *locator, const char *default_section){ 109np_arg_list *
108 FILE *inifile=NULL; 110np_get_defaults(const char *locator, const char *default_section)
109 np_arg_list *defaults=NULL; 111{
112 FILE *inifile = NULL;
113 np_arg_list *defaults = NULL;
110 np_ini_info i; 114 np_ini_info i;
111 115
112 parse_locator(locator, default_section, &i); 116 parse_locator(locator, default_section, &i);
113 if(strcmp(i.file, "-")==0){ 117 if (strcmp(i.file, "-") == 0)
114 inifile=stdin; 118 inifile = stdin;
115 } else { 119 else
116 inifile=fopen(i.file, "r"); 120 inifile = fopen(i.file, "r");
117 } 121
118 if(inifile==NULL) die(STATE_UNKNOWN, "%s\n", _("Can't read config file")); 122 if (inifile == NULL)
119 if(read_defaults(inifile, i.stanza, &defaults)==FALSE) 123 die(STATE_UNKNOWN, "%s\n", _("Can't read config file"));
120 die(STATE_UNKNOWN, _("Invalid section '%s' in config file '%s'\n"), i.stanza, i.file); 124 if (read_defaults(inifile, i.stanza, &defaults) == FALSE)
125 die(STATE_UNKNOWN,
126 _("Invalid section '%s' in config file '%s'\n"), i.stanza,
127 i.file);
121 128
122 free(i.file); 129 free(i.file);
123 if(inifile!=stdin) fclose(inifile); 130 if (inifile != stdin)
131 fclose(inifile);
124 free(i.stanza); 132 free(i.stanza);
125 return defaults; 133 return defaults;
126} 134}
@@ -131,67 +139,76 @@ np_arg_list* np_get_defaults(const char *locator, const char *default_section){
131 * be extra careful about user-supplied input (i.e. avoiding possible 139 * be extra careful about user-supplied input (i.e. avoiding possible
132 * format string vulnerabilities, etc) 140 * format string vulnerabilities, etc)
133 */ 141 */
134static int read_defaults(FILE *f, const char *stanza, np_arg_list **opts){ 142static int
135 int c, status=FALSE; 143read_defaults(FILE *f, const char *stanza, np_arg_list **opts)
144{
145 int c, status = FALSE;
136 size_t i, stanza_len; 146 size_t i, stanza_len;
137 enum { NOSTANZA, WRONGSTANZA, RIGHTSTANZA } stanzastate=NOSTANZA; 147 enum { NOSTANZA, WRONGSTANZA, RIGHTSTANZA } stanzastate = NOSTANZA;
138 148
139 stanza_len=strlen(stanza); 149 stanza_len = strlen(stanza);
140 150
141 /* our little stanza-parsing state machine. */ 151 /* our little stanza-parsing state machine. */
142 while((c=fgetc(f))!=EOF){ 152 while ((c = fgetc(f)) != EOF) {
143 /* gobble up leading whitespace */ 153 /* gobble up leading whitespace */
144 if(isspace(c)) continue; 154 if (isspace(c))
145 switch(c){ 155 continue;
156 switch (c) {
146 /* globble up coment lines */ 157 /* globble up coment lines */
147 case ';': 158 case ';':
148 case '#': 159 case '#':
149 GOBBLE_TO(f, c, '\n'); 160 GOBBLE_TO(f, c, '\n');
150 break; 161 break;
151 /* start of a stanza. check to see if it matches */ 162 /* start of a stanza. check to see if it matches */
152 case '[': 163 case '[':
153 stanzastate=WRONGSTANZA; 164 stanzastate = WRONGSTANZA;
154 for(i=0; i<stanza_len; i++){ 165 for (i = 0; i < stanza_len; i++) {
155 c=fgetc(f); 166 c = fgetc(f);
156 /* Strip leading whitespace */ 167 /* Strip leading whitespace */
157 if(i==0) for(c; isspace(c); c=fgetc(f)); 168 if (i == 0)
158 /* nope, read to the end of the line */ 169 for (c; isspace(c); c = fgetc(f))
159 if(c!=stanza[i]) { 170 continue;
160 GOBBLE_TO(f, c, '\n'); 171 /* nope, read to the end of the line */
161 break; 172 if (c != stanza[i]) {
162 } 173 GOBBLE_TO(f, c, '\n');
174 break;
163 } 175 }
164 /* if it matched up to here and the next char is ']'... */ 176 }
165 if(i==stanza_len){ 177 /* if it matched up to here and the next char is ']'... */
166 c=fgetc(f); 178 if (i == stanza_len) {
167 /* Strip trailing whitespace */ 179 c = fgetc(f);
168 for(c; isspace(c); c=fgetc(f)); 180 /* Strip trailing whitespace */
169 if(c==']') stanzastate=RIGHTSTANZA; 181 for (c; isspace(c); c = fgetc(f))
170 } 182 continue;
171 break; 183 if (c == ']')
184 stanzastate = RIGHTSTANZA;
185 }
186 break;
172 /* otherwise, we're in the body of a stanza or a parse error */ 187 /* otherwise, we're in the body of a stanza or a parse error */
173 default: 188 default:
174 switch(stanzastate){ 189 switch (stanzastate) {
175 /* we never found the start of the first stanza, so 190 /* we never found the start of the first stanza, so
176 * we're dealing with a config error 191 * we're dealing with a config error
177 */ 192 */
178 case NOSTANZA: 193 case NOSTANZA:
179 die(STATE_UNKNOWN, "%s\n", _("Config file error")); 194 die(STATE_UNKNOWN, "%s\n",
180 break; 195 _("Config file error"));
181 /* we're in a stanza, but for a different plugin */ 196 break;
182 case WRONGSTANZA: 197 /* we're in a stanza, but for a different plugin */
183 GOBBLE_TO(f, c, '\n'); 198 case WRONGSTANZA:
184 break; 199 GOBBLE_TO(f, c, '\n');
185 /* okay, this is where we start taking the config */ 200 break;
186 case RIGHTSTANZA: 201 /* okay, this is where we start taking the config */
187 ungetc(c, f); 202 case RIGHTSTANZA:
188 if(add_option(f, opts)){ 203 ungetc(c, f);
189 die(STATE_UNKNOWN, "%s\n", _("Config file error")); 204 if (add_option(f, opts)) {
190 } 205 die(STATE_UNKNOWN, "%s\n",
191 status=TRUE; 206 _("Config file error"));
192 break;
193 } 207 }
208 status = TRUE;
194 break; 209 break;
210 }
211 break;
195 } 212 }
196 } 213 }
197 return status; 214 return status;
@@ -204,103 +221,118 @@ static int read_defaults(FILE *f, const char *stanza, np_arg_list **opts){
204 * --option[=value] 221 * --option[=value]
205 * appending it to the linked list optbuf. 222 * appending it to the linked list optbuf.
206 */ 223 */
207static int add_option(FILE *f, np_arg_list **optlst){ 224static int
208 np_arg_list *opttmp=*optlst, *optnew; 225add_option(FILE *f, np_arg_list **optlst)
209 char *linebuf=NULL, *lineend=NULL, *optptr=NULL, *optend=NULL; 226{
210 char *eqptr=NULL, *valptr=NULL, *spaceptr=NULL, *valend=NULL; 227 np_arg_list *opttmp = *optlst, *optnew;
211 short done_reading=0, equals=0, value=0; 228 char *linebuf = NULL, *lineend = NULL, *optptr = NULL, *optend = NULL;
212 size_t cfg_len=0, read_sz=8, linebuf_sz=0, read_pos=0; 229 char *eqptr = NULL, *valptr = NULL, *spaceptr = NULL, *valend = NULL;
213 size_t opt_len=0, val_len=0; 230 short done_reading = 0, equals = 0, value = 0;
231 size_t cfg_len = 0, read_sz = 8, linebuf_sz = 0, read_pos = 0;
232 size_t opt_len = 0, val_len = 0;
214 233
215 /* read one line from the file */ 234 /* read one line from the file */
216 while(!done_reading){ 235 while (!done_reading) {
217 /* grow if necessary */ 236 /* grow if necessary */
218 if(linebuf==NULL || read_pos+read_sz >= linebuf_sz){ 237 if (linebuf == NULL || read_pos + read_sz >= linebuf_sz) {
219 linebuf_sz=(linebuf_sz>0)?linebuf_sz<<1:read_sz; 238 linebuf_sz = linebuf_sz > 0 ? linebuf_sz << 1 : read_sz;
220 linebuf=realloc(linebuf, linebuf_sz); 239 linebuf = realloc(linebuf, linebuf_sz);
221 if(linebuf==NULL) die(STATE_UNKNOWN, _("malloc() failed!\n")); 240 if (linebuf == NULL)
241 die(STATE_UNKNOWN, _("malloc() failed!\n"));
222 } 242 }
223 if(fgets(&linebuf[read_pos], read_sz, f)==NULL) done_reading=1; 243 if (fgets(&linebuf[read_pos], read_sz, f) == NULL)
244 done_reading = 1;
224 else { 245 else {
225 read_pos=strlen(linebuf); 246 read_pos = strlen(linebuf);
226 if(linebuf[read_pos-1]=='\n') { 247 if (linebuf[read_pos - 1] == '\n') {
227 linebuf[--read_pos]='\0'; 248 linebuf[--read_pos] = '\0';
228 done_reading=1; 249 done_reading = 1;
229 } 250 }
230 } 251 }
231 } 252 }
232 lineend=&linebuf[read_pos]; 253 lineend = &linebuf[read_pos];
233 /* all that to read one line. isn't C fun? :) now comes the parsing :/ */ 254 /* all that to read one line. isn't C fun? :) now comes the parsing :/ */
234 255
235 /* skip leading whitespace */ 256 /* skip leading whitespace */
236 for(optptr=linebuf; optptr<lineend && isspace(*optptr); optptr++); 257 for (optptr = linebuf; optptr < lineend && isspace(*optptr); optptr++)
258 continue;
237 /* continue to '=' or EOL, watching for spaces that might precede it */ 259 /* continue to '=' or EOL, watching for spaces that might precede it */
238 for(eqptr=optptr; eqptr<lineend && *eqptr!='='; eqptr++){ 260 for (eqptr = optptr; eqptr < lineend && *eqptr != '='; eqptr++) {
239 if(isspace(*eqptr) && optend==NULL) optend=eqptr; 261 if (isspace(*eqptr) && optend == NULL)
240 else optend=NULL; 262 optend = eqptr;
263 else
264 optend = NULL;
241 } 265 }
242 if(optend==NULL) optend=eqptr; 266 if (optend == NULL)
267 optend = eqptr;
243 --optend; 268 --optend;
244 /* ^[[:space:]]*=foo is a syntax error */ 269 /* ^[[:space:]]*=foo is a syntax error */
245 if(optptr==eqptr) die(STATE_UNKNOWN, "%s\n", _("Config file error")); 270 if (optptr == eqptr)
271 die(STATE_UNKNOWN, "%s\n", _("Config file error"));
246 /* continue from '=' to start of value or EOL */ 272 /* continue from '=' to start of value or EOL */
247 for(valptr=eqptr+1; valptr<lineend && isspace(*valptr); valptr++); 273 for (valptr = eqptr + 1; valptr < lineend && isspace(*valptr);
274 valptr++)
275 continue;
248 /* continue to the end of value */ 276 /* continue to the end of value */
249 for(valend=valptr; valend<lineend; valend++); 277 for (valend = valptr; valend < lineend; valend++)
278 continue;
250 --valend; 279 --valend;
251 /* Finally trim off trailing spaces */ 280 /* Finally trim off trailing spaces */
252 for(valend; isspace(*valend); valend--); 281 for (valend; isspace(*valend); valend--)
282 continue;
253 /* calculate the length of "--foo" */ 283 /* calculate the length of "--foo" */
254 opt_len=1+optend-optptr; 284 opt_len = 1 + optend - optptr;
255 /* 1-character params needs only one dash */ 285 /* 1-character params needs only one dash */
256 if(opt_len==1) 286 if (opt_len == 1)
257 cfg_len=1+(opt_len); 287 cfg_len = 1 + (opt_len);
258 else 288 else
259 cfg_len=2+(opt_len); 289 cfg_len = 2 + (opt_len);
260 /* if valptr<lineend then we have to also allocate space for "=bar" */ 290 /* if valptr<lineend then we have to also allocate space for "=bar" */
261 if(valptr<lineend) { 291 if (valptr < lineend) {
262 equals=value=1; 292 equals = value = 1;
263 val_len=1+valend-valptr; 293 val_len = 1 + valend - valptr;
264 cfg_len+=1+val_len; 294 cfg_len += 1 + val_len;
265 } 295 }
266 /* if valptr==valend then we have "=" but no "bar" */ 296 /* if valptr==valend then we have "=" but no "bar" */
267 else if(valptr==lineend) { 297 else if (valptr == lineend) {
268 equals=1; 298 equals = 1;
269 cfg_len+=1; 299 cfg_len += 1;
270 } 300 }
271 /* A line with no equal sign isn't valid */ 301 /* A line with no equal sign isn't valid */
272 if(equals==0) die(STATE_UNKNOWN, "%s\n", _("Config file error")); 302 if (equals == 0)
303 die(STATE_UNKNOWN, "%s\n", _("Config file error"));
273 304
274 /* okay, now we have all the info we need, so we create a new np_arg_list 305 /* okay, now we have all the info we need, so we create a new np_arg_list
275 * element and set the argument... 306 * element and set the argument...
276 */ 307 */
277 optnew=malloc(sizeof(np_arg_list)); 308 optnew = malloc(sizeof(np_arg_list));
278 optnew->next=NULL; 309 optnew->next = NULL;
279 310
280 read_pos=0; 311 read_pos = 0;
281 optnew->arg=malloc(cfg_len+1); 312 optnew->arg = malloc(cfg_len + 1);
282 /* 1-character params needs only one dash */ 313 /* 1-character params needs only one dash */
283 if(opt_len==1) { 314 if (opt_len == 1) {
284 strncpy(&optnew->arg[read_pos], "-", 1); 315 strncpy(&optnew->arg[read_pos], "-", 1);
285 read_pos+=1; 316 read_pos += 1;
286 } else { 317 } else {
287 strncpy(&optnew->arg[read_pos], "--", 2); 318 strncpy(&optnew->arg[read_pos], "--", 2);
288 read_pos+=2; 319 read_pos += 2;
289 } 320 }
290 strncpy(&optnew->arg[read_pos], optptr, opt_len); read_pos+=opt_len; 321 strncpy(&optnew->arg[read_pos], optptr, opt_len);
291 if(value) { 322 read_pos += opt_len;
292 optnew->arg[read_pos++]='='; 323 if (value) {
293 strncpy(&optnew->arg[read_pos], valptr, val_len); read_pos+=val_len; 324 optnew->arg[read_pos++] = '=';
325 strncpy(&optnew->arg[read_pos], valptr, val_len);
326 read_pos += val_len;
294 } 327 }
295 optnew->arg[read_pos]='\0'; 328 optnew->arg[read_pos] = '\0';
296 329
297 /* ...and put that to the end of the list */ 330 /* ...and put that to the end of the list */
298 if(*optlst==NULL) { 331 if (*optlst == NULL)
299 *optlst=optnew; 332 *optlst = optnew;
300 } else { 333 else {
301 while(opttmp->next!=NULL) { 334 while (opttmp->next != NULL)
302 opttmp=opttmp->next; 335 opttmp = opttmp->next;
303 }
304 opttmp->next = optnew; 336 opttmp->next = optnew;
305 } 337 }
306 338
@@ -308,20 +340,22 @@ static int add_option(FILE *f, np_arg_list **optlst){
308 return 0; 340 return 0;
309} 341}
310 342
311static char *default_file_in_path(void){ 343static char *
344default_file_in_path(void)
345{
312 char *config_path, **file; 346 char *config_path, **file;
313 char *dir, *ini_file, *tokens; 347 char *dir, *ini_file, *tokens;
314 348
315 if((config_path=getenv("NAGIOS_CONFIG_PATH"))==NULL) 349 if ((config_path = getenv("NAGIOS_CONFIG_PATH")) == NULL)
316 return NULL; 350 return NULL;
317 351
318 if((tokens=strdup(config_path))==NULL) 352 if ((tokens = strdup(config_path)) == NULL)
319 die(STATE_UNKNOWN, _("Insufficient Memory")); 353 die(STATE_UNKNOWN, _("Insufficient Memory"));
320 for(dir=strtok(tokens, ":"); dir!=NULL; dir=strtok(NULL, ":")){ 354 for (dir = strtok(tokens, ":"); dir != NULL; dir = strtok(NULL, ":")) {
321 for(file=default_ini_file_names; *file!=NULL; file++){ 355 for (file = default_ini_file_names; *file != NULL; file++) {
322 if((asprintf(&ini_file, "%s/%s", dir, *file))<0) 356 if ((asprintf(&ini_file, "%s/%s", dir, *file)) < 0)
323 die(STATE_UNKNOWN, _("Insufficient Memory")); 357 die(STATE_UNKNOWN, _("Insufficient Memory"));
324 if(access(ini_file, F_OK)==0){ 358 if (access(ini_file, F_OK) == 0) {
325 free(tokens); 359 free(tokens);
326 return ini_file; 360 return ini_file;
327 } 361 }
@@ -331,14 +365,16 @@ static char *default_file_in_path(void){
331 return NULL; 365 return NULL;
332} 366}
333 367
334static char *default_file(void){ 368static char *
369default_file(void)
370{
335 char **p, *ini_file; 371 char **p, *ini_file;
336 372
337 if((ini_file=getenv("MP_CONFIG_FILE"))!=NULL || 373 if ((ini_file = getenv("MP_CONFIG_FILE")) != NULL ||
338 (ini_file=default_file_in_path())!=NULL) 374 (ini_file = default_file_in_path()) != NULL)
339 return ini_file; 375 return ini_file;
340 for(p=default_ini_path_names; *p!=NULL; p++) 376 for (p = default_ini_path_names; *p != NULL; p++)
341 if (access(*p, F_OK)==0) 377 if (access(*p, F_OK) == 0)
342 return *p; 378 return *p;
343 return NULL; 379 return NULL;
344} 380}