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.c554
1 files changed, 308 insertions, 246 deletions
diff --git a/lib/utils_base.c b/lib/utils_base.c
index f8592f41..ff9540c7 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,48 @@ 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 if ((cmp_perfdata_value(my_range.start, value) < 1) && (cmp_perfdata_value(value, my_range.end) <= 0)) {
229 is_inside = true;
230 } else {
231 is_inside = false;
232 }
233 } else if (my_range.start_infinity == false && my_range.end_infinity == true) {
234 // range: .........|---inside---------
235 // value
236 if (cmp_perfdata_value(my_range.start, value) < 0) {
237 is_inside = true;
238 } else {
239 is_inside = false;
240 }
241 } else if (my_range.start_infinity == true && my_range.end_infinity == false) {
242 // range: -inside--------|....................
243 // value
244 if (cmp_perfdata_value(value, my_range.end) == -1) {
245 is_inside = true;
246 } else {
247 is_inside = false;
248 }
249 } else {
250 // range from -inf to inf, so always inside
251 is_inside = true;
252 }
253
254 if ((is_inside && my_range.alert_on_inside_range == INSIDE) || (!is_inside && my_range.alert_on_inside_range == OUTSIDE)) {
255 return true;
256 }
257
258 return false;
259}
260
226/* Returns true if alert should be raised based on the range */ 261/* Returns true if alert should be raised based on the range */
227bool check_range(double value, range *my_range) 262bool check_range(double value, range *my_range) {
228{
229 bool no = false; 263 bool no = false;
230 bool yes = true; 264 bool yes = true;
231 265
@@ -237,30 +271,28 @@ bool check_range(double value, range *my_range)
237 if (my_range->end_infinity == false && my_range->start_infinity == false) { 271 if (my_range->end_infinity == false && my_range->start_infinity == false) {
238 if ((my_range->start <= value) && (value <= my_range->end)) { 272 if ((my_range->start <= value) && (value <= my_range->end)) {
239 return no; 273 return no;
240 } else {
241 return yes;
242 } 274 }
243 } else if (my_range->start_infinity == false && my_range->end_infinity == true) { 275 return yes;
276 }
277
278 if (my_range->start_infinity == false && my_range->end_infinity == true) {
244 if (my_range->start <= value) { 279 if (my_range->start <= value) {
245 return no; 280 return no;
246 } else {
247 return yes;
248 } 281 }
249 } else if (my_range->start_infinity == true && my_range->end_infinity == false) { 282 return yes;
283 }
284
285 if (my_range->start_infinity == true && my_range->end_infinity == false) {
250 if (value <= my_range->end) { 286 if (value <= my_range->end) {
251 return no; 287 return no;
252 } else {
253 return yes;
254 } 288 }
255 } else { 289 return yes;
256 return no;
257 } 290 }
291 return no;
258} 292}
259 293
260/* Returns status */ 294/* Returns status */
261int 295int get_status(double value, thresholds *my_thresholds) {
262get_status(double value, thresholds *my_thresholds)
263{
264 if (my_thresholds->critical != NULL) { 296 if (my_thresholds->critical != NULL) {
265 if (check_range(value, my_thresholds->critical) == true) { 297 if (check_range(value, my_thresholds->critical) == true) {
266 return STATE_CRITICAL; 298 return STATE_CRITICAL;
@@ -274,27 +306,28 @@ get_status(double value, thresholds *my_thresholds)
274 return STATE_OK; 306 return STATE_OK;
275} 307}
276 308
277char *np_escaped_string (const char *string) { 309char *np_escaped_string(const char *string) {
278 char *data; 310 char *data;
279 int i, j=0; 311 int i;
312 int j = 0;
280 data = strdup(string); 313 data = strdup(string);
281 for (i=0; data[i]; i++) { 314 for (i = 0; data[i]; i++) {
282 if (data[i] == '\\') { 315 if (data[i] == '\\') {
283 switch(data[++i]) { 316 switch (data[++i]) {
284 case 'n': 317 case 'n':
285 data[j++] = '\n'; 318 data[j++] = '\n';
286 break; 319 break;
287 case 'r': 320 case 'r':
288 data[j++] = '\r'; 321 data[j++] = '\r';
289 break; 322 break;
290 case 't': 323 case 't':
291 data[j++] = '\t'; 324 data[j++] = '\t';
292 break; 325 break;
293 case '\\': 326 case '\\':
294 data[j++] = '\\'; 327 data[j++] = '\\';
295 break; 328 break;
296 default: 329 default:
297 data[j++] = data[i]; 330 data[j++] = data[i];
298 } 331 }
299 } else { 332 } else {
300 data[j++] = data[i]; 333 data[j++] = data[i];
@@ -313,33 +346,41 @@ int np_check_if_root(void) { return (geteuid() == 0); }
313 * data strings. 346 * data strings.
314 */ 347 */
315char *np_extract_value(const char *varlist, const char *name, char sep) { 348char *np_extract_value(const char *varlist, const char *name, char sep) {
316 char *tmp=NULL, *value=NULL; 349 char *tmp = NULL;
350 char *value = NULL;
317 int i; 351 int i;
318 352
319 while (1) { 353 while (1) {
320 /* Strip any leading space */ 354 /* Strip any leading space */
321 for (; isspace(varlist[0]); varlist++); 355 for (; isspace(varlist[0]); varlist++)
356 ;
322 357
323 if (strncmp(name, varlist, strlen(name)) == 0) { 358 if (strncmp(name, varlist, strlen(name)) == 0) {
324 varlist += strlen(name); 359 varlist += strlen(name);
325 /* strip trailing spaces */ 360 /* strip trailing spaces */
326 for (; isspace(varlist[0]); varlist++); 361 for (; isspace(varlist[0]); varlist++)
362 ;
327 363
328 if (varlist[0] == '=') { 364 if (varlist[0] == '=') {
329 /* We matched the key, go past the = sign */ 365 /* We matched the key, go past the = sign */
330 varlist++; 366 varlist++;
331 /* strip leading spaces */ 367 /* strip leading spaces */
332 for (; isspace(varlist[0]); varlist++); 368 for (; isspace(varlist[0]); varlist++)
369 ;
333 370
334 if ((tmp = index(varlist, sep))) { 371 if ((tmp = index(varlist, sep))) {
335 /* Value is delimited by a comma */ 372 /* Value is delimited by a comma */
336 if (tmp-varlist == 0) continue; 373 if (tmp - varlist == 0) {
337 value = (char *)calloc(1, tmp-varlist+1); 374 continue;
338 strncpy(value, varlist, tmp-varlist); 375 }
339 value[tmp-varlist] = '\0'; 376 value = (char *)calloc(1, tmp - varlist + 1);
377 strncpy(value, varlist, tmp - varlist);
378 value[tmp - varlist] = '\0';
340 } else { 379 } else {
341 /* Value is delimited by a \0 */ 380 /* Value is delimited by a \0 */
342 if (strlen(varlist) == 0) continue; 381 if (strlen(varlist) == 0) {
382 continue;
383 }
343 value = (char *)calloc(1, strlen(varlist) + 1); 384 value = (char *)calloc(1, strlen(varlist) + 1);
344 strncpy(value, varlist, strlen(varlist)); 385 strncpy(value, varlist, strlen(varlist));
345 value[strlen(varlist)] = '\0'; 386 value[strlen(varlist)] = '\0';
@@ -357,14 +398,16 @@ char *np_extract_value(const char *varlist, const char *name, char sep) {
357 } 398 }
358 399
359 /* Clean-up trailing spaces/newlines */ 400 /* Clean-up trailing spaces/newlines */
360 if (value) for (i=strlen(value)-1; isspace(value[i]); i--) value[i] = '\0'; 401 if (value) {
402 for (i = strlen(value) - 1; isspace(value[i]); i--) {
403 value[i] = '\0';
404 }
405 }
361 406
362 return value; 407 return value;
363} 408}
364 409
365const char * 410const char *state_text(int result) {
366state_text (int result)
367{
368 switch (result) { 411 switch (result) {
369 case STATE_OK: 412 case STATE_OK:
370 return "OK"; 413 return "OK";
@@ -383,15 +426,19 @@ state_text (int result)
383 * Read a string representing a state (ok, warning... or numeric: 0, 1) and 426 * Read a string representing a state (ok, warning... or numeric: 0, 1) and
384 * return the corresponding STATE_ value or ERROR) 427 * return the corresponding STATE_ value or ERROR)
385 */ 428 */
386int mp_translate_state (char *state_text) { 429int mp_translate_state(char *state_text) {
387 if (!strcasecmp(state_text,"OK") || !strcmp(state_text,"0")) 430 if (!strcasecmp(state_text, "OK") || !strcmp(state_text, "0")) {
388 return STATE_OK; 431 return STATE_OK;
389 if (!strcasecmp(state_text,"WARNING") || !strcmp(state_text,"1")) 432 }
433 if (!strcasecmp(state_text, "WARNING") || !strcmp(state_text, "1")) {
390 return STATE_WARNING; 434 return STATE_WARNING;
391 if (!strcasecmp(state_text,"CRITICAL") || !strcmp(state_text,"2")) 435 }
436 if (!strcasecmp(state_text, "CRITICAL") || !strcmp(state_text, "2")) {
392 return STATE_CRITICAL; 437 return STATE_CRITICAL;
393 if (!strcasecmp(state_text,"UNKNOWN") || !strcmp(state_text,"3")) 438 }
439 if (!strcasecmp(state_text, "UNKNOWN") || !strcmp(state_text, "3")) {
394 return STATE_UNKNOWN; 440 return STATE_UNKNOWN;
441 }
395 return ERROR; 442 return ERROR;
396} 443}
397 444
@@ -400,11 +447,11 @@ int mp_translate_state (char *state_text) {
400 * hopefully a unique key per service/plugin invocation. Use the extra-opts 447 * hopefully a unique key per service/plugin invocation. Use the extra-opts
401 * parse of argv, so that uniqueness in parameters are reflected there. 448 * parse of argv, so that uniqueness in parameters are reflected there.
402 */ 449 */
403char *_np_state_generate_key() { 450char *_np_state_generate_key(void) {
404 int i; 451 int i;
405 char **argv = this_monitoring_plugin->argv; 452 char **argv = this_monitoring_plugin->argv;
406 char keyname[41]; 453 char keyname[41];
407 char *p=NULL; 454 char *p = NULL;
408 455
409 unsigned char result[256]; 456 unsigned char result[256];
410 457
@@ -418,7 +465,7 @@ char *_np_state_generate_key() {
418 465
419 EVP_DigestInit(ctx, EVP_sha256()); 466 EVP_DigestInit(ctx, EVP_sha256());
420 467
421 for(i=0; i<this_monitoring_plugin->argc; i++) { 468 for (i = 0; i < this_monitoring_plugin->argc; i++) {
422 EVP_DigestUpdate(ctx, argv[i], strlen(argv[i])); 469 EVP_DigestUpdate(ctx, argv[i], strlen(argv[i]));
423 } 470 }
424 471
@@ -427,28 +474,28 @@ char *_np_state_generate_key() {
427 474
428 struct sha256_ctx ctx; 475 struct sha256_ctx ctx;
429 476
430 for(i=0; i<this_monitoring_plugin->argc; i++) { 477 for (i = 0; i < this_monitoring_plugin->argc; i++) {
431 sha256_process_bytes(argv[i], strlen(argv[i]), &ctx); 478 sha256_process_bytes(argv[i], strlen(argv[i]), &ctx);
432 } 479 }
433 480
434 sha256_finish_ctx(&ctx, result); 481 sha256_finish_ctx(&ctx, result);
435#endif // FOUNDOPENSSL 482#endif // FOUNDOPENSSL
436 483
437 for (i=0; i<20; ++i) { 484 for (i = 0; i < 20; ++i) {
438 sprintf(&keyname[2*i], "%02x", result[i]); 485 sprintf(&keyname[2 * i], "%02x", result[i]);
439 } 486 }
440 487
441 keyname[40]='\0'; 488 keyname[40] = '\0';
442 489
443 p = strdup(keyname); 490 p = strdup(keyname);
444 if(p==NULL) { 491 if (p == NULL) {
445 die(STATE_UNKNOWN, _("Cannot execute strdup: %s"), strerror(errno)); 492 die(STATE_UNKNOWN, _("Cannot execute strdup: %s"), strerror(errno));
446 } 493 }
447 return p; 494 return p;
448} 495}
449 496
450void _cleanup_state_data() { 497void _cleanup_state_data(void) {
451 if (this_monitoring_plugin->state->state_data!=NULL) { 498 if (this_monitoring_plugin->state->state_data != NULL) {
452 np_free(this_monitoring_plugin->state->state_data->data); 499 np_free(this_monitoring_plugin->state->state_data->data);
453 np_free(this_monitoring_plugin->state->state_data); 500 np_free(this_monitoring_plugin->state->state_data);
454 } 501 }
@@ -459,19 +506,21 @@ void _cleanup_state_data() {
459 * envvar NAGIOS_PLUGIN_STATE_DIRECTORY 506 * envvar NAGIOS_PLUGIN_STATE_DIRECTORY
460 * statically compiled shared state directory 507 * statically compiled shared state directory
461 */ 508 */
462char* _np_state_calculate_location_prefix(){ 509char *_np_state_calculate_location_prefix(void) {
463 char *env_dir; 510 char *env_dir;
464 511
465 /* Do not allow passing MP_STATE_PATH in setuid plugins 512 /* Do not allow passing MP_STATE_PATH in setuid plugins
466 * for security reasons */ 513 * for security reasons */
467 if (!mp_suid()) { 514 if (!mp_suid()) {
468 env_dir = getenv("MP_STATE_PATH"); 515 env_dir = getenv("MP_STATE_PATH");
469 if(env_dir && env_dir[0] != '\0') 516 if (env_dir && env_dir[0] != '\0') {
470 return env_dir; 517 return env_dir;
518 }
471 /* This is the former ENV, for backward-compatibility */ 519 /* This is the former ENV, for backward-compatibility */
472 env_dir = getenv("NAGIOS_PLUGIN_STATE_DIRECTORY"); 520 env_dir = getenv("NAGIOS_PLUGIN_STATE_DIRECTORY");
473 if(env_dir && env_dir[0] != '\0') 521 if (env_dir && env_dir[0] != '\0') {
474 return env_dir; 522 return env_dir;
523 }
475 } 524 }
476 525
477 return NP_STATE_DIR_PREFIX; 526 return NP_STATE_DIR_PREFIX;
@@ -486,46 +535,47 @@ void np_enable_state(char *keyname, int expected_data_version) {
486 state_key *this_state = NULL; 535 state_key *this_state = NULL;
487 char *temp_filename = NULL; 536 char *temp_filename = NULL;
488 char *temp_keyname = NULL; 537 char *temp_keyname = NULL;
489 char *p=NULL; 538 char *p = NULL;
490 int ret; 539 int ret;
491 540
492 if(this_monitoring_plugin==NULL) 541 if (this_monitoring_plugin == NULL) {
493 die(STATE_UNKNOWN, _("This requires np_init to be called")); 542 die(STATE_UNKNOWN, _("This requires np_init to be called"));
543 }
494 544
495 this_state = (state_key *) calloc(1, sizeof(state_key)); 545 this_state = (state_key *)calloc(1, sizeof(state_key));
496 if(this_state==NULL) 546 if (this_state == NULL) {
497 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), 547 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), strerror(errno));
498 strerror(errno)); 548 }
499 549
500 if(keyname==NULL) { 550 if (keyname == NULL) {
501 temp_keyname = _np_state_generate_key(); 551 temp_keyname = _np_state_generate_key();
502 } else { 552 } else {
503 temp_keyname = strdup(keyname); 553 temp_keyname = strdup(keyname);
504 if(temp_keyname==NULL) 554 if (temp_keyname == NULL) {
505 die(STATE_UNKNOWN, _("Cannot execute strdup: %s"), strerror(errno)); 555 die(STATE_UNKNOWN, _("Cannot execute strdup: %s"), strerror(errno));
556 }
506 } 557 }
507 /* Die if invalid characters used for keyname */ 558 /* Die if invalid characters used for keyname */
508 p = temp_keyname; 559 p = temp_keyname;
509 while(*p!='\0') { 560 while (*p != '\0') {
510 if(! (isalnum(*p) || *p == '_')) { 561 if (!(isalnum(*p) || *p == '_')) {
511 die(STATE_UNKNOWN, _("Invalid character for keyname - only alphanumerics or '_'")); 562 die(STATE_UNKNOWN, _("Invalid character for keyname - only alphanumerics or '_'"));
512 } 563 }
513 p++; 564 p++;
514 } 565 }
515 this_state->name=temp_keyname; 566 this_state->name = temp_keyname;
516 this_state->plugin_name=this_monitoring_plugin->plugin_name; 567 this_state->plugin_name = this_monitoring_plugin->plugin_name;
517 this_state->data_version=expected_data_version; 568 this_state->data_version = expected_data_version;
518 this_state->state_data=NULL; 569 this_state->state_data = NULL;
519 570
520 /* Calculate filename */ 571 /* Calculate filename */
521 ret = asprintf(&temp_filename, "%s/%lu/%s/%s", 572 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(), 573 this_monitoring_plugin->plugin_name, this_state->name);
523 this_monitoring_plugin->plugin_name, this_state->name); 574 if (ret < 0) {
524 if (ret < 0) 575 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), strerror(errno));
525 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), 576 }
526 strerror(errno));
527 577
528 this_state->_filename=temp_filename; 578 this_state->_filename = temp_filename;
529 579
530 this_monitoring_plugin->state = this_state; 580 this_monitoring_plugin->state = this_state;
531} 581}
@@ -537,24 +587,25 @@ void np_enable_state(char *keyname, int expected_data_version) {
537 * If numerically lower, then return as no previous state. die with UNKNOWN 587 * If numerically lower, then return as no previous state. die with UNKNOWN
538 * if exceptional error. 588 * if exceptional error.
539 */ 589 */
540state_data *np_state_read() { 590state_data *np_state_read(void) {
541 state_data *this_state_data=NULL; 591 state_data *this_state_data = NULL;
542 FILE *statefile; 592 FILE *statefile;
543 bool rc = false; 593 bool rc = false;
544 594
545 if(this_monitoring_plugin==NULL) 595 if (this_monitoring_plugin == NULL) {
546 die(STATE_UNKNOWN, _("This requires np_init to be called")); 596 die(STATE_UNKNOWN, _("This requires np_init to be called"));
597 }
547 598
548 /* Open file. If this fails, no previous state found */ 599 /* Open file. If this fails, no previous state found */
549 statefile = fopen( this_monitoring_plugin->state->_filename, "r" ); 600 statefile = fopen(this_monitoring_plugin->state->_filename, "r");
550 if(statefile!=NULL) { 601 if (statefile != NULL) {
551 602
552 this_state_data = (state_data *) calloc(1, sizeof(state_data)); 603 this_state_data = (state_data *)calloc(1, sizeof(state_data));
553 if(this_state_data==NULL) 604 if (this_state_data == NULL) {
554 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), 605 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), strerror(errno));
555 strerror(errno)); 606 }
556 607
557 this_state_data->data=NULL; 608 this_state_data->data = NULL;
558 this_monitoring_plugin->state->state_data = this_state_data; 609 this_monitoring_plugin->state->state_data = this_state_data;
559 610
560 rc = _np_state_read_file(statefile); 611 rc = _np_state_read_file(statefile);
@@ -562,7 +613,7 @@ state_data *np_state_read() {
562 fclose(statefile); 613 fclose(statefile);
563 } 614 }
564 615
565 if(!rc) { 616 if (!rc) {
566 _cleanup_state_data(); 617 _cleanup_state_data();
567 } 618 }
568 619
@@ -577,60 +628,70 @@ bool _np_state_read_file(FILE *f) {
577 size_t pos; 628 size_t pos;
578 char *line; 629 char *line;
579 int i; 630 int i;
580 int failure=0; 631 int failure = 0;
581 time_t current_time, data_time; 632 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; 633 enum {
634 STATE_FILE_VERSION,
635 STATE_DATA_VERSION,
636 STATE_DATA_TIME,
637 STATE_DATA_TEXT,
638 STATE_DATA_END
639 } expected = STATE_FILE_VERSION;
583 640
584 time(&current_time); 641 time(&current_time);
585 642
586 /* Note: This introduces a limit of 1024 bytes in the string data */ 643 /* Note: This introduces a limit of 1024 bytes in the string data */
587 line = (char *) calloc(1, 1024); 644 line = (char *)calloc(1, 1024);
588 if(line==NULL) 645 if (line == NULL) {
589 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), 646 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), strerror(errno));
590 strerror(errno)); 647 }
591 648
592 while(!failure && (fgets(line,1024,f))!=NULL){ 649 while (!failure && (fgets(line, 1024, f)) != NULL) {
593 pos=strlen(line); 650 pos = strlen(line);
594 if(line[pos-1]=='\n') { 651 if (line[pos - 1] == '\n') {
595 line[pos-1]='\0'; 652 line[pos - 1] = '\0';
596 } 653 }
597 654
598 if(line[0] == '#') continue; 655 if (line[0] == '#') {
656 continue;
657 }
599 658
600 switch(expected) { 659 switch (expected) {
601 case STATE_FILE_VERSION: 660 case STATE_FILE_VERSION:
602 i=atoi(line); 661 i = atoi(line);
603 if(i!=NP_STATE_FORMAT_VERSION) 662 if (i != NP_STATE_FORMAT_VERSION) {
604 failure++; 663 failure++;
605 else 664 } else {
606 expected=STATE_DATA_VERSION; 665 expected = STATE_DATA_VERSION;
607 break; 666 }
608 case STATE_DATA_VERSION: 667 break;
609 i=atoi(line); 668 case STATE_DATA_VERSION:
610 if(i != this_monitoring_plugin->state->data_version) 669 i = atoi(line);
611 failure++; 670 if (i != this_monitoring_plugin->state->data_version) {
612 else 671 failure++;
613 expected=STATE_DATA_TIME; 672 } else {
614 break; 673 expected = STATE_DATA_TIME;
615 case STATE_DATA_TIME: 674 }
616 /* If time > now, error */ 675 break;
617 data_time=strtoul(line,NULL,10); 676 case STATE_DATA_TIME:
618 if(data_time > current_time) 677 /* If time > now, error */
619 failure++; 678 data_time = strtoul(line, NULL, 10);
620 else { 679 if (data_time > current_time) {
621 this_monitoring_plugin->state->state_data->time = data_time; 680 failure++;
622 expected=STATE_DATA_TEXT; 681 } else {
623 } 682 this_monitoring_plugin->state->state_data->time = data_time;
624 break; 683 expected = STATE_DATA_TEXT;
625 case STATE_DATA_TEXT: 684 }
626 this_monitoring_plugin->state->state_data->data = strdup(line); 685 break;
627 if(this_monitoring_plugin->state->state_data->data==NULL) 686 case STATE_DATA_TEXT:
628 die(STATE_UNKNOWN, _("Cannot execute strdup: %s"), strerror(errno)); 687 this_monitoring_plugin->state->state_data->data = strdup(line);
629 expected=STATE_DATA_END; 688 if (this_monitoring_plugin->state->state_data->data == NULL) {
630 status=true; 689 die(STATE_UNKNOWN, _("Cannot execute strdup: %s"), strerror(errno));
631 break; 690 }
632 case STATE_DATA_END: 691 expected = STATE_DATA_END;
633 ; 692 status = true;
693 break;
694 case STATE_DATA_END:;
634 } 695 }
635 } 696 }
636 697
@@ -647,77 +708,78 @@ bool _np_state_read_file(FILE *f) {
647 */ 708 */
648void np_state_write_string(time_t data_time, char *data_string) { 709void np_state_write_string(time_t data_time, char *data_string) {
649 FILE *fp; 710 FILE *fp;
650 char *temp_file=NULL; 711 char *temp_file = NULL;
651 int fd=0, result=0; 712 int fd = 0, result = 0;
652 time_t current_time; 713 time_t current_time;
653 char *directories=NULL; 714 char *directories = NULL;
654 char *p=NULL; 715 char *p = NULL;
655 716
656 if(data_time==0) 717 if (data_time == 0) {
657 time(&current_time); 718 time(&current_time);
658 else 719 } else {
659 current_time=data_time; 720 current_time = data_time;
721 }
660 722
661 /* If file doesn't currently exist, create directories */ 723 /* If file doesn't currently exist, create directories */
662 if(access(this_monitoring_plugin->state->_filename,F_OK)!=0) { 724 if (access(this_monitoring_plugin->state->_filename, F_OK) != 0) {
663 result = asprintf(&directories, "%s", this_monitoring_plugin->state->_filename); 725 result = asprintf(&directories, "%s", this_monitoring_plugin->state->_filename);
664 if(result < 0) 726 if (result < 0) {
665 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), 727 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), strerror(errno));
666 strerror(errno)); 728 }
667 729
668 for(p=directories+1; *p; p++) { 730 for (p = directories + 1; *p; p++) {
669 if(*p=='/') { 731 if (*p == '/') {
670 *p='\0'; 732 *p = '\0';
671 if((access(directories,F_OK)!=0) && (mkdir(directories, S_IRWXU)!=0)) { 733 if ((access(directories, F_OK) != 0) && (mkdir(directories, S_IRWXU) != 0)) {
672 /* Can't free this! Otherwise error message is wrong! */ 734 /* Can't free this! Otherwise error message is wrong! */
673 /* np_free(directories); */ 735 /* np_free(directories); */
674 die(STATE_UNKNOWN, _("Cannot create directory: %s"), directories); 736 die(STATE_UNKNOWN, _("Cannot create directory: %s"), directories);
675 } 737 }
676 *p='/'; 738 *p = '/';
677 } 739 }
678 } 740 }
679 np_free(directories); 741 np_free(directories);
680 } 742 }
681 743
682 result = asprintf(&temp_file,"%s.XXXXXX",this_monitoring_plugin->state->_filename); 744 result = asprintf(&temp_file, "%s.XXXXXX", this_monitoring_plugin->state->_filename);
683 if(result < 0) 745 if (result < 0) {
684 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), 746 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), strerror(errno));
685 strerror(errno)); 747 }
686 748
687 if((fd=mkstemp(temp_file))==-1) { 749 if ((fd = mkstemp(temp_file)) == -1) {
688 np_free(temp_file); 750 np_free(temp_file);
689 die(STATE_UNKNOWN, _("Cannot create temporary filename")); 751 die(STATE_UNKNOWN, _("Cannot create temporary filename"));
690 } 752 }
691 753
692 fp=(FILE *)fdopen(fd,"w"); 754 fp = (FILE *)fdopen(fd, "w");
693 if(fp==NULL) { 755 if (fp == NULL) {
694 close(fd); 756 close(fd);
695 unlink(temp_file); 757 unlink(temp_file);
696 np_free(temp_file); 758 np_free(temp_file);
697 die(STATE_UNKNOWN, _("Unable to open temporary state file")); 759 die(STATE_UNKNOWN, _("Unable to open temporary state file"));
698 } 760 }
699 761
700 fprintf(fp,"# NP State file\n"); 762 fprintf(fp, "# NP State file\n");
701 fprintf(fp,"%d\n",NP_STATE_FORMAT_VERSION); 763 fprintf(fp, "%d\n", NP_STATE_FORMAT_VERSION);
702 fprintf(fp,"%d\n",this_monitoring_plugin->state->data_version); 764 fprintf(fp, "%d\n", this_monitoring_plugin->state->data_version);
703 fprintf(fp,"%lu\n",current_time); 765 fprintf(fp, "%lu\n", current_time);
704 fprintf(fp,"%s\n",data_string); 766 fprintf(fp, "%s\n", data_string);
705 767
706 fchmod(fd, S_IRUSR | S_IWUSR | S_IRGRP); 768 fchmod(fd, S_IRUSR | S_IWUSR | S_IRGRP);
707 769
708 fflush(fp); 770 fflush(fp);
709 771
710 result=fclose(fp); 772 result = fclose(fp);
711 773
712 fsync(fd); 774 fsync(fd);
713 775
714 if(result!=0) { 776 if (result != 0) {
715 unlink(temp_file); 777 unlink(temp_file);
716 np_free(temp_file); 778 np_free(temp_file);
717 die(STATE_UNKNOWN, _("Error writing temp file")); 779 die(STATE_UNKNOWN, _("Error writing temp file"));
718 } 780 }
719 781
720 if(rename(temp_file, this_monitoring_plugin->state->_filename)!=0) { 782 if (rename(temp_file, this_monitoring_plugin->state->_filename) != 0) {
721 unlink(temp_file); 783 unlink(temp_file);
722 np_free(temp_file); 784 np_free(temp_file);
723 die(STATE_UNKNOWN, _("Cannot rename state temp file")); 785 die(STATE_UNKNOWN, _("Cannot rename state temp file"));