X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=lib%2Fparse_ini.c;h=004396fe803378c18c501bb17743364b8cb6508b;hb=6b782ebfd4832c1fe621556bcf894162b8caa8aa;hp=f22a14764565a3e6f96c298833292a96a85e4e12;hpb=60b672d49687b71400275bab010fe779a71c9345;p=nagiosplug.git diff --git a/lib/parse_ini.c b/lib/parse_ini.c index f22a147..004396f 100644 --- a/lib/parse_ini.c +++ b/lib/parse_ini.c @@ -1,36 +1,37 @@ /***************************************************************************** -* +* * Nagios-plugins parse_ini library * * License: GPL -* Copyright (c) 2007 nagios-plugins team -* -* Last Modified: $Date$ -* -* This file is part of Nagios-plugins. +* Copyright (c) 2007 Nagios Plugins Development Team * -* Nagios-plugins is free software: you can redistribute it and/or modify +* 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 * (at your option) any later version. * -* Nagios-plugins is distributed in the hope that it will be useful, +* This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License -* along with Nagios-plugins. If not, see . +* 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) */ @@ -43,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 char* 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, char **optbuf, size_t *bufsize); +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)); @@ -66,37 +74,42 @@ 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 */ -char* np_get_defaults(const char *locator, const char *default_section){ +/* 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; - char *defaults=NULL; + np_arg_list *defaults=NULL; np_ini_info i; parse_locator(locator, default_section, &i); /* 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; + 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); + if(inifile!=stdin) fclose(inifile); } free(i.stanza); - return defaults; + return defaults; } /* read_defaults is where the meat of the parsing takes place. @@ -105,10 +118,9 @@ char* 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 char* read_defaults(FILE *f, const char *stanza){ - int c; - char *opts=NULL; - size_t i, stanza_len, opts_buf_size=0; +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; stanza_len=strlen(stanza); @@ -119,6 +131,7 @@ static char* 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; @@ -127,15 +140,19 @@ static char* read_defaults(FILE *f, const char *stanza){ stanzastate=WRONGSTANZA; for(i=0; i= bs){ - bs=(bs>0)?(bs+cfg_len+2)<<1:cfg_len+1; - newbuf=realloc(newbuf, bs); - if(newbuf==NULL) die(STATE_UNKNOWN, _("malloc() failed!\n")); + optnew=(np_arg_list *)malloc(sizeof(np_arg_list)); + optnew->next=NULL; + + read_pos=0; + optnew->arg=(char *)malloc(cfg_len+1); + /* 1-character params needs only one dash */ + if(opt_len==1) { + strncpy(&optnew->arg[read_pos], "-", 1); + read_pos+=1; + } else { + strncpy(&optnew->arg[read_pos], "--", 2); + read_pos+=2; } - if(read_pos>0) newbuf[read_pos++]=' '; - strncpy(&newbuf[read_pos], "--", 2); read_pos+=2; - strncpy(&newbuf[read_pos], optptr, opt_len); read_pos+=opt_len; - if(equals) newbuf[read_pos++]='='; + strncpy(&optnew->arg[read_pos], optptr, opt_len); read_pos+=opt_len; if(value) { - strncpy(&newbuf[read_pos], valptr, val_len); read_pos+=val_len; + optnew->arg[read_pos++]='='; + strncpy(&optnew->arg[read_pos], valptr, val_len); read_pos+=val_len; } - newbuf[read_pos]='\0'; + optnew->arg[read_pos]='\0'; - *optbuf=newbuf; - *bufsize=bs; + /* ...and put that to the end of the list */ + if(*optlst==NULL) { + *optlst=optnew; + } else { + while(opttmp->next!=NULL) { + opttmp=opttmp->next; + } + opttmp->next = optnew; + } free(linebuf); 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; +} +