X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=lib%2Fparse_ini.c;h=004396fe803378c18c501bb17743364b8cb6508b;hb=1a5a83bb82c35d888229fe9f815fbc663c0f4d3c;hp=b555316e0ab18b82838d403a360280f365a3478b;hpb=ffab7ee68b32d44ae2f35f688f417cd0109b0b45;p=nagiosplug.git diff --git a/lib/parse_ini.c b/lib/parse_ini.c index b555316..004396f 100644 --- a/lib/parse_ini.c +++ b/lib/parse_ini.c @@ -5,9 +5,6 @@ * License: GPL * Copyright (c) 2007 Nagios Plugins Development Team * -* Last Modified: $Date$ -* -* * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -21,15 +18,20 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . * -* $Id$ * *****************************************************************************/ #include "common.h" -#include "parse_ini.h" #include "utils_base.h" +#include "parse_ini.h" #include +#include +#include +#include + +/* TODO: die like N::P if config file is not found */ + /* np_ini_info contains the result of parsing a "locator" in the format * [stanza_name][@config_filename] (check_foo@/etc/foo.ini, for example) */ @@ -42,19 +44,26 @@ typedef struct { #define GOBBLE_TO(f, c, n) do { (c)=fgetc((f)); } while((c)!=EOF && (c)!=(n)) /* internal function that returns the constructed defaults options */ -static np_arg_list* read_defaults(FILE *f, const char *stanza); +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); +/* internal function to stat() files */ +static int test_file(const char* env, int len, const char* file, char* temp_file); /* 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, stanza_len; + size_t locator_len=0, stanza_len=0; - locator_len=strlen(locator); - stanza_len=strcspn(locator, "@"); + /* if locator is NULL we'll use default values */ + if(locator){ + 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)); @@ -65,17 +74,20 @@ static void parse_locator(const char *locator, const char *def_stanza, np_ini_in } /* if there is no @file part */ if(stanza_len==locator_len){ - i->file=strdup(NP_DEFAULT_INI_PATH); + i->file=default_file(); + if(strcmp(i->file, "") == 0){ + die(STATE_UNKNOWN, _("Cannot find '%s' or '%s' in any standard location.\n"), NP_DEFAULT_INI_FILENAME1, NP_DEFAULT_INI_FILENAME2); + } } else { i->file=strdup(&(locator[stanza_len+1])); } - + if(i->file==NULL || i->stanza==NULL){ die(STATE_UNKNOWN, _("malloc() failed!\n")); } } -/* this is the externally visible function used by plugins */ +/* 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; @@ -85,17 +97,19 @@ np_arg_list* np_get_defaults(const char *locator, const char *default_section){ /* if a file was specified or if we're using the default file */ if(i.file != NULL && strlen(i.file) > 0){ if(strcmp(i.file, "-")==0){ - inifile=stdout; /* FIXME: Shouldn't it be 'stdin' ??? */ + inifile=stdin; } else { inifile=fopen(i.file, "r"); } - if(inifile==NULL) die(STATE_UNKNOWN, _("Config file error")); - defaults=read_defaults(inifile, i.stanza); + if(inifile==NULL) die(STATE_UNKNOWN, _("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!=stdout) fclose(inifile); /* FIXME: Shouldn't it be 'stdin' ??? */ + if(inifile!=stdin) fclose(inifile); } free(i.stanza); - return defaults; + return defaults; } /* read_defaults is where the meat of the parsing takes place. @@ -104,9 +118,8 @@ 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 np_arg_list* read_defaults(FILE *f, const char *stanza){ - int c; - np_arg_list *opts=NULL; +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; @@ -118,6 +131,7 @@ static np_arg_list* read_defaults(FILE *f, const char *stanza){ if(isspace(c)) continue; switch(c){ /* globble up coment lines */ + case ';': case '#': GOBBLE_TO(f, c, '\n'); break; @@ -126,6 +140,8 @@ static np_arg_list* read_defaults(FILE *f, const char *stanza){ stanzastate=WRONGSTANZA; for(i=0; iarg=(char *)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; } else { @@ -256,17 +275,17 @@ static int add_option(FILE *f, np_arg_list **optlst){ read_pos+=2; } strncpy(&optnew->arg[read_pos], optptr, opt_len); read_pos+=opt_len; - if(equals) optnew->arg[read_pos++]='='; if(value) { + optnew->arg[read_pos++]='='; strncpy(&optnew->arg[read_pos], valptr, val_len); read_pos+=val_len; } optnew->arg[read_pos]='\0'; /* ...and put that to the end of the list */ - if (*optlst==NULL) { + if(*optlst==NULL) { *optlst=optnew; } else { - while (opttmp->next!=NULL) { + while(opttmp->next!=NULL) { opttmp=opttmp->next; } opttmp->next = optnew; @@ -276,3 +295,72 @@ static int add_option(FILE *f, np_arg_list **optlst){ return 0; } +static char* default_file(void){ + struct stat sb; + char *np_env=NULL, *default_file=NULL; + char temp_file[MAX_INPUT_BUFFER]; + size_t len; + + if((np_env=getenv("NAGIOS_CONFIG_PATH"))!=NULL) { + /* skip any starting colon... */ + while(*np_env==':') np_env++; + /* Look for NP_DEFAULT_INI_FILENAME1 and NP_DEFAULT_INI_FILENAME2 in + * every PATHs defined (colon-separated). + */ + while((len=strcspn(np_env,":"))>0){ + /* Test NP_DEFAULT_INI_FILENAME[1-2] in current np_env token */ + if(test_file(np_env,len,NP_DEFAULT_INI_FILENAME1,temp_file)==1 || + test_file(np_env,len,NP_DEFAULT_INI_FILENAME2,temp_file)==1){ + default_file=strdup(temp_file); + break; + } + + /* Move on to the next token */ + np_env+=len; + while(*np_env==':') np_env++; + } /* while(...) */ + } /* if(getenv("NAGIOS_CONFIG_PATH")) */ + + /* Look for NP_DEFAULT_INI_FILENAME1 in NP_DEFAULT_INI_NAGIOS_PATH[1-4] */ + if(!default_file){ + if(test_file(NP_DEFAULT_INI_NAGIOS_PATH1,strlen(NP_DEFAULT_INI_NAGIOS_PATH1),NP_DEFAULT_INI_FILENAME1,temp_file)==1 || + test_file(NP_DEFAULT_INI_NAGIOS_PATH2,strlen(NP_DEFAULT_INI_NAGIOS_PATH2),NP_DEFAULT_INI_FILENAME1,temp_file)==1 || + test_file(NP_DEFAULT_INI_NAGIOS_PATH3,strlen(NP_DEFAULT_INI_NAGIOS_PATH3),NP_DEFAULT_INI_FILENAME1,temp_file)==1 || + test_file(NP_DEFAULT_INI_NAGIOS_PATH4,strlen(NP_DEFAULT_INI_NAGIOS_PATH4),NP_DEFAULT_INI_FILENAME1,temp_file)==1) + default_file=strdup(temp_file); + } + + /* Look for NP_DEFAULT_INI_FILENAME2 in NP_DEFAULT_INI_PATH[1-3] */ + if(!default_file){ + if(test_file(NP_DEFAULT_INI_PATH1,strlen(NP_DEFAULT_INI_PATH1),NP_DEFAULT_INI_FILENAME2,temp_file)==1 || + test_file(NP_DEFAULT_INI_PATH2,strlen(NP_DEFAULT_INI_PATH2),NP_DEFAULT_INI_FILENAME2,temp_file)==1 || + test_file(NP_DEFAULT_INI_PATH3,strlen(NP_DEFAULT_INI_PATH3),NP_DEFAULT_INI_FILENAME2,temp_file)==1) + default_file=strdup(temp_file); + } + + /* Return default_file or empty string (should return NULL if we want plugins + * to die there)... + */ + if(default_file) + return default_file; + return ""; +} + +/* put together len bytes from env and the filename and test for its + * existence. Returns 1 if found, 0 if not and -1 if test wasn't performed. + */ +static int test_file(const char* env, int len, const char* file, char* temp_file){ + struct stat sb; + + /* test if len + filelen + '/' + '\0' fits in temp_file */ + if((len+strlen(file)+2)>MAX_INPUT_BUFFER) return -1; + + strncpy(temp_file,env,len); + temp_file[len]='\0'; + strncat(temp_file,"/",len+1); + strncat(temp_file,file,len+strlen(file)+1); + + if(stat(temp_file, &sb) != -1) return 1; + return 0; +} +