From 6004d95868fcd9badbc0f026980a4a3597eb22db Mon Sep 17 00:00:00 2001 From: Thomas Guyot-Sionnest Date: Sat, 15 Mar 2008 04:51:45 +0000 Subject: [PATCH] This commit consist of two changes: 1. Make np_get_defaults return a linked list instead of a string. It will then be easy to convert the linked list back to an argument array. 2. Fix tests 3-4 of test_ini.c. A test_ini.t was added too. parse_ini and test_ini aren't included yet in the build makefiles. git-svn-id: https://nagiosplug.svn.sourceforge.net/svnroot/nagiosplug/nagiosplug/trunk@1945 f882894a-f735-0410-b71e-b25c423dba1c --- lib/parse_ini.c | 76 +++++++++++++++++++++++--------------------- lib/parse_ini.h | 9 +++++- lib/tests/test_ini.c | 25 ++++++++++++--- lib/tests/test_ini.t | 6 ++++ 4 files changed, 74 insertions(+), 42 deletions(-) create mode 100755 lib/tests/test_ini.t diff --git a/lib/parse_ini.c b/lib/parse_ini.c index ef56be9..c915d79 100644 --- a/lib/parse_ini.c +++ b/lib/parse_ini.c @@ -42,9 +42,9 @@ 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 np_arg_list* read_defaults(FILE *f, const char *stanza); /* 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); /* parse_locator decomposes a string of the form * [stanza][@filename] @@ -76,9 +76,9 @@ static void parse_locator(const char *locator, const char *def_stanza, np_ini_in } /* this is the externally visible function used by plugins */ -char* np_get_defaults(const char *locator, const char *default_section){ +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); @@ -104,10 +104,10 @@ 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){ +static np_arg_list* read_defaults(FILE *f, const char *stanza){ int c; - char *opts=NULL; - size_t i, stanza_len, opts_buf_size=0; + np_arg_list *opts=NULL; + size_t i, stanza_len; enum { NOSTANZA, WRONGSTANZA, RIGHTSTANZA } stanzastate=NOSTANZA; stanza_len=strlen(stanza); @@ -154,7 +154,7 @@ static char* read_defaults(FILE *f, const char *stanza){ /* okay, this is where we start taking the config */ case RIGHTSTANZA: ungetc(c, f); - if(add_option(f, &opts, &opts_buf_size)){ + if(add_option(f, &opts)){ die(STATE_UNKNOWN, _("Config file error")); } break; @@ -170,15 +170,14 @@ static char* read_defaults(FILE *f, const char *stanza){ * ^option[[:space:]]*(=[[:space:]]*value)? * and creates it as a cmdline argument * --option[=value] - * appending it to the string pointed to by optbuf (which will - * be dynamically grown if needed) + * appending it to the linked list optbuf. */ -static int add_option(FILE *f, char **optbuf, size_t *bufsize){ - char *newbuf=*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, bs=*bufsize; + 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 */ @@ -214,14 +213,13 @@ static int add_option(FILE *f, char **optbuf, size_t *bufsize){ if(optptr==eqptr) die(STATE_UNKNOWN, _("Config file error\n")); /* continue from '=' to start of value or EOL */ for(valptr=eqptr+1; valptr= 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")); - } - 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++]='='; + optnew=(np_arg_list *)malloc(sizeof(np_arg_list)); + optnew->next=NULL; + + read_pos=0; + optnew->arg=(char *)malloc(cfg_len+1); + strncpy(&optnew->arg[read_pos], "--", 2); read_pos+=2; + strncpy(&optnew->arg[read_pos], optptr, opt_len); read_pos+=opt_len; + if(equals) optnew->arg[read_pos++]='='; if(value) { - strncpy(&newbuf[read_pos], valptr, val_len); read_pos+=val_len; + 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; diff --git a/lib/parse_ini.h b/lib/parse_ini.h index 1c28c7d..fea745c 100644 --- a/lib/parse_ini.h +++ b/lib/parse_ini.h @@ -6,6 +6,13 @@ * configuration files. */ +/* np_arg_list is a linked list of arguments passed between the ini + * parser and the argument parser to construct the final array */ +typedef struct np_arg_el { + char *arg; + struct np_arg_el *next; +} np_arg_list; + /* NP_DEFAULT_INI_PATH: compile-time default location for ini file */ #ifndef NP_DEFAULT_INI_PATH # define NP_DEFAULT_INI_PATH "/etc/nagios-plugins/plugins.ini" @@ -14,6 +21,6 @@ /* np_load_defaults: load the default configuration (if present) for * a plugin from the ini file */ -char* np_get_defaults(const char *locator, const char *default_section); +np_arg_list* np_get_defaults(const char *locator, const char *default_section); #endif /* _PARSE_INI_H_ */ diff --git a/lib/tests/test_ini.c b/lib/tests/test_ini.c index 302a2e5..b02d145 100644 --- a/lib/tests/test_ini.c +++ b/lib/tests/test_ini.c @@ -19,6 +19,7 @@ #include "common.h" #include "parse_ini.h" +#include "utils_base.h" #include "tap.h" @@ -29,6 +30,22 @@ void my_free(char *string) { } } +char* +list2str(np_arg_list *optlst) +{ + char *optstr=NULL; + + /* Put everything as a space-separated string */ + while (optlst) { + asprintf(&optstr, "%s%s ", optstr?optstr:"", optlst->arg); + optlst=optlst->next; + } + /* Strip last whitespace */ + optstr[strlen(optstr)-1]='\0'; + + return optstr; +} + int main (int argc, char **argv) { @@ -36,11 +53,11 @@ main (int argc, char **argv) plan_tests(4); - optstr=np_get_defaults("section@./config-tiny.ini", "check_disk"); + optstr=list2str(np_get_defaults("section@./config-tiny.ini", "check_disk")); ok( !strcmp(optstr, "--one=two --Foo=Bar --this=Your Mother! --blank="), "config-tiny.ini's section as expected"); my_free(optstr); - optstr=np_get_defaults("@./config-tiny.ini", "section"); + optstr=list2str(np_get_defaults("@./config-tiny.ini", "section")); ok( !strcmp(optstr, "--one=two --Foo=Bar --this=Your Mother! --blank="), "Used default section name, without specific"); my_free(optstr); @@ -51,7 +68,7 @@ main (int argc, char **argv) my_free(optstr); */ - optstr=np_get_defaults("Section Two@./config-tiny.ini", "check_disk"); + optstr=list2str(np_get_defaults("Section Two@./config-tiny.ini", "check_disk")); ok( !strcmp(optstr, "--something else=blah --remove=whitespace"), "config-tiny.ini's Section Two as expected"); my_free(optstr); @@ -70,7 +87,7 @@ main (int argc, char **argv) my_free(optstr); */ - optstr=np_get_defaults("check_mysql@./plugin.ini", "check_disk"); + optstr=list2str(np_get_defaults("check_mysql@./plugin.ini", "check_disk")); ok( !strcmp(optstr, "--username=operator --password=secret"), "plugin.ini's check_mysql as expected"); my_free(optstr); diff --git a/lib/tests/test_ini.t b/lib/tests/test_ini.t new file mode 100755 index 0000000..b130a01 --- /dev/null +++ b/lib/tests/test_ini.t @@ -0,0 +1,6 @@ +#!/usr/bin/perl +use Test::More; +if (! -e "./test_ini") { + plan skip_all => "./test_ini not compiled - please install tap library to test"; +} +exec "./test_ini"; -- 2.30.2