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.c459
1 files changed, 50 insertions, 409 deletions
diff --git a/lib/utils_base.c b/lib/utils_base.c
index ff9540c7..28e6dc47 100644
--- a/lib/utils_base.c
+++ b/lib/utils_base.c
@@ -25,6 +25,7 @@
25 *****************************************************************************/ 25 *****************************************************************************/
26 26
27#include "../plugins/common.h" 27#include "../plugins/common.h"
28#include "states.h"
28#include <stdarg.h> 29#include <stdarg.h>
29#include "utils_base.h" 30#include "utils_base.h"
30#include <ctype.h> 31#include <ctype.h>
@@ -33,20 +34,20 @@
33#include <unistd.h> 34#include <unistd.h>
34#include <sys/types.h> 35#include <sys/types.h>
35 36
36#define np_free(ptr) \ 37#define np_free(ptr) \
37 { \ 38 { \
38 if (ptr) { \ 39 if (ptr) { \
39 free(ptr); \ 40 free(ptr); \
40 ptr = NULL; \ 41 ptr = NULL; \
41 } \ 42 } \
42 } 43 }
43 44
44monitoring_plugin *this_monitoring_plugin = NULL; 45monitoring_plugin *this_monitoring_plugin = NULL;
45 46
46int timeout_state = STATE_CRITICAL; 47mp_state_enum timeout_state = STATE_CRITICAL;
47unsigned int timeout_interval = DEFAULT_SOCKET_TIMEOUT; 48unsigned int timeout_interval = DEFAULT_SOCKET_TIMEOUT;
48 49
49bool _np_state_read_file(FILE *); 50bool _np_state_read_file(FILE *state_file);
50 51
51void np_init(char *plugin_name, int argc, char **argv) { 52void np_init(char *plugin_name, int argc, char **argv) {
52 if (this_monitoring_plugin == NULL) { 53 if (this_monitoring_plugin == NULL) {
@@ -74,14 +75,6 @@ void np_set_args(int argc, char **argv) {
74 75
75void np_cleanup(void) { 76void np_cleanup(void) {
76 if (this_monitoring_plugin != NULL) { 77 if (this_monitoring_plugin != NULL) {
77 if (this_monitoring_plugin->state != NULL) {
78 if (this_monitoring_plugin->state->state_data) {
79 np_free(this_monitoring_plugin->state->state_data->data);
80 np_free(this_monitoring_plugin->state->state_data);
81 }
82 np_free(this_monitoring_plugin->state->name);
83 np_free(this_monitoring_plugin->state);
84 }
85 np_free(this_monitoring_plugin->plugin_name); 78 np_free(this_monitoring_plugin->plugin_name);
86 np_free(this_monitoring_plugin); 79 np_free(this_monitoring_plugin);
87 } 80 }
@@ -153,7 +146,8 @@ range *parse_range_string(char *str) {
153 set_range_end(temp_range, end); 146 set_range_end(temp_range, end);
154 } 147 }
155 148
156 if (temp_range->start_infinity == true || temp_range->end_infinity == true || temp_range->start <= temp_range->end) { 149 if (temp_range->start_infinity || temp_range->end_infinity ||
150 temp_range->start <= temp_range->end) {
157 return temp_range; 151 return temp_range;
158 } 152 }
159 free(temp_range); 153 free(temp_range);
@@ -205,12 +199,14 @@ void print_thresholds(const char *threshold_name, thresholds *my_threshold) {
205 printf("Threshold not set"); 199 printf("Threshold not set");
206 } else { 200 } else {
207 if (my_threshold->warning) { 201 if (my_threshold->warning) {
208 printf("Warning: start=%g end=%g; ", my_threshold->warning->start, my_threshold->warning->end); 202 printf("Warning: start=%g end=%g; ", my_threshold->warning->start,
203 my_threshold->warning->end);
209 } else { 204 } else {
210 printf("Warning not set; "); 205 printf("Warning not set; ");
211 } 206 }
212 if (my_threshold->critical) { 207 if (my_threshold->critical) {
213 printf("Critical: start=%g end=%g", my_threshold->critical->start, my_threshold->critical->end); 208 printf("Critical: start=%g end=%g", my_threshold->critical->start,
209 my_threshold->critical->end);
214 } else { 210 } else {
215 printf("Critical not set"); 211 printf("Critical not set");
216 } 212 }
@@ -222,36 +218,26 @@ void print_thresholds(const char *threshold_name, thresholds *my_threshold) {
222bool mp_check_range(const mp_perfdata_value value, const mp_range my_range) { 218bool mp_check_range(const mp_perfdata_value value, const mp_range my_range) {
223 bool is_inside = false; 219 bool is_inside = false;
224 220
225 if (my_range.end_infinity == false && my_range.start_infinity == false) { 221 if (!my_range.end_infinity && !my_range.start_infinity) {
226 // range: .........|---inside---|........... 222 // range: .........|---inside---|...........
227 // value 223 // value
228 if ((cmp_perfdata_value(my_range.start, value) < 1) && (cmp_perfdata_value(value, my_range.end) <= 0)) { 224 is_inside = ((cmp_perfdata_value(value, my_range.start) >= 0) &&
229 is_inside = true; 225 (cmp_perfdata_value(value, my_range.end) <= 0));
230 } else { 226 } else if (!my_range.start_infinity && my_range.end_infinity) {
231 is_inside = false;
232 }
233 } else if (my_range.start_infinity == false && my_range.end_infinity == true) {
234 // range: .........|---inside--------- 227 // range: .........|---inside---------
235 // value 228 // value
236 if (cmp_perfdata_value(my_range.start, value) < 0) { 229 is_inside = (cmp_perfdata_value(value, my_range.start) >= 0);
237 is_inside = true; 230 } else if (my_range.start_infinity && !my_range.end_infinity) {
238 } else {
239 is_inside = false;
240 }
241 } else if (my_range.start_infinity == true && my_range.end_infinity == false) {
242 // range: -inside--------|.................... 231 // range: -inside--------|....................
243 // value 232 // value
244 if (cmp_perfdata_value(value, my_range.end) == -1) { 233 is_inside = (cmp_perfdata_value(value, my_range.end) == -1);
245 is_inside = true;
246 } else {
247 is_inside = false;
248 }
249 } else { 234 } else {
250 // range from -inf to inf, so always inside 235 // range from -inf to inf, so always inside
251 is_inside = true; 236 is_inside = true;
252 } 237 }
253 238
254 if ((is_inside && my_range.alert_on_inside_range == INSIDE) || (!is_inside && my_range.alert_on_inside_range == OUTSIDE)) { 239 if ((is_inside && my_range.alert_on_inside_range == INSIDE) ||
240 (!is_inside && my_range.alert_on_inside_range == OUTSIDE)) {
255 return true; 241 return true;
256 } 242 }
257 243
@@ -268,21 +254,21 @@ bool check_range(double value, range *my_range) {
268 yes = false; 254 yes = false;
269 } 255 }
270 256
271 if (my_range->end_infinity == false && my_range->start_infinity == false) { 257 if (!my_range->end_infinity && !my_range->start_infinity) {
272 if ((my_range->start <= value) && (value <= my_range->end)) { 258 if ((my_range->start <= value) && (value <= my_range->end)) {
273 return no; 259 return no;
274 } 260 }
275 return yes; 261 return yes;
276 } 262 }
277 263
278 if (my_range->start_infinity == false && my_range->end_infinity == true) { 264 if (!my_range->start_infinity && my_range->end_infinity) {
279 if (my_range->start <= value) { 265 if (my_range->start <= value) {
280 return no; 266 return no;
281 } 267 }
282 return yes; 268 return yes;
283 } 269 }
284 270
285 if (my_range->start_infinity == true && my_range->end_infinity == false) { 271 if (my_range->start_infinity && !my_range->end_infinity) {
286 if (value <= my_range->end) { 272 if (value <= my_range->end) {
287 return no; 273 return no;
288 } 274 }
@@ -292,14 +278,14 @@ bool check_range(double value, range *my_range) {
292} 278}
293 279
294/* Returns status */ 280/* Returns status */
295int get_status(double value, thresholds *my_thresholds) { 281mp_state_enum get_status(double value, thresholds *my_thresholds) {
296 if (my_thresholds->critical != NULL) { 282 if (my_thresholds->critical != NULL) {
297 if (check_range(value, my_thresholds->critical) == true) { 283 if (check_range(value, my_thresholds->critical)) {
298 return STATE_CRITICAL; 284 return STATE_CRITICAL;
299 } 285 }
300 } 286 }
301 if (my_thresholds->warning != NULL) { 287 if (my_thresholds->warning != NULL) {
302 if (check_range(value, my_thresholds->warning) == true) { 288 if (check_range(value, my_thresholds->warning)) {
303 return STATE_WARNING; 289 return STATE_WARNING;
304 } 290 }
305 } 291 }
@@ -308,32 +294,31 @@ int get_status(double value, thresholds *my_thresholds) {
308 294
309char *np_escaped_string(const char *string) { 295char *np_escaped_string(const char *string) {
310 char *data; 296 char *data;
311 int i; 297 int write_index = 0;
312 int j = 0;
313 data = strdup(string); 298 data = strdup(string);
314 for (i = 0; data[i]; i++) { 299 for (int i = 0; data[i]; i++) {
315 if (data[i] == '\\') { 300 if (data[i] == '\\') {
316 switch (data[++i]) { 301 switch (data[++i]) {
317 case 'n': 302 case 'n':
318 data[j++] = '\n'; 303 data[write_index++] = '\n';
319 break; 304 break;
320 case 'r': 305 case 'r':
321 data[j++] = '\r'; 306 data[write_index++] = '\r';
322 break; 307 break;
323 case 't': 308 case 't':
324 data[j++] = '\t'; 309 data[write_index++] = '\t';
325 break; 310 break;
326 case '\\': 311 case '\\':
327 data[j++] = '\\'; 312 data[write_index++] = '\\';
328 break; 313 break;
329 default: 314 default:
330 data[j++] = data[i]; 315 data[write_index++] = data[i];
331 } 316 }
332 } else { 317 } else {
333 data[j++] = data[i]; 318 data[write_index++] = data[i];
334 } 319 }
335 } 320 }
336 data[j] = '\0'; 321 data[write_index] = '\0';
337 return data; 322 return data;
338} 323}
339 324
@@ -348,33 +333,35 @@ int np_check_if_root(void) { return (geteuid() == 0); }
348char *np_extract_value(const char *varlist, const char *name, char sep) { 333char *np_extract_value(const char *varlist, const char *name, char sep) {
349 char *tmp = NULL; 334 char *tmp = NULL;
350 char *value = NULL; 335 char *value = NULL;
351 int i;
352 336
353 while (1) { 337 while (true) {
354 /* Strip any leading space */ 338 /* Strip any leading space */
355 for (; isspace(varlist[0]); varlist++) 339 for (; isspace(varlist[0]); varlist++) {
356 ; 340 ;
341 }
357 342
358 if (strncmp(name, varlist, strlen(name)) == 0) { 343 if (strncmp(name, varlist, strlen(name)) == 0) {
359 varlist += strlen(name); 344 varlist += strlen(name);
360 /* strip trailing spaces */ 345 /* strip trailing spaces */
361 for (; isspace(varlist[0]); varlist++) 346 for (; isspace(varlist[0]); varlist++) {
362 ; 347 ;
348 }
363 349
364 if (varlist[0] == '=') { 350 if (varlist[0] == '=') {
365 /* We matched the key, go past the = sign */ 351 /* We matched the key, go past the = sign */
366 varlist++; 352 varlist++;
367 /* strip leading spaces */ 353 /* strip leading spaces */
368 for (; isspace(varlist[0]); varlist++) 354 for (; isspace(varlist[0]); varlist++) {
369 ; 355 ;
356 }
370 357
371 if ((tmp = index(varlist, sep))) { 358 if ((tmp = index(varlist, sep))) {
372 /* Value is delimited by a comma */ 359 /* Value is delimited by a comma */
373 if (tmp - varlist == 0) { 360 if (tmp - varlist == 0) {
374 continue; 361 continue;
375 } 362 }
376 value = (char *)calloc(1, tmp - varlist + 1); 363 value = (char *)calloc(1, (unsigned long)(tmp - varlist + 1));
377 strncpy(value, varlist, tmp - varlist); 364 strncpy(value, varlist, (unsigned long)(tmp - varlist));
378 value[tmp - varlist] = '\0'; 365 value[tmp - varlist] = '\0';
379 } else { 366 } else {
380 /* Value is delimited by a \0 */ 367 /* Value is delimited by a \0 */
@@ -399,7 +386,7 @@ char *np_extract_value(const char *varlist, const char *name, char sep) {
399 386
400 /* Clean-up trailing spaces/newlines */ 387 /* Clean-up trailing spaces/newlines */
401 if (value) { 388 if (value) {
402 for (i = strlen(value) - 1; isspace(value[i]); i--) { 389 for (unsigned long i = strlen(value) - 1; isspace(value[i]); i--) {
403 value[i] = '\0'; 390 value[i] = '\0';
404 } 391 }
405 } 392 }
@@ -407,7 +394,7 @@ char *np_extract_value(const char *varlist, const char *name, char sep) {
407 return value; 394 return value;
408} 395}
409 396
410const char *state_text(int result) { 397const char *state_text(mp_state_enum result) {
411 switch (result) { 398 switch (result) {
412 case STATE_OK: 399 case STATE_OK:
413 return "OK"; 400 return "OK";
@@ -441,349 +428,3 @@ int mp_translate_state(char *state_text) {
441 } 428 }
442 return ERROR; 429 return ERROR;
443} 430}
444
445/*
446 * Returns a string to use as a keyname, based on an md5 hash of argv, thus
447 * hopefully a unique key per service/plugin invocation. Use the extra-opts
448 * parse of argv, so that uniqueness in parameters are reflected there.
449 */
450char *_np_state_generate_key(void) {
451 int i;
452 char **argv = this_monitoring_plugin->argv;
453 char keyname[41];
454 char *p = NULL;
455
456 unsigned char result[256];
457
458#ifdef USE_OPENSSL
459 /*
460 * This code path is chosen if openssl is available (which should be the most common
461 * scenario). Alternatively, the gnulib implementation/
462 *
463 */
464 EVP_MD_CTX *ctx = EVP_MD_CTX_new();
465
466 EVP_DigestInit(ctx, EVP_sha256());
467
468 for (i = 0; i < this_monitoring_plugin->argc; i++) {
469 EVP_DigestUpdate(ctx, argv[i], strlen(argv[i]));
470 }
471
472 EVP_DigestFinal(ctx, result, NULL);
473#else
474
475 struct sha256_ctx ctx;
476
477 for (i = 0; i < this_monitoring_plugin->argc; i++) {
478 sha256_process_bytes(argv[i], strlen(argv[i]), &ctx);
479 }
480
481 sha256_finish_ctx(&ctx, result);
482#endif // FOUNDOPENSSL
483
484 for (i = 0; i < 20; ++i) {
485 sprintf(&keyname[2 * i], "%02x", result[i]);
486 }
487
488 keyname[40] = '\0';
489
490 p = strdup(keyname);
491 if (p == NULL) {
492 die(STATE_UNKNOWN, _("Cannot execute strdup: %s"), strerror(errno));
493 }
494 return p;
495}
496
497void _cleanup_state_data(void) {
498 if (this_monitoring_plugin->state->state_data != NULL) {
499 np_free(this_monitoring_plugin->state->state_data->data);
500 np_free(this_monitoring_plugin->state->state_data);
501 }
502}
503
504/*
505 * Internal function. Returns either:
506 * envvar NAGIOS_PLUGIN_STATE_DIRECTORY
507 * statically compiled shared state directory
508 */
509char *_np_state_calculate_location_prefix(void) {
510 char *env_dir;
511
512 /* Do not allow passing MP_STATE_PATH in setuid plugins
513 * for security reasons */
514 if (!mp_suid()) {
515 env_dir = getenv("MP_STATE_PATH");
516 if (env_dir && env_dir[0] != '\0') {
517 return env_dir;
518 }
519 /* This is the former ENV, for backward-compatibility */
520 env_dir = getenv("NAGIOS_PLUGIN_STATE_DIRECTORY");
521 if (env_dir && env_dir[0] != '\0') {
522 return env_dir;
523 }
524 }
525
526 return NP_STATE_DIR_PREFIX;
527}
528
529/*
530 * Initiatializer for state routines.
531 * Sets variables. Generates filename. Returns np_state_key. die with
532 * UNKNOWN if exception
533 */
534void np_enable_state(char *keyname, int expected_data_version) {
535 state_key *this_state = NULL;
536 char *temp_filename = NULL;
537 char *temp_keyname = NULL;
538 char *p = NULL;
539 int ret;
540
541 if (this_monitoring_plugin == NULL) {
542 die(STATE_UNKNOWN, _("This requires np_init to be called"));
543 }
544
545 this_state = (state_key *)calloc(1, sizeof(state_key));
546 if (this_state == NULL) {
547 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), strerror(errno));
548 }
549
550 if (keyname == NULL) {
551 temp_keyname = _np_state_generate_key();
552 } else {
553 temp_keyname = strdup(keyname);
554 if (temp_keyname == NULL) {
555 die(STATE_UNKNOWN, _("Cannot execute strdup: %s"), strerror(errno));
556 }
557 }
558 /* Die if invalid characters used for keyname */
559 p = temp_keyname;
560 while (*p != '\0') {
561 if (!(isalnum(*p) || *p == '_')) {
562 die(STATE_UNKNOWN, _("Invalid character for keyname - only alphanumerics or '_'"));
563 }
564 p++;
565 }
566 this_state->name = temp_keyname;
567 this_state->plugin_name = this_monitoring_plugin->plugin_name;
568 this_state->data_version = expected_data_version;
569 this_state->state_data = NULL;
570
571 /* Calculate filename */
572 ret = asprintf(&temp_filename, "%s/%lu/%s/%s", _np_state_calculate_location_prefix(), (unsigned long)geteuid(),
573 this_monitoring_plugin->plugin_name, this_state->name);
574 if (ret < 0) {
575 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), strerror(errno));
576 }
577
578 this_state->_filename = temp_filename;
579
580 this_monitoring_plugin->state = this_state;
581}
582
583/*
584 * Will return NULL if no data is available (first run). If key currently
585 * exists, read data. If state file format version is not expected, return
586 * as if no data. Get state data version number and compares to expected.
587 * If numerically lower, then return as no previous state. die with UNKNOWN
588 * if exceptional error.
589 */
590state_data *np_state_read(void) {
591 state_data *this_state_data = NULL;
592 FILE *statefile;
593 bool rc = false;
594
595 if (this_monitoring_plugin == NULL) {
596 die(STATE_UNKNOWN, _("This requires np_init to be called"));
597 }
598
599 /* Open file. If this fails, no previous state found */
600 statefile = fopen(this_monitoring_plugin->state->_filename, "r");
601 if (statefile != NULL) {
602
603 this_state_data = (state_data *)calloc(1, sizeof(state_data));
604 if (this_state_data == NULL) {
605 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), strerror(errno));
606 }
607
608 this_state_data->data = NULL;
609 this_monitoring_plugin->state->state_data = this_state_data;
610
611 rc = _np_state_read_file(statefile);
612
613 fclose(statefile);
614 }
615
616 if (!rc) {
617 _cleanup_state_data();
618 }
619
620 return this_monitoring_plugin->state->state_data;
621}
622
623/*
624 * Read the state file
625 */
626bool _np_state_read_file(FILE *f) {
627 bool status = false;
628 size_t pos;
629 char *line;
630 int i;
631 int failure = 0;
632 time_t current_time, data_time;
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;
640
641 time(&current_time);
642
643 /* Note: This introduces a limit of 1024 bytes in the string data */
644 line = (char *)calloc(1, 1024);
645 if (line == NULL) {
646 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), strerror(errno));
647 }
648
649 while (!failure && (fgets(line, 1024, f)) != NULL) {
650 pos = strlen(line);
651 if (line[pos - 1] == '\n') {
652 line[pos - 1] = '\0';
653 }
654
655 if (line[0] == '#') {
656 continue;
657 }
658
659 switch (expected) {
660 case STATE_FILE_VERSION:
661 i = atoi(line);
662 if (i != NP_STATE_FORMAT_VERSION) {
663 failure++;
664 } else {
665 expected = STATE_DATA_VERSION;
666 }
667 break;
668 case STATE_DATA_VERSION:
669 i = atoi(line);
670 if (i != this_monitoring_plugin->state->data_version) {
671 failure++;
672 } else {
673 expected = STATE_DATA_TIME;
674 }
675 break;
676 case STATE_DATA_TIME:
677 /* If time > now, error */
678 data_time = strtoul(line, NULL, 10);
679 if (data_time > current_time) {
680 failure++;
681 } else {
682 this_monitoring_plugin->state->state_data->time = data_time;
683 expected = STATE_DATA_TEXT;
684 }
685 break;
686 case STATE_DATA_TEXT:
687 this_monitoring_plugin->state->state_data->data = strdup(line);
688 if (this_monitoring_plugin->state->state_data->data == NULL) {
689 die(STATE_UNKNOWN, _("Cannot execute strdup: %s"), strerror(errno));
690 }
691 expected = STATE_DATA_END;
692 status = true;
693 break;
694 case STATE_DATA_END:;
695 }
696 }
697
698 np_free(line);
699 return status;
700}
701
702/*
703 * If time=NULL, use current time. Create state file, with state format
704 * version, default text. Writes version, time, and data. Avoid locking
705 * problems - use mv to write and then swap. Possible loss of state data if
706 * two things writing to same key at same time.
707 * Will die with UNKNOWN if errors
708 */
709void np_state_write_string(time_t data_time, char *data_string) {
710 FILE *fp;
711 char *temp_file = NULL;
712 int fd = 0, result = 0;
713 time_t current_time;
714 char *directories = NULL;
715 char *p = NULL;
716
717 if (data_time == 0) {
718 time(&current_time);
719 } else {
720 current_time = data_time;
721 }
722
723 /* If file doesn't currently exist, create directories */
724 if (access(this_monitoring_plugin->state->_filename, F_OK) != 0) {
725 result = asprintf(&directories, "%s", this_monitoring_plugin->state->_filename);
726 if (result < 0) {
727 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), strerror(errno));
728 }
729
730 for (p = directories + 1; *p; p++) {
731 if (*p == '/') {
732 *p = '\0';
733 if ((access(directories, F_OK) != 0) && (mkdir(directories, S_IRWXU) != 0)) {
734 /* Can't free this! Otherwise error message is wrong! */
735 /* np_free(directories); */
736 die(STATE_UNKNOWN, _("Cannot create directory: %s"), directories);
737 }
738 *p = '/';
739 }
740 }
741 np_free(directories);
742 }
743
744 result = asprintf(&temp_file, "%s.XXXXXX", this_monitoring_plugin->state->_filename);
745 if (result < 0) {
746 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), strerror(errno));
747 }
748
749 if ((fd = mkstemp(temp_file)) == -1) {
750 np_free(temp_file);
751 die(STATE_UNKNOWN, _("Cannot create temporary filename"));
752 }
753
754 fp = (FILE *)fdopen(fd, "w");
755 if (fp == NULL) {
756 close(fd);
757 unlink(temp_file);
758 np_free(temp_file);
759 die(STATE_UNKNOWN, _("Unable to open temporary state file"));
760 }
761
762 fprintf(fp, "# NP State file\n");
763 fprintf(fp, "%d\n", NP_STATE_FORMAT_VERSION);
764 fprintf(fp, "%d\n", this_monitoring_plugin->state->data_version);
765 fprintf(fp, "%lu\n", current_time);
766 fprintf(fp, "%s\n", data_string);
767
768 fchmod(fd, S_IRUSR | S_IWUSR | S_IRGRP);
769
770 fflush(fp);
771
772 result = fclose(fp);
773
774 fsync(fd);
775
776 if (result != 0) {
777 unlink(temp_file);
778 np_free(temp_file);
779 die(STATE_UNKNOWN, _("Error writing temp file"));
780 }
781
782 if (rename(temp_file, this_monitoring_plugin->state->_filename) != 0) {
783 unlink(temp_file);
784 np_free(temp_file);
785 die(STATE_UNKNOWN, _("Cannot rename state temp file"));
786 }
787
788 np_free(temp_file);
789}