diff options
Diffstat (limited to 'lib/parse_ini.c')
-rw-r--r-- | lib/parse_ini.c | 346 |
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 @@ #include "common.h" #include "utils_base.h" #include "parse_ini.h" -#include <ctype.h> +#include <ctype.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> @@ -64,63 +64,71 @@ static char *default_ini_path_names[] = { /* internal function that returns the constructed defaults options */ static int read_defaults(FILE *f, const char *stanza, np_arg_list **opts); + /* internal function that converts a single line into options format */ static int add_option(FILE *f, np_arg_list **optlst); + /* internal function to find default file */ -static char* default_file(void); +static char *default_file(void); /* parse_locator decomposes a string of the form * [stanza][@filename] * into its seperate parts */ -static void parse_locator(const char *locator, const char *def_stanza, np_ini_info *i){ - size_t locator_len=0, stanza_len=0; +static void +parse_locator(const char *locator, const char *def_stanza, np_ini_info *i) +{ + size_t locator_len = 0, stanza_len = 0; /* if locator is NULL we'll use default values */ - if(locator){ - locator_len=strlen(locator); - stanza_len=strcspn(locator, "@"); + if (locator != NULL) { + locator_len = strlen(locator); + stanza_len = strcspn(locator, "@"); } /* if a non-default stanza is provided */ - if(stanza_len>0){ - i->stanza=(char*)malloc(sizeof(char)*(stanza_len+1)); + if (stanza_len > 0) { + i->stanza = malloc(sizeof(char) * (stanza_len + 1)); strncpy(i->stanza, locator, stanza_len); - i->stanza[stanza_len]='\0'; - } else { /* otherwise we use the default stanza */ - i->stanza=strdup(def_stanza); - } - if(i->stanza==NULL){ + i->stanza[stanza_len] = '\0'; + } else /* otherwise we use the default stanza */ + i->stanza = strdup(def_stanza); + + if (i->stanza == NULL) die(STATE_UNKNOWN, _("malloc() failed!\n")); - } - /* if there is no @file part */ - if(stanza_len==locator_len){ - i->file=default_file(); - } else { - i->file=strdup(&(locator[stanza_len+1])); - } - if(i->file==NULL || i->file[0]=='\0'){ - die(STATE_UNKNOWN, _("Cannot find config file in any standard location.\n")); - } + + /* check whether there's an @file part */ + i->file = stanza_len == locator_len + ? default_file() + : strdup(&(locator[stanza_len + 1])); + if (i->file == NULL || i->file[0] == '\0') + die(STATE_UNKNOWN, + _("Cannot find config file in any standard location.\n")); } /* this is the externally visible function used by extra_opts */ -np_arg_list* np_get_defaults(const char *locator, const char *default_section){ - FILE *inifile=NULL; - np_arg_list *defaults=NULL; +np_arg_list * +np_get_defaults(const char *locator, const char *default_section) +{ + FILE *inifile = NULL; + np_arg_list *defaults = NULL; np_ini_info i; parse_locator(locator, default_section, &i); - if(strcmp(i.file, "-")==0){ - inifile=stdin; - } else { - inifile=fopen(i.file, "r"); - } - if(inifile==NULL) die(STATE_UNKNOWN, "%s\n", _("Can't read config file")); - if(read_defaults(inifile, i.stanza, &defaults)==FALSE) - die(STATE_UNKNOWN, _("Invalid section '%s' in config file '%s'\n"), i.stanza, i.file); + if (strcmp(i.file, "-") == 0) + inifile = stdin; + else + inifile = fopen(i.file, "r"); + + if (inifile == NULL) + die(STATE_UNKNOWN, "%s\n", _("Can't read config file")); + if (read_defaults(inifile, i.stanza, &defaults) == FALSE) + die(STATE_UNKNOWN, + _("Invalid section '%s' in config file '%s'\n"), i.stanza, + i.file); free(i.file); - if(inifile!=stdin) fclose(inifile); + if (inifile != stdin) + fclose(inifile); free(i.stanza); return defaults; } @@ -131,67 +139,76 @@ np_arg_list* np_get_defaults(const char *locator, const char *default_section){ * be extra careful about user-supplied input (i.e. avoiding possible * format string vulnerabilities, etc) */ -static int read_defaults(FILE *f, const char *stanza, np_arg_list **opts){ - int c, status=FALSE; +static int +read_defaults(FILE *f, const char *stanza, np_arg_list **opts) +{ + int c, status = FALSE; size_t i, stanza_len; - enum { NOSTANZA, WRONGSTANZA, RIGHTSTANZA } stanzastate=NOSTANZA; + enum { NOSTANZA, WRONGSTANZA, RIGHTSTANZA } stanzastate = NOSTANZA; - stanza_len=strlen(stanza); + stanza_len = strlen(stanza); /* our little stanza-parsing state machine. */ - while((c=fgetc(f))!=EOF){ + while ((c = fgetc(f)) != EOF) { /* gobble up leading whitespace */ - if(isspace(c)) continue; - switch(c){ + if (isspace(c)) + continue; + switch (c) { /* globble up coment lines */ - case ';': - case '#': - GOBBLE_TO(f, c, '\n'); - break; + case ';': + case '#': + GOBBLE_TO(f, c, '\n'); + break; /* start of a stanza. check to see if it matches */ - case '[': - stanzastate=WRONGSTANZA; - for(i=0; i<stanza_len; i++){ - c=fgetc(f); - /* Strip leading whitespace */ - if(i==0) for(c; isspace(c); c=fgetc(f)); - /* nope, read to the end of the line */ - if(c!=stanza[i]) { - GOBBLE_TO(f, c, '\n'); - break; - } + case '[': + stanzastate = WRONGSTANZA; + for (i = 0; i < stanza_len; i++) { + c = fgetc(f); + /* Strip leading whitespace */ + if (i == 0) + for (c; isspace(c); c = fgetc(f)) + continue; + /* nope, read to the end of the line */ + if (c != stanza[i]) { + GOBBLE_TO(f, c, '\n'); + break; } - /* if it matched up to here and the next char is ']'... */ - if(i==stanza_len){ - c=fgetc(f); - /* Strip trailing whitespace */ - for(c; isspace(c); c=fgetc(f)); - if(c==']') stanzastate=RIGHTSTANZA; - } - break; + } + /* if it matched up to here and the next char is ']'... */ + if (i == stanza_len) { + c = fgetc(f); + /* Strip trailing whitespace */ + for (c; isspace(c); c = fgetc(f)) + continue; + if (c == ']') + stanzastate = RIGHTSTANZA; + } + break; /* otherwise, we're in the body of a stanza or a parse error */ - default: - switch(stanzastate){ - /* we never found the start of the first stanza, so - * we're dealing with a config error - */ - case NOSTANZA: - die(STATE_UNKNOWN, "%s\n", _("Config file error")); - break; - /* we're in a stanza, but for a different plugin */ - case WRONGSTANZA: - GOBBLE_TO(f, c, '\n'); - break; - /* okay, this is where we start taking the config */ - case RIGHTSTANZA: - ungetc(c, f); - if(add_option(f, opts)){ - die(STATE_UNKNOWN, "%s\n", _("Config file error")); - } - status=TRUE; - break; + default: + switch (stanzastate) { + /* we never found the start of the first stanza, so + * we're dealing with a config error + */ + case NOSTANZA: + die(STATE_UNKNOWN, "%s\n", + _("Config file error")); + break; + /* we're in a stanza, but for a different plugin */ + case WRONGSTANZA: + GOBBLE_TO(f, c, '\n'); + break; + /* okay, this is where we start taking the config */ + case RIGHTSTANZA: + ungetc(c, f); + if (add_option(f, opts)) { + die(STATE_UNKNOWN, "%s\n", + _("Config file error")); } + status = TRUE; break; + } + break; } } return status; @@ -204,103 +221,118 @@ static int read_defaults(FILE *f, const char *stanza, np_arg_list **opts){ * --option[=value] * appending it to the linked list optbuf. */ -static int add_option(FILE *f, np_arg_list **optlst){ - np_arg_list *opttmp=*optlst, *optnew; - char *linebuf=NULL, *lineend=NULL, *optptr=NULL, *optend=NULL; - char *eqptr=NULL, *valptr=NULL, *spaceptr=NULL, *valend=NULL; - short done_reading=0, equals=0, value=0; - size_t cfg_len=0, read_sz=8, linebuf_sz=0, read_pos=0; - size_t opt_len=0, val_len=0; +static int +add_option(FILE *f, np_arg_list **optlst) +{ + np_arg_list *opttmp = *optlst, *optnew; + char *linebuf = NULL, *lineend = NULL, *optptr = NULL, *optend = NULL; + char *eqptr = NULL, *valptr = NULL, *spaceptr = NULL, *valend = NULL; + short done_reading = 0, equals = 0, value = 0; + size_t cfg_len = 0, read_sz = 8, linebuf_sz = 0, read_pos = 0; + size_t opt_len = 0, val_len = 0; /* read one line from the file */ - while(!done_reading){ + while (!done_reading) { /* grow if necessary */ - if(linebuf==NULL || read_pos+read_sz >= linebuf_sz){ - linebuf_sz=(linebuf_sz>0)?linebuf_sz<<1:read_sz; - linebuf=realloc(linebuf, linebuf_sz); - if(linebuf==NULL) die(STATE_UNKNOWN, _("malloc() failed!\n")); + if (linebuf == NULL || read_pos + read_sz >= linebuf_sz) { + linebuf_sz = linebuf_sz > 0 ? linebuf_sz << 1 : read_sz; + linebuf = realloc(linebuf, linebuf_sz); + if (linebuf == NULL) + die(STATE_UNKNOWN, _("malloc() failed!\n")); } - if(fgets(&linebuf[read_pos], read_sz, f)==NULL) done_reading=1; + if (fgets(&linebuf[read_pos], read_sz, f) == NULL) + done_reading = 1; else { - read_pos=strlen(linebuf); - if(linebuf[read_pos-1]=='\n') { - linebuf[--read_pos]='\0'; - done_reading=1; + read_pos = strlen(linebuf); + if (linebuf[read_pos - 1] == '\n') { + linebuf[--read_pos] = '\0'; + done_reading = 1; } } } - lineend=&linebuf[read_pos]; + lineend = &linebuf[read_pos]; /* all that to read one line. isn't C fun? :) now comes the parsing :/ */ /* skip leading whitespace */ - for(optptr=linebuf; optptr<lineend && isspace(*optptr); optptr++); + for (optptr = linebuf; optptr < lineend && isspace(*optptr); optptr++) + continue; /* continue to '=' or EOL, watching for spaces that might precede it */ - for(eqptr=optptr; eqptr<lineend && *eqptr!='='; eqptr++){ - if(isspace(*eqptr) && optend==NULL) optend=eqptr; - else optend=NULL; + for (eqptr = optptr; eqptr < lineend && *eqptr != '='; eqptr++) { + if (isspace(*eqptr) && optend == NULL) + optend = eqptr; + else + optend = NULL; } - if(optend==NULL) optend=eqptr; + if (optend == NULL) + optend = eqptr; --optend; /* ^[[:space:]]*=foo is a syntax error */ - if(optptr==eqptr) die(STATE_UNKNOWN, "%s\n", _("Config file error")); + if (optptr == eqptr) + die(STATE_UNKNOWN, "%s\n", _("Config file error")); /* continue from '=' to start of value or EOL */ - for(valptr=eqptr+1; valptr<lineend && isspace(*valptr); valptr++); + for (valptr = eqptr + 1; valptr < lineend && isspace(*valptr); + valptr++) + continue; /* continue to the end of value */ - for(valend=valptr; valend<lineend; valend++); + for (valend = valptr; valend < lineend; valend++) + continue; --valend; /* Finally trim off trailing spaces */ - for(valend; isspace(*valend); valend--); + for (valend; isspace(*valend); valend--) + continue; /* calculate the length of "--foo" */ - opt_len=1+optend-optptr; + opt_len = 1 + optend - optptr; /* 1-character params needs only one dash */ - if(opt_len==1) - cfg_len=1+(opt_len); + if (opt_len == 1) + cfg_len = 1 + (opt_len); else - cfg_len=2+(opt_len); + cfg_len = 2 + (opt_len); /* if valptr<lineend then we have to also allocate space for "=bar" */ - if(valptr<lineend) { - equals=value=1; - val_len=1+valend-valptr; - cfg_len+=1+val_len; + if (valptr < lineend) { + equals = value = 1; + val_len = 1 + valend - valptr; + cfg_len += 1 + val_len; } /* if valptr==valend then we have "=" but no "bar" */ - else if(valptr==lineend) { - equals=1; - cfg_len+=1; + else if (valptr == lineend) { + equals = 1; + cfg_len += 1; } /* A line with no equal sign isn't valid */ - if(equals==0) die(STATE_UNKNOWN, "%s\n", _("Config file error")); + if (equals == 0) + die(STATE_UNKNOWN, "%s\n", _("Config file error")); /* okay, now we have all the info we need, so we create a new np_arg_list * element and set the argument... */ - optnew=malloc(sizeof(np_arg_list)); - optnew->next=NULL; + optnew = malloc(sizeof(np_arg_list)); + optnew->next = NULL; - read_pos=0; - optnew->arg=malloc(cfg_len+1); + read_pos = 0; + optnew->arg = malloc(cfg_len + 1); /* 1-character params needs only one dash */ - if(opt_len==1) { + if (opt_len == 1) { strncpy(&optnew->arg[read_pos], "-", 1); - read_pos+=1; + read_pos += 1; } else { strncpy(&optnew->arg[read_pos], "--", 2); - read_pos+=2; + read_pos += 2; } - strncpy(&optnew->arg[read_pos], optptr, opt_len); read_pos+=opt_len; - if(value) { - optnew->arg[read_pos++]='='; - strncpy(&optnew->arg[read_pos], valptr, val_len); read_pos+=val_len; + strncpy(&optnew->arg[read_pos], optptr, opt_len); + read_pos += opt_len; + if (value) { + optnew->arg[read_pos++] = '='; + strncpy(&optnew->arg[read_pos], valptr, val_len); + read_pos += val_len; } - optnew->arg[read_pos]='\0'; + optnew->arg[read_pos] = '\0'; /* ...and put that to the end of the list */ - if(*optlst==NULL) { - *optlst=optnew; - } else { - while(opttmp->next!=NULL) { - opttmp=opttmp->next; - } + if (*optlst == NULL) + *optlst = optnew; + else { + while (opttmp->next != NULL) + opttmp = opttmp->next; opttmp->next = optnew; } @@ -308,20 +340,22 @@ static int add_option(FILE *f, np_arg_list **optlst){ return 0; } -static char *default_file_in_path(void){ +static char * +default_file_in_path(void) +{ char *config_path, **file; char *dir, *ini_file, *tokens; - if((config_path=getenv("NAGIOS_CONFIG_PATH"))==NULL) + if ((config_path = getenv("NAGIOS_CONFIG_PATH")) == NULL) return NULL; - if((tokens=strdup(config_path))==NULL) + if ((tokens = strdup(config_path)) == NULL) die(STATE_UNKNOWN, _("Insufficient Memory")); - for(dir=strtok(tokens, ":"); dir!=NULL; dir=strtok(NULL, ":")){ - for(file=default_ini_file_names; *file!=NULL; file++){ - if((asprintf(&ini_file, "%s/%s", dir, *file))<0) + for (dir = strtok(tokens, ":"); dir != NULL; dir = strtok(NULL, ":")) { + for (file = default_ini_file_names; *file != NULL; file++) { + if ((asprintf(&ini_file, "%s/%s", dir, *file)) < 0) die(STATE_UNKNOWN, _("Insufficient Memory")); - if(access(ini_file, F_OK)==0){ + if (access(ini_file, F_OK) == 0) { free(tokens); return ini_file; } @@ -331,14 +365,16 @@ static char *default_file_in_path(void){ return NULL; } -static char *default_file(void){ +static char * +default_file(void) +{ char **p, *ini_file; - if((ini_file=getenv("MP_CONFIG_FILE"))!=NULL || - (ini_file=default_file_in_path())!=NULL) + if ((ini_file = getenv("MP_CONFIG_FILE")) != NULL || + (ini_file = default_file_in_path()) != NULL) return ini_file; - for(p=default_ini_path_names; *p!=NULL; p++) - if (access(*p, F_OK)==0) + for (p = default_ini_path_names; *p != NULL; p++) + if (access(*p, F_OK) == 0) return *p; return NULL; } |