diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/parse_ini.c | 76 | ||||
-rw-r--r-- | lib/parse_ini.h | 9 | ||||
-rw-r--r-- | lib/tests/test_ini.c | 25 | ||||
-rwxr-xr-x | lib/tests/test_ini.t | 6 |
4 files changed, 74 insertions, 42 deletions
diff --git a/lib/parse_ini.c b/lib/parse_ini.c index ef56be95..c915d795 100644 --- a/lib/parse_ini.c +++ b/lib/parse_ini.c | |||
@@ -42,9 +42,9 @@ typedef struct { | |||
42 | #define GOBBLE_TO(f, c, n) do { (c)=fgetc((f)); } while((c)!=EOF && (c)!=(n)) | 42 | #define GOBBLE_TO(f, c, n) do { (c)=fgetc((f)); } while((c)!=EOF && (c)!=(n)) |
43 | 43 | ||
44 | /* internal function that returns the constructed defaults options */ | 44 | /* internal function that returns the constructed defaults options */ |
45 | static char* read_defaults(FILE *f, const char *stanza); | 45 | static np_arg_list* read_defaults(FILE *f, const char *stanza); |
46 | /* internal function that converts a single line into options format */ | 46 | /* internal function that converts a single line into options format */ |
47 | static int add_option(FILE *f, char **optbuf, size_t *bufsize); | 47 | static int add_option(FILE *f, np_arg_list **optlst); |
48 | 48 | ||
49 | /* parse_locator decomposes a string of the form | 49 | /* parse_locator decomposes a string of the form |
50 | * [stanza][@filename] | 50 | * [stanza][@filename] |
@@ -76,9 +76,9 @@ static void parse_locator(const char *locator, const char *def_stanza, np_ini_in | |||
76 | } | 76 | } |
77 | 77 | ||
78 | /* this is the externally visible function used by plugins */ | 78 | /* this is the externally visible function used by plugins */ |
79 | char* np_get_defaults(const char *locator, const char *default_section){ | 79 | np_arg_list* np_get_defaults(const char *locator, const char *default_section){ |
80 | FILE *inifile=NULL; | 80 | FILE *inifile=NULL; |
81 | char *defaults=NULL; | 81 | np_arg_list *defaults=NULL; |
82 | np_ini_info i; | 82 | np_ini_info i; |
83 | 83 | ||
84 | parse_locator(locator, default_section, &i); | 84 | parse_locator(locator, default_section, &i); |
@@ -104,10 +104,10 @@ char* np_get_defaults(const char *locator, const char *default_section){ | |||
104 | * be extra careful about user-supplied input (i.e. avoiding possible | 104 | * be extra careful about user-supplied input (i.e. avoiding possible |
105 | * format string vulnerabilities, etc) | 105 | * format string vulnerabilities, etc) |
106 | */ | 106 | */ |
107 | static char* read_defaults(FILE *f, const char *stanza){ | 107 | static np_arg_list* read_defaults(FILE *f, const char *stanza){ |
108 | int c; | 108 | int c; |
109 | char *opts=NULL; | 109 | np_arg_list *opts=NULL; |
110 | size_t i, stanza_len, opts_buf_size=0; | 110 | size_t i, stanza_len; |
111 | enum { NOSTANZA, WRONGSTANZA, RIGHTSTANZA } stanzastate=NOSTANZA; | 111 | enum { NOSTANZA, WRONGSTANZA, RIGHTSTANZA } stanzastate=NOSTANZA; |
112 | 112 | ||
113 | stanza_len=strlen(stanza); | 113 | stanza_len=strlen(stanza); |
@@ -154,7 +154,7 @@ static char* read_defaults(FILE *f, const char *stanza){ | |||
154 | /* okay, this is where we start taking the config */ | 154 | /* okay, this is where we start taking the config */ |
155 | case RIGHTSTANZA: | 155 | case RIGHTSTANZA: |
156 | ungetc(c, f); | 156 | ungetc(c, f); |
157 | if(add_option(f, &opts, &opts_buf_size)){ | 157 | if(add_option(f, &opts)){ |
158 | die(STATE_UNKNOWN, _("Config file error")); | 158 | die(STATE_UNKNOWN, _("Config file error")); |
159 | } | 159 | } |
160 | break; | 160 | break; |
@@ -170,15 +170,14 @@ static char* read_defaults(FILE *f, const char *stanza){ | |||
170 | * ^option[[:space:]]*(=[[:space:]]*value)? | 170 | * ^option[[:space:]]*(=[[:space:]]*value)? |
171 | * and creates it as a cmdline argument | 171 | * and creates it as a cmdline argument |
172 | * --option[=value] | 172 | * --option[=value] |
173 | * appending it to the string pointed to by optbuf (which will | 173 | * appending it to the linked list optbuf. |
174 | * be dynamically grown if needed) | ||
175 | */ | 174 | */ |
176 | static int add_option(FILE *f, char **optbuf, size_t *bufsize){ | 175 | static int add_option(FILE *f, np_arg_list **optlst){ |
177 | char *newbuf=*optbuf; | 176 | np_arg_list *opttmp=*optlst, *optnew; |
178 | char *linebuf=NULL, *lineend=NULL, *optptr=NULL, *optend=NULL; | 177 | char *linebuf=NULL, *lineend=NULL, *optptr=NULL, *optend=NULL; |
179 | char *eqptr=NULL, *valptr=NULL, *spaceptr=NULL, *valend=NULL; | 178 | char *eqptr=NULL, *valptr=NULL, *spaceptr=NULL, *valend=NULL; |
180 | short done_reading=0, equals=0, value=0; | 179 | short done_reading=0, equals=0, value=0; |
181 | size_t cfg_len=0, read_sz=8, linebuf_sz=0, read_pos=0, bs=*bufsize; | 180 | size_t cfg_len=0, read_sz=8, linebuf_sz=0, read_pos=0; |
182 | size_t opt_len=0, val_len=0; | 181 | size_t opt_len=0, val_len=0; |
183 | 182 | ||
184 | /* read one line from the file */ | 183 | /* read one line from the file */ |
@@ -214,14 +213,13 @@ static int add_option(FILE *f, char **optbuf, size_t *bufsize){ | |||
214 | if(optptr==eqptr) die(STATE_UNKNOWN, _("Config file error\n")); | 213 | if(optptr==eqptr) die(STATE_UNKNOWN, _("Config file error\n")); |
215 | /* continue from '=' to start of value or EOL */ | 214 | /* continue from '=' to start of value or EOL */ |
216 | for(valptr=eqptr+1; valptr<lineend && isspace(*valptr); valptr++); | 215 | for(valptr=eqptr+1; valptr<lineend && isspace(*valptr); valptr++); |
217 | /* continue to the end of value, watching for trailing space/comments */ | 216 | /* continue to the end of value (FIXME: watching for trailing comments) */ |
218 | for(valend=valptr; valend<lineend; valend++){ | 217 | for(valend=valptr; valend<lineend; valend++) |
219 | if(isspace(*valend) && spaceptr==NULL) spaceptr=valend; | 218 | /* FIXME: N::P doesn't allow comments. Remove next line and parse_ini won't either */ |
220 | else if(*valend=='#') break; | 219 | if(*valend=='#') break; |
221 | else spaceptr=NULL; | ||
222 | } | ||
223 | if(spaceptr!=NULL) valend=spaceptr; | ||
224 | --valend; | 220 | --valend; |
221 | /* Finally trim off trailing spaces */ | ||
222 | for(valend; isspace(*valend); valend--); | ||
225 | /* calculate the length of "--foo" */ | 223 | /* calculate the length of "--foo" */ |
226 | opt_len=1+optend-optptr; | 224 | opt_len=1+optend-optptr; |
227 | cfg_len=2+(opt_len); | 225 | cfg_len=2+(opt_len); |
@@ -237,27 +235,31 @@ static int add_option(FILE *f, char **optbuf, size_t *bufsize){ | |||
237 | cfg_len+=1; | 235 | cfg_len+=1; |
238 | } | 236 | } |
239 | 237 | ||
240 | /* okay, now we have all the info we need, so we grow the default opts | 238 | /* okay, now we have all the info we need, so we create a new np_arg_list |
241 | * buffer if it's necessary, and put everything together. | 239 | * element and set the argument... |
242 | * (+2 is for a potential space and a null byte) | ||
243 | */ | 240 | */ |
244 | read_pos=(newbuf==NULL)?0:strlen(newbuf); | 241 | optnew=(np_arg_list *)malloc(sizeof(np_arg_list)); |
245 | if(newbuf==NULL || read_pos+cfg_len+2 >= bs){ | 242 | optnew->next=NULL; |
246 | bs=(bs>0)?(bs+cfg_len+2)<<1:cfg_len+1; | 243 | |
247 | newbuf=realloc(newbuf, bs); | 244 | read_pos=0; |
248 | if(newbuf==NULL) die(STATE_UNKNOWN, _("malloc() failed!\n")); | 245 | optnew->arg=(char *)malloc(cfg_len+1); |
249 | } | 246 | strncpy(&optnew->arg[read_pos], "--", 2); read_pos+=2; |
250 | if(read_pos>0) newbuf[read_pos++]=' '; | 247 | strncpy(&optnew->arg[read_pos], optptr, opt_len); read_pos+=opt_len; |
251 | strncpy(&newbuf[read_pos], "--", 2); read_pos+=2; | 248 | if(equals) optnew->arg[read_pos++]='='; |
252 | strncpy(&newbuf[read_pos], optptr, opt_len); read_pos+=opt_len; | ||
253 | if(equals) newbuf[read_pos++]='='; | ||
254 | if(value) { | 249 | if(value) { |
255 | strncpy(&newbuf[read_pos], valptr, val_len); read_pos+=val_len; | 250 | strncpy(&optnew->arg[read_pos], valptr, val_len); read_pos+=val_len; |
256 | } | 251 | } |
257 | newbuf[read_pos]='\0'; | 252 | optnew->arg[read_pos]='\0'; |
258 | 253 | ||
259 | *optbuf=newbuf; | 254 | /* ...and put that to the end of the list */ |
260 | *bufsize=bs; | 255 | if (*optlst==NULL) { |
256 | *optlst=optnew; | ||
257 | } else { | ||
258 | while (opttmp->next!=NULL) { | ||
259 | opttmp=opttmp->next; | ||
260 | } | ||
261 | opttmp->next = optnew; | ||
262 | } | ||
261 | 263 | ||
262 | free(linebuf); | 264 | free(linebuf); |
263 | return 0; | 265 | return 0; |
diff --git a/lib/parse_ini.h b/lib/parse_ini.h index 1c28c7de..fea745c5 100644 --- a/lib/parse_ini.h +++ b/lib/parse_ini.h | |||
@@ -6,6 +6,13 @@ | |||
6 | * configuration files. | 6 | * configuration files. |
7 | */ | 7 | */ |
8 | 8 | ||
9 | /* np_arg_list is a linked list of arguments passed between the ini | ||
10 | * parser and the argument parser to construct the final array */ | ||
11 | typedef struct np_arg_el { | ||
12 | char *arg; | ||
13 | struct np_arg_el *next; | ||
14 | } np_arg_list; | ||
15 | |||
9 | /* NP_DEFAULT_INI_PATH: compile-time default location for ini file */ | 16 | /* NP_DEFAULT_INI_PATH: compile-time default location for ini file */ |
10 | #ifndef NP_DEFAULT_INI_PATH | 17 | #ifndef NP_DEFAULT_INI_PATH |
11 | # define NP_DEFAULT_INI_PATH "/etc/nagios-plugins/plugins.ini" | 18 | # define NP_DEFAULT_INI_PATH "/etc/nagios-plugins/plugins.ini" |
@@ -14,6 +21,6 @@ | |||
14 | /* np_load_defaults: load the default configuration (if present) for | 21 | /* np_load_defaults: load the default configuration (if present) for |
15 | * a plugin from the ini file | 22 | * a plugin from the ini file |
16 | */ | 23 | */ |
17 | char* np_get_defaults(const char *locator, const char *default_section); | 24 | np_arg_list* np_get_defaults(const char *locator, const char *default_section); |
18 | 25 | ||
19 | #endif /* _PARSE_INI_H_ */ | 26 | #endif /* _PARSE_INI_H_ */ |
diff --git a/lib/tests/test_ini.c b/lib/tests/test_ini.c index 302a2e56..b02d1452 100644 --- a/lib/tests/test_ini.c +++ b/lib/tests/test_ini.c | |||
@@ -19,6 +19,7 @@ | |||
19 | 19 | ||
20 | #include "common.h" | 20 | #include "common.h" |
21 | #include "parse_ini.h" | 21 | #include "parse_ini.h" |
22 | #include "utils_base.h" | ||
22 | 23 | ||
23 | #include "tap.h" | 24 | #include "tap.h" |
24 | 25 | ||
@@ -29,6 +30,22 @@ void my_free(char *string) { | |||
29 | } | 30 | } |
30 | } | 31 | } |
31 | 32 | ||
33 | char* | ||
34 | list2str(np_arg_list *optlst) | ||
35 | { | ||
36 | char *optstr=NULL; | ||
37 | |||
38 | /* Put everything as a space-separated string */ | ||
39 | while (optlst) { | ||
40 | asprintf(&optstr, "%s%s ", optstr?optstr:"", optlst->arg); | ||
41 | optlst=optlst->next; | ||
42 | } | ||
43 | /* Strip last whitespace */ | ||
44 | optstr[strlen(optstr)-1]='\0'; | ||
45 | |||
46 | return optstr; | ||
47 | } | ||
48 | |||
32 | int | 49 | int |
33 | main (int argc, char **argv) | 50 | main (int argc, char **argv) |
34 | { | 51 | { |
@@ -36,11 +53,11 @@ main (int argc, char **argv) | |||
36 | 53 | ||
37 | plan_tests(4); | 54 | plan_tests(4); |
38 | 55 | ||
39 | optstr=np_get_defaults("section@./config-tiny.ini", "check_disk"); | 56 | optstr=list2str(np_get_defaults("section@./config-tiny.ini", "check_disk")); |
40 | ok( !strcmp(optstr, "--one=two --Foo=Bar --this=Your Mother! --blank="), "config-tiny.ini's section as expected"); | 57 | ok( !strcmp(optstr, "--one=two --Foo=Bar --this=Your Mother! --blank="), "config-tiny.ini's section as expected"); |
41 | my_free(optstr); | 58 | my_free(optstr); |
42 | 59 | ||
43 | optstr=np_get_defaults("@./config-tiny.ini", "section"); | 60 | optstr=list2str(np_get_defaults("@./config-tiny.ini", "section")); |
44 | ok( !strcmp(optstr, "--one=two --Foo=Bar --this=Your Mother! --blank="), "Used default section name, without specific"); | 61 | ok( !strcmp(optstr, "--one=two --Foo=Bar --this=Your Mother! --blank="), "Used default section name, without specific"); |
45 | my_free(optstr); | 62 | my_free(optstr); |
46 | 63 | ||
@@ -51,7 +68,7 @@ main (int argc, char **argv) | |||
51 | my_free(optstr); | 68 | my_free(optstr); |
52 | */ | 69 | */ |
53 | 70 | ||
54 | optstr=np_get_defaults("Section Two@./config-tiny.ini", "check_disk"); | 71 | optstr=list2str(np_get_defaults("Section Two@./config-tiny.ini", "check_disk")); |
55 | ok( !strcmp(optstr, "--something else=blah --remove=whitespace"), "config-tiny.ini's Section Two as expected"); | 72 | ok( !strcmp(optstr, "--something else=blah --remove=whitespace"), "config-tiny.ini's Section Two as expected"); |
56 | my_free(optstr); | 73 | my_free(optstr); |
57 | 74 | ||
@@ -70,7 +87,7 @@ main (int argc, char **argv) | |||
70 | my_free(optstr); | 87 | my_free(optstr); |
71 | */ | 88 | */ |
72 | 89 | ||
73 | optstr=np_get_defaults("check_mysql@./plugin.ini", "check_disk"); | 90 | optstr=list2str(np_get_defaults("check_mysql@./plugin.ini", "check_disk")); |
74 | ok( !strcmp(optstr, "--username=operator --password=secret"), "plugin.ini's check_mysql as expected"); | 91 | ok( !strcmp(optstr, "--username=operator --password=secret"), "plugin.ini's check_mysql as expected"); |
75 | my_free(optstr); | 92 | my_free(optstr); |
76 | 93 | ||
diff --git a/lib/tests/test_ini.t b/lib/tests/test_ini.t new file mode 100755 index 00000000..b130a01b --- /dev/null +++ b/lib/tests/test_ini.t | |||
@@ -0,0 +1,6 @@ | |||
1 | #!/usr/bin/perl | ||
2 | use Test::More; | ||
3 | if (! -e "./test_ini") { | ||
4 | plan skip_all => "./test_ini not compiled - please install tap library to test"; | ||
5 | } | ||
6 | exec "./test_ini"; | ||