summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorGreg Cox <gcox@fibbsbozza.local>2014-07-29 22:52:12 (GMT)
committerGreg Cox <gcox@fibbsbozza.local>2014-07-29 22:52:12 (GMT)
commit4273dd06ff3e52094d6b267d00e8c51dd74de364 (patch)
tree425d127da5dbec7013999ed01b469fc3f72992d9 /lib
parentf05e7016320f4671fbf86cc5abc277efea20f79e (diff)
parent6f3d5825b203b75aef8d68bf0d117e7a1a4c0616 (diff)
downloadmonitoring-plugins-4273dd06ff3e52094d6b267d00e8c51dd74de364.tar.gz
Merge remote-tracking branch 'upstream/master'refs/pull/1257/head
Conflicts: plugins/netutils.c
Diffstat (limited to 'lib')
-rw-r--r--lib/parse_ini.c492
-rw-r--r--lib/parse_ini.h42
-rw-r--r--lib/tests/test_utils.c8
-rw-r--r--lib/utils_base.c17
-rw-r--r--lib/utils_base.h3
-rw-r--r--lib/utils_cmd.c3
6 files changed, 274 insertions, 291 deletions
diff --git a/lib/parse_ini.c b/lib/parse_ini.c
index 76953e9..25abc89 100644
--- a/lib/parse_ini.c
+++ b/lib/parse_ini.c
@@ -22,16 +22,15 @@
22*****************************************************************************/ 22*****************************************************************************/
23 23
24#include "common.h" 24#include "common.h"
25#include "idpriv.h"
25#include "utils_base.h" 26#include "utils_base.h"
26#include "parse_ini.h" 27#include "parse_ini.h"
27#include <ctype.h>
28 28
29#include <ctype.h>
29#include <sys/types.h> 30#include <sys/types.h>
30#include <sys/stat.h> 31#include <sys/stat.h>
31#include <unistd.h> 32#include <unistd.h>
32 33
33/* TODO: die like N::P if config file is not found */
34
35/* np_ini_info contains the result of parsing a "locator" in the format 34/* np_ini_info contains the result of parsing a "locator" in the format
36 * [stanza_name][@config_filename] (check_foo@/etc/foo.ini, for example) 35 * [stanza_name][@config_filename] (check_foo@/etc/foo.ini, for example)
37 */ 36 */
@@ -40,254 +39,314 @@ typedef struct {
40 char *stanza; 39 char *stanza;
41} np_ini_info; 40} np_ini_info;
42 41
42static char *default_ini_file_names[] = {
43 "monitoring-plugins.ini",
44 "plugins.ini",
45 "nagios-plugins.ini",
46 NULL
47};
48
49static char *default_ini_path_names[] = {
50 "/usr/local/etc/monitoring-plugins/monitoring-plugins.ini",
51 "/usr/local/etc/monitoring-plugins.ini",
52 "/etc/monitoring-plugins/monitoring-plugins.ini",
53 "/etc/monitoring-plugins.ini",
54 /* deprecated path names (for backward compatibility): */
55 "/etc/nagios/plugins.ini",
56 "/usr/local/nagios/etc/plugins.ini",
57 "/usr/local/etc/nagios/plugins.ini",
58 "/etc/opt/nagios/plugins.ini",
59 "/etc/nagios-plugins.ini",
60 "/usr/local/etc/nagios-plugins.ini",
61 "/etc/opt/nagios-plugins.ini",
62 NULL
63};
64
43/* eat all characters from a FILE pointer until n is encountered */ 65/* eat all characters from a FILE pointer until n is encountered */
44#define GOBBLE_TO(f, c, n) do { (c)=fgetc((f)); } while((c)!=EOF && (c)!=(n)) 66#define GOBBLE_TO(f, c, n) do { (c)=fgetc((f)); } while((c)!=EOF && (c)!=(n))
45 67
46/* internal function that returns the constructed defaults options */ 68/* internal function that returns the constructed defaults options */
47static int read_defaults(FILE *f, const char *stanza, np_arg_list **opts); 69static int read_defaults(FILE *f, const char *stanza, np_arg_list **opts);
70
48/* internal function that converts a single line into options format */ 71/* internal function that converts a single line into options format */
49static int add_option(FILE *f, np_arg_list **optlst); 72static int add_option(FILE *f, np_arg_list **optlst);
50/* internal function to find default file */
51static char* default_file(void);
52/* internal function to test files access */
53static int test_file(const char* env, int len, const char* file, char* temp_file);
54 73
55/* parse_locator decomposes a string of the form 74/* internal functions to find default file */
75static char *default_file(void);
76static char *default_file_in_path(void);
77
78/*
79 * Parse_locator decomposes a string of the form
56 * [stanza][@filename] 80 * [stanza][@filename]
57 * into its seperate parts 81 * into its seperate parts.
58 */ 82 */
59static void parse_locator(const char *locator, const char *def_stanza, np_ini_info *i){ 83static void
60 size_t locator_len=0, stanza_len=0; 84parse_locator(const char *locator, const char *def_stanza, np_ini_info *i)
85{
86 size_t locator_len = 0, stanza_len = 0;
61 87
62 /* if locator is NULL we'll use default values */ 88 /* if locator is NULL we'll use default values */
63 if(locator){ 89 if (locator != NULL) {
64 locator_len=strlen(locator); 90 locator_len = strlen(locator);
65 stanza_len=strcspn(locator, "@"); 91 stanza_len = strcspn(locator, "@");
66 } 92 }
67 /* if a non-default stanza is provided */ 93 /* if a non-default stanza is provided */
68 if(stanza_len>0){ 94 if (stanza_len > 0) {
69 i->stanza=(char*)malloc(sizeof(char)*(stanza_len+1)); 95 i->stanza = malloc(sizeof(char) * (stanza_len + 1));
70 strncpy(i->stanza, locator, stanza_len); 96 strncpy(i->stanza, locator, stanza_len);
71 i->stanza[stanza_len]='\0'; 97 i->stanza[stanza_len] = '\0';
72 } else { /* otherwise we use the default stanza */ 98 } else /* otherwise we use the default stanza */
73 i->stanza=strdup(def_stanza); 99 i->stanza = strdup(def_stanza);
74 }
75 /* if there is no @file part */
76 if(stanza_len==locator_len){
77 i->file=default_file();
78 if(strcmp(i->file, "") == 0){
79 die(STATE_UNKNOWN, _("Cannot find '%s' or '%s' in any standard location.\n"), NP_DEFAULT_INI_FILENAME1, NP_DEFAULT_INI_FILENAME2);
80 }
81 } else {
82 i->file=strdup(&(locator[stanza_len+1]));
83 }
84 100
85 if(i->file==NULL || i->stanza==NULL){ 101 if (i->stanza == NULL)
86 die(STATE_UNKNOWN, _("malloc() failed!\n")); 102 die(STATE_UNKNOWN, _("malloc() failed!\n"));
87 } 103
104 /* check whether there's an @file part */
105 i->file = stanza_len == locator_len
106 ? default_file()
107 : strdup(&(locator[stanza_len + 1]));
108 if (i->file == NULL || i->file[0] == '\0')
109 die(STATE_UNKNOWN,
110 _("Cannot find config file in any standard location.\n"));
88} 111}
89 112
90/* this is the externally visible function used by extra_opts */ 113/*
91np_arg_list* np_get_defaults(const char *locator, const char *default_section){ 114 * This is the externally visible function used by extra_opts.
92 FILE *inifile=NULL; 115 */
93 np_arg_list *defaults=NULL; 116np_arg_list *
117np_get_defaults(const char *locator, const char *default_section)
118{
119 FILE *inifile = NULL;
120 np_arg_list *defaults = NULL;
94 np_ini_info i; 121 np_ini_info i;
122 int is_suid_plugin = mp_suid();
95 123
96 parse_locator(locator, default_section, &i); 124 if (is_suid_plugin && idpriv_temp_drop() == -1)
97 /* if a file was specified or if we're using the default file */ 125 die(STATE_UNKNOWN, _("Cannot drop privileges: %s\n"),
98 if(i.file != NULL && strlen(i.file) > 0){ 126 strerror(errno));
99 if(strcmp(i.file, "-")==0){
100 inifile=stdin;
101 } else {
102 inifile=fopen(i.file, "r");
103 }
104 if(inifile==NULL) die(STATE_UNKNOWN, "%s\n", _("Can't read config file"));
105 if(read_defaults(inifile, i.stanza, &defaults)==FALSE)
106 die(STATE_UNKNOWN, _("Invalid section '%s' in config file '%s'\n"), i.stanza, i.file);
107 127
108 free(i.file); 128 parse_locator(locator, default_section, &i);
109 if(inifile!=stdin) fclose(inifile); 129 inifile = strcmp(i.file, "-") == 0 ? stdin : fopen(i.file, "r");
110 } 130
131 if (inifile == NULL)
132 die(STATE_UNKNOWN, _("Can't read config file: %s\n"),
133 strerror(errno));
134 if (read_defaults(inifile, i.stanza, &defaults) == FALSE)
135 die(STATE_UNKNOWN,
136 _("Invalid section '%s' in config file '%s'\n"), i.stanza,
137 i.file);
138
139 free(i.file);
140 if (inifile != stdin)
141 fclose(inifile);
111 free(i.stanza); 142 free(i.stanza);
143 if (is_suid_plugin && idpriv_temp_restore() == -1)
144 die(STATE_UNKNOWN, _("Cannot restore privileges: %s\n"),
145 strerror(errno));
146
112 return defaults; 147 return defaults;
113} 148}
114 149
115/* read_defaults is where the meat of the parsing takes place. 150/*
151 * The read_defaults() function is where the meat of the parsing takes place.
116 * 152 *
117 * note that this may be called by a setuid binary, so we need to 153 * Note that this may be called by a setuid binary, so we need to
118 * be extra careful about user-supplied input (i.e. avoiding possible 154 * be extra careful about user-supplied input (i.e. avoiding possible
119 * format string vulnerabilities, etc) 155 * format string vulnerabilities, etc).
120 */ 156 */
121static int read_defaults(FILE *f, const char *stanza, np_arg_list **opts){ 157static int
122 int c, status=FALSE; 158read_defaults(FILE *f, const char *stanza, np_arg_list **opts)
159{
160 int c, status = FALSE;
123 size_t i, stanza_len; 161 size_t i, stanza_len;
124 enum { NOSTANZA, WRONGSTANZA, RIGHTSTANZA } stanzastate=NOSTANZA; 162 enum { NOSTANZA, WRONGSTANZA, RIGHTSTANZA } stanzastate = NOSTANZA;
125 163
126 stanza_len=strlen(stanza); 164 stanza_len = strlen(stanza);
127 165
128 /* our little stanza-parsing state machine. */ 166 /* our little stanza-parsing state machine */
129 while((c=fgetc(f))!=EOF){ 167 while ((c = fgetc(f)) != EOF) {
130 /* gobble up leading whitespace */ 168 /* gobble up leading whitespace */
131 if(isspace(c)) continue; 169 if (isspace(c))
132 switch(c){ 170 continue;
171 switch (c) {
133 /* globble up coment lines */ 172 /* globble up coment lines */
134 case ';': 173 case ';':
135 case '#': 174 case '#':
136 GOBBLE_TO(f, c, '\n'); 175 GOBBLE_TO(f, c, '\n');
137 break; 176 break;
138 /* start of a stanza. check to see if it matches */ 177 /* start of a stanza, check to see if it matches */
139 case '[': 178 case '[':
140 stanzastate=WRONGSTANZA; 179 stanzastate = WRONGSTANZA;
141 for(i=0; i<stanza_len; i++){ 180 for (i = 0; i < stanza_len; i++) {
142 c=fgetc(f); 181 c = fgetc(f);
143 /* Strip leading whitespace */ 182 /* strip leading whitespace */
144 if(i==0) for(c; isspace(c); c=fgetc(f)); 183 if (i == 0)
145 /* nope, read to the end of the line */ 184 for (; isspace(c); c = fgetc(f))
146 if(c!=stanza[i]) { 185 continue;
147 GOBBLE_TO(f, c, '\n'); 186 /* nope, read to the end of the line */
148 break; 187 if (c != stanza[i]) {
149 } 188 GOBBLE_TO(f, c, '\n');
150 } 189 break;
151 /* if it matched up to here and the next char is ']'... */
152 if(i==stanza_len){
153 c=fgetc(f);
154 /* Strip trailing whitespace */
155 for(c; isspace(c); c=fgetc(f));
156 if(c==']') stanzastate=RIGHTSTANZA;
157 } 190 }
158 break; 191 }
192 /* if it matched up to here and the next char is ']'... */
193 if (i == stanza_len) {
194 c = fgetc(f);
195 /* strip trailing whitespace */
196 for (; isspace(c); c = fgetc(f))
197 continue;
198 if (c == ']')
199 stanzastate = RIGHTSTANZA;
200 }
201 break;
159 /* otherwise, we're in the body of a stanza or a parse error */ 202 /* otherwise, we're in the body of a stanza or a parse error */
160 default: 203 default:
161 switch(stanzastate){ 204 switch (stanzastate) {
162 /* we never found the start of the first stanza, so 205 /* we never found the start of the first stanza, so
163 * we're dealing with a config error 206 * we're dealing with a config error
164 */ 207 */
165 case NOSTANZA: 208 case NOSTANZA:
166 die(STATE_UNKNOWN, "%s\n", _("Config file error")); 209 die(STATE_UNKNOWN, "%s\n",
167 break; 210 _("Config file error"));
168 /* we're in a stanza, but for a different plugin */ 211 /* we're in a stanza, but for a different plugin */
169 case WRONGSTANZA: 212 case WRONGSTANZA:
170 GOBBLE_TO(f, c, '\n'); 213 GOBBLE_TO(f, c, '\n');
171 break; 214 break;
172 /* okay, this is where we start taking the config */ 215 /* okay, this is where we start taking the config */
173 case RIGHTSTANZA: 216 case RIGHTSTANZA:
174 ungetc(c, f); 217 ungetc(c, f);
175 if(add_option(f, opts)){ 218 if (add_option(f, opts)) {
176 die(STATE_UNKNOWN, "%s\n", _("Config file error")); 219 die(STATE_UNKNOWN, "%s\n",
177 } 220 _("Config file error"));
178 status=TRUE;
179 break;
180 } 221 }
222 status = TRUE;
181 break; 223 break;
224 }
225 break;
182 } 226 }
183 } 227 }
184 return status; 228 return status;
185} 229}
186 230
187/* 231/*
188 * read one line of input in the format 232 * Read one line of input in the format
189 * ^option[[:space:]]*(=[[:space:]]*value)? 233 * ^option[[:space:]]*(=[[:space:]]*value)?
190 * and creates it as a cmdline argument 234 * and create it as a cmdline argument
191 * --option[=value] 235 * --option[=value]
192 * appending it to the linked list optbuf. 236 * appending it to the linked list optbuf.
193 */ 237 */
194static int add_option(FILE *f, np_arg_list **optlst){ 238static int
195 np_arg_list *opttmp=*optlst, *optnew; 239add_option(FILE *f, np_arg_list **optlst)
196 char *linebuf=NULL, *lineend=NULL, *optptr=NULL, *optend=NULL; 240{
197 char *eqptr=NULL, *valptr=NULL, *spaceptr=NULL, *valend=NULL; 241 np_arg_list *opttmp = *optlst, *optnew;
198 short done_reading=0, equals=0, value=0; 242 char *linebuf = NULL, *lineend = NULL, *optptr = NULL, *optend = NULL;
199 size_t cfg_len=0, read_sz=8, linebuf_sz=0, read_pos=0; 243 char *eqptr = NULL, *valptr = NULL, *valend = NULL;
200 size_t opt_len=0, val_len=0; 244 short done_reading = 0, equals = 0, value = 0;
245 size_t cfg_len = 0, read_sz = 8, linebuf_sz = 0, read_pos = 0;
246 size_t opt_len = 0, val_len = 0;
201 247
202 /* read one line from the file */ 248 /* read one line from the file */
203 while(!done_reading){ 249 while (!done_reading) {
204 /* grow if necessary */ 250 /* grow if necessary */
205 if(linebuf==NULL || read_pos+read_sz >= linebuf_sz){ 251 if (linebuf == NULL || read_pos + read_sz >= linebuf_sz) {
206 linebuf_sz=(linebuf_sz>0)?linebuf_sz<<1:read_sz; 252 linebuf_sz = linebuf_sz > 0 ? linebuf_sz << 1 : read_sz;
207 linebuf=realloc(linebuf, linebuf_sz); 253 linebuf = realloc(linebuf, linebuf_sz);
208 if(linebuf==NULL) die(STATE_UNKNOWN, _("malloc() failed!\n")); 254 if (linebuf == NULL)
255 die(STATE_UNKNOWN, _("malloc() failed!\n"));
209 } 256 }
210 if(fgets(&linebuf[read_pos], read_sz, f)==NULL) done_reading=1; 257 if (fgets(&linebuf[read_pos], (int)read_sz, f) == NULL)
258 done_reading = 1;
211 else { 259 else {
212 read_pos=strlen(linebuf); 260 read_pos = strlen(linebuf);
213 if(linebuf[read_pos-1]=='\n') { 261 if (linebuf[read_pos - 1] == '\n') {
214 linebuf[--read_pos]='\0'; 262 linebuf[--read_pos] = '\0';
215 done_reading=1; 263 done_reading = 1;
216 } 264 }
217 } 265 }
218 } 266 }
219 lineend=&linebuf[read_pos]; 267 lineend = &linebuf[read_pos];
220 /* all that to read one line. isn't C fun? :) now comes the parsing :/ */ 268 /* all that to read one line, isn't C fun? :) now comes the parsing :/ */
221 269
222 /* skip leading whitespace */ 270 /* skip leading whitespace */
223 for(optptr=linebuf; optptr<lineend && isspace(*optptr); optptr++); 271 for (optptr = linebuf; optptr < lineend && isspace(*optptr); optptr++)
272 continue;
224 /* continue to '=' or EOL, watching for spaces that might precede it */ 273 /* continue to '=' or EOL, watching for spaces that might precede it */
225 for(eqptr=optptr; eqptr<lineend && *eqptr!='='; eqptr++){ 274 for (eqptr = optptr; eqptr < lineend && *eqptr != '='; eqptr++) {
226 if(isspace(*eqptr) && optend==NULL) optend=eqptr; 275 if (isspace(*eqptr) && optend == NULL)
227 else optend=NULL; 276 optend = eqptr;
277 else
278 optend = NULL;
228 } 279 }
229 if(optend==NULL) optend=eqptr; 280 if (optend == NULL)
281 optend = eqptr;
230 --optend; 282 --optend;
231 /* ^[[:space:]]*=foo is a syntax error */ 283 /* ^[[:space:]]*=foo is a syntax error */
232 if(optptr==eqptr) die(STATE_UNKNOWN, "%s\n", _("Config file error")); 284 if (optptr == eqptr)
285 die(STATE_UNKNOWN, "%s\n", _("Config file error"));
233 /* continue from '=' to start of value or EOL */ 286 /* continue from '=' to start of value or EOL */
234 for(valptr=eqptr+1; valptr<lineend && isspace(*valptr); valptr++); 287 for (valptr = eqptr + 1; valptr < lineend && isspace(*valptr);
288 valptr++)
289 continue;
235 /* continue to the end of value */ 290 /* continue to the end of value */
236 for(valend=valptr; valend<lineend; valend++); 291 for (valend = valptr; valend < lineend; valend++)
292 continue;
237 --valend; 293 --valend;
238 /* Finally trim off trailing spaces */ 294 /* finally trim off trailing spaces */
239 for(valend; isspace(*valend); valend--); 295 for (; isspace(*valend); valend--)
296 continue;
240 /* calculate the length of "--foo" */ 297 /* calculate the length of "--foo" */
241 opt_len=1+optend-optptr; 298 opt_len = (size_t)(1 + optend - optptr);
242 /* 1-character params needs only one dash */ 299 /* 1-character params needs only one dash */
243 if(opt_len==1) 300 if (opt_len == 1)
244 cfg_len=1+(opt_len); 301 cfg_len = 1 + (opt_len);
245 else 302 else
246 cfg_len=2+(opt_len); 303 cfg_len = 2 + (opt_len);
247 /* if valptr<lineend then we have to also allocate space for "=bar" */ 304 /* if valptr<lineend then we have to also allocate space for "=bar" */
248 if(valptr<lineend) { 305 if (valptr < lineend) {
249 equals=value=1; 306 equals = value = 1;
250 val_len=1+valend-valptr; 307 val_len = (size_t)(1 + valend - valptr);
251 cfg_len+=1+val_len; 308 cfg_len += 1 + val_len;
252 } 309 }
253 /* if valptr==valend then we have "=" but no "bar" */ 310 /* if valptr==valend then we have "=" but no "bar" */
254 else if(valptr==lineend) { 311 else if (valptr == lineend) {
255 equals=1; 312 equals = 1;
256 cfg_len+=1; 313 cfg_len += 1;
257 } 314 }
258 /* A line with no equal sign isn't valid */ 315 /* a line with no equal sign isn't valid */
259 if(equals==0) die(STATE_UNKNOWN, "%s\n", _("Config file error")); 316 if (equals == 0)
317 die(STATE_UNKNOWN, "%s\n", _("Config file error"));
260 318
261 /* okay, now we have all the info we need, so we create a new np_arg_list 319 /* okay, now we have all the info we need, so we create a new np_arg_list
262 * element and set the argument... 320 * element and set the argument...
263 */ 321 */
264 optnew=(np_arg_list *)malloc(sizeof(np_arg_list)); 322 optnew = malloc(sizeof(np_arg_list));
265 optnew->next=NULL; 323 optnew->next = NULL;
266 324
267 read_pos=0; 325 read_pos = 0;
268 optnew->arg=(char *)malloc(cfg_len+1); 326 optnew->arg = malloc(cfg_len + 1);
269 /* 1-character params needs only one dash */ 327 /* 1-character params needs only one dash */
270 if(opt_len==1) { 328 if (opt_len == 1) {
271 strncpy(&optnew->arg[read_pos], "-", 1); 329 strncpy(&optnew->arg[read_pos], "-", 1);
272 read_pos+=1; 330 read_pos += 1;
273 } else { 331 } else {
274 strncpy(&optnew->arg[read_pos], "--", 2); 332 strncpy(&optnew->arg[read_pos], "--", 2);
275 read_pos+=2; 333 read_pos += 2;
276 } 334 }
277 strncpy(&optnew->arg[read_pos], optptr, opt_len); read_pos+=opt_len; 335 strncpy(&optnew->arg[read_pos], optptr, opt_len);
278 if(value) { 336 read_pos += opt_len;
279 optnew->arg[read_pos++]='='; 337 if (value) {
280 strncpy(&optnew->arg[read_pos], valptr, val_len); read_pos+=val_len; 338 optnew->arg[read_pos++] = '=';
339 strncpy(&optnew->arg[read_pos], valptr, val_len);
340 read_pos += val_len;
281 } 341 }
282 optnew->arg[read_pos]='\0'; 342 optnew->arg[read_pos] = '\0';
283 343
284 /* ...and put that to the end of the list */ 344 /* ...and put that to the end of the list */
285 if(*optlst==NULL) { 345 if (*optlst == NULL)
286 *optlst=optnew; 346 *optlst = optnew;
287 } else { 347 else {
288 while(opttmp->next!=NULL) { 348 while (opttmp->next != NULL)
289 opttmp=opttmp->next; 349 opttmp = opttmp->next;
290 }
291 opttmp->next = optnew; 350 opttmp->next = optnew;
292 } 351 }
293 352
@@ -295,71 +354,42 @@ static int add_option(FILE *f, np_arg_list **optlst){
295 return 0; 354 return 0;
296} 355}
297 356
298static char* default_file(void){ 357static char *
299 struct stat sb; 358default_file(void)
300 char *np_env=NULL, *default_file=NULL; 359{
301 char temp_file[MAX_INPUT_BUFFER]; 360 char **p, *ini_file;
302 size_t len; 361
303 362 if ((ini_file = getenv("MP_CONFIG_FILE")) != NULL ||
304 if((np_env=getenv("NAGIOS_CONFIG_PATH"))!=NULL) { 363 (ini_file = default_file_in_path()) != NULL)
305 /* skip any starting colon... */ 364 return ini_file;
306 while(*np_env==':') np_env++; 365 for (p = default_ini_path_names; *p != NULL; p++)
307 /* Look for NP_DEFAULT_INI_FILENAME1 and NP_DEFAULT_INI_FILENAME2 in 366 if (access(*p, F_OK) == 0)
308 * every PATHs defined (colon-separated). 367 return *p;
309 */ 368 return NULL;
310 while((len=strcspn(np_env,":"))>0){
311 /* Test NP_DEFAULT_INI_FILENAME[1-2] in current np_env token */
312 if(test_file(np_env,len,NP_DEFAULT_INI_FILENAME1,temp_file)==1 ||
313 test_file(np_env,len,NP_DEFAULT_INI_FILENAME2,temp_file)==1){
314 default_file=strdup(temp_file);
315 break;
316 }
317
318 /* Move on to the next token */
319 np_env+=len;
320 while(*np_env==':') np_env++;
321 } /* while(...) */
322 } /* if(getenv("NAGIOS_CONFIG_PATH")) */
323
324 /* Look for NP_DEFAULT_INI_FILENAME1 in NP_DEFAULT_INI_NAGIOS_PATH[1-4] */
325 if(!default_file){
326 if(test_file(NP_DEFAULT_INI_NAGIOS_PATH1,strlen(NP_DEFAULT_INI_NAGIOS_PATH1),NP_DEFAULT_INI_FILENAME1,temp_file)==1 ||
327 test_file(NP_DEFAULT_INI_NAGIOS_PATH2,strlen(NP_DEFAULT_INI_NAGIOS_PATH2),NP_DEFAULT_INI_FILENAME1,temp_file)==1 ||
328 test_file(NP_DEFAULT_INI_NAGIOS_PATH3,strlen(NP_DEFAULT_INI_NAGIOS_PATH3),NP_DEFAULT_INI_FILENAME1,temp_file)==1 ||
329 test_file(NP_DEFAULT_INI_NAGIOS_PATH4,strlen(NP_DEFAULT_INI_NAGIOS_PATH4),NP_DEFAULT_INI_FILENAME1,temp_file)==1)
330 default_file=strdup(temp_file);
331 }
332
333 /* Look for NP_DEFAULT_INI_FILENAME2 in NP_DEFAULT_INI_PATH[1-3] */
334 if(!default_file){
335 if(test_file(NP_DEFAULT_INI_PATH1,strlen(NP_DEFAULT_INI_PATH1),NP_DEFAULT_INI_FILENAME2,temp_file)==1 ||
336 test_file(NP_DEFAULT_INI_PATH2,strlen(NP_DEFAULT_INI_PATH2),NP_DEFAULT_INI_FILENAME2,temp_file)==1 ||
337 test_file(NP_DEFAULT_INI_PATH3,strlen(NP_DEFAULT_INI_PATH3),NP_DEFAULT_INI_FILENAME2,temp_file)==1)
338 default_file=strdup(temp_file);
339 }
340
341 /* Return default_file or empty string (should return NULL if we want plugins
342 * to die there)...
343 */
344 if(default_file)
345 return default_file;
346 return "";
347} 369}
348 370
349/* put together len bytes from env and the filename and test for its 371static char *
350 * existence. Returns 1 if found, 0 if not and -1 if test wasn't performed. 372default_file_in_path(void)
351 */ 373{
352static int test_file(const char* env, int len, const char* file, char* temp_file){ 374 char *config_path, **file;
353 375 char *dir, *ini_file, *tokens;
354 /* test if len + filelen + '/' + '\0' fits in temp_file */ 376
355 if((len+strlen(file)+2)>MAX_INPUT_BUFFER) return -1; 377 if ((config_path = getenv("NAGIOS_CONFIG_PATH")) == NULL)
356 378 return NULL;
357 strncpy(temp_file,env,len); 379 /* shall we spit out a warning that NAGIOS_CONFIG_PATH is deprecated? */
358 temp_file[len]='\0'; 380
359 strncat(temp_file,"/",len+1); 381 if ((tokens = strdup(config_path)) == NULL)
360 strncat(temp_file,file,len+strlen(file)+1); 382 die(STATE_UNKNOWN, "%s\n", _("Insufficient Memory"));
361 383 for (dir = strtok(tokens, ":"); dir != NULL; dir = strtok(NULL, ":")) {
362 if(access(temp_file, F_OK) == 0) return 1; 384 for (file = default_ini_file_names; *file != NULL; file++) {
363 return 0; 385 if ((asprintf(&ini_file, "%s/%s", dir, *file)) < 0)
386 die(STATE_UNKNOWN, "%s\n", _("Insufficient Memory"));
387 if (access(ini_file, F_OK) == 0) {
388 free(tokens);
389 return ini_file;
390 }
391 }
392 }
393 free(tokens);
394 return NULL;
364} 395}
365
diff --git a/lib/parse_ini.h b/lib/parse_ini.h
index a3a494e..e37601b 100644
--- a/lib/parse_ini.h
+++ b/lib/parse_ini.h
@@ -13,50 +13,10 @@ typedef struct np_arg_el {
13 struct np_arg_el *next; 13 struct np_arg_el *next;
14} np_arg_list; 14} np_arg_list;
15 15
16/* FIXME: This is in plugins/common.c. Should be eventually moved to lib/
17 * (although for this particular one a configure settings should be ideal)
18 */
19#ifndef MAX_INPUT_BUFFER
20# define MAX_INPUT_BUFFER 8192
21#endif /* MAX_INPUT_BUFFER */
22
23/* Filenames (see below) */
24#ifndef NP_DEFAULT_INI_FILENAME1
25# define NP_DEFAULT_INI_FILENAME1 "plugins.ini"
26#endif /* NP_DEFAULT_INI_FILENAME1 */
27#ifndef NP_DEFAULT_INI_FILENAME2
28# define NP_DEFAULT_INI_FILENAME2 "nagios-plugins.ini"
29#endif /* NP_DEFAULT_INI_FILENAME2 */
30
31/* Config paths ending in nagios (search for NP_DEFAULT_INI_FILENAME1) */
32#ifndef NP_DEFAULT_INI_NAGIOS_PATH1
33# define NP_DEFAULT_INI_NAGIOS_PATH1 "/etc/nagios"
34#endif /* NP_DEFAULT_INI_NAGIOS_PATH1 */
35#ifndef NP_DEFAULT_INI_NAGIOS_PATH2
36# define NP_DEFAULT_INI_NAGIOS_PATH2 "/usr/local/nagios/etc"
37#endif /* NP_DEFAULT_INI_NAGIOS_PATH2 */
38#ifndef NP_DEFAULT_INI_NAGIOS_PATH3
39# define NP_DEFAULT_INI_NAGIOS_PATH3 "/usr/local/etc/nagios"
40#endif /* NP_DEFAULT_INI_NAGIOS_PATH3 */
41#ifndef NP_DEFAULT_INI_NAGIOS_PATH4
42# define NP_DEFAULT_INI_NAGIOS_PATH4 "/etc/opt/nagios"
43#endif /* NP_DEFAULT_INI_NAGIOS_PATH4 */
44
45/* Config paths not ending in nagios (search for NP_DEFAULT_INI_FILENAME2) */
46#ifndef NP_DEFAULT_INI_PATH1
47# define NP_DEFAULT_INI_PATH1 "/etc"
48#endif /* NP_DEFAULT_INI_PATH1 */
49#ifndef NP_DEFAULT_INI_PATH2
50# define NP_DEFAULT_INI_PATH2 "/usr/local/etc"
51#endif /* NP_DEFAULT_INI_PATH2 */
52#ifndef NP_DEFAULT_INI_PATH3
53# define NP_DEFAULT_INI_PATH3 "/etc/opt"
54#endif /* NP_DEFAULT_INI_PATH3 */
55
56/* np_load_defaults: load the default configuration (if present) for 16/* np_load_defaults: load the default configuration (if present) for
57 * a plugin from the ini file 17 * a plugin from the ini file
58 */ 18 */
59np_arg_list* np_get_defaults(const char *locator, const char *default_section); 19np_arg_list *np_get_defaults(const char *locator, const char *default_section);
60 20
61#endif /* _PARSE_INI_H_ */ 21#endif /* _PARSE_INI_H_ */
62 22
diff --git a/lib/tests/test_utils.c b/lib/tests/test_utils.c
index 356887d..f35b7e2 100644
--- a/lib/tests/test_utils.c
+++ b/lib/tests/test_utils.c
@@ -21,6 +21,7 @@
21 21
22#include "tap.h" 22#include "tap.h"
23 23
24#include <unistd.h>
24#include <sys/types.h> 25#include <sys/types.h>
25#include <sys/stat.h> 26#include <sys/stat.h>
26 27
@@ -29,6 +30,7 @@
29int 30int
30main (int argc, char **argv) 31main (int argc, char **argv)
31{ 32{
33 char state_path[1024];
32 range *range; 34 range *range;
33 double temp; 35 double temp;
34 thresholds *thresholds = NULL; 36 thresholds *thresholds = NULL;
@@ -345,9 +347,10 @@ main (int argc, char **argv)
345 347
346 np_enable_state("allowedchars_in_keyname", 77); 348 np_enable_state("allowedchars_in_keyname", 77);
347 temp_state_key = this_monitoring_plugin->state; 349 temp_state_key = this_monitoring_plugin->state;
350 sprintf(state_path, "/usr/local/nagios/var/%lu/check_test/allowedchars_in_keyname", (unsigned long)geteuid());
348 ok( !strcmp(temp_state_key->plugin_name, "check_test"), "Got plugin name" ); 351 ok( !strcmp(temp_state_key->plugin_name, "check_test"), "Got plugin name" );
349 ok( !strcmp(temp_state_key->name, "allowedchars_in_keyname"), "Got key name with valid chars" ); 352 ok( !strcmp(temp_state_key->name, "allowedchars_in_keyname"), "Got key name with valid chars" );
350 ok( !strcmp(temp_state_key->_filename, "/usr/local/nagios/var/check_test/allowedchars_in_keyname"), "Got internal filename" ); 353 ok( !strcmp(temp_state_key->_filename, state_path), "Got internal filename" );
351 354
352 355
353 /* Don't do this test just yet. Will die */ 356 /* Don't do this test just yet. Will die */
@@ -359,12 +362,13 @@ main (int argc, char **argv)
359 362
360 np_enable_state("funnykeyname", 54); 363 np_enable_state("funnykeyname", 54);
361 temp_state_key = this_monitoring_plugin->state; 364 temp_state_key = this_monitoring_plugin->state;
365 sprintf(state_path, "/usr/local/nagios/var/%lu/check_test/funnykeyname", (unsigned long)geteuid());
362 ok( !strcmp(temp_state_key->plugin_name, "check_test"), "Got plugin name" ); 366 ok( !strcmp(temp_state_key->plugin_name, "check_test"), "Got plugin name" );
363 ok( !strcmp(temp_state_key->name, "funnykeyname"), "Got key name" ); 367 ok( !strcmp(temp_state_key->name, "funnykeyname"), "Got key name" );
364 368
365 369
366 370
367 ok( !strcmp(temp_state_key->_filename, "/usr/local/nagios/var/check_test/funnykeyname"), "Got internal filename" ); 371 ok( !strcmp(temp_state_key->_filename, state_path), "Got internal filename" );
368 ok( temp_state_key->data_version==54, "Version set" ); 372 ok( temp_state_key->data_version==54, "Version set" );
369 373
370 temp_state_data = np_state_read(); 374 temp_state_data = np_state_read();
diff --git a/lib/utils_base.c b/lib/utils_base.c
index 04c4b4f..addf26b 100644
--- a/lib/utils_base.c
+++ b/lib/utils_base.c
@@ -300,19 +300,6 @@ char *np_escaped_string (const char *string) {
300 300
301int np_check_if_root(void) { return (geteuid() == 0); } 301int np_check_if_root(void) { return (geteuid() == 0); }
302 302
303int np_warn_if_not_root(void) {
304 int status = np_check_if_root();
305 if(!status) {
306 printf(_("Warning: "));
307 printf(_("This plugin must be either run as root or setuid root.\n"));
308 printf(_("To run as root, you can use a tool like sudo.\n"));
309 printf(_("To set the setuid permissions, use the command:\n"));
310 /* XXX could we use something like progname? */
311 printf("\tchmod u+s yourpluginfile\n");
312 }
313 return status;
314}
315
316/* 303/*
317 * Extract the value from key/value pairs, or return NULL. The value returned 304 * Extract the value from key/value pairs, or return NULL. The value returned
318 * can be free()ed. 305 * can be free()ed.
@@ -489,7 +476,9 @@ void np_enable_state(char *keyname, int expected_data_version) {
489 this_state->state_data=NULL; 476 this_state->state_data=NULL;
490 477
491 /* Calculate filename */ 478 /* Calculate filename */
492 asprintf(&temp_filename, "%s/%s/%s", _np_state_calculate_location_prefix(), this_monitoring_plugin->plugin_name, this_state->name); 479 asprintf(&temp_filename, "%s/%lu/%s/%s",
480 _np_state_calculate_location_prefix(), (unsigned long)geteuid(),
481 this_monitoring_plugin->plugin_name, this_state->name);
493 this_state->_filename=temp_filename; 482 this_state->_filename=temp_filename;
494 483
495 this_monitoring_plugin->state = this_state; 484 this_monitoring_plugin->state = this_state;
diff --git a/lib/utils_base.h b/lib/utils_base.h
index d69b0da..42ae0c0 100644
--- a/lib/utils_base.h
+++ b/lib/utils_base.h
@@ -75,9 +75,6 @@ void die (int, const char *, ...) __attribute__((noreturn,format(printf, 2, 3)))
75/* a simple check to see if we're running as root. 75/* a simple check to see if we're running as root.
76 * returns zero on failure, nonzero on success */ 76 * returns zero on failure, nonzero on success */
77int np_check_if_root(void); 77int np_check_if_root(void);
78/* and a helpful wrapper around that. it returns the same status
79 * code from the above function, in case it's helpful for testing */
80int np_warn_if_not_root(void);
81 78
82/* mp_suid() returns true if the real and effective uids differs, such as when 79/* mp_suid() returns true if the real and effective uids differs, such as when
83 * running a suid plugin */ 80 * running a suid plugin */
diff --git a/lib/utils_cmd.c b/lib/utils_cmd.c
index 4c6d0be..9e214bd 100644
--- a/lib/utils_cmd.c
+++ b/lib/utils_cmd.c
@@ -390,6 +390,9 @@ cmd_file_read ( char *filename, output *out, int flags)
390 390
391 if(out) 391 if(out)
392 out->lines = _cmd_fetch_output (fd, out, flags); 392 out->lines = _cmd_fetch_output (fd, out, flags);
393
394 if (close(fd) == -1)
395 die( STATE_UNKNOWN, _("Error closing %s: %s"), filename, strerror(errno) );
393 396
394 return 0; 397 return 0;
395} 398}