summaryrefslogtreecommitdiffstats
path: root/lib/utils_base.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/utils_base.c')
-rw-r--r--lib/utils_base.c542
1 files changed, 296 insertions, 246 deletions
diff --git a/lib/utils_base.c b/lib/utils_base.c
index f8592f41..c49a473f 100644
--- a/lib/utils_base.c
+++ b/lib/utils_base.c
@@ -1,28 +1,28 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* utils_base.c 3 * utils_base.c
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2006 Monitoring Plugins Development Team 6 * Copyright (c) 2006 - 2024 Monitoring Plugins Development Team
7* 7 *
8* Library of useful functions for plugins 8 * Library of useful functions for plugins
9* 9 *
10* 10 *
11* This program is free software: you can redistribute it and/or modify 11 * This program is free software: you can redistribute it and/or modify
12* it under the terms of the GNU General Public License as published by 12 * it under the terms of the GNU General Public License as published by
13* the Free Software Foundation, either version 3 of the License, or 13 * the Free Software Foundation, either version 3 of the License, or
14* (at your option) any later version. 14 * (at your option) any later version.
15* 15 *
16* This program is distributed in the hope that it will be useful, 16 * This program is distributed in the hope that it will be useful,
17* but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19* GNU General Public License for more details. 19 * GNU General Public License for more details.
20* 20 *
21* You should have received a copy of the GNU General Public License 21 * You should have received a copy of the GNU General Public License
22* along with this program. If not, see <http://www.gnu.org/licenses/>. 22 * along with this program. If not, see <http://www.gnu.org/licenses/>.
23* 23 *
24* 24 *
25*****************************************************************************/ 25 *****************************************************************************/
26 26
27#include "../plugins/common.h" 27#include "../plugins/common.h"
28#include <stdarg.h> 28#include <stdarg.h>
@@ -33,43 +33,49 @@
33#include <unistd.h> 33#include <unistd.h>
34#include <sys/types.h> 34#include <sys/types.h>
35 35
36#define np_free(ptr) { if(ptr) { free(ptr); ptr = NULL; } } 36#define np_free(ptr) \
37 { \
38 if (ptr) { \
39 free(ptr); \
40 ptr = NULL; \
41 } \
42 }
37 43
38monitoring_plugin *this_monitoring_plugin=NULL; 44monitoring_plugin *this_monitoring_plugin = NULL;
39 45
40int timeout_state = STATE_CRITICAL; 46int timeout_state = STATE_CRITICAL;
41unsigned int timeout_interval = DEFAULT_SOCKET_TIMEOUT; 47unsigned int timeout_interval = DEFAULT_SOCKET_TIMEOUT;
42 48
43bool _np_state_read_file(FILE *); 49bool _np_state_read_file(FILE *);
44 50
45void np_init( char *plugin_name, int argc, char **argv ) { 51void np_init(char *plugin_name, int argc, char **argv) {
46 if (this_monitoring_plugin==NULL) { 52 if (this_monitoring_plugin == NULL) {
47 this_monitoring_plugin = calloc(1, sizeof(monitoring_plugin)); 53 this_monitoring_plugin = calloc(1, sizeof(monitoring_plugin));
48 if (this_monitoring_plugin==NULL) { 54 if (this_monitoring_plugin == NULL) {
49 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), 55 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), strerror(errno));
50 strerror(errno));
51 } 56 }
52 this_monitoring_plugin->plugin_name = strdup(plugin_name); 57 this_monitoring_plugin->plugin_name = strdup(plugin_name);
53 if (this_monitoring_plugin->plugin_name==NULL) 58 if (this_monitoring_plugin->plugin_name == NULL) {
54 die(STATE_UNKNOWN, _("Cannot execute strdup: %s"), strerror(errno)); 59 die(STATE_UNKNOWN, _("Cannot execute strdup: %s"), strerror(errno));
60 }
55 this_monitoring_plugin->argc = argc; 61 this_monitoring_plugin->argc = argc;
56 this_monitoring_plugin->argv = argv; 62 this_monitoring_plugin->argv = argv;
57 } 63 }
58} 64}
59 65
60void np_set_args( int argc, char **argv ) { 66void np_set_args(int argc, char **argv) {
61 if (this_monitoring_plugin==NULL) 67 if (this_monitoring_plugin == NULL) {
62 die(STATE_UNKNOWN, _("This requires np_init to be called")); 68 die(STATE_UNKNOWN, _("This requires np_init to be called"));
69 }
63 70
64 this_monitoring_plugin->argc = argc; 71 this_monitoring_plugin->argc = argc;
65 this_monitoring_plugin->argv = argv; 72 this_monitoring_plugin->argv = argv;
66} 73}
67 74
68 75void np_cleanup(void) {
69void np_cleanup() { 76 if (this_monitoring_plugin != NULL) {
70 if (this_monitoring_plugin!=NULL) { 77 if (this_monitoring_plugin->state != NULL) {
71 if(this_monitoring_plugin->state!=NULL) { 78 if (this_monitoring_plugin->state->state_data) {
72 if(this_monitoring_plugin->state->state_data) {
73 np_free(this_monitoring_plugin->state->state_data->data); 79 np_free(this_monitoring_plugin->state->state_data->data);
74 np_free(this_monitoring_plugin->state->state_data); 80 np_free(this_monitoring_plugin->state->state_data);
75 } 81 }
@@ -79,48 +85,43 @@ void np_cleanup() {
79 np_free(this_monitoring_plugin->plugin_name); 85 np_free(this_monitoring_plugin->plugin_name);
80 np_free(this_monitoring_plugin); 86 np_free(this_monitoring_plugin);
81 } 87 }
82 this_monitoring_plugin=NULL; 88 this_monitoring_plugin = NULL;
83} 89}
84 90
85/* Hidden function to get a pointer to this_monitoring_plugin for testing */ 91/* Hidden function to get a pointer to this_monitoring_plugin for testing */
86void _get_monitoring_plugin( monitoring_plugin **pointer ){ 92void _get_monitoring_plugin(monitoring_plugin **pointer) { *pointer = this_monitoring_plugin; }
87 *pointer = this_monitoring_plugin;
88}
89 93
90void 94void die(int result, const char *fmt, ...) {
91die (int result, const char *fmt, ...) 95 if (fmt != NULL) {
92{
93 if(fmt!=NULL) {
94 va_list ap; 96 va_list ap;
95 va_start (ap, fmt); 97 va_start(ap, fmt);
96 vprintf (fmt, ap); 98 vprintf(fmt, ap);
97 va_end (ap); 99 va_end(ap);
98 } 100 }
99 101
100 if(this_monitoring_plugin!=NULL) { 102 if (this_monitoring_plugin != NULL) {
101 np_cleanup(); 103 np_cleanup();
102 } 104 }
103 exit (result); 105 exit(result);
104} 106}
105 107
106void set_range_start (range *this, double value) { 108void set_range_start(range *this, double value) {
107 this->start = value; 109 this->start = value;
108 this->start_infinity = false; 110 this->start_infinity = false;
109} 111}
110 112
111void set_range_end (range *this, double value) { 113void set_range_end(range *this, double value) {
112 this->end = value; 114 this->end = value;
113 this->end_infinity = false; 115 this->end_infinity = false;
114} 116}
115 117
116range 118range *parse_range_string(char *str) {
117*parse_range_string (char *str) {
118 range *temp_range; 119 range *temp_range;
119 double start; 120 double start;
120 double end; 121 double end;
121 char *end_str; 122 char *end_str;
122 123
123 temp_range = (range *) calloc(1, sizeof(range)); 124 temp_range = (range *)calloc(1, sizeof(range));
124 125
125 /* Set defaults */ 126 /* Set defaults */
126 temp_range->start = 0; 127 temp_range->start = 0;
@@ -140,10 +141,10 @@ range
140 if (str[0] == '~') { 141 if (str[0] == '~') {
141 temp_range->start_infinity = true; 142 temp_range->start_infinity = true;
142 } else { 143 } else {
143 start = strtod(str, NULL); /* Will stop at the ':' */ 144 start = strtod(str, NULL); /* Will stop at the ':' */
144 set_range_start(temp_range, start); 145 set_range_start(temp_range, start);
145 } 146 }
146 end_str++; /* Move past the ':' */ 147 end_str++; /* Move past the ':' */
147 } else { 148 } else {
148 end_str = str; 149 end_str = str;
149 } 150 }
@@ -152,9 +153,7 @@ range
152 set_range_end(temp_range, end); 153 set_range_end(temp_range, end);
153 } 154 }
154 155
155 if (temp_range->start_infinity == true || 156 if (temp_range->start_infinity == true || temp_range->end_infinity == true || temp_range->start <= temp_range->end) {
156 temp_range->end_infinity == true ||
157 temp_range->start <= temp_range->end) {
158 return temp_range; 157 return temp_range;
159 } 158 }
160 free(temp_range); 159 free(temp_range);
@@ -162,14 +161,12 @@ range
162} 161}
163 162
164/* returns 0 if okay, otherwise 1 */ 163/* returns 0 if okay, otherwise 1 */
165int 164int _set_thresholds(thresholds **my_thresholds, char *warn_string, char *critical_string) {
166_set_thresholds(thresholds **my_thresholds, char *warn_string, char *critical_string)
167{
168 thresholds *temp_thresholds = NULL; 165 thresholds *temp_thresholds = NULL;
169 166
170 if ((temp_thresholds = calloc(1, sizeof(thresholds))) == NULL) 167 if ((temp_thresholds = calloc(1, sizeof(thresholds))) == NULL) {
171 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), 168 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), strerror(errno));
172 strerror(errno)); 169 }
173 170
174 temp_thresholds->warning = NULL; 171 temp_thresholds->warning = NULL;
175 temp_thresholds->critical = NULL; 172 temp_thresholds->critical = NULL;
@@ -190,9 +187,7 @@ _set_thresholds(thresholds **my_thresholds, char *warn_string, char *critical_st
190 return 0; 187 return 0;
191} 188}
192 189
193void 190void set_thresholds(thresholds **my_thresholds, char *warn_string, char *critical_string) {
194set_thresholds(thresholds **my_thresholds, char *warn_string, char *critical_string)
195{
196 switch (_set_thresholds(my_thresholds, warn_string, critical_string)) { 191 switch (_set_thresholds(my_thresholds, warn_string, critical_string)) {
197 case 0: 192 case 0:
198 return; 193 return;
@@ -206,7 +201,7 @@ set_thresholds(thresholds **my_thresholds, char *warn_string, char *critical_str
206 201
207void print_thresholds(const char *threshold_name, thresholds *my_threshold) { 202void print_thresholds(const char *threshold_name, thresholds *my_threshold) {
208 printf("%s - ", threshold_name); 203 printf("%s - ", threshold_name);
209 if (! my_threshold) { 204 if (!my_threshold) {
210 printf("Threshold not set"); 205 printf("Threshold not set");
211 } else { 206 } else {
212 if (my_threshold->warning) { 207 if (my_threshold->warning) {
@@ -223,9 +218,36 @@ void print_thresholds(const char *threshold_name, thresholds *my_threshold) {
223 printf("\n"); 218 printf("\n");
224} 219}
225 220
221/* Returns true if alert should be raised based on the range, false otherwise */
222bool mp_check_range(const mp_perfdata_value value, const mp_range my_range) {
223 bool is_inside = false;
224
225 if (my_range.end_infinity == false && my_range.start_infinity == false) {
226 // range: .........|---inside---|...........
227 // value
228 is_inside = ((cmp_perfdata_value(my_range.start, value) < 1) && (cmp_perfdata_value(value, my_range.end) <= 0));
229 } else if (my_range.start_infinity == false && my_range.end_infinity == true) {
230 // range: .........|---inside---------
231 // value
232 is_inside = (cmp_perfdata_value(my_range.start, value) < 0);
233 } else if (my_range.start_infinity == true && my_range.end_infinity == false) {
234 // range: -inside--------|....................
235 // value
236 is_inside = (cmp_perfdata_value(value, my_range.end) == -1);
237 } else {
238 // range from -inf to inf, so always inside
239 is_inside = true;
240 }
241
242 if ((is_inside && my_range.alert_on_inside_range == INSIDE) || (!is_inside && my_range.alert_on_inside_range == OUTSIDE)) {
243 return true;
244 }
245
246 return false;
247}
248
226/* Returns true if alert should be raised based on the range */ 249/* Returns true if alert should be raised based on the range */
227bool check_range(double value, range *my_range) 250bool check_range(double value, range *my_range) {
228{
229 bool no = false; 251 bool no = false;
230 bool yes = true; 252 bool yes = true;
231 253
@@ -237,30 +259,28 @@ bool check_range(double value, range *my_range)
237 if (my_range->end_infinity == false && my_range->start_infinity == false) { 259 if (my_range->end_infinity == false && my_range->start_infinity == false) {
238 if ((my_range->start <= value) && (value <= my_range->end)) { 260 if ((my_range->start <= value) && (value <= my_range->end)) {
239 return no; 261 return no;
240 } else {
241 return yes;
242 } 262 }
243 } else if (my_range->start_infinity == false && my_range->end_infinity == true) { 263 return yes;
264 }
265
266 if (my_range->start_infinity == false && my_range->end_infinity == true) {
244 if (my_range->start <= value) { 267 if (my_range->start <= value) {
245 return no; 268 return no;
246 } else {
247 return yes;
248 } 269 }
249 } else if (my_range->start_infinity == true && my_range->end_infinity == false) { 270 return yes;
271 }
272
273 if (my_range->start_infinity == true && my_range->end_infinity == false) {
250 if (value <= my_range->end) { 274 if (value <= my_range->end) {
251 return no; 275 return no;
252 } else {
253 return yes;
254 } 276 }
255 } else { 277 return yes;
256 return no;
257 } 278 }
279 return no;
258} 280}
259 281
260/* Returns status */ 282/* Returns status */
261int 283int get_status(double value, thresholds *my_thresholds) {
262get_status(double value, thresholds *my_thresholds)
263{
264 if (my_thresholds->critical != NULL) { 284 if (my_thresholds->critical != NULL) {
265 if (check_range(value, my_thresholds->critical) == true) { 285 if (check_range(value, my_thresholds->critical) == true) {
266 return STATE_CRITICAL; 286 return STATE_CRITICAL;
@@ -274,27 +294,28 @@ get_status(double value, thresholds *my_thresholds)
274 return STATE_OK; 294 return STATE_OK;
275} 295}
276 296
277char *np_escaped_string (const char *string) { 297char *np_escaped_string(const char *string) {
278 char *data; 298 char *data;
279 int i, j=0; 299 int i;
300 int j = 0;
280 data = strdup(string); 301 data = strdup(string);
281 for (i=0; data[i]; i++) { 302 for (i = 0; data[i]; i++) {
282 if (data[i] == '\\') { 303 if (data[i] == '\\') {
283 switch(data[++i]) { 304 switch (data[++i]) {
284 case 'n': 305 case 'n':
285 data[j++] = '\n'; 306 data[j++] = '\n';
286 break; 307 break;
287 case 'r': 308 case 'r':
288 data[j++] = '\r'; 309 data[j++] = '\r';
289 break; 310 break;
290 case 't': 311 case 't':
291 data[j++] = '\t'; 312 data[j++] = '\t';
292 break; 313 break;
293 case '\\': 314 case '\\':
294 data[j++] = '\\'; 315 data[j++] = '\\';
295 break; 316 break;
296 default: 317 default:
297 data[j++] = data[i]; 318 data[j++] = data[i];
298 } 319 }
299 } else { 320 } else {
300 data[j++] = data[i]; 321 data[j++] = data[i];
@@ -313,33 +334,41 @@ int np_check_if_root(void) { return (geteuid() == 0); }
313 * data strings. 334 * data strings.
314 */ 335 */
315char *np_extract_value(const char *varlist, const char *name, char sep) { 336char *np_extract_value(const char *varlist, const char *name, char sep) {
316 char *tmp=NULL, *value=NULL; 337 char *tmp = NULL;
338 char *value = NULL;
317 int i; 339 int i;
318 340
319 while (1) { 341 while (1) {
320 /* Strip any leading space */ 342 /* Strip any leading space */
321 for (; isspace(varlist[0]); varlist++); 343 for (; isspace(varlist[0]); varlist++)
344 ;
322 345
323 if (strncmp(name, varlist, strlen(name)) == 0) { 346 if (strncmp(name, varlist, strlen(name)) == 0) {
324 varlist += strlen(name); 347 varlist += strlen(name);
325 /* strip trailing spaces */ 348 /* strip trailing spaces */
326 for (; isspace(varlist[0]); varlist++); 349 for (; isspace(varlist[0]); varlist++)
350 ;
327 351
328 if (varlist[0] == '=') { 352 if (varlist[0] == '=') {
329 /* We matched the key, go past the = sign */ 353 /* We matched the key, go past the = sign */
330 varlist++; 354 varlist++;
331 /* strip leading spaces */ 355 /* strip leading spaces */
332 for (; isspace(varlist[0]); varlist++); 356 for (; isspace(varlist[0]); varlist++)
357 ;
333 358
334 if ((tmp = index(varlist, sep))) { 359 if ((tmp = index(varlist, sep))) {
335 /* Value is delimited by a comma */ 360 /* Value is delimited by a comma */
336 if (tmp-varlist == 0) continue; 361 if (tmp - varlist == 0) {
337 value = (char *)calloc(1, tmp-varlist+1); 362 continue;
338 strncpy(value, varlist, tmp-varlist); 363 }
339 value[tmp-varlist] = '\0'; 364 value = (char *)calloc(1, tmp - varlist + 1);
365 strncpy(value, varlist, tmp - varlist);
366 value[tmp - varlist] = '\0';
340 } else { 367 } else {
341 /* Value is delimited by a \0 */ 368 /* Value is delimited by a \0 */
342 if (strlen(varlist) == 0) continue; 369 if (strlen(varlist) == 0) {
370 continue;
371 }
343 value = (char *)calloc(1, strlen(varlist) + 1); 372 value = (char *)calloc(1, strlen(varlist) + 1);
344 strncpy(value, varlist, strlen(varlist)); 373 strncpy(value, varlist, strlen(varlist));
345 value[strlen(varlist)] = '\0'; 374 value[strlen(varlist)] = '\0';
@@ -357,14 +386,16 @@ char *np_extract_value(const char *varlist, const char *name, char sep) {
357 } 386 }
358 387
359 /* Clean-up trailing spaces/newlines */ 388 /* Clean-up trailing spaces/newlines */
360 if (value) for (i=strlen(value)-1; isspace(value[i]); i--) value[i] = '\0'; 389 if (value) {
390 for (i = strlen(value) - 1; isspace(value[i]); i--) {
391 value[i] = '\0';
392 }
393 }
361 394
362 return value; 395 return value;
363} 396}
364 397
365const char * 398const char *state_text(int result) {
366state_text (int result)
367{
368 switch (result) { 399 switch (result) {
369 case STATE_OK: 400 case STATE_OK:
370 return "OK"; 401 return "OK";
@@ -383,15 +414,19 @@ state_text (int result)
383 * Read a string representing a state (ok, warning... or numeric: 0, 1) and 414 * Read a string representing a state (ok, warning... or numeric: 0, 1) and
384 * return the corresponding STATE_ value or ERROR) 415 * return the corresponding STATE_ value or ERROR)
385 */ 416 */
386int mp_translate_state (char *state_text) { 417int mp_translate_state(char *state_text) {
387 if (!strcasecmp(state_text,"OK") || !strcmp(state_text,"0")) 418 if (!strcasecmp(state_text, "OK") || !strcmp(state_text, "0")) {
388 return STATE_OK; 419 return STATE_OK;
389 if (!strcasecmp(state_text,"WARNING") || !strcmp(state_text,"1")) 420 }
421 if (!strcasecmp(state_text, "WARNING") || !strcmp(state_text, "1")) {
390 return STATE_WARNING; 422 return STATE_WARNING;
391 if (!strcasecmp(state_text,"CRITICAL") || !strcmp(state_text,"2")) 423 }
424 if (!strcasecmp(state_text, "CRITICAL") || !strcmp(state_text, "2")) {
392 return STATE_CRITICAL; 425 return STATE_CRITICAL;
393 if (!strcasecmp(state_text,"UNKNOWN") || !strcmp(state_text,"3")) 426 }
427 if (!strcasecmp(state_text, "UNKNOWN") || !strcmp(state_text, "3")) {
394 return STATE_UNKNOWN; 428 return STATE_UNKNOWN;
429 }
395 return ERROR; 430 return ERROR;
396} 431}
397 432
@@ -400,11 +435,11 @@ int mp_translate_state (char *state_text) {
400 * hopefully a unique key per service/plugin invocation. Use the extra-opts 435 * hopefully a unique key per service/plugin invocation. Use the extra-opts
401 * parse of argv, so that uniqueness in parameters are reflected there. 436 * parse of argv, so that uniqueness in parameters are reflected there.
402 */ 437 */
403char *_np_state_generate_key() { 438char *_np_state_generate_key(void) {
404 int i; 439 int i;
405 char **argv = this_monitoring_plugin->argv; 440 char **argv = this_monitoring_plugin->argv;
406 char keyname[41]; 441 char keyname[41];
407 char *p=NULL; 442 char *p = NULL;
408 443
409 unsigned char result[256]; 444 unsigned char result[256];
410 445
@@ -418,7 +453,7 @@ char *_np_state_generate_key() {
418 453
419 EVP_DigestInit(ctx, EVP_sha256()); 454 EVP_DigestInit(ctx, EVP_sha256());
420 455
421 for(i=0; i<this_monitoring_plugin->argc; i++) { 456 for (i = 0; i < this_monitoring_plugin->argc; i++) {
422 EVP_DigestUpdate(ctx, argv[i], strlen(argv[i])); 457 EVP_DigestUpdate(ctx, argv[i], strlen(argv[i]));
423 } 458 }
424 459
@@ -427,28 +462,28 @@ char *_np_state_generate_key() {
427 462
428 struct sha256_ctx ctx; 463 struct sha256_ctx ctx;
429 464
430 for(i=0; i<this_monitoring_plugin->argc; i++) { 465 for (i = 0; i < this_monitoring_plugin->argc; i++) {
431 sha256_process_bytes(argv[i], strlen(argv[i]), &ctx); 466 sha256_process_bytes(argv[i], strlen(argv[i]), &ctx);
432 } 467 }
433 468
434 sha256_finish_ctx(&ctx, result); 469 sha256_finish_ctx(&ctx, result);
435#endif // FOUNDOPENSSL 470#endif // FOUNDOPENSSL
436 471
437 for (i=0; i<20; ++i) { 472 for (i = 0; i < 20; ++i) {
438 sprintf(&keyname[2*i], "%02x", result[i]); 473 sprintf(&keyname[2 * i], "%02x", result[i]);
439 } 474 }
440 475
441 keyname[40]='\0'; 476 keyname[40] = '\0';
442 477
443 p = strdup(keyname); 478 p = strdup(keyname);
444 if(p==NULL) { 479 if (p == NULL) {
445 die(STATE_UNKNOWN, _("Cannot execute strdup: %s"), strerror(errno)); 480 die(STATE_UNKNOWN, _("Cannot execute strdup: %s"), strerror(errno));
446 } 481 }
447 return p; 482 return p;
448} 483}
449 484
450void _cleanup_state_data() { 485void _cleanup_state_data(void) {
451 if (this_monitoring_plugin->state->state_data!=NULL) { 486 if (this_monitoring_plugin->state->state_data != NULL) {
452 np_free(this_monitoring_plugin->state->state_data->data); 487 np_free(this_monitoring_plugin->state->state_data->data);
453 np_free(this_monitoring_plugin->state->state_data); 488 np_free(this_monitoring_plugin->state->state_data);
454 } 489 }
@@ -459,19 +494,21 @@ void _cleanup_state_data() {
459 * envvar NAGIOS_PLUGIN_STATE_DIRECTORY 494 * envvar NAGIOS_PLUGIN_STATE_DIRECTORY
460 * statically compiled shared state directory 495 * statically compiled shared state directory
461 */ 496 */
462char* _np_state_calculate_location_prefix(){ 497char *_np_state_calculate_location_prefix(void) {
463 char *env_dir; 498 char *env_dir;
464 499
465 /* Do not allow passing MP_STATE_PATH in setuid plugins 500 /* Do not allow passing MP_STATE_PATH in setuid plugins
466 * for security reasons */ 501 * for security reasons */
467 if (!mp_suid()) { 502 if (!mp_suid()) {
468 env_dir = getenv("MP_STATE_PATH"); 503 env_dir = getenv("MP_STATE_PATH");
469 if(env_dir && env_dir[0] != '\0') 504 if (env_dir && env_dir[0] != '\0') {
470 return env_dir; 505 return env_dir;
506 }
471 /* This is the former ENV, for backward-compatibility */ 507 /* This is the former ENV, for backward-compatibility */
472 env_dir = getenv("NAGIOS_PLUGIN_STATE_DIRECTORY"); 508 env_dir = getenv("NAGIOS_PLUGIN_STATE_DIRECTORY");
473 if(env_dir && env_dir[0] != '\0') 509 if (env_dir && env_dir[0] != '\0') {
474 return env_dir; 510 return env_dir;
511 }
475 } 512 }
476 513
477 return NP_STATE_DIR_PREFIX; 514 return NP_STATE_DIR_PREFIX;
@@ -486,46 +523,47 @@ void np_enable_state(char *keyname, int expected_data_version) {
486 state_key *this_state = NULL; 523 state_key *this_state = NULL;
487 char *temp_filename = NULL; 524 char *temp_filename = NULL;
488 char *temp_keyname = NULL; 525 char *temp_keyname = NULL;
489 char *p=NULL; 526 char *p = NULL;
490 int ret; 527 int ret;
491 528
492 if(this_monitoring_plugin==NULL) 529 if (this_monitoring_plugin == NULL) {
493 die(STATE_UNKNOWN, _("This requires np_init to be called")); 530 die(STATE_UNKNOWN, _("This requires np_init to be called"));
531 }
494 532
495 this_state = (state_key *) calloc(1, sizeof(state_key)); 533 this_state = (state_key *)calloc(1, sizeof(state_key));
496 if(this_state==NULL) 534 if (this_state == NULL) {
497 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), 535 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), strerror(errno));
498 strerror(errno)); 536 }
499 537
500 if(keyname==NULL) { 538 if (keyname == NULL) {
501 temp_keyname = _np_state_generate_key(); 539 temp_keyname = _np_state_generate_key();
502 } else { 540 } else {
503 temp_keyname = strdup(keyname); 541 temp_keyname = strdup(keyname);
504 if(temp_keyname==NULL) 542 if (temp_keyname == NULL) {
505 die(STATE_UNKNOWN, _("Cannot execute strdup: %s"), strerror(errno)); 543 die(STATE_UNKNOWN, _("Cannot execute strdup: %s"), strerror(errno));
544 }
506 } 545 }
507 /* Die if invalid characters used for keyname */ 546 /* Die if invalid characters used for keyname */
508 p = temp_keyname; 547 p = temp_keyname;
509 while(*p!='\0') { 548 while (*p != '\0') {
510 if(! (isalnum(*p) || *p == '_')) { 549 if (!(isalnum(*p) || *p == '_')) {
511 die(STATE_UNKNOWN, _("Invalid character for keyname - only alphanumerics or '_'")); 550 die(STATE_UNKNOWN, _("Invalid character for keyname - only alphanumerics or '_'"));
512 } 551 }
513 p++; 552 p++;
514 } 553 }
515 this_state->name=temp_keyname; 554 this_state->name = temp_keyname;
516 this_state->plugin_name=this_monitoring_plugin->plugin_name; 555 this_state->plugin_name = this_monitoring_plugin->plugin_name;
517 this_state->data_version=expected_data_version; 556 this_state->data_version = expected_data_version;
518 this_state->state_data=NULL; 557 this_state->state_data = NULL;
519 558
520 /* Calculate filename */ 559 /* Calculate filename */
521 ret = asprintf(&temp_filename, "%s/%lu/%s/%s", 560 ret = asprintf(&temp_filename, "%s/%lu/%s/%s", _np_state_calculate_location_prefix(), (unsigned long)geteuid(),
522 _np_state_calculate_location_prefix(), (unsigned long)geteuid(), 561 this_monitoring_plugin->plugin_name, this_state->name);
523 this_monitoring_plugin->plugin_name, this_state->name); 562 if (ret < 0) {
524 if (ret < 0) 563 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), strerror(errno));
525 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), 564 }
526 strerror(errno));
527 565
528 this_state->_filename=temp_filename; 566 this_state->_filename = temp_filename;
529 567
530 this_monitoring_plugin->state = this_state; 568 this_monitoring_plugin->state = this_state;
531} 569}
@@ -537,24 +575,25 @@ void np_enable_state(char *keyname, int expected_data_version) {
537 * If numerically lower, then return as no previous state. die with UNKNOWN 575 * If numerically lower, then return as no previous state. die with UNKNOWN
538 * if exceptional error. 576 * if exceptional error.
539 */ 577 */
540state_data *np_state_read() { 578state_data *np_state_read(void) {
541 state_data *this_state_data=NULL; 579 state_data *this_state_data = NULL;
542 FILE *statefile; 580 FILE *statefile;
543 bool rc = false; 581 bool rc = false;
544 582
545 if(this_monitoring_plugin==NULL) 583 if (this_monitoring_plugin == NULL) {
546 die(STATE_UNKNOWN, _("This requires np_init to be called")); 584 die(STATE_UNKNOWN, _("This requires np_init to be called"));
585 }
547 586
548 /* Open file. If this fails, no previous state found */ 587 /* Open file. If this fails, no previous state found */
549 statefile = fopen( this_monitoring_plugin->state->_filename, "r" ); 588 statefile = fopen(this_monitoring_plugin->state->_filename, "r");
550 if(statefile!=NULL) { 589 if (statefile != NULL) {
551 590
552 this_state_data = (state_data *) calloc(1, sizeof(state_data)); 591 this_state_data = (state_data *)calloc(1, sizeof(state_data));
553 if(this_state_data==NULL) 592 if (this_state_data == NULL) {
554 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), 593 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), strerror(errno));
555 strerror(errno)); 594 }
556 595
557 this_state_data->data=NULL; 596 this_state_data->data = NULL;
558 this_monitoring_plugin->state->state_data = this_state_data; 597 this_monitoring_plugin->state->state_data = this_state_data;
559 598
560 rc = _np_state_read_file(statefile); 599 rc = _np_state_read_file(statefile);
@@ -562,7 +601,7 @@ state_data *np_state_read() {
562 fclose(statefile); 601 fclose(statefile);
563 } 602 }
564 603
565 if(!rc) { 604 if (!rc) {
566 _cleanup_state_data(); 605 _cleanup_state_data();
567 } 606 }
568 607
@@ -577,60 +616,70 @@ bool _np_state_read_file(FILE *f) {
577 size_t pos; 616 size_t pos;
578 char *line; 617 char *line;
579 int i; 618 int i;
580 int failure=0; 619 int failure = 0;
581 time_t current_time, data_time; 620 time_t current_time, data_time;
582 enum { STATE_FILE_VERSION, STATE_DATA_VERSION, STATE_DATA_TIME, STATE_DATA_TEXT, STATE_DATA_END } expected=STATE_FILE_VERSION; 621 enum {
622 STATE_FILE_VERSION,
623 STATE_DATA_VERSION,
624 STATE_DATA_TIME,
625 STATE_DATA_TEXT,
626 STATE_DATA_END
627 } expected = STATE_FILE_VERSION;
583 628
584 time(&current_time); 629 time(&current_time);
585 630
586 /* Note: This introduces a limit of 1024 bytes in the string data */ 631 /* Note: This introduces a limit of 1024 bytes in the string data */
587 line = (char *) calloc(1, 1024); 632 line = (char *)calloc(1, 1024);
588 if(line==NULL) 633 if (line == NULL) {
589 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), 634 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), strerror(errno));
590 strerror(errno)); 635 }
591 636
592 while(!failure && (fgets(line,1024,f))!=NULL){ 637 while (!failure && (fgets(line, 1024, f)) != NULL) {
593 pos=strlen(line); 638 pos = strlen(line);
594 if(line[pos-1]=='\n') { 639 if (line[pos - 1] == '\n') {
595 line[pos-1]='\0'; 640 line[pos - 1] = '\0';
596 } 641 }
597 642
598 if(line[0] == '#') continue; 643 if (line[0] == '#') {
644 continue;
645 }
599 646
600 switch(expected) { 647 switch (expected) {
601 case STATE_FILE_VERSION: 648 case STATE_FILE_VERSION:
602 i=atoi(line); 649 i = atoi(line);
603 if(i!=NP_STATE_FORMAT_VERSION) 650 if (i != NP_STATE_FORMAT_VERSION) {
604 failure++; 651 failure++;
605 else 652 } else {
606 expected=STATE_DATA_VERSION; 653 expected = STATE_DATA_VERSION;
607 break; 654 }
608 case STATE_DATA_VERSION: 655 break;
609 i=atoi(line); 656 case STATE_DATA_VERSION:
610 if(i != this_monitoring_plugin->state->data_version) 657 i = atoi(line);
611 failure++; 658 if (i != this_monitoring_plugin->state->data_version) {
612 else 659 failure++;
613 expected=STATE_DATA_TIME; 660 } else {
614 break; 661 expected = STATE_DATA_TIME;
615 case STATE_DATA_TIME: 662 }
616 /* If time > now, error */ 663 break;
617 data_time=strtoul(line,NULL,10); 664 case STATE_DATA_TIME:
618 if(data_time > current_time) 665 /* If time > now, error */
619 failure++; 666 data_time = strtoul(line, NULL, 10);
620 else { 667 if (data_time > current_time) {
621 this_monitoring_plugin->state->state_data->time = data_time; 668 failure++;
622 expected=STATE_DATA_TEXT; 669 } else {
623 } 670 this_monitoring_plugin->state->state_data->time = data_time;
624 break; 671 expected = STATE_DATA_TEXT;
625 case STATE_DATA_TEXT: 672 }
626 this_monitoring_plugin->state->state_data->data = strdup(line); 673 break;
627 if(this_monitoring_plugin->state->state_data->data==NULL) 674 case STATE_DATA_TEXT:
628 die(STATE_UNKNOWN, _("Cannot execute strdup: %s"), strerror(errno)); 675 this_monitoring_plugin->state->state_data->data = strdup(line);
629 expected=STATE_DATA_END; 676 if (this_monitoring_plugin->state->state_data->data == NULL) {
630 status=true; 677 die(STATE_UNKNOWN, _("Cannot execute strdup: %s"), strerror(errno));
631 break; 678 }
632 case STATE_DATA_END: 679 expected = STATE_DATA_END;
633 ; 680 status = true;
681 break;
682 case STATE_DATA_END:;
634 } 683 }
635 } 684 }
636 685
@@ -647,77 +696,78 @@ bool _np_state_read_file(FILE *f) {
647 */ 696 */
648void np_state_write_string(time_t data_time, char *data_string) { 697void np_state_write_string(time_t data_time, char *data_string) {
649 FILE *fp; 698 FILE *fp;
650 char *temp_file=NULL; 699 char *temp_file = NULL;
651 int fd=0, result=0; 700 int fd = 0, result = 0;
652 time_t current_time; 701 time_t current_time;
653 char *directories=NULL; 702 char *directories = NULL;
654 char *p=NULL; 703 char *p = NULL;
655 704
656 if(data_time==0) 705 if (data_time == 0) {
657 time(&current_time); 706 time(&current_time);
658 else 707 } else {
659 current_time=data_time; 708 current_time = data_time;
709 }
660 710
661 /* If file doesn't currently exist, create directories */ 711 /* If file doesn't currently exist, create directories */
662 if(access(this_monitoring_plugin->state->_filename,F_OK)!=0) { 712 if (access(this_monitoring_plugin->state->_filename, F_OK) != 0) {
663 result = asprintf(&directories, "%s", this_monitoring_plugin->state->_filename); 713 result = asprintf(&directories, "%s", this_monitoring_plugin->state->_filename);
664 if(result < 0) 714 if (result < 0) {
665 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), 715 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), strerror(errno));
666 strerror(errno)); 716 }
667 717
668 for(p=directories+1; *p; p++) { 718 for (p = directories + 1; *p; p++) {
669 if(*p=='/') { 719 if (*p == '/') {
670 *p='\0'; 720 *p = '\0';
671 if((access(directories,F_OK)!=0) && (mkdir(directories, S_IRWXU)!=0)) { 721 if ((access(directories, F_OK) != 0) && (mkdir(directories, S_IRWXU) != 0)) {
672 /* Can't free this! Otherwise error message is wrong! */ 722 /* Can't free this! Otherwise error message is wrong! */
673 /* np_free(directories); */ 723 /* np_free(directories); */
674 die(STATE_UNKNOWN, _("Cannot create directory: %s"), directories); 724 die(STATE_UNKNOWN, _("Cannot create directory: %s"), directories);
675 } 725 }
676 *p='/'; 726 *p = '/';
677 } 727 }
678 } 728 }
679 np_free(directories); 729 np_free(directories);
680 } 730 }
681 731
682 result = asprintf(&temp_file,"%s.XXXXXX",this_monitoring_plugin->state->_filename); 732 result = asprintf(&temp_file, "%s.XXXXXX", this_monitoring_plugin->state->_filename);
683 if(result < 0) 733 if (result < 0) {
684 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), 734 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), strerror(errno));
685 strerror(errno)); 735 }
686 736
687 if((fd=mkstemp(temp_file))==-1) { 737 if ((fd = mkstemp(temp_file)) == -1) {
688 np_free(temp_file); 738 np_free(temp_file);
689 die(STATE_UNKNOWN, _("Cannot create temporary filename")); 739 die(STATE_UNKNOWN, _("Cannot create temporary filename"));
690 } 740 }
691 741
692 fp=(FILE *)fdopen(fd,"w"); 742 fp = (FILE *)fdopen(fd, "w");
693 if(fp==NULL) { 743 if (fp == NULL) {
694 close(fd); 744 close(fd);
695 unlink(temp_file); 745 unlink(temp_file);
696 np_free(temp_file); 746 np_free(temp_file);
697 die(STATE_UNKNOWN, _("Unable to open temporary state file")); 747 die(STATE_UNKNOWN, _("Unable to open temporary state file"));
698 } 748 }
699 749
700 fprintf(fp,"# NP State file\n"); 750 fprintf(fp, "# NP State file\n");
701 fprintf(fp,"%d\n",NP_STATE_FORMAT_VERSION); 751 fprintf(fp, "%d\n", NP_STATE_FORMAT_VERSION);
702 fprintf(fp,"%d\n",this_monitoring_plugin->state->data_version); 752 fprintf(fp, "%d\n", this_monitoring_plugin->state->data_version);
703 fprintf(fp,"%lu\n",current_time); 753 fprintf(fp, "%lu\n", current_time);
704 fprintf(fp,"%s\n",data_string); 754 fprintf(fp, "%s\n", data_string);
705 755
706 fchmod(fd, S_IRUSR | S_IWUSR | S_IRGRP); 756 fchmod(fd, S_IRUSR | S_IWUSR | S_IRGRP);
707 757
708 fflush(fp); 758 fflush(fp);
709 759
710 result=fclose(fp); 760 result = fclose(fp);
711 761
712 fsync(fd); 762 fsync(fd);
713 763
714 if(result!=0) { 764 if (result != 0) {
715 unlink(temp_file); 765 unlink(temp_file);
716 np_free(temp_file); 766 np_free(temp_file);
717 die(STATE_UNKNOWN, _("Error writing temp file")); 767 die(STATE_UNKNOWN, _("Error writing temp file"));
718 } 768 }
719 769
720 if(rename(temp_file, this_monitoring_plugin->state->_filename)!=0) { 770 if (rename(temp_file, this_monitoring_plugin->state->_filename) != 0) {
721 unlink(temp_file); 771 unlink(temp_file);
722 np_free(temp_file); 772 np_free(temp_file);
723 die(STATE_UNKNOWN, _("Cannot rename state temp file")); 773 die(STATE_UNKNOWN, _("Cannot rename state temp file"));