1 /***************************************************************************** 2 * 3 * MACROS.C - Common macro functions for Nagios 4 * 5 * Copyright (c) 1999-2010 Ethan Galstad (egalstad@nagios.org) 6 * Last Modified: 08-06-2010 7 * 8 * License: 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License version 2 as 12 * published by the Free Software Foundation. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 22 * 23 *****************************************************************************/ 24 25 #include "../include/macros.h" 26 #include "../include/config.h" 27 #include "../include/common.h" 28 #include "../include/objects.h" 29 #include "../include/statusdata.h" 30 #include "../include/comments.h" 31 #ifdef NSCORE 32 #include "../include/nagios.h" 33 #else 34 #include "../include/cgiutils.h" 35 #endif 36 37 #ifdef NSCORE 38 extern int use_large_installation_tweaks; 39 extern int enable_environment_macros; 40 #endif 41 42 extern char *illegal_output_chars; 43 44 extern contact *contact_list; 45 extern contactgroup *contactgroup_list; 46 extern host *host_list; 47 extern hostgroup *hostgroup_list; 48 extern service *service_list; 49 extern servicegroup *servicegroup_list; 50 extern command *command_list; 51 extern timeperiod *timeperiod_list; 52 53 char *macro_x_names[MACRO_X_COUNT]; /* the macro names */ 54 char *macro_user[MAX_USER_MACROS]; /* $USERx$ macros */ 55 56 struct macro_key_code { 57 char *name; /* macro key name */ 58 int code; /* numeric macro code, usable in case statements */ 59 int clean_options; 60 char *value; 61 }; 62 63 struct macro_key_code macro_keys[MACRO_X_COUNT]; 64 65 /* 66 * These point to their corresponding pointer arrays in global_macros 67 * AFTER macros have been initialized. 68 * 69 * They really only exist so that eventbroker modules that reference 70 * them won't need to be re-compiled, although modules that rely 71 * on their values after having run a certain command will require an 72 * update 73 */ 74 char **macro_x = NULL; 75 76 /* 77 * scoped to this file to prevent (unintentional) mischief, 78 * but see base/notifications.c for how to use it 79 */ 80 static nagios_macros global_macros; 81 82 83 nagios_macros *get_global_macros(void) { 84 return &global_macros; 85 } 86 87 /******************************************************************/ 88 /************************ MACRO FUNCTIONS *************************/ 89 /******************************************************************/ 90 91 /* 92 * locate a macro key based on its name by using a binary search 93 * over all keys. O(log(n)) complexity and a vast improvement over 94 * the previous linear scan 95 */ 96 const struct macro_key_code *find_macro_key(const char *name) { 97 unsigned int high, low = 0; 98 int value; 99 struct macro_key_code *key; 100 101 high = MACRO_X_COUNT; 102 while(high - low > 0) { 103 unsigned int mid = low + ((high - low) / 2); 104 key = ¯o_keys[mid]; 105 value = strcmp(name, key->name); 106 if(value == 0) { 107 return key; 108 } 109 if(value > 0) 110 low = mid + 1; 111 else 112 high = mid; 113 } 114 return NULL; 115 } 116 117 118 /* 119 * replace macros in notification commands with their values, 120 * the thread-safe version 121 */ 122 int process_macros_r(nagios_macros *mac, char *input_buffer, char **output_buffer, int options) { 123 char *temp_buffer = NULL; 124 char *save_buffer = NULL; 125 char *buf_ptr = NULL; 126 char *delim_ptr = NULL; 127 int in_macro = FALSE; 128 int x = 0; 129 char *selected_macro = NULL; 130 char *original_macro = NULL; 131 char *cleaned_macro = NULL; 132 int clean_macro = FALSE; 133 int found_macro_x = FALSE; 134 int result = OK; 135 int clean_options = 0; 136 int free_macro = FALSE; 137 int macro_options = 0; 138 139 log_debug_info(DEBUGL_FUNCTIONS, 0, "process_macros_r()\n"); 140 141 if(output_buffer == NULL) 142 return ERROR; 143 144 *output_buffer = (char *)strdup(""); 145 146 if(input_buffer == NULL) 147 return ERROR; 148 149 in_macro = FALSE; 150 151 log_debug_info(DEBUGL_MACROS, 1, "**** BEGIN MACRO PROCESSING ***********\n"); 152 log_debug_info(DEBUGL_MACROS, 1, "Processing: '%s'\n", input_buffer); 153 154 /* use a duplicate of original buffer, so we don't modify the original */ 155 save_buffer = buf_ptr = (input_buffer ? strdup(input_buffer) : NULL); 156 157 while(buf_ptr) { 158 159 /* save pointer to this working part of buffer */ 160 temp_buffer = buf_ptr; 161 162 /* find the next delimiter - terminate preceding string and advance buffer pointer for next run */ 163 if((delim_ptr = strchr(buf_ptr, '$'))) { 164 delim_ptr[0] = '\x0'; 165 buf_ptr = (char *)delim_ptr + 1; 166 } 167 /* no delimiter found - we already have the last of the buffer */ 168 else 169 buf_ptr = NULL; 170 171 log_debug_info(DEBUGL_MACROS, 2, " Processing part: '%s'\n", temp_buffer); 172 173 selected_macro = NULL; 174 found_macro_x = FALSE; 175 clean_macro = FALSE; 176 177 /* we're in plain text... */ 178 if(in_macro == FALSE) { 179 180 /* add the plain text to the end of the already processed buffer */ 181 *output_buffer = (char *)realloc(*output_buffer, strlen(*output_buffer) + strlen(temp_buffer) + 1); 182 strcat(*output_buffer, temp_buffer); 183 184 log_debug_info(DEBUGL_MACROS, 2, " Not currently in macro. Running output (%lu): '%s'\n", (unsigned long)strlen(*output_buffer), *output_buffer); 185 in_macro = TRUE; 186 } 187 188 /* looks like we're in a macro, so process it... */ 189 else { 190 191 /* reset clean options */ 192 clean_options = 0; 193 194 /* grab the macro value */ 195 result = grab_macro_value_r(mac, temp_buffer, &selected_macro, &clean_options, &free_macro); 196 log_debug_info(DEBUGL_MACROS, 2, " Processed '%s', Clean Options: %d, Free: %d\n", temp_buffer, clean_options, free_macro); 197 198 /* an error occurred - we couldn't parse the macro, so continue on */ 199 if(result == ERROR) { 200 log_debug_info(DEBUGL_MACROS, 0, " WARNING: An error occurred processing macro '%s'!\n", temp_buffer); 201 if(free_macro == TRUE) 202 my_free(selected_macro); 203 } 204 205 /* we already have a macro... */ 206 if(result == OK) 207 x = 0; 208 209 /* an escaped $ is done by specifying two $$ next to each other */ 210 else if(!strcmp(temp_buffer, "")) { 211 log_debug_info(DEBUGL_MACROS, 2, " Escaped $. Running output (%lu): '%s'\n", (unsigned long)strlen(*output_buffer), *output_buffer); 212 *output_buffer = (char *)realloc(*output_buffer, strlen(*output_buffer) + 2); 213 strcat(*output_buffer, "$"); 214 } 215 216 /* a non-macro, just some user-defined string between two $s */ 217 else { 218 log_debug_info(DEBUGL_MACROS, 2, " Non-macro. Running output (%lu): '%s'\n", (unsigned long)strlen(*output_buffer), *output_buffer); 219 220 /* add the plain text to the end of the already processed buffer */ 221 *output_buffer = (char *)realloc(*output_buffer, strlen(*output_buffer) + strlen(temp_buffer) + 3); 222 strcat(*output_buffer, "$"); 223 strcat(*output_buffer, temp_buffer); 224 strcat(*output_buffer, "$"); 225 } 226 227 /* insert macro */ 228 if(selected_macro != NULL) { 229 log_debug_info(DEBUGL_MACROS, 2, " Processed '%s', Clean Options: %d, Free: %d\n", temp_buffer, clean_options, free_macro); 230 231 /* include any cleaning options passed back to us */ 232 macro_options = (options | clean_options); 233 234 log_debug_info(DEBUGL_MACROS, 2, " Cleaning options: global=%d, local=%d, effective=%d\n", options, clean_options, macro_options); 235 236 /* URL encode the macro if requested - this allocates new memory */ 237 if(macro_options & URL_ENCODE_MACRO_CHARS) { 238 original_macro = selected_macro; 239 selected_macro = get_url_encoded_string(selected_macro); 240 if(free_macro == TRUE) { 241 my_free(original_macro); 242 } 243 free_macro = TRUE; 244 } 245 246 /* some macros are cleaned... */ 247 if(clean_macro == TRUE || ((macro_options & STRIP_ILLEGAL_MACRO_CHARS) || (macro_options & ESCAPE_MACRO_CHARS))) { 248 249 /* add the (cleaned) processed macro to the end of the already processed buffer */ 250 if(selected_macro != NULL && (cleaned_macro = clean_macro_chars(selected_macro, macro_options)) != NULL) { 251 *output_buffer = (char *)realloc(*output_buffer, strlen(*output_buffer) + strlen(cleaned_macro) + 1); 252 strcat(*output_buffer, cleaned_macro); 253 254 log_debug_info(DEBUGL_MACROS, 2, " Cleaned macro. Running output (%lu): '%s'\n", (unsigned long)strlen(*output_buffer), *output_buffer); 255 } 256 } 257 258 /* others are not cleaned */ 259 else { 260 /* add the processed macro to the end of the already processed buffer */ 261 if(selected_macro != NULL) { 262 *output_buffer = (char *)realloc(*output_buffer, strlen(*output_buffer) + strlen(selected_macro) + 1); 263 strcat(*output_buffer, selected_macro); 264 265 log_debug_info(DEBUGL_MACROS, 2, " Uncleaned macro. Running output (%lu): '%s'\n", (unsigned long)strlen(*output_buffer), *output_buffer); 266 } 267 } 268 269 /* free memory if necessary (if we URL encoded the macro or we were told to do so by grab_macro_value()) */ 270 if(free_macro == TRUE) 271 my_free(selected_macro); 272 273 log_debug_info(DEBUGL_MACROS, 2, " Just finished macro. Running output (%lu): '%s'\n", (unsigned long)strlen(*output_buffer), *output_buffer); 274 } 275 276 in_macro = FALSE; 277 } 278 } 279 280 /* free copy of input buffer */ 281 my_free(save_buffer); 282 283 log_debug_info(DEBUGL_MACROS, 1, " Done. Final output: '%s'\n", *output_buffer); 284 log_debug_info(DEBUGL_MACROS, 1, "**** END MACRO PROCESSING *************\n"); 285 286 return OK; 287 } 288 289 int process_macros(char *input_buffer, char **output_buffer, int options) { 290 return process_macros_r(&global_macros, input_buffer, output_buffer, options); 291 } 292 293 /******************************************************************/ 294 /********************** MACRO GRAB FUNCTIONS **********************/ 295 /******************************************************************/ 296 297 /* grab macros that are specific to a particular host */ 298 int grab_host_macros_r(nagios_macros *mac, host *hst) { 299 /* clear host-related macros */ 300 clear_host_macros_r(mac); 301 clear_hostgroup_macros_r(mac); 302 303 /* save pointer to host */ 304 mac->host_ptr = hst; 305 mac->hostgroup_ptr = NULL; 306 307 if(hst == NULL) 308 return ERROR; 309 310 #ifdef NSCORE 311 /* save pointer to host's first/primary hostgroup */ 312 if(hst->hostgroups_ptr) 313 mac->hostgroup_ptr = (hostgroup *)hst->hostgroups_ptr->object_ptr; 314 #endif 315 316 return OK; 317 } 318 319 int grab_host_macros(host *hst) { 320 return grab_host_macros_r(&global_macros, hst); 321 } 322 323 324 /* grab hostgroup macros */ 325 int grab_hostgroup_macros_r(nagios_macros *mac, hostgroup *hg) { 326 /* clear hostgroup macros */ 327 clear_hostgroup_macros_r(mac); 328 329 /* save the hostgroup pointer for later */ 330 mac->hostgroup_ptr = hg; 331 332 if(hg == NULL) 333 return ERROR; 334 335 return OK; 336 } 337 338 int grab_hostgroup_macros(hostgroup *hg) { 339 return grab_hostgroup_macros_r(&global_macros, hg); 340 } 341 342 343 /* grab macros that are specific to a particular service */ 344 int grab_service_macros_r(nagios_macros *mac, service *svc) { 345 346 /* clear service-related macros */ 347 clear_service_macros_r(mac); 348 clear_servicegroup_macros_r(mac); 349 350 /* save pointer for later */ 351 mac->service_ptr = svc; 352 mac->servicegroup_ptr = NULL; 353 354 if(svc == NULL) 355 return ERROR; 356 357 #ifdef NSCORE 358 /* save first/primary servicegroup pointer for later */ 359 if(svc->servicegroups_ptr) 360 mac->servicegroup_ptr = (servicegroup *)svc->servicegroups_ptr->object_ptr; 361 #endif 362 363 return OK; 364 } 365 366 int grab_service_macros(service *svc) { 367 return grab_service_macros_r(&global_macros, svc); 368 } 369 370 371 /* grab macros that are specific to a particular servicegroup */ 372 int grab_servicegroup_macros_r(nagios_macros *mac, servicegroup *sg) { 373 /* clear servicegroup macros */ 374 clear_servicegroup_macros_r(mac); 375 376 /* save the pointer for later */ 377 mac->servicegroup_ptr = sg; 378 379 if(sg == NULL) 380 return ERROR; 381 382 return OK; 383 } 384 385 int grab_servicegroup_macros(servicegroup *sg) { 386 return grab_servicegroup_macros_r(&global_macros, sg); 387 } 388 389 390 /* grab macros that are specific to a particular contact */ 391 int grab_contact_macros_r(nagios_macros *mac, contact *cntct) { 392 /* clear contact-related macros */ 393 clear_contact_macros_r(mac); 394 clear_contactgroup_macros_r(mac); 395 396 /* save pointer to contact for later */ 397 mac->contact_ptr = cntct; 398 mac->contactgroup_ptr = NULL; 399 400 if(cntct == NULL) 401 return ERROR; 402 403 #ifdef NSCORE 404 /* save pointer to first/primary contactgroup for later */ 405 if(cntct->contactgroups_ptr) 406 mac->contactgroup_ptr = (contactgroup *)cntct->contactgroups_ptr->object_ptr; 407 #endif 408 409 return OK; 410 } 411 412 int grab_contact_macros(contact *cntct) { 413 return grab_contact_macros_r(&global_macros, cntct); 414 } 415 416 417 /******************************************************************/ 418 /******************* MACRO GENERATION FUNCTIONS *******************/ 419 /******************************************************************/ 420 421 /* this is the big one */ 422 int grab_macro_value_r(nagios_macros *mac, char *macro_buffer, char **output, int *clean_options, int *free_macro) { 423 char *buf = NULL; 424 char *ptr = NULL; 425 char *macro_name = NULL; 426 char *arg[2] = {NULL, NULL}; 427 contact *temp_contact = NULL; 428 contactgroup *temp_contactgroup = NULL; 429 contactsmember *temp_contactsmember = NULL; 430 char *temp_buffer = NULL; 431 int delimiter_len = 0; 432 int x, result = OK; 433 const struct macro_key_code *mkey; 434 435 /* for the early cases, this is the default */ 436 *free_macro = FALSE; 437 438 if(output == NULL) 439 return ERROR; 440 441 /* clear the old macro value */ 442 my_free(*output); 443 444 if(macro_buffer == NULL || clean_options == NULL || free_macro == NULL) 445 return ERROR; 446 447 448 /* 449 * We handle argv and user macros first, since those are by far 450 * the most commonly accessed ones (3.4 and 1.005 per check, 451 * respectively). Since neither of them requires that we copy 452 * the original buffer, we can also get away with some less 453 * code for these simple cases. 454 */ 455 if(strstr(macro_buffer, "ARG") == macro_buffer) { 456 457 /* which arg do we want? */ 458 x = atoi(macro_buffer + 3); 459 460 if(x <= 0 || x > MAX_COMMAND_ARGUMENTS) { 461 return ERROR; 462 } 463 464 /* use a pre-computed macro value */ 465 *output = mac->argv[x - 1]; 466 return OK; 467 } 468 469 if(strstr(macro_buffer, "USER") == macro_buffer) { 470 471 /* which macro do we want? */ 472 x = atoi(macro_buffer + 4); 473 474 if(x <= 0 || x > MAX_USER_MACROS) { 475 return ERROR; 476 } 477 478 /* use a pre-computed macro value */ 479 *output = macro_user[x - 1]; 480 return OK; 481 } 482 483 /* most frequently used "x" macro gets a shortcut */ 484 if(mac->host_ptr && !strcmp(macro_buffer, "HOSTADDRESS")) { 485 if(mac->host_ptr->address) 486 *output = mac->host_ptr->address; 487 return OK; 488 } 489 490 /* work with a copy of the original buffer */ 491 if((buf = (char *)strdup(macro_buffer)) == NULL) 492 return ERROR; 493 494 /* BY DEFAULT, TELL CALLER TO FREE MACRO BUFFER WHEN DONE */ 495 *free_macro = TRUE; 496 497 /* macro name is at start of buffer */ 498 macro_name = buf; 499 500 /* see if there's an argument - if so, this is most likely an on-demand macro */ 501 if((ptr = strchr(buf, ':'))) { 502 503 ptr[0] = '\x0'; 504 ptr++; 505 506 /* save the first argument - host name, hostgroup name, etc. */ 507 arg[0] = ptr; 508 509 /* try and find a second argument */ 510 if((ptr = strchr(ptr, ':'))) { 511 512 ptr[0] = '\x0'; 513 ptr++; 514 515 /* save second argument - service description or delimiter */ 516 arg[1] = ptr; 517 } 518 } 519 520 if((mkey = find_macro_key(macro_name))) { 521 log_debug_info(DEBUGL_MACROS, 2, " macros[%d] (%s) match.\n", mkey->code, macro_x_names[mkey->code]); 522 if(mkey->clean_options) { 523 *clean_options |= mkey->clean_options; 524 log_debug_info(DEBUGL_MACROS, 2, " New clean options: %d\n", *clean_options); 525 } 526 527 /* get the macro value */ 528 result = grab_macrox_value_r(mac, mkey->code, arg[0], arg[1], output, free_macro); 529 } 530 /***** CONTACT ADDRESS MACROS *****/ 531 /* NOTE: the code below should be broken out into a separate function */ 532 else if(strstr(macro_name, "CONTACTADDRESS") == macro_name) { 533 534 /* which address do we want? */ 535 x = atoi(macro_name + 14) - 1; 536 537 /* regular macro */ 538 if(arg[0] == NULL) { 539 540 /* use the saved pointer */ 541 if((temp_contact = mac->contact_ptr) == NULL) { 542 my_free(buf); 543 return ERROR; 544 } 545 546 /* get the macro value by reference, so no need to free() */ 547 *free_macro = FALSE; 548 result = grab_contact_address_macro(x, temp_contact, output); 549 } 550 551 /* on-demand macro */ 552 else { 553 554 /* on-demand contact macro with a contactgroup and a delimiter */ 555 if(arg[1] != NULL) { 556 557 if((temp_contactgroup = find_contactgroup(arg[0])) == NULL) 558 return ERROR; 559 560 delimiter_len = strlen(arg[1]); 561 562 /* concatenate macro values for all contactgroup members */ 563 for(temp_contactsmember = temp_contactgroup->members; temp_contactsmember != NULL; temp_contactsmember = temp_contactsmember->next) { 564 565 #ifdef NSCORE 566 if((temp_contact = temp_contactsmember->contact_ptr) == NULL) 567 continue; 568 if((temp_contact = find_contact(temp_contactsmember->contact_name)) == NULL) 569 continue; 570 #endif 571 572 /* get the macro value for this contact */ 573 grab_contact_address_macro(x, temp_contact, &temp_buffer); 574 575 if(temp_buffer == NULL) 576 continue; 577 578 /* add macro value to already running macro */ 579 if(*output == NULL) 580 *output = (char *)strdup(temp_buffer); 581 else { 582 if((*output = (char *)realloc(*output, strlen(*output) + strlen(temp_buffer) + delimiter_len + 1)) == NULL) 583 continue; 584 strcat(*output, arg[1]); 585 strcat(*output, temp_buffer); 586 } 587 my_free(temp_buffer); 588 } 589 } 590 591 /* else on-demand contact macro */ 592 else { 593 594 /* find the contact */ 595 if((temp_contact = find_contact(arg[0])) == NULL) { 596 my_free(buf); 597 return ERROR; 598 } 599 600 /* get the macro value */ 601 result = grab_contact_address_macro(x, temp_contact, output); 602 } 603 } 604 } 605 606 /***** CUSTOM VARIABLE MACROS *****/ 607 else if(macro_name[0] == '_') { 608 609 /* get the macro value */ 610 result = grab_custom_macro_value_r(mac, macro_name, arg[0], arg[1], output); 611 } 612 613 /* no macro matched... */ 614 else { 615 log_debug_info(DEBUGL_MACROS, 0, " WARNING: Could not find a macro matching '%s'!\n", macro_name); 616 result = ERROR; 617 } 618 619 /* free memory */ 620 my_free(buf); 621 622 return result; 623 } 624 625 int grab_macro_value(char *macro_buffer, char **output, int *clean_options, int *free_macro) { 626 return grab_macro_value_r(&global_macros, macro_buffer, output, clean_options, free_macro); 627 } 628 629 630 int grab_macrox_value_r(nagios_macros *mac, int macro_type, char *arg1, char *arg2, char **output, int *free_macro) { 631 host *temp_host = NULL; 632 hostgroup *temp_hostgroup = NULL; 633 hostsmember *temp_hostsmember = NULL; 634 service *temp_service = NULL; 635 servicegroup *temp_servicegroup = NULL; 636 servicesmember *temp_servicesmember = NULL; 637 contact *temp_contact = NULL; 638 contactgroup *temp_contactgroup = NULL; 639 contactsmember *temp_contactsmember = NULL; 640 char *temp_buffer = NULL; 641 int result = OK; 642 int delimiter_len = 0; 643 int free_sub_macro = FALSE; 644 #ifdef NSCORE 645 register int x; 646 int authorized = TRUE; 647 int problem = TRUE; 648 int hosts_up = 0; 649 int hosts_down = 0; 650 int hosts_unreachable = 0; 651 int hosts_down_unhandled = 0; 652 int hosts_unreachable_unhandled = 0; 653 int host_problems = 0; 654 int host_problems_unhandled = 0; 655 int services_ok = 0; 656 int services_warning = 0; 657 int services_unknown = 0; 658 int services_critical = 0; 659 int services_warning_unhandled = 0; 660 int services_unknown_unhandled = 0; 661 int services_critical_unhandled = 0; 662 int service_problems = 0; 663 int service_problems_unhandled = 0; 664 #endif 665 666 667 if(output == NULL || free_macro == NULL) 668 return ERROR; 669 670 /* BY DEFAULT, TELL CALLER TO FREE MACRO BUFFER WHEN DONE */ 671 *free_macro = TRUE; 672 673 /* handle the macro */ 674 switch(macro_type) { 675 676 /***************/ 677 /* HOST MACROS */ 678 /***************/ 679 case MACRO_HOSTNAME: 680 case MACRO_HOSTALIAS: 681 case MACRO_HOSTADDRESS: 682 case MACRO_LASTHOSTCHECK: 683 case MACRO_LASTHOSTSTATECHANGE: 684 case MACRO_HOSTOUTPUT: 685 case MACRO_HOSTPERFDATA: 686 case MACRO_HOSTSTATE: 687 case MACRO_HOSTSTATEID: 688 case MACRO_HOSTATTEMPT: 689 case MACRO_HOSTEXECUTIONTIME: 690 case MACRO_HOSTLATENCY: 691 case MACRO_HOSTDURATION: 692 case MACRO_HOSTDURATIONSEC: 693 case MACRO_HOSTDOWNTIME: 694 case MACRO_HOSTSTATETYPE: 695 case MACRO_HOSTPERCENTCHANGE: 696 case MACRO_HOSTACKAUTHOR: 697 case MACRO_HOSTACKCOMMENT: 698 case MACRO_LASTHOSTUP: 699 case MACRO_LASTHOSTDOWN: 700 case MACRO_LASTHOSTUNREACHABLE: 701 case MACRO_HOSTCHECKCOMMAND: 702 case MACRO_HOSTDISPLAYNAME: 703 case MACRO_HOSTACTIONURL: 704 case MACRO_HOSTNOTESURL: 705 case MACRO_HOSTNOTES: 706 case MACRO_HOSTCHECKTYPE: 707 case MACRO_LONGHOSTOUTPUT: 708 case MACRO_HOSTNOTIFICATIONNUMBER: 709 case MACRO_HOSTNOTIFICATIONID: 710 case MACRO_HOSTEVENTID: 711 case MACRO_LASTHOSTEVENTID: 712 case MACRO_HOSTGROUPNAMES: 713 case MACRO_HOSTACKAUTHORNAME: 714 case MACRO_HOSTACKAUTHORALIAS: 715 case MACRO_MAXHOSTATTEMPTS: 716 case MACRO_TOTALHOSTSERVICES: 717 case MACRO_TOTALHOSTSERVICESOK: 718 case MACRO_TOTALHOSTSERVICESWARNING: 719 case MACRO_TOTALHOSTSERVICESUNKNOWN: 720 case MACRO_TOTALHOSTSERVICESCRITICAL: 721 case MACRO_HOSTPROBLEMID: 722 case MACRO_LASTHOSTPROBLEMID: 723 case MACRO_LASTHOSTSTATE: 724 case MACRO_LASTHOSTSTATEID: 725 726 /* a standard host macro */ 727 if(arg2 == NULL) { 728 729 /* find the host for on-demand macros */ 730 if(arg1) { 731 if((temp_host = find_host(arg1)) == NULL) 732 return ERROR; 733 } 734 735 /* else use saved host pointer */ 736 else if((temp_host = mac->host_ptr) == NULL) 737 return ERROR; 738 739 /* get the host macro value */ 740 result = grab_standard_host_macro_r(mac, macro_type, temp_host, output, free_macro); 741 } 742 743 /* a host macro with a hostgroup name and delimiter */ 744 else { 745 746 if((temp_hostgroup = find_hostgroup(arg1)) == NULL) 747 return ERROR; 748 749 delimiter_len = strlen(arg2); 750 751 /* concatenate macro values for all hostgroup members */ 752 for(temp_hostsmember = temp_hostgroup->members; temp_hostsmember != NULL; temp_hostsmember = temp_hostsmember->next) { 753 754 #ifdef NSCORE 755 if((temp_host = temp_hostsmember->host_ptr) == NULL) 756 continue; 757 #else 758 if((temp_host = find_host(temp_hostsmember->host_name)) == NULL) 759 continue; 760 #endif 761 762 /* get the macro value for this host */ 763 grab_standard_host_macro_r(mac, macro_type, temp_host, &temp_buffer, &free_sub_macro); 764 765 if(temp_buffer == NULL) 766 continue; 767 768 /* add macro value to already running macro */ 769 if(*output == NULL) 770 *output = (char *)strdup(temp_buffer); 771 else { 772 if((*output = (char *)realloc(*output, strlen(*output) + strlen(temp_buffer) + delimiter_len + 1)) == NULL) 773 continue; 774 strcat(*output, arg2); 775 strcat(*output, temp_buffer); 776 } 777 if(free_sub_macro == TRUE) 778 my_free(temp_buffer); 779 } 780 } 781 break; 782 783 /********************/ 784 /* HOSTGROUP MACROS */ 785 /********************/ 786 case MACRO_HOSTGROUPNAME: 787 case MACRO_HOSTGROUPALIAS: 788 case MACRO_HOSTGROUPNOTES: 789 case MACRO_HOSTGROUPNOTESURL: 790 case MACRO_HOSTGROUPACTIONURL: 791 case MACRO_HOSTGROUPMEMBERS: 792 793 /* a standard hostgroup macro */ 794 /* use the saved hostgroup pointer */ 795 if(arg1 == NULL) { 796 if((temp_hostgroup = mac->hostgroup_ptr) == NULL) 797 return ERROR; 798 } 799 800 /* else find the hostgroup for on-demand macros */ 801 else { 802 if((temp_hostgroup = find_hostgroup(arg1)) == NULL) 803 return ERROR; 804 } 805 806 /* get the hostgroup macro value */ 807 result = grab_standard_hostgroup_macro_r(mac, macro_type, temp_hostgroup, output); 808 break; 809 810 /******************/ 811 /* SERVICE MACROS */ 812 /******************/ 813 case MACRO_SERVICEDESC: 814 case MACRO_SERVICESTATE: 815 case MACRO_SERVICESTATEID: 816 case MACRO_SERVICEATTEMPT: 817 case MACRO_LASTSERVICECHECK: 818 case MACRO_LASTSERVICESTATECHANGE: 819 case MACRO_SERVICEOUTPUT: 820 case MACRO_SERVICEPERFDATA: 821 case MACRO_SERVICEEXECUTIONTIME: 822 case MACRO_SERVICELATENCY: 823 case MACRO_SERVICEDURATION: 824 case MACRO_SERVICEDURATIONSEC: 825 case MACRO_SERVICEDOWNTIME: 826 case MACRO_SERVICESTATETYPE: 827 case MACRO_SERVICEPERCENTCHANGE: 828 case MACRO_SERVICEACKAUTHOR: 829 case MACRO_SERVICEACKCOMMENT: 830 case MACRO_LASTSERVICEOK: 831 case MACRO_LASTSERVICEWARNING: 832 case MACRO_LASTSERVICEUNKNOWN: 833 case MACRO_LASTSERVICECRITICAL: 834 case MACRO_SERVICECHECKCOMMAND: 835 case MACRO_SERVICEDISPLAYNAME: 836 case MACRO_SERVICEACTIONURL: 837 case MACRO_SERVICENOTESURL: 838 case MACRO_SERVICENOTES: 839 case MACRO_SERVICECHECKTYPE: 840 case MACRO_LONGSERVICEOUTPUT: 841 case MACRO_SERVICENOTIFICATIONNUMBER: 842 case MACRO_SERVICENOTIFICATIONID: 843 case MACRO_SERVICEEVENTID: 844 case MACRO_LASTSERVICEEVENTID: 845 case MACRO_SERVICEGROUPNAMES: 846 case MACRO_SERVICEACKAUTHORNAME: 847 case MACRO_SERVICEACKAUTHORALIAS: 848 case MACRO_MAXSERVICEATTEMPTS: 849 case MACRO_SERVICEISVOLATILE: 850 case MACRO_SERVICEPROBLEMID: 851 case MACRO_LASTSERVICEPROBLEMID: 852 case MACRO_LASTSERVICESTATE: 853 case MACRO_LASTSERVICESTATEID: 854 855 /* use saved service pointer */ 856 if(arg1 == NULL && arg2 == NULL) { 857 858 if((temp_service = mac->service_ptr) == NULL) 859 return ERROR; 860 861 result = grab_standard_service_macro_r(mac, macro_type, temp_service, output, free_macro); 862 } 863 864 /* else and ondemand macro... */ 865 else { 866 867 /* if first arg is blank, it means use the current host name */ 868 if(arg1 == NULL || arg1[0] == '\x0') { 869 870 if(mac->host_ptr == NULL) 871 return ERROR; 872 873 if((temp_service = find_service(mac->host_ptr->name, arg2))) { 874 875 /* get the service macro value */ 876 result = grab_standard_service_macro_r(mac, macro_type, temp_service, output, free_macro); 877 } 878 } 879 880 /* on-demand macro with both host and service name */ 881 else if((temp_service = find_service(arg1, arg2))) { 882 883 /* get the service macro value */ 884 result = grab_standard_service_macro_r(mac, macro_type, temp_service, output, free_macro); 885 } 886 887 /* else we have a service macro with a servicegroup name and a delimiter... */ 888 else if(arg1 && arg2) { 889 890 if((temp_servicegroup = find_servicegroup(arg1)) == NULL) 891 return ERROR; 892 893 delimiter_len = strlen(arg2); 894 895 /* concatenate macro values for all servicegroup members */ 896 for(temp_servicesmember = temp_servicegroup->members; temp_servicesmember != NULL; temp_servicesmember = temp_servicesmember->next) { 897 898 #ifdef NSCORE 899 if((temp_service = temp_servicesmember->service_ptr) == NULL) 900 continue; 901 #else 902 if((temp_service = find_service(temp_servicesmember->host_name, temp_servicesmember->service_description)) == NULL) 903 continue; 904 #endif 905 906 /* get the macro value for this service */ 907 grab_standard_service_macro_r(mac, macro_type, temp_service, &temp_buffer, &free_sub_macro); 908 909 if(temp_buffer == NULL) 910 continue; 911 912 /* add macro value to already running macro */ 913 if(*output == NULL) 914 *output = (char *)strdup(temp_buffer); 915 else { 916 if((*output = (char *)realloc(*output, strlen(*output) + strlen(temp_buffer) + delimiter_len + 1)) == NULL) 917 continue; 918 strcat(*output, arg2); 919 strcat(*output, temp_buffer); 920 } 921 if(free_sub_macro == TRUE) 922 my_free(temp_buffer); 923 } 924 } 925 else 926 return ERROR; 927 } 928 break; 929 930 /***********************/ 931 /* SERVICEGROUP MACROS */ 932 /***********************/ 933 case MACRO_SERVICEGROUPNAME: 934 case MACRO_SERVICEGROUPALIAS: 935 case MACRO_SERVICEGROUPNOTES: 936 case MACRO_SERVICEGROUPNOTESURL: 937 case MACRO_SERVICEGROUPACTIONURL: 938 case MACRO_SERVICEGROUPMEMBERS: 939 /* a standard servicegroup macro */ 940 /* use the saved servicegroup pointer */ 941 if(arg1 == NULL) { 942 if((temp_servicegroup = mac->servicegroup_ptr) == NULL) 943 return ERROR; 944 } 945 946 /* else find the servicegroup for on-demand macros */ 947 else { 948 if((temp_servicegroup = find_servicegroup(arg1)) == NULL) 949 return ERROR; 950 } 951 952 /* get the servicegroup macro value */ 953 result = grab_standard_servicegroup_macro_r(mac, macro_type, temp_servicegroup, output); 954 break; 955 956 /******************/ 957 /* CONTACT MACROS */ 958 /******************/ 959 case MACRO_CONTACTNAME: 960 case MACRO_CONTACTALIAS: 961 case MACRO_CONTACTEMAIL: 962 case MACRO_CONTACTPAGER: 963 case MACRO_CONTACTGROUPNAMES: 964 /* a standard contact macro */ 965 if(arg2 == NULL) { 966 967 /* find the contact for on-demand macros */ 968 if(arg1) { 969 if((temp_contact = find_contact(arg1)) == NULL) 970 return ERROR; 971 } 972 973 /* else use saved contact pointer */ 974 else if((temp_contact = mac->contact_ptr) == NULL) 975 return ERROR; 976 977 /* get the contact macro value */ 978 result = grab_standard_contact_macro_r(mac, macro_type, temp_contact, output); 979 } 980 981 /* a contact macro with a contactgroup name and delimiter */ 982 else { 983 984 if((temp_contactgroup = find_contactgroup(arg1)) == NULL) 985 return ERROR; 986 987 delimiter_len = strlen(arg2); 988 989 /* concatenate macro values for all contactgroup members */ 990 for(temp_contactsmember = temp_contactgroup->members; temp_contactsmember != NULL; temp_contactsmember = temp_contactsmember->next) { 991 992 #ifdef NSCORE 993 if((temp_contact = temp_contactsmember->contact_ptr) == NULL) 994 continue; 995 #else 996 if((temp_contact = find_contact(temp_contactsmember->contact_name)) == NULL) 997 continue; 998 #endif 999 1000 /* get the macro value for this contact */ 1001 grab_standard_contact_macro_r(mac, macro_type, temp_contact, &temp_buffer); 1002 1003 if(temp_buffer == NULL) 1004 continue; 1005 1006 /* add macro value to already running macro */ 1007 if(*output == NULL) 1008 *output = (char *)strdup(temp_buffer); 1009 else { 1010 if((*output = (char *)realloc(*output, strlen(*output) + strlen(temp_buffer) + delimiter_len + 1)) == NULL) 1011 continue; 1012 strcat(*output, arg2); 1013 strcat(*output, temp_buffer); 1014 } 1015 my_free(temp_buffer); 1016 } 1017 } 1018 break; 1019 1020 /***********************/ 1021 /* CONTACTGROUP MACROS */ 1022 /***********************/ 1023 case MACRO_CONTACTGROUPNAME: 1024 case MACRO_CONTACTGROUPALIAS: 1025 case MACRO_CONTACTGROUPMEMBERS: 1026 /* a standard contactgroup macro */ 1027 /* use the saved contactgroup pointer */ 1028 if(arg1 == NULL) { 1029 if((temp_contactgroup = mac->contactgroup_ptr) == NULL) 1030 return ERROR; 1031 } 1032 1033 /* else find the contactgroup for on-demand macros */ 1034 else { 1035 if((temp_contactgroup = find_contactgroup(arg1)) == NULL) 1036 return ERROR; 1037 } 1038 1039 /* get the contactgroup macro value */ 1040 result = grab_standard_contactgroup_macro(macro_type, temp_contactgroup, output); 1041 break; 1042 1043 /***********************/ 1044 /* NOTIFICATION MACROS */ 1045 /***********************/ 1046 case MACRO_NOTIFICATIONTYPE: 1047 case MACRO_NOTIFICATIONNUMBER: 1048 case MACRO_NOTIFICATIONRECIPIENTS: 1049 case MACRO_NOTIFICATIONISESCALATED: 1050 case MACRO_NOTIFICATIONAUTHOR: 1051 case MACRO_NOTIFICATIONAUTHORNAME: 1052 case MACRO_NOTIFICATIONAUTHORALIAS: 1053 case MACRO_NOTIFICATIONCOMMENT: 1054 1055 /* notification macros have already been pre-computed */ 1056 *output = mac->x[macro_type]; 1057 *free_macro = FALSE; 1058 break; 1059 1060 /********************/ 1061 /* DATE/TIME MACROS */ 1062 /********************/ 1063 case MACRO_LONGDATETIME: 1064 case MACRO_SHORTDATETIME: 1065 case MACRO_DATE: 1066 case MACRO_TIME: 1067 case MACRO_TIMET: 1068 case MACRO_ISVALIDTIME: 1069 case MACRO_NEXTVALIDTIME: 1070 1071 /* calculate macros */ 1072 result = grab_datetime_macro_r(mac, macro_type, arg1, arg2, output); 1073 break; 1074 1075 /*****************/ 1076 /* STATIC MACROS */ 1077 /*****************/ 1078 case MACRO_ADMINEMAIL: 1079 case MACRO_ADMINPAGER: 1080 case MACRO_MAINCONFIGFILE: 1081 case MACRO_STATUSDATAFILE: 1082 case MACRO_RETENTIONDATAFILE: 1083 case MACRO_OBJECTCACHEFILE: 1084 case MACRO_TEMPFILE: 1085 case MACRO_LOGFILE: 1086 case MACRO_RESOURCEFILE: 1087 case MACRO_COMMANDFILE: 1088 case MACRO_HOSTPERFDATAFILE: 1089 case MACRO_SERVICEPERFDATAFILE: 1090 case MACRO_PROCESSSTARTTIME: 1091 case MACRO_TEMPPATH: 1092 case MACRO_EVENTSTARTTIME: 1093 1094 /* no need to do any more work - these are already precomputed for us */ 1095 *output = global_macros.x[macro_type]; 1096 *free_macro = FALSE; 1097 break; 1098 1099 /******************/ 1100 /* SUMMARY MACROS */ 1101 /******************/ 1102 case MACRO_TOTALHOSTSUP: 1103 case MACRO_TOTALHOSTSDOWN: 1104 case MACRO_TOTALHOSTSUNREACHABLE: 1105 case MACRO_TOTALHOSTSDOWNUNHANDLED: 1106 case MACRO_TOTALHOSTSUNREACHABLEUNHANDLED: 1107 case MACRO_TOTALHOSTPROBLEMS: 1108 case MACRO_TOTALHOSTPROBLEMSUNHANDLED: 1109 case MACRO_TOTALSERVICESOK: 1110 case MACRO_TOTALSERVICESWARNING: 1111 case MACRO_TOTALSERVICESCRITICAL: 1112 case MACRO_TOTALSERVICESUNKNOWN: 1113 case MACRO_TOTALSERVICESWARNINGUNHANDLED: 1114 case MACRO_TOTALSERVICESCRITICALUNHANDLED: 1115 case MACRO_TOTALSERVICESUNKNOWNUNHANDLED: 1116 case MACRO_TOTALSERVICEPROBLEMS: 1117 case MACRO_TOTALSERVICEPROBLEMSUNHANDLED: 1118 1119 #ifdef NSCORE 1120 /* generate summary macros if needed */ 1121 if(mac->x[MACRO_TOTALHOSTSUP] == NULL) { 1122 1123 /* get host totals */ 1124 for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) { 1125 1126 /* filter totals based on contact if necessary */ 1127 if(mac->contact_ptr != NULL) 1128 authorized = is_contact_for_host(temp_host, mac->contact_ptr); 1129 1130 if(authorized == TRUE) { 1131 problem = TRUE; 1132 1133 if(temp_host->current_state == HOST_UP && temp_host->has_been_checked == TRUE) 1134 hosts_up++; 1135 else if(temp_host->current_state == HOST_DOWN) { 1136 if(temp_host->scheduled_downtime_depth > 0) 1137 problem = FALSE; 1138 if(temp_host->problem_has_been_acknowledged == TRUE) 1139 problem = FALSE; 1140 if(temp_host->checks_enabled == FALSE) 1141 problem = FALSE; 1142 if(problem == TRUE) 1143 hosts_down_unhandled++; 1144 hosts_down++; 1145 } 1146 else if(temp_host->current_state == HOST_UNREACHABLE) { 1147 if(temp_host->scheduled_downtime_depth > 0) 1148 problem = FALSE; 1149 if(temp_host->problem_has_been_acknowledged == TRUE) 1150 problem = FALSE; 1151 if(temp_host->checks_enabled == FALSE) 1152 problem = FALSE; 1153 if(problem == TRUE) 1154 hosts_down_unhandled++; 1155 hosts_unreachable++; 1156 } 1157 } 1158 } 1159 1160 host_problems = hosts_down + hosts_unreachable; 1161 host_problems_unhandled = hosts_down_unhandled + hosts_unreachable_unhandled; 1162 1163 /* get service totals */ 1164 for(temp_service = service_list; temp_service != NULL; temp_service = temp_service->next) { 1165 1166 /* filter totals based on contact if necessary */ 1167 if(mac->contact_ptr != NULL) 1168 authorized = is_contact_for_service(temp_service, mac->contact_ptr); 1169 1170 if(authorized == TRUE) { 1171 problem = TRUE; 1172 1173 if(temp_service->current_state == STATE_OK && temp_service->has_been_checked == TRUE) 1174 services_ok++; 1175 else if(temp_service->current_state == STATE_WARNING) { 1176 temp_host = find_host(temp_service->host_name); 1177 if(temp_host != NULL && (temp_host->current_state == HOST_DOWN || temp_host->current_state == HOST_UNREACHABLE)) 1178 problem = FALSE; 1179 if(temp_service->scheduled_downtime_depth > 0) 1180 problem = FALSE; 1181 if(temp_service->problem_has_been_acknowledged == TRUE) 1182 problem = FALSE; 1183 if(temp_service->checks_enabled == FALSE) 1184 problem = FALSE; 1185 if(problem == TRUE) 1186 services_warning_unhandled++; 1187 services_warning++; 1188 } 1189 else if(temp_service->current_state == STATE_UNKNOWN) { 1190 temp_host = find_host(temp_service->host_name); 1191 if(temp_host != NULL && (temp_host->current_state == HOST_DOWN || temp_host->current_state == HOST_UNREACHABLE)) 1192 problem = FALSE; 1193 if(temp_service->scheduled_downtime_depth > 0) 1194 problem = FALSE; 1195 if(temp_service->problem_has_been_acknowledged == TRUE) 1196 problem = FALSE; 1197 if(temp_service->checks_enabled == FALSE) 1198 problem = FALSE; 1199 if(problem == TRUE) 1200 services_unknown_unhandled++; 1201 services_unknown++; 1202 } 1203 else if(temp_service->current_state == STATE_CRITICAL) { 1204 temp_host = find_host(temp_service->host_name); 1205 if(temp_host != NULL && (temp_host->current_state == HOST_DOWN || temp_host->current_state == HOST_UNREACHABLE)) 1206 problem = FALSE; 1207 if(temp_service->scheduled_downtime_depth > 0) 1208 problem = FALSE; 1209 if(temp_service->problem_has_been_acknowledged == TRUE) 1210 problem = FALSE; 1211 if(temp_service->checks_enabled == FALSE) 1212 problem = FALSE; 1213 if(problem == TRUE) 1214 services_critical_unhandled++; 1215 services_critical++; 1216 } 1217 } 1218 } 1219 1220 service_problems = services_warning + services_critical + services_unknown; 1221 service_problems_unhandled = services_warning_unhandled + services_critical_unhandled + services_unknown_unhandled; 1222 1223 /* these macros are time-intensive to compute, and will likely be used together, so save them all for future use */ 1224 for(x = MACRO_TOTALHOSTSUP; x <= MACRO_TOTALSERVICEPROBLEMSUNHANDLED; x++) 1225 my_free(mac->x[x]); 1226 asprintf(&mac->x[MACRO_TOTALHOSTSUP], "%d", hosts_up); 1227 asprintf(&mac->x[MACRO_TOTALHOSTSDOWN], "%d", hosts_down); 1228 asprintf(&mac->x[MACRO_TOTALHOSTSUNREACHABLE], "%d", hosts_unreachable); 1229 asprintf(&mac->x[MACRO_TOTALHOSTSDOWNUNHANDLED], "%d", hosts_down_unhandled); 1230 asprintf(&mac->x[MACRO_TOTALHOSTSUNREACHABLEUNHANDLED], "%d", hosts_unreachable_unhandled); 1231 asprintf(&mac->x[MACRO_TOTALHOSTPROBLEMS], "%d", host_problems); 1232 asprintf(&mac->x[MACRO_TOTALHOSTPROBLEMSUNHANDLED], "%d", host_problems_unhandled); 1233 asprintf(&mac->x[MACRO_TOTALSERVICESOK], "%d", services_ok); 1234 asprintf(&mac->x[MACRO_TOTALSERVICESWARNING], "%d", services_warning); 1235 asprintf(&mac->x[MACRO_TOTALSERVICESCRITICAL], "%d", services_critical); 1236 asprintf(&mac->x[MACRO_TOTALSERVICESUNKNOWN], "%d", services_unknown); 1237 asprintf(&mac->x[MACRO_TOTALSERVICESWARNINGUNHANDLED], "%d", services_warning_unhandled); 1238 asprintf(&mac->x[MACRO_TOTALSERVICESCRITICALUNHANDLED], "%d", services_critical_unhandled); 1239 asprintf(&mac->x[MACRO_TOTALSERVICESUNKNOWNUNHANDLED], "%d", services_unknown_unhandled); 1240 asprintf(&mac->x[MACRO_TOTALSERVICEPROBLEMS], "%d", service_problems); 1241 asprintf(&mac->x[MACRO_TOTALSERVICEPROBLEMSUNHANDLED], "%d", service_problems_unhandled); 1242 } 1243 1244 /* return only the macro the user requested */ 1245 *output = mac->x[macro_type]; 1246 1247 /* tell caller to NOT free memory when done */ 1248 *free_macro = FALSE; 1249 #endif 1250 break; 1251 1252 default: 1253 log_debug_info(DEBUGL_MACROS, 0, "UNHANDLED MACRO #%d! THIS IS A BUG!\n", macro_type); 1254 return ERROR; 1255 break; 1256 } 1257 1258 return result; 1259 } 1260 1261 int grab_macrox_value(int macro_type, char *arg1, char *arg2, char **output, int *free_macro) { 1262 return grab_macrox_value_r(&global_macros, macro_type, arg1, arg2, output, free_macro); 1263 } 1264 1265 1266 /* calculates the value of a custom macro */ 1267 int grab_custom_macro_value_r(nagios_macros *mac, char *macro_name, char *arg1, char *arg2, char **output) { 1268 host *temp_host = NULL; 1269 hostgroup *temp_hostgroup = NULL; 1270 hostsmember *temp_hostsmember = NULL; 1271 service *temp_service = NULL; 1272 servicegroup *temp_servicegroup = NULL; 1273 servicesmember *temp_servicesmember = NULL; 1274 contact *temp_contact = NULL; 1275 contactgroup *temp_contactgroup = NULL; 1276 contactsmember *temp_contactsmember = NULL; 1277 int delimiter_len = 0; 1278 char *temp_buffer = NULL; 1279 int result = OK; 1280 1281 if(macro_name == NULL || output == NULL) 1282 return ERROR; 1283 1284 /***** CUSTOM HOST MACRO *****/ 1285 if(strstr(macro_name, "_HOST") == macro_name) { 1286 1287 /* a standard host macro */ 1288 if(arg2 == NULL) { 1289 1290 /* find the host for on-demand macros */ 1291 if(arg1) { 1292 if((temp_host = find_host(arg1)) == NULL) 1293 return ERROR; 1294 } 1295 1296 /* else use saved host pointer */ 1297 else if((temp_host = mac->host_ptr) == NULL) 1298 return ERROR; 1299 1300 /* get the host macro value */ 1301 result = grab_custom_object_macro_r(mac, macro_name + 5, temp_host->custom_variables, output); 1302 } 1303 1304 /* a host macro with a hostgroup name and delimiter */ 1305 else { 1306 if((temp_hostgroup = find_hostgroup(arg1)) == NULL) 1307 return ERROR; 1308 1309 delimiter_len = strlen(arg2); 1310 1311 /* concatenate macro values for all hostgroup members */ 1312 for(temp_hostsmember = temp_hostgroup->members; temp_hostsmember != NULL; temp_hostsmember = temp_hostsmember->next) { 1313 1314 #ifdef NSCORE 1315 if((temp_host = temp_hostsmember->host_ptr) == NULL) 1316 continue; 1317 #else 1318 if((temp_host = find_host(temp_hostsmember->host_name)) == NULL) 1319 continue; 1320 #endif 1321 1322 /* get the macro value for this host */ 1323 grab_custom_macro_value_r(mac, macro_name, temp_host->name, NULL, &temp_buffer); 1324 1325 if(temp_buffer == NULL) 1326 continue; 1327 1328 /* add macro value to already running macro */ 1329 if(*output == NULL) 1330 *output = (char *)strdup(temp_buffer); 1331 else { 1332 if((*output = (char *)realloc(*output, strlen(*output) + strlen(temp_buffer) + delimiter_len + 1)) == NULL) 1333 continue; 1334 strcat(*output, arg2); 1335 strcat(*output, temp_buffer); 1336 } 1337 my_free(temp_buffer); 1338 } 1339 } 1340 } 1341 1342 /***** CUSTOM SERVICE MACRO *****/ 1343 else if(strstr(macro_name, "_SERVICE") == macro_name) { 1344 1345 /* use saved service pointer */ 1346 if(arg1 == NULL && arg2 == NULL) { 1347 1348 if((temp_service = mac->service_ptr) == NULL) 1349 return ERROR; 1350 1351 /* get the service macro value */ 1352 result = grab_custom_object_macro_r(mac, macro_name + 8, temp_service->custom_variables, output); 1353 } 1354 1355 /* else and ondemand macro... */ 1356 else { 1357 1358 /* if first arg is blank, it means use the current host name */ 1359 if(mac->host_ptr == NULL) 1360 return ERROR; 1361 if((temp_service = find_service((mac->host_ptr) ? mac->host_ptr->name : NULL, arg2))) { 1362 1363 /* get the service macro value */ 1364 result = grab_custom_object_macro_r(mac, macro_name + 8, temp_service->custom_variables, output); 1365 } 1366 1367 /* else we have a service macro with a servicegroup name and a delimiter... */ 1368 else { 1369 1370 if((temp_servicegroup = find_servicegroup(arg1)) == NULL) 1371 return ERROR; 1372 1373 delimiter_len = strlen(arg2); 1374 1375 /* concatenate macro values for all servicegroup members */ 1376 for(temp_servicesmember = temp_servicegroup->members; temp_servicesmember != NULL; temp_servicesmember = temp_servicesmember->next) { 1377 1378 #ifdef NSCORE 1379 if((temp_service = temp_servicesmember->service_ptr) == NULL) 1380 continue; 1381 #else 1382 if((temp_service = find_service(temp_servicesmember->host_name, temp_servicesmember->service_description)) == NULL) 1383 continue; 1384 #endif 1385 1386 /* get the macro value for this service */ 1387 grab_custom_macro_value_r(mac, macro_name, temp_service->host_name, temp_service->description, &temp_buffer); 1388 1389 if(temp_buffer == NULL) 1390 continue; 1391 1392 /* add macro value to already running macro */ 1393 if(*output == NULL) 1394 *output = (char *)strdup(temp_buffer); 1395 else { 1396 if((*output = (char *)realloc(*output, strlen(*output) + strlen(temp_buffer) + delimiter_len + 1)) == NULL) 1397 continue; 1398 strcat(*output, arg2); 1399 strcat(*output, temp_buffer); 1400 } 1401 my_free(temp_buffer); 1402 } 1403 } 1404 } 1405 } 1406 1407 /***** CUSTOM CONTACT VARIABLE *****/ 1408 else if(strstr(macro_name, "_CONTACT") == macro_name) { 1409 1410 /* a standard contact macro */ 1411 if(arg2 == NULL) { 1412 1413 /* find the contact for on-demand macros */ 1414 if(arg1) { 1415 if((temp_contact = find_contact(arg1)) == NULL) 1416 return ERROR; 1417 } 1418 1419 /* else use saved contact pointer */ 1420 else if((temp_contact = mac->contact_ptr) == NULL) 1421 return ERROR; 1422 1423 /* get the contact macro value */ 1424 result = grab_custom_object_macro_r(mac, macro_name + 8, temp_contact->custom_variables, output); 1425 } 1426 1427 /* a contact macro with a contactgroup name and delimiter */ 1428 else { 1429 1430 if((temp_contactgroup = find_contactgroup(arg1)) == NULL) 1431 return ERROR; 1432 1433 delimiter_len = strlen(arg2); 1434 1435 /* concatenate macro values for all contactgroup members */ 1436 for(temp_contactsmember = temp_contactgroup->members; temp_contactsmember != NULL; temp_contactsmember = temp_contactsmember->next) { 1437 1438 #ifdef NSCORE 1439 if((temp_contact = temp_contactsmember->contact_ptr) == NULL) 1440 continue; 1441 #else 1442 if((temp_contact = find_contact(temp_contactsmember->contact_name)) == NULL) 1443 continue; 1444 #endif 1445 1446 /* get the macro value for this contact */ 1447 grab_custom_macro_value_r(mac, macro_name, temp_contact->name, NULL, &temp_buffer); 1448 1449 if(temp_buffer == NULL) 1450 continue; 1451 1452 /* add macro value to already running macro */ 1453 if(*output == NULL) 1454 *output = (char *)strdup(temp_buffer); 1455 else { 1456 if((*output = (char *)realloc(*output, strlen(*output) + strlen(temp_buffer) + delimiter_len + 1)) == NULL) 1457 continue; 1458 strcat(*output, arg2); 1459 strcat(*output, temp_buffer); 1460 } 1461 my_free(temp_buffer); 1462 } 1463 } 1464 } 1465 1466 else 1467 return ERROR; 1468 1469 return result; 1470 } 1471 1472 int grab_custom_macro_value(char *macro_name, char *arg1, char *arg2, char **output) { 1473 return grab_custom_macro_value_r(&global_macros, macro_name, arg1, arg2, output); 1474 } 1475 1476 1477 /* calculates a date/time macro */ 1478 int grab_datetime_macro_r(nagios_macros *mac, int macro_type, char *arg1, char *arg2, char **output) { 1479 time_t current_time = 0L; 1480 timeperiod *temp_timeperiod = NULL; 1481 time_t test_time = 0L; 1482 #ifdef NSCORE 1483 time_t next_valid_time = 0L; 1484 #endif 1485 1486 if(output == NULL) 1487 return ERROR; 1488 1489 /* get the current time */ 1490 time(¤t_time); 1491 1492 /* parse args, do prep work */ 1493 switch(macro_type) { 1494 1495 case MACRO_ISVALIDTIME: 1496 case MACRO_NEXTVALIDTIME: 1497 1498 /* find the timeperiod */ 1499 if((temp_timeperiod = find_timeperiod(arg1)) == NULL) 1500 return ERROR; 1501 1502 /* what timestamp should we use? */ 1503 if(arg2) 1504 test_time = (time_t)strtoul(arg2, NULL, 0); 1505 else 1506 test_time = current_time; 1507 break; 1508 1509 default: 1510 break; 1511 } 1512 1513 /* calculate the value */ 1514 switch(macro_type) { 1515 1516 case MACRO_LONGDATETIME: 1517 if(*output == NULL) 1518 *output = (char *)malloc(MAX_DATETIME_LENGTH); 1519 if(*output) 1520 get_datetime_string(¤t_time, *output, MAX_DATETIME_LENGTH, LONG_DATE_TIME); 1521 break; 1522 1523 case MACRO_SHORTDATETIME: 1524 if(*output == NULL) 1525 *output = (char *)malloc(MAX_DATETIME_LENGTH); 1526 if(*output) 1527 get_datetime_string(¤t_time, *output, MAX_DATETIME_LENGTH, SHORT_DATE_TIME); 1528 break; 1529 1530 case MACRO_DATE: 1531 if(*output == NULL) 1532 *output = (char *)malloc(MAX_DATETIME_LENGTH); 1533 if(*output) 1534 get_datetime_string(¤t_time, *output, MAX_DATETIME_LENGTH, SHORT_DATE); 1535 break; 1536 1537 case MACRO_TIME: 1538 if(*output == NULL) 1539 *output = (char *)malloc(MAX_DATETIME_LENGTH); 1540 if(*output) 1541 get_datetime_string(¤t_time, *output, MAX_DATETIME_LENGTH, SHORT_TIME); 1542 break; 1543 1544 case MACRO_TIMET: 1545 asprintf(output, "%lu", (unsigned long)current_time); 1546 break; 1547 1548 #ifdef NSCORE 1549 case MACRO_ISVALIDTIME: 1550 asprintf(output, "%d", (check_time_against_period(test_time, temp_timeperiod) == OK) ? 1 : 0); 1551 break; 1552 1553 case MACRO_NEXTVALIDTIME: 1554 get_next_valid_time(test_time, &next_valid_time, temp_timeperiod); 1555 if(next_valid_time == test_time && check_time_against_period(test_time, temp_timeperiod) == ERROR) 1556 next_valid_time = (time_t)0L; 1557 asprintf(output, "%lu", (unsigned long)next_valid_time); 1558 break; 1559 #endif 1560 1561 default: 1562 return ERROR; 1563 break; 1564 } 1565 1566 return OK; 1567 } 1568 1569 int grab_datetime_macro(int macro_type, char *arg1, char *arg2, char **output) { 1570 return grab_datetime_macro_r(&global_macros, macro_type, arg1, arg2, output); 1571 } 1572 1573 1574 /* calculates a host macro */ 1575 int grab_standard_host_macro_r(nagios_macros *mac, int macro_type, host *temp_host, char **output, int *free_macro) { 1576 char *temp_buffer = NULL; 1577 #ifdef NSCORE 1578 hostgroup *temp_hostgroup = NULL; 1579 servicesmember *temp_servicesmember = NULL; 1580 service *temp_service = NULL; 1581 objectlist *temp_objectlist = NULL; 1582 time_t current_time = 0L; 1583 unsigned long duration = 0L; 1584 int days = 0; 1585 int hours = 0; 1586 int minutes = 0; 1587 int seconds = 0; 1588 char *buf1 = NULL; 1589 char *buf2 = NULL; 1590 int total_host_services = 0; 1591 int total_host_services_ok = 0; 1592 int total_host_services_warning = 0; 1593 int total_host_services_unknown = 0; 1594 int total_host_services_critical = 0; 1595 #endif 1596 1597 if(temp_host == NULL || output == NULL || free_macro == NULL) 1598 return ERROR; 1599 1600 /* BY DEFAULT TELL CALLER TO FREE MACRO BUFFER WHEN DONE */ 1601 *free_macro = TRUE; 1602 1603 /* get the macro */ 1604 switch(macro_type) { 1605 1606 case MACRO_HOSTNAME: 1607 *output = (char *)strdup(temp_host->name); 1608 break; 1609 case MACRO_HOSTDISPLAYNAME: 1610 if(temp_host->display_name) 1611 *output = (char *)strdup(temp_host->display_name); 1612 break; 1613 case MACRO_HOSTALIAS: 1614 *output = (char *)strdup(temp_host->alias); 1615 break; 1616 case MACRO_HOSTADDRESS: 1617 *output = (char *)strdup(temp_host->address); 1618 break; 1619 #ifdef NSCORE 1620 case MACRO_HOSTSTATE: 1621 if(temp_host->current_state == HOST_DOWN) 1622 *output = (char *)strdup("DOWN"); 1623 else if(temp_host->current_state == HOST_UNREACHABLE) 1624 *output = (char *)strdup("UNREACHABLE"); 1625 else 1626 *output = (char *)strdup("UP"); 1627 break; 1628 case MACRO_HOSTSTATEID: 1629 asprintf(output, "%d", temp_host->current_state); 1630 break; 1631 case MACRO_LASTHOSTSTATE: 1632 if(temp_host->last_state == HOST_DOWN) 1633 *output = (char *)strdup("DOWN"); 1634 else if(temp_host->last_state == HOST_UNREACHABLE) 1635 *output = (char *)strdup("UNREACHABLE"); 1636 else 1637 *output = (char *)strdup("UP"); 1638 break; 1639 case MACRO_LASTHOSTSTATEID: 1640 asprintf(output, "%d", temp_host->last_state); 1641 break; 1642 case MACRO_HOSTCHECKTYPE: 1643 asprintf(output, "%s", (temp_host->check_type == HOST_CHECK_PASSIVE) ? "PASSIVE" : "ACTIVE"); 1644 break; 1645 case MACRO_HOSTSTATETYPE: 1646 asprintf(output, "%s", (temp_host->state_type == HARD_STATE) ? "HARD" : "SOFT"); 1647 break; 1648 case MACRO_HOSTOUTPUT: 1649 if(temp_host->plugin_output) 1650 *output = (char *)strdup(temp_host->plugin_output); 1651 break; 1652 case MACRO_LONGHOSTOUTPUT: 1653 if(temp_host->long_plugin_output) 1654 *output = (char *)strdup(temp_host->long_plugin_output); 1655 break; 1656 case MACRO_HOSTPERFDATA: 1657 if(temp_host->perf_data) 1658 *output = (char *)strdup(temp_host->perf_data); 1659 break; 1660 #endif 1661 case MACRO_HOSTCHECKCOMMAND: 1662 if(temp_host->host_check_command) 1663 *output = (char *)strdup(temp_host->host_check_command); 1664 break; 1665 #ifdef NSCORE 1666 case MACRO_HOSTATTEMPT: 1667 asprintf(output, "%d", temp_host->current_attempt); 1668 break; 1669 case MACRO_MAXHOSTATTEMPTS: 1670 asprintf(output, "%d", temp_host->max_attempts); 1671 break; 1672 case MACRO_HOSTDOWNTIME: 1673 asprintf(output, "%d", temp_host->scheduled_downtime_depth); 1674 break; 1675 case MACRO_HOSTPERCENTCHANGE: 1676 asprintf(output, "%.2f", temp_host->percent_state_change); 1677 break; 1678 case MACRO_HOSTDURATIONSEC: 1679 case MACRO_HOSTDURATION: 1680 time(¤t_time); 1681 duration = (unsigned long)(current_time - temp_host->last_state_change); 1682 1683 if(macro_type == MACRO_HOSTDURATIONSEC) 1684 asprintf(output, "%lu", duration); 1685 else { 1686 1687 days = duration / 86400; 1688 duration -= (days * 86400); 1689 hours = duration / 3600; 1690 duration -= (hours * 3600); 1691 minutes = duration / 60; 1692 duration -= (minutes * 60); 1693 seconds = duration; 1694 asprintf(output, "%dd %dh %dm %ds", days, hours, minutes, seconds); 1695 } 1696 break; 1697 case MACRO_HOSTEXECUTIONTIME: 1698 asprintf(output, "%.3f", temp_host->execution_time); 1699 break; 1700 case MACRO_HOSTLATENCY: 1701 asprintf(output, "%.3f", temp_host->latency); 1702 break; 1703 case MACRO_LASTHOSTCHECK: 1704 asprintf(output, "%lu", (unsigned long)temp_host->last_check); 1705 break; 1706 case MACRO_LASTHOSTSTATECHANGE: 1707 asprintf(output, "%lu", (unsigned long)temp_host->last_state_change); 1708 break; 1709 case MACRO_LASTHOSTUP: 1710 asprintf(output, "%lu", (unsigned long)temp_host->last_time_up); 1711 break; 1712 case MACRO_LASTHOSTDOWN: 1713 asprintf(output, "%lu", (unsigned long)temp_host->last_time_down); 1714 break; 1715 case MACRO_LASTHOSTUNREACHABLE: 1716 asprintf(output, "%lu", (unsigned long)temp_host->last_time_unreachable); 1717 break; 1718 case MACRO_HOSTNOTIFICATIONNUMBER: 1719 asprintf(output, "%d", temp_host->current_notification_number); 1720 break; 1721 case MACRO_HOSTNOTIFICATIONID: 1722 asprintf(output, "%lu", temp_host->current_notification_id); 1723 break; 1724 case MACRO_HOSTEVENTID: 1725 asprintf(output, "%lu", temp_host->current_event_id); 1726 break; 1727 case MACRO_LASTHOSTEVENTID: 1728 asprintf(output, "%lu", temp_host->last_event_id); 1729 break; 1730 case MACRO_HOSTPROBLEMID: 1731 asprintf(output, "%lu", temp_host->current_problem_id); 1732 break; 1733 case MACRO_LASTHOSTPROBLEMID: 1734 asprintf(output, "%lu", temp_host->last_problem_id); 1735 break; 1736 #endif 1737 case MACRO_HOSTACTIONURL: 1738 if(temp_host->action_url) 1739 *output = (char *)strdup(temp_host->action_url); 1740 break; 1741 case MACRO_HOSTNOTESURL: 1742 if(temp_host->notes_url) 1743 *output = (char *)strdup(temp_host->notes_url); 1744 break; 1745 case MACRO_HOSTNOTES: 1746 if(temp_host->notes) 1747 *output = (char *)strdup(temp_host->notes); 1748 break; 1749 #ifdef NSCORE 1750 case MACRO_HOSTGROUPNAMES: 1751 /* find all hostgroups this host is associated with */ 1752 for(temp_objectlist = temp_host->hostgroups_ptr; temp_objectlist != NULL; temp_objectlist = temp_objectlist->next) { 1753 1754 if((temp_hostgroup = (hostgroup *)temp_objectlist->object_ptr) == NULL) 1755 continue; 1756 1757 asprintf(&buf1, "%s%s%s", (buf2) ? buf2 : "", (buf2) ? "," : "", temp_hostgroup->group_name); 1758 my_free(buf2); 1759 buf2 = buf1; 1760 } 1761 if(buf2) { 1762 *output = (char *)strdup(buf2); 1763 my_free(buf2); 1764 } 1765 break; 1766 case MACRO_TOTALHOSTSERVICES: 1767 case MACRO_TOTALHOSTSERVICESOK: 1768 case MACRO_TOTALHOSTSERVICESWARNING: 1769 case MACRO_TOTALHOSTSERVICESUNKNOWN: 1770 case MACRO_TOTALHOSTSERVICESCRITICAL: 1771 1772 /* generate host service summary macros (if they haven't already been computed) */ 1773 if(mac->x[MACRO_TOTALHOSTSERVICES] == NULL) { 1774 1775 for(temp_servicesmember = temp_host->services; temp_servicesmember != NULL; temp_servicesmember = temp_servicesmember->next) { 1776 if((temp_service = temp_servicesmember->service_ptr) == NULL) 1777 continue; 1778 1779 total_host_services++; 1780 1781 switch(temp_service->current_state) { 1782 case STATE_OK: 1783 total_host_services_ok++; 1784 break; 1785 case STATE_WARNING: 1786 total_host_services_warning++; 1787 break; 1788 case STATE_UNKNOWN: 1789 total_host_services_unknown++; 1790 break; 1791 case STATE_CRITICAL: 1792 total_host_services_critical++; 1793 break; 1794 default: 1795 break; 1796 } 1797 } 1798 1799 /* these macros are time-intensive to compute, and will likely be used together, so save them all for future use */ 1800 my_free(mac->x[MACRO_TOTALHOSTSERVICES]); 1801 asprintf(&mac->x[MACRO_TOTALHOSTSERVICES], "%d", total_host_services); 1802 my_free(mac->x[MACRO_TOTALHOSTSERVICESOK]); 1803 asprintf(&mac->x[MACRO_TOTALHOSTSERVICESOK], "%d", total_host_services_ok); 1804 my_free(mac->x[MACRO_TOTALHOSTSERVICESWARNING]); 1805 asprintf(&mac->x[MACRO_TOTALHOSTSERVICESWARNING], "%d", total_host_services_warning); 1806 my_free(mac->x[MACRO_TOTALHOSTSERVICESUNKNOWN]); 1807 asprintf(&mac->x[MACRO_TOTALHOSTSERVICESUNKNOWN], "%d", total_host_services_unknown); 1808 my_free(mac->x[MACRO_TOTALHOSTSERVICESCRITICAL]); 1809 asprintf(&mac->x[MACRO_TOTALHOSTSERVICESCRITICAL], "%d", total_host_services_critical); 1810 } 1811 1812 /* return only the macro the user requested */ 1813 *output = mac->x[macro_type]; 1814 1815 /* tell caller to NOT free memory when done */ 1816 *free_macro = FALSE; 1817 break; 1818 #endif 1819 /***************/ 1820 /* MISC MACROS */ 1821 /***************/ 1822 case MACRO_HOSTACKAUTHOR: 1823 case MACRO_HOSTACKAUTHORNAME: 1824 case MACRO_HOSTACKAUTHORALIAS: 1825 case MACRO_HOSTACKCOMMENT: 1826 /* no need to do any more work - these are already precomputed elsewhere */ 1827 /* NOTE: these macros won't work as on-demand macros */ 1828 *output = mac->x[macro_type]; 1829 *free_macro = FALSE; 1830 break; 1831 1832 default: 1833 log_debug_info(DEBUGL_MACROS, 0, "UNHANDLED HOST MACRO #%d! THIS IS A BUG!\n", macro_type); 1834 return ERROR; 1835 break; 1836 } 1837 1838 /* post-processing */ 1839 /* notes, notes URL and action URL macros may themselves contain macros, so process them... */ 1840 switch(macro_type) { 1841 case MACRO_HOSTACTIONURL: 1842 case MACRO_HOSTNOTESURL: 1843 process_macros_r(mac, *output, &temp_buffer, URL_ENCODE_MACRO_CHARS); 1844 my_free(*output); 1845 *output = temp_buffer; 1846 break; 1847 case MACRO_HOSTNOTES: 1848 process_macros_r(mac, *output, &temp_buffer, 0); 1849 my_free(*output); 1850 *output = temp_buffer; 1851 break; 1852 default: 1853 break; 1854 } 1855 1856 return OK; 1857 } 1858 1859 int grab_standard_host_macro(int macro_type, host *temp_host, char **output, int *free_macro) { 1860 return grab_standard_host_macro_r(&global_macros, macro_type, temp_host, output, free_macro); 1861 } 1862 1863 1864 /* computes a hostgroup macro */ 1865 int grab_standard_hostgroup_macro_r(nagios_macros *mac, int macro_type, hostgroup *temp_hostgroup, char **output) { 1866 hostsmember *temp_hostsmember = NULL; 1867 char *temp_buffer = NULL; 1868 unsigned int temp_len = 0; 1869 unsigned int init_len = 0; 1870 1871 if(temp_hostgroup == NULL || output == NULL) 1872 return ERROR; 1873 1874 /* get the macro value */ 1875 switch(macro_type) { 1876 case MACRO_HOSTGROUPNAME: 1877 *output = (char *)strdup(temp_hostgroup->group_name); 1878 break; 1879 case MACRO_HOSTGROUPALIAS: 1880 if(temp_hostgroup->alias) 1881 *output = (char *)strdup(temp_hostgroup->alias); 1882 break; 1883 case MACRO_HOSTGROUPMEMBERS: 1884 /* make the calculations for total string length */ 1885 for(temp_hostsmember = temp_hostgroup->members; temp_hostsmember != NULL; temp_hostsmember = temp_hostsmember->next) { 1886 if(temp_hostsmember->host_name == NULL) 1887 continue; 1888 if(temp_len == 0) { 1889 temp_len += strlen(temp_hostsmember->host_name) + 1; 1890 } 1891 else { 1892 temp_len += strlen(temp_hostsmember->host_name) + 2; 1893 } 1894 } 1895 /* allocate or reallocate the memory buffer */ 1896 if(*output == NULL) { 1897 *output = (char *)malloc(temp_len); 1898 } 1899 else { 1900 init_len = strlen(*output); 1901 temp_len += init_len; 1902 *output = (char *)realloc(*output, temp_len); 1903 } 1904 /* now fill in the string with the member names */ 1905 for(temp_hostsmember = temp_hostgroup->members; temp_hostsmember != NULL; temp_hostsmember = temp_hostsmember->next) { 1906 if(temp_hostsmember->host_name == NULL) 1907 continue; 1908 temp_buffer = *output + init_len; 1909 if(init_len == 0) { /* If our buffer didn't contain anything, we just need to write "%s,%s" */ 1910 init_len += sprintf(temp_buffer, "%s", temp_hostsmember->host_name); 1911 } 1912 else { 1913 init_len += sprintf(temp_buffer, ",%s", temp_hostsmember->host_name); 1914 } 1915 } 1916 break; 1917 case MACRO_HOSTGROUPACTIONURL: 1918 if(temp_hostgroup->action_url) 1919 *output = (char *)strdup(temp_hostgroup->action_url); 1920 break; 1921 case MACRO_HOSTGROUPNOTESURL: 1922 if(temp_hostgroup->notes_url) 1923 *output = (char *)strdup(temp_hostgroup->notes_url); 1924 break; 1925 case MACRO_HOSTGROUPNOTES: 1926 if(temp_hostgroup->notes) 1927 *output = (char *)strdup(temp_hostgroup->notes); 1928 break; 1929 default: 1930 log_debug_info(DEBUGL_MACROS, 0, "UNHANDLED HOSTGROUP MACRO #%d! THIS IS A BUG!\n", macro_type); 1931 return ERROR; 1932 break; 1933 } 1934 1935 /* post-processing */ 1936 /* notes, notes URL and action URL macros may themselves contain macros, so process them... */ 1937 switch(macro_type) { 1938 case MACRO_HOSTGROUPACTIONURL: 1939 case MACRO_HOSTGROUPNOTESURL: 1940 process_macros_r(mac, *output, &temp_buffer, URL_ENCODE_MACRO_CHARS); 1941 my_free(*output); 1942 *output = temp_buffer; 1943 break; 1944 case MACRO_HOSTGROUPNOTES: 1945 process_macros_r(mac, *output, &temp_buffer, 0); 1946 my_free(*output); 1947 *output = temp_buffer; 1948 break; 1949 default: 1950 break; 1951 } 1952 1953 return OK; 1954 } 1955 1956 int grab_standard_hostgroup_macro(int macro_type, hostgroup *temp_hostgroup, char **output) { 1957 return grab_standard_hostgroup_macro_r(&global_macros, macro_type, temp_hostgroup, output); 1958 } 1959 1960 1961 /* computes a service macro */ 1962 int grab_standard_service_macro_r(nagios_macros *mac, int macro_type, service *temp_service, char **output, int *free_macro) { 1963 char *temp_buffer = NULL; 1964 #ifdef NSCORE 1965 servicegroup *temp_servicegroup = NULL; 1966 objectlist *temp_objectlist = NULL; 1967 time_t current_time = 0L; 1968 unsigned long duration = 0L; 1969 int days = 0; 1970 int hours = 0; 1971 int minutes = 0; 1972 int seconds = 0; 1973 char *buf1 = NULL; 1974 char *buf2 = NULL; 1975 #endif 1976 1977 if(temp_service == NULL || output == NULL) 1978 return ERROR; 1979 1980 /* BY DEFAULT TELL CALLER TO FREE MACRO BUFFER WHEN DONE */ 1981 *free_macro = TRUE; 1982 1983 /* get the macro value */ 1984 switch(macro_type) { 1985 case MACRO_SERVICEDESC: 1986 *output = (char *)strdup(temp_service->description); 1987 break; 1988 case MACRO_SERVICEDISPLAYNAME: 1989 if(temp_service->display_name) 1990 *output = (char *)strdup(temp_service->display_name); 1991 break; 1992 #ifdef NSCORE 1993 case MACRO_SERVICEOUTPUT: 1994 if(temp_service->plugin_output) 1995 *output = (char *)strdup(temp_service->plugin_output); 1996 break; 1997 case MACRO_LONGSERVICEOUTPUT: 1998 if(temp_service->long_plugin_output) 1999 *output = (char *)strdup(temp_service->long_plugin_output); 2000 break; 2001 case MACRO_SERVICEPERFDATA: 2002 if(temp_service->perf_data) 2003 *output = (char *)strdup(temp_service->perf_data); 2004 break; 2005 #endif 2006 case MACRO_SERVICECHECKCOMMAND: 2007 if(temp_service->service_check_command) 2008 *output = (char *)strdup(temp_service->service_check_command); 2009 break; 2010 #ifdef NSCORE 2011 case MACRO_SERVICECHECKTYPE: 2012 *output = (char *)strdup((temp_service->check_type == SERVICE_CHECK_PASSIVE) ? "PASSIVE" : "ACTIVE"); 2013 break; 2014 case MACRO_SERVICESTATETYPE: 2015 *output = (char *)strdup((temp_service->state_type == HARD_STATE) ? "HARD" : "SOFT"); 2016 break; 2017 case MACRO_SERVICESTATE: 2018 if(temp_service->current_state == STATE_OK) 2019 *output = (char *)strdup("OK"); 2020 else if(temp_service->current_state == STATE_WARNING) 2021 *output = (char *)strdup("WARNING"); 2022 else if(temp_service->current_state == STATE_CRITICAL) 2023 *output = (char *)strdup("CRITICAL"); 2024 else 2025 *output = (char *)strdup("UNKNOWN"); 2026 break; 2027 case MACRO_SERVICESTATEID: 2028 asprintf(output, "%d", temp_service->current_state); 2029 break; 2030 case MACRO_LASTSERVICESTATE: 2031 if(temp_service->last_state == STATE_OK) 2032 *output = (char *)strdup("OK"); 2033 else if(temp_service->last_state == STATE_WARNING) 2034 *output = (char *)strdup("WARNING"); 2035 else if(temp_service->last_state == STATE_CRITICAL) 2036 *output = (char *)strdup("CRITICAL"); 2037 else 2038 *output = (char *)strdup("UNKNOWN"); 2039 break; 2040 case MACRO_LASTSERVICESTATEID: 2041 asprintf(output, "%d", temp_service->last_state); 2042 break; 2043 #endif 2044 case MACRO_SERVICEISVOLATILE: 2045 asprintf(output, "%d", temp_service->is_volatile); 2046 break; 2047 #ifdef NSCORE 2048 case MACRO_SERVICEATTEMPT: 2049 asprintf(output, "%d", temp_service->current_attempt); 2050 break; 2051 case MACRO_MAXSERVICEATTEMPTS: 2052 asprintf(output, "%d", temp_service->max_attempts); 2053 break; 2054 case MACRO_SERVICEEXECUTIONTIME: 2055 asprintf(output, "%.3f", temp_service->execution_time); 2056 break; 2057 case MACRO_SERVICELATENCY: 2058 asprintf(output, "%.3f", temp_service->latency); 2059 break; 2060 case MACRO_LASTSERVICECHECK: 2061 asprintf(output, "%lu", (unsigned long)temp_service->last_check); 2062 break; 2063 case MACRO_LASTSERVICESTATECHANGE: 2064 asprintf(output, "%lu", (unsigned long)temp_service->last_state_change); 2065 break; 2066 case MACRO_LASTSERVICEOK: 2067 asprintf(output, "%lu", (unsigned long)temp_service->last_time_ok); 2068 break; 2069 case MACRO_LASTSERVICEWARNING: 2070 asprintf(output, "%lu", (unsigned long)temp_service->last_time_warning); 2071 break; 2072 case MACRO_LASTSERVICEUNKNOWN: 2073 asprintf(output, "%lu", (unsigned long)temp_service->last_time_unknown); 2074 break; 2075 case MACRO_LASTSERVICECRITICAL: 2076 asprintf(output, "%lu", (unsigned long)temp_service->last_time_critical); 2077 break; 2078 case MACRO_SERVICEDOWNTIME: 2079 asprintf(output, "%d", temp_service->scheduled_downtime_depth); 2080 break; 2081 case MACRO_SERVICEPERCENTCHANGE: 2082 asprintf(output, "%.2f", temp_service->percent_state_change); 2083 break; 2084 case MACRO_SERVICEDURATIONSEC: 2085 case MACRO_SERVICEDURATION: 2086 2087 time(¤t_time); 2088 duration = (unsigned long)(current_time - temp_service->last_state_change); 2089 2090 /* get the state duration in seconds */ 2091 if(macro_type == MACRO_SERVICEDURATIONSEC) 2092 asprintf(output, "%lu", duration); 2093 2094 /* get the state duration */ 2095 else { 2096 days = duration / 86400; 2097 duration -= (days * 86400); 2098 hours = duration / 3600; 2099 duration -= (hours * 3600); 2100 minutes = duration / 60; 2101 duration -= (minutes * 60); 2102 seconds = duration; 2103 asprintf(output, "%dd %dh %dm %ds", days, hours, minutes, seconds); 2104 } 2105 break; 2106 case MACRO_SERVICENOTIFICATIONNUMBER: 2107 asprintf(output, "%d", temp_service->current_notification_number); 2108 break; 2109 case MACRO_SERVICENOTIFICATIONID: 2110 asprintf(output, "%lu", temp_service->current_notification_id); 2111 break; 2112 case MACRO_SERVICEEVENTID: 2113 asprintf(output, "%lu", temp_service->current_event_id); 2114 break; 2115 case MACRO_LASTSERVICEEVENTID: 2116 asprintf(output, "%lu", temp_service->last_event_id); 2117 break; 2118 case MACRO_SERVICEPROBLEMID: 2119 asprintf(output, "%lu", temp_service->current_problem_id); 2120 break; 2121 case MACRO_LASTSERVICEPROBLEMID: 2122 asprintf(output, "%lu", temp_service->last_problem_id); 2123 break; 2124 #endif 2125 case MACRO_SERVICEACTIONURL: 2126 if(temp_service->action_url) 2127 *output = (char *)strdup(temp_service->action_url); 2128 break; 2129 case MACRO_SERVICENOTESURL: 2130 if(temp_service->notes_url) 2131 *output = (char *)strdup(temp_service->notes_url); 2132 break; 2133 case MACRO_SERVICENOTES: 2134 if(temp_service->notes) 2135 *output = (char *)strdup(temp_service->notes); 2136 break; 2137 #ifdef NSCORE 2138 case MACRO_SERVICEGROUPNAMES: 2139 /* find all servicegroups this service is associated with */ 2140 for(temp_objectlist = temp_service->servicegroups_ptr; temp_objectlist != NULL; temp_objectlist = temp_objectlist->next) { 2141 2142 if((temp_servicegroup = (servicegroup *)temp_objectlist->object_ptr) == NULL) 2143 continue; 2144 2145 asprintf(&buf1, "%s%s%s", (buf2) ? buf2 : "", (buf2) ? "," : "", temp_servicegroup->group_name); 2146 my_free(buf2); 2147 buf2 = buf1; 2148 } 2149 if(buf2) { 2150 *output = (char *)strdup(buf2); 2151 my_free(buf2); 2152 } 2153 break; 2154 #endif 2155 /***************/ 2156 /* MISC MACROS */ 2157 /***************/ 2158 case MACRO_SERVICEACKAUTHOR: 2159 case MACRO_SERVICEACKAUTHORNAME: 2160 case MACRO_SERVICEACKAUTHORALIAS: 2161 case MACRO_SERVICEACKCOMMENT: 2162 /* no need to do any more work - these are already precomputed elsewhere */ 2163 /* NOTE: these macros won't work as on-demand macros */ 2164 *output = mac->x[macro_type]; 2165 *free_macro = FALSE; 2166 break; 2167 2168 default: 2169 log_debug_info(DEBUGL_MACROS, 0, "UNHANDLED SERVICE MACRO #%d! THIS IS A BUG!\n", macro_type); 2170 return ERROR; 2171 break; 2172 } 2173 2174 /* post-processing */ 2175 /* notes, notes URL and action URL macros may themselves contain macros, so process them... */ 2176 switch(macro_type) { 2177 case MACRO_SERVICEACTIONURL: 2178 case MACRO_SERVICENOTESURL: 2179 process_macros_r(mac, *output, &temp_buffer, URL_ENCODE_MACRO_CHARS); 2180 my_free(*output); 2181 *output = temp_buffer; 2182 break; 2183 case MACRO_SERVICENOTES: 2184 process_macros_r(mac, *output, &temp_buffer, 0); 2185 my_free(*output); 2186 *output = temp_buffer; 2187 break; 2188 default: 2189 break; 2190 } 2191 2192 return OK; 2193 } 2194 2195 int grab_standard_service_macro(int macro_type, service *temp_service, char **output, int *free_macro) { 2196 return grab_standard_service_macro_r(&global_macros, macro_type, temp_service, output, free_macro); 2197 } 2198 2199 2200 /* computes a servicegroup macro */ 2201 int grab_standard_servicegroup_macro_r(nagios_macros *mac, int macro_type, servicegroup *temp_servicegroup, char **output) { 2202 servicesmember *temp_servicesmember = NULL; 2203 char *temp_buffer = NULL; 2204 unsigned int temp_len = 0; 2205 unsigned int init_len = 0; 2206 2207 if(temp_servicegroup == NULL || output == NULL) 2208 return ERROR; 2209 2210 /* get the macro value */ 2211 switch(macro_type) { 2212 case MACRO_SERVICEGROUPNAME: 2213 *output = (char *)strdup(temp_servicegroup->group_name); 2214 break; 2215 case MACRO_SERVICEGROUPALIAS: 2216 if(temp_servicegroup->alias) 2217 *output = (char *)strdup(temp_servicegroup->alias); 2218 break; 2219 case MACRO_SERVICEGROUPMEMBERS: 2220 /* make the calculations for total string length */ 2221 for(temp_servicesmember = temp_servicegroup->members; temp_servicesmember != NULL; temp_servicesmember = temp_servicesmember->next) { 2222 if(temp_servicesmember->host_name == NULL || temp_servicesmember->service_description == NULL) 2223 continue; 2224 if(temp_len == 0) { 2225 temp_len += strlen(temp_servicesmember->host_name) + strlen(temp_servicesmember->service_description) + 2; 2226 } 2227 else { 2228 temp_len += strlen(temp_servicesmember->host_name) + strlen(temp_servicesmember->service_description) + 3; 2229 } 2230 } 2231 /* allocate or reallocate the memory buffer */ 2232 if(*output == NULL) { 2233 *output = (char *)malloc(temp_len); 2234 } 2235 else { 2236 init_len = strlen(*output); 2237 temp_len += init_len; 2238 *output = (char *)realloc(*output, temp_len); 2239 } 2240 /* now fill in the string with the group members */ 2241 for(temp_servicesmember = temp_servicegroup->members; temp_servicesmember != NULL; temp_servicesmember = temp_servicesmember->next) { 2242 if(temp_servicesmember->host_name == NULL || temp_servicesmember->service_description == NULL) 2243 continue; 2244 temp_buffer = *output + init_len; 2245 if(init_len == 0) { /* If our buffer didn't contain anything, we just need to write "%s,%s" */ 2246 init_len += sprintf(temp_buffer, "%s,%s", temp_servicesmember->host_name, temp_servicesmember->service_description); 2247 } 2248 else { /* Now we need to write ",%s,%s" */ 2249 init_len += sprintf(temp_buffer, ",%s,%s", temp_servicesmember->host_name, temp_servicesmember->service_description); 2250 } 2251 } 2252 break; 2253 case MACRO_SERVICEGROUPACTIONURL: 2254 if(temp_servicegroup->action_url) 2255 *output = (char *)strdup(temp_servicegroup->action_url); 2256 break; 2257 case MACRO_SERVICEGROUPNOTESURL: 2258 if(temp_servicegroup->notes_url) 2259 *output = (char *)strdup(temp_servicegroup->notes_url); 2260 break; 2261 case MACRO_SERVICEGROUPNOTES: 2262 if(temp_servicegroup->notes) 2263 *output = (char *)strdup(temp_servicegroup->notes); 2264 break; 2265 default: 2266 log_debug_info(DEBUGL_MACROS, 0, "UNHANDLED SERVICEGROUP MACRO #%d! THIS IS A BUG!\n", macro_type); 2267 return ERROR; 2268 } 2269 2270 /* post-processing */ 2271 /* notes, notes URL and action URL macros may themselves contain macros, so process them... */ 2272 switch(macro_type) { 2273 case MACRO_SERVICEGROUPACTIONURL: 2274 case MACRO_SERVICEGROUPNOTESURL: 2275 process_macros_r(mac, *output, &temp_buffer, URL_ENCODE_MACRO_CHARS); 2276 my_free(*output); 2277 *output = temp_buffer; 2278 break; 2279 case MACRO_SERVICEGROUPNOTES: 2280 process_macros_r(mac, *output, &temp_buffer, 0); 2281 my_free(*output); 2282 *output = temp_buffer; 2283 break; 2284 default: 2285 break; 2286 } 2287 2288 return OK; 2289 } 2290 2291 int grab_standard_servicegroup_macro(int macro_type, servicegroup *temp_servicegroup, char **output) { 2292 return grab_standard_servicegroup_macro_r(&global_macros, macro_type, temp_servicegroup, output); 2293 } 2294 2295 2296 /* computes a contact macro */ 2297 int grab_standard_contact_macro_r(nagios_macros *mac, int macro_type, contact *temp_contact, char **output) { 2298 #ifdef NSCORE 2299 contactgroup *temp_contactgroup = NULL; 2300 objectlist *temp_objectlist = NULL; 2301 char *buf1 = NULL; 2302 char *buf2 = NULL; 2303 #endif 2304 2305 if(temp_contact == NULL || output == NULL) 2306 return ERROR; 2307 2308 /* get the macro value */ 2309 switch(macro_type) { 2310 case MACRO_CONTACTNAME: 2311 *output = (char *)strdup(temp_contact->name); 2312 break; 2313 case MACRO_CONTACTALIAS: 2314 *output = (char *)strdup(temp_contact->alias); 2315 break; 2316 case MACRO_CONTACTEMAIL: 2317 if(temp_contact->email) 2318 *output = (char *)strdup(temp_contact->email); 2319 break; 2320 case MACRO_CONTACTPAGER: 2321 if(temp_contact->pager) 2322 *output = (char *)strdup(temp_contact->pager); 2323 break; 2324 #ifdef NSCORE 2325 case MACRO_CONTACTGROUPNAMES: 2326 /* get the contactgroup names */ 2327 /* find all contactgroups this contact is a member of */ 2328 for(temp_objectlist = temp_contact->contactgroups_ptr; temp_objectlist != NULL; temp_objectlist = temp_objectlist->next) { 2329 2330 if((temp_contactgroup = (contactgroup *)temp_objectlist->object_ptr) == NULL) 2331 continue; 2332 2333 asprintf(&buf1, "%s%s%s", (buf2) ? buf2 : "", (buf2) ? "," : "", temp_contactgroup->group_name); 2334 my_free(buf2); 2335 buf2 = buf1; 2336 } 2337 if(buf2) { 2338 *output = (char *)strdup(buf2); 2339 my_free(buf2); 2340 } 2341 break; 2342 #endif 2343 default: 2344 log_debug_info(DEBUGL_MACROS, 0, "UNHANDLED CONTACT MACRO #%d! THIS IS A BUG!\n", macro_type); 2345 return ERROR; 2346 } 2347 2348 return OK; 2349 } 2350 2351 int grab_standard_contact_macro(int macro_type, contact *temp_contact, char **output) { 2352 return grab_standard_contact_macro_r(&global_macros, macro_type, temp_contact, output); 2353 } 2354 2355 2356 /* computes a contact address macro */ 2357 int grab_contact_address_macro(int macro_num, contact *temp_contact, char **output) { 2358 if(macro_num < 0 || macro_num >= MAX_CONTACT_ADDRESSES) 2359 return ERROR; 2360 2361 if(temp_contact == NULL || output == NULL) 2362 return ERROR; 2363 2364 /* get the macro */ 2365 if(temp_contact->address[macro_num]) 2366 *output = temp_contact->address[macro_num]; 2367 2368 return OK; 2369 } 2370 2371 2372 2373 /* computes a contactgroup macro */ 2374 int grab_standard_contactgroup_macro(int macro_type, contactgroup *temp_contactgroup, char **output) { 2375 contactsmember *temp_contactsmember = NULL; 2376 2377 if(temp_contactgroup == NULL || output == NULL) 2378 return ERROR; 2379 2380 /* get the macro value */ 2381 switch(macro_type) { 2382 case MACRO_CONTACTGROUPNAME: 2383 *output = (char *)strdup(temp_contactgroup->group_name); 2384 break; 2385 case MACRO_CONTACTGROUPALIAS: 2386 if(temp_contactgroup->alias) 2387 *output = (char *)strdup(temp_contactgroup->alias); 2388 break; 2389 case MACRO_CONTACTGROUPMEMBERS: 2390 /* get the member list */ 2391 for(temp_contactsmember = temp_contactgroup->members; temp_contactsmember != NULL; temp_contactsmember = temp_contactsmember->next) { 2392 if(temp_contactsmember->contact_name == NULL) 2393 continue; 2394 if(*output == NULL) 2395 *output = (char *)strdup(temp_contactsmember->contact_name); 2396 else if((*output = (char *)realloc(*output, strlen(*output) + strlen(temp_contactsmember->contact_name) + 2))) { 2397 strcat(*output, ","); 2398 strcat(*output, temp_contactsmember->contact_name); 2399 } 2400 } 2401 break; 2402 default: 2403 log_debug_info(DEBUGL_MACROS, 0, "UNHANDLED CONTACTGROUP MACRO #%d! THIS IS A BUG!\n", macro_type); 2404 return ERROR; 2405 } 2406 2407 return OK; 2408 } 2409 2410 2411 /* computes a custom object macro */ 2412 int grab_custom_object_macro_r(nagios_macros *mac, char *macro_name, customvariablesmember *vars, char **output) { 2413 customvariablesmember *temp_customvariablesmember = NULL; 2414 int result = ERROR; 2415 2416 if(macro_name == NULL || vars == NULL || output == NULL) 2417 return ERROR; 2418 2419 /* get the custom variable */ 2420 for(temp_customvariablesmember = vars; temp_customvariablesmember != NULL; temp_customvariablesmember = temp_customvariablesmember->next) { 2421 2422 if(temp_customvariablesmember->variable_name == NULL) 2423 continue; 2424 2425 if(!strcmp(macro_name, temp_customvariablesmember->variable_name)) { 2426 if(temp_customvariablesmember->variable_value) 2427 *output = (char *)strdup(temp_customvariablesmember->variable_value); 2428 result = OK; 2429 break; 2430 } 2431 } 2432 2433 return result; 2434 } 2435 2436 int grab_custom_object_macro(char *macro_name, customvariablesmember *vars, char **output) { 2437 return grab_custom_object_macro_r(&global_macros, macro_name, vars, output); 2438 } 2439 2440 2441 /******************************************************************/ 2442 /********************* MACRO STRING FUNCTIONS *********************/ 2443 /******************************************************************/ 2444 2445 /* cleans illegal characters in macros before output */ 2446 char *clean_macro_chars(char *macro, int options) { 2447 register int x = 0; 2448 register int y = 0; 2449 register int z = 0; 2450 register int ch = 0; 2451 register int len = 0; 2452 register int illegal_char = 0; 2453 2454 if(macro == NULL) 2455 return ""; 2456 2457 len = (int)strlen(macro); 2458 2459 /* strip illegal characters out of macro */ 2460 if(options & STRIP_ILLEGAL_MACRO_CHARS) { 2461 2462 for(y = 0, x = 0; x < len; x++) { 2463 2464 /*ch=(int)macro[x];*/ 2465 /* allow non-ASCII characters (Japanese, etc) */ 2466 ch = macro[x] & 0xff; 2467 2468 /* illegal ASCII characters */ 2469 if(ch < 32 || ch == 127) 2470 continue; 2471 2472 /* illegal user-specified characters */ 2473 illegal_char = FALSE; 2474 if(illegal_output_chars != NULL) { 2475 for(z = 0; illegal_output_chars[z] != '\x0'; z++) { 2476 if(ch == (int)illegal_output_chars[z]) { 2477 illegal_char = TRUE; 2478 break; 2479 } 2480 } 2481 } 2482 2483 if(illegal_char == FALSE) 2484 macro[y++] = macro[x]; 2485 } 2486 2487 macro[y++] = '\x0'; 2488 } 2489 2490 #ifdef ON_HOLD_FOR_NOW 2491 /* escape nasty character in macro */ 2492 if(options & ESCAPE_MACRO_CHARS) { 2493 } 2494 #endif 2495 2496 return macro; 2497 } 2498 2499 2500 2501 /* encodes a string in proper URL format */ 2502 char *get_url_encoded_string(char *input) { 2503 register int x = 0; 2504 register int y = 0; 2505 char *encoded_url_string = NULL; 2506 char temp_expansion[6] = ""; 2507 2508 2509 /* bail if no input */ 2510 if(input == NULL) 2511 return NULL; 2512 2513 /* allocate enough memory to escape all characters if necessary */ 2514 if((encoded_url_string = (char *)malloc((strlen(input) * 3) + 1)) == NULL) 2515 return NULL; 2516 2517 /* check/encode all characters */ 2518 for(x = 0, y = 0; input[x] != (char)'\x0'; x++) { 2519 2520 /* alpha-numeric characters and a few other characters don't get encoded */ 2521 if(((char)input[x] >= '0' && (char)input[x] <= '9') || ((char)input[x] >= 'A' && (char)input[x] <= 'Z') || ((char)input[x] >= (char)'a' && (char)input[x] <= (char)'z') || (char)input[x] == (char)'.' || (char)input[x] == (char)'-' || (char)input[x] == (char)'_' || (char)input[x] == (char)':' || (char)input[x] == (char)'/' || (char)input[x] == (char)'?' || (char)input[x] == (char)'=' || (char)input[x] == (char)'&') { 2522 encoded_url_string[y] = input[x]; 2523 y++; 2524 } 2525 2526 /* spaces are pluses */ 2527 else if((char)input[x] <= (char)' ') { 2528 encoded_url_string[y] = '+'; 2529 y++; 2530 } 2531 2532 /* anything else gets represented by its hex value */ 2533 else { 2534 encoded_url_string[y] = '\x0'; 2535 sprintf(temp_expansion, "%%%02X", (unsigned int)(input[x] & 0xFF)); 2536 strcat(encoded_url_string, temp_expansion); 2537 y += 3; 2538 } 2539 } 2540 2541 /* terminate encoded string */ 2542 encoded_url_string[y] = '\x0'; 2543 2544 return encoded_url_string; 2545 } 2546 2547 2548 static int macro_key_cmp(const void *a_, const void *b_) { 2549 struct macro_key_code *a = (struct macro_key_code *)a_; 2550 struct macro_key_code *b = (struct macro_key_code *)b_; 2551 2552 return strcmp(a->name, b->name); 2553 } 2554 2555 2556 /******************************************************************/ 2557 /***************** MACRO INITIALIZATION FUNCTIONS *****************/ 2558 /******************************************************************/ 2559 2560 /* initializes global macros */ 2561 int init_macros(void) { 2562 init_macrox_names(); 2563 int x; 2564 2565 /* 2566 * non-volatile macros are free()'d when they're set. 2567 * We must do this in order to not lose the constant 2568 * ones when we get SIGHUP or a RESTART_PROGRAM event 2569 * from the command fifo. Otherwise a memset() would 2570 * have been better. 2571 */ 2572 clear_volatile_macros_r(&global_macros); 2573 2574 /* backwards compatibility hack */ 2575 macro_x = global_macros.x; 2576 2577 /* 2578 * Now build an ordered list of X macro names so we can 2579 * do binary lookups later and avoid a ton of strcmp()'s 2580 * for each and every check that gets run. A hash table 2581 * is actually slower, since the most frequently used 2582 * keys are so long and a binary lookup is completed in 2583 * 7 steps for up to ~200 keys, worst case. 2584 */ 2585 for(x = 0; x < MACRO_X_COUNT; x++) { 2586 macro_keys[x].code = x; 2587 macro_keys[x].name = macro_x_names[x]; 2588 macro_keys[x].clean_options = 0; 2589 2590 /* host/service output/perfdata and author/comment macros should get cleaned */ 2591 if((x >= 16 && x <= 19) || (x >= 49 && x <= 52) || (x >= 99 && x <= 100) || (x >= 124 && x <= 127)) { 2592 macro_keys[x].clean_options = (STRIP_ILLEGAL_MACRO_CHARS | ESCAPE_MACRO_CHARS); 2593 } 2594 /* url macros should get cleaned */ 2595 if((x >= 125 && x <= 126) || (x >= 128 && x <= 129) || (x >= 77 && x <= 78) || (x >= 74 && x <= 75)) { 2596 macro_keys[x].clean_options = URL_ENCODE_MACRO_CHARS; 2597 } 2598 } 2599 2600 qsort(macro_keys, x, sizeof(struct macro_key_code), macro_key_cmp); 2601 return OK; 2602 } 2603 2604 /* 2605 * initializes the names of macros, using this nifty little macro 2606 * which ensures we never add any typos to the list 2607 */ 2608 #define add_macrox_name(name) macro_x_names[MACRO_##name] = strdup(#name) 2609 int init_macrox_names(void) { 2610 register int x = 0; 2611 2612 /* initialize macro names */ 2613 for(x = 0; x < MACRO_X_COUNT; x++) 2614 macro_x_names[x] = NULL; 2615 2616 /* initialize each macro name */ 2617 add_macrox_name(HOSTNAME); 2618 add_macrox_name(HOSTALIAS); 2619 add_macrox_name(HOSTADDRESS); 2620 add_macrox_name(SERVICEDESC); 2621 add_macrox_name(SERVICESTATE); 2622 add_macrox_name(SERVICESTATEID); 2623 add_macrox_name(SERVICEATTEMPT); 2624 add_macrox_name(SERVICEISVOLATILE); 2625 add_macrox_name(LONGDATETIME); 2626 add_macrox_name(SHORTDATETIME); 2627 add_macrox_name(DATE); 2628 add_macrox_name(TIME); 2629 add_macrox_name(TIMET); 2630 add_macrox_name(LASTHOSTCHECK); 2631 add_macrox_name(LASTSERVICECHECK); 2632 add_macrox_name(LASTHOSTSTATECHANGE); 2633 add_macrox_name(LASTSERVICESTATECHANGE); 2634 add_macrox_name(HOSTOUTPUT); 2635 add_macrox_name(SERVICEOUTPUT); 2636 add_macrox_name(HOSTPERFDATA); 2637 add_macrox_name(SERVICEPERFDATA); 2638 add_macrox_name(CONTACTNAME); 2639 add_macrox_name(CONTACTALIAS); 2640 add_macrox_name(CONTACTEMAIL); 2641 add_macrox_name(CONTACTPAGER); 2642 add_macrox_name(ADMINEMAIL); 2643 add_macrox_name(ADMINPAGER); 2644 add_macrox_name(HOSTSTATE); 2645 add_macrox_name(HOSTSTATEID); 2646 add_macrox_name(HOSTATTEMPT); 2647 add_macrox_name(NOTIFICATIONTYPE); 2648 add_macrox_name(NOTIFICATIONNUMBER); 2649 add_macrox_name(NOTIFICATIONISESCALATED); 2650 add_macrox_name(HOSTEXECUTIONTIME); 2651 add_macrox_name(SERVICEEXECUTIONTIME); 2652 add_macrox_name(HOSTLATENCY); 2653 add_macrox_name(SERVICELATENCY); 2654 add_macrox_name(HOSTDURATION); 2655 add_macrox_name(SERVICEDURATION); 2656 add_macrox_name(HOSTDURATIONSEC); 2657 add_macrox_name(SERVICEDURATIONSEC); 2658 add_macrox_name(HOSTDOWNTIME); 2659 add_macrox_name(SERVICEDOWNTIME); 2660 add_macrox_name(HOSTSTATETYPE); 2661 add_macrox_name(SERVICESTATETYPE); 2662 add_macrox_name(HOSTPERCENTCHANGE); 2663 add_macrox_name(SERVICEPERCENTCHANGE); 2664 add_macrox_name(HOSTGROUPNAME); 2665 add_macrox_name(HOSTGROUPALIAS); 2666 add_macrox_name(SERVICEGROUPNAME); 2667 add_macrox_name(SERVICEGROUPALIAS); 2668 add_macrox_name(HOSTACKAUTHOR); 2669 add_macrox_name(HOSTACKCOMMENT); 2670 add_macrox_name(SERVICEACKAUTHOR); 2671 add_macrox_name(SERVICEACKCOMMENT); 2672 add_macrox_name(LASTSERVICEOK); 2673 add_macrox_name(LASTSERVICEWARNING); 2674 add_macrox_name(LASTSERVICEUNKNOWN); 2675 add_macrox_name(LASTSERVICECRITICAL); 2676 add_macrox_name(LASTHOSTUP); 2677 add_macrox_name(LASTHOSTDOWN); 2678 add_macrox_name(LASTHOSTUNREACHABLE); 2679 add_macrox_name(SERVICECHECKCOMMAND); 2680 add_macrox_name(HOSTCHECKCOMMAND); 2681 add_macrox_name(MAINCONFIGFILE); 2682 add_macrox_name(STATUSDATAFILE); 2683 add_macrox_name(HOSTDISPLAYNAME); 2684 add_macrox_name(SERVICEDISPLAYNAME); 2685 add_macrox_name(RETENTIONDATAFILE); 2686 add_macrox_name(OBJECTCACHEFILE); 2687 add_macrox_name(TEMPFILE); 2688 add_macrox_name(LOGFILE); 2689 add_macrox_name(RESOURCEFILE); 2690 add_macrox_name(COMMANDFILE); 2691 add_macrox_name(HOSTPERFDATAFILE); 2692 add_macrox_name(SERVICEPERFDATAFILE); 2693 add_macrox_name(HOSTACTIONURL); 2694 add_macrox_name(HOSTNOTESURL); 2695 add_macrox_name(HOSTNOTES); 2696 add_macrox_name(SERVICEACTIONURL); 2697 add_macrox_name(SERVICENOTESURL); 2698 add_macrox_name(SERVICENOTES); 2699 add_macrox_name(TOTALHOSTSUP); 2700 add_macrox_name(TOTALHOSTSDOWN); 2701 add_macrox_name(TOTALHOSTSUNREACHABLE); 2702 add_macrox_name(TOTALHOSTSDOWNUNHANDLED); 2703 add_macrox_name(TOTALHOSTSUNREACHABLEUNHANDLED); 2704 add_macrox_name(TOTALHOSTPROBLEMS); 2705 add_macrox_name(TOTALHOSTPROBLEMSUNHANDLED); 2706 add_macrox_name(TOTALSERVICESOK); 2707 add_macrox_name(TOTALSERVICESWARNING); 2708 add_macrox_name(TOTALSERVICESCRITICAL); 2709 add_macrox_name(TOTALSERVICESUNKNOWN); 2710 add_macrox_name(TOTALSERVICESWARNINGUNHANDLED); 2711 add_macrox_name(TOTALSERVICESCRITICALUNHANDLED); 2712 add_macrox_name(TOTALSERVICESUNKNOWNUNHANDLED); 2713 add_macrox_name(TOTALSERVICEPROBLEMS); 2714 add_macrox_name(TOTALSERVICEPROBLEMSUNHANDLED); 2715 add_macrox_name(PROCESSSTARTTIME); 2716 add_macrox_name(HOSTCHECKTYPE); 2717 add_macrox_name(SERVICECHECKTYPE); 2718 add_macrox_name(LONGHOSTOUTPUT); 2719 add_macrox_name(LONGSERVICEOUTPUT); 2720 add_macrox_name(TEMPPATH); 2721 add_macrox_name(HOSTNOTIFICATIONNUMBER); 2722 add_macrox_name(SERVICENOTIFICATIONNUMBER); 2723 add_macrox_name(HOSTNOTIFICATIONID); 2724 add_macrox_name(SERVICENOTIFICATIONID); 2725 add_macrox_name(HOSTEVENTID); 2726 add_macrox_name(LASTHOSTEVENTID); 2727 add_macrox_name(SERVICEEVENTID); 2728 add_macrox_name(LASTSERVICEEVENTID); 2729 add_macrox_name(HOSTGROUPNAMES); 2730 add_macrox_name(SERVICEGROUPNAMES); 2731 add_macrox_name(HOSTACKAUTHORNAME); 2732 add_macrox_name(HOSTACKAUTHORALIAS); 2733 add_macrox_name(SERVICEACKAUTHORNAME); 2734 add_macrox_name(SERVICEACKAUTHORALIAS); 2735 add_macrox_name(MAXHOSTATTEMPTS); 2736 add_macrox_name(MAXSERVICEATTEMPTS); 2737 add_macrox_name(TOTALHOSTSERVICES); 2738 add_macrox_name(TOTALHOSTSERVICESOK); 2739 add_macrox_name(TOTALHOSTSERVICESWARNING); 2740 add_macrox_name(TOTALHOSTSERVICESUNKNOWN); 2741 add_macrox_name(TOTALHOSTSERVICESCRITICAL); 2742 add_macrox_name(HOSTGROUPNOTES); 2743 add_macrox_name(HOSTGROUPNOTESURL); 2744 add_macrox_name(HOSTGROUPACTIONURL); 2745 add_macrox_name(SERVICEGROUPNOTES); 2746 add_macrox_name(SERVICEGROUPNOTESURL); 2747 add_macrox_name(SERVICEGROUPACTIONURL); 2748 add_macrox_name(HOSTGROUPMEMBERS); 2749 add_macrox_name(SERVICEGROUPMEMBERS); 2750 add_macrox_name(CONTACTGROUPNAME); 2751 add_macrox_name(CONTACTGROUPALIAS); 2752 add_macrox_name(CONTACTGROUPMEMBERS); 2753 add_macrox_name(CONTACTGROUPNAMES); 2754 add_macrox_name(NOTIFICATIONRECIPIENTS); 2755 add_macrox_name(NOTIFICATIONAUTHOR); 2756 add_macrox_name(NOTIFICATIONAUTHORNAME); 2757 add_macrox_name(NOTIFICATIONAUTHORALIAS); 2758 add_macrox_name(NOTIFICATIONCOMMENT); 2759 add_macrox_name(EVENTSTARTTIME); 2760 add_macrox_name(HOSTPROBLEMID); 2761 add_macrox_name(LASTHOSTPROBLEMID); 2762 add_macrox_name(SERVICEPROBLEMID); 2763 add_macrox_name(LASTSERVICEPROBLEMID); 2764 add_macrox_name(ISVALIDTIME); 2765 add_macrox_name(NEXTVALIDTIME); 2766 add_macrox_name(LASTHOSTSTATE); 2767 add_macrox_name(LASTHOSTSTATEID); 2768 add_macrox_name(LASTSERVICESTATE); 2769 add_macrox_name(LASTSERVICESTATEID); 2770 2771 return OK; 2772 } 2773 2774 2775 /******************************************************************/ 2776 /********************* MACRO CLEANUP FUNCTIONS ********************/ 2777 /******************************************************************/ 2778 2779 /* free memory associated with the macrox names */ 2780 int free_macrox_names(void) { 2781 register int x = 0; 2782 2783 /* free each macro name */ 2784 for(x = 0; x < MACRO_X_COUNT; x++) 2785 my_free(macro_x_names[x]); 2786 2787 return OK; 2788 } 2789 2790 2791 2792 /* clear argv macros - used in commands */ 2793 int clear_argv_macros_r(nagios_macros *mac) { 2794 register int x = 0; 2795 2796 /* command argument macros */ 2797 for(x = 0; x < MAX_COMMAND_ARGUMENTS; x++) 2798 my_free(mac->argv[x]); 2799 2800 return OK; 2801 } 2802 2803 int clear_argv_macros(void) { 2804 return clear_argv_macros_r(&global_macros); 2805 } 2806 2807 /* 2808 * copies non-volatile macros from global macro_x to **dest, which 2809 * must be large enough to hold at least MACRO_X_COUNT entries. 2810 * We use a shortlived macro to save up on typing 2811 */ 2812 #define cp_macro(name) dest[MACRO_##name] = global_macros.x[MACRO_##name] 2813 void copy_constant_macros(char **dest) { 2814 cp_macro(ADMINEMAIL); 2815 cp_macro(ADMINPAGER); 2816 cp_macro(MAINCONFIGFILE); 2817 cp_macro(STATUSDATAFILE); 2818 cp_macro(RETENTIONDATAFILE); 2819 cp_macro(OBJECTCACHEFILE); 2820 cp_macro(TEMPFILE); 2821 cp_macro(LOGFILE); 2822 cp_macro(RESOURCEFILE); 2823 cp_macro(COMMANDFILE); 2824 cp_macro(HOSTPERFDATAFILE); 2825 cp_macro(SERVICEPERFDATAFILE); 2826 cp_macro(PROCESSSTARTTIME); 2827 cp_macro(TEMPPATH); 2828 cp_macro(EVENTSTARTTIME); 2829 } 2830 #undef cp_macro 2831 2832 /* clear all macros that are not "constant" (i.e. they change throughout the course of monitoring) */ 2833 int clear_volatile_macros_r(nagios_macros *mac) { 2834 customvariablesmember *this_customvariablesmember = NULL; 2835 customvariablesmember *next_customvariablesmember = NULL; 2836 register int x = 0; 2837 2838 for(x = 0; x < MACRO_X_COUNT; x++) { 2839 switch(x) { 2840 2841 case MACRO_ADMINEMAIL: 2842 case MACRO_ADMINPAGER: 2843 case MACRO_MAINCONFIGFILE: 2844 case MACRO_STATUSDATAFILE: 2845 case MACRO_RETENTIONDATAFILE: 2846 case MACRO_OBJECTCACHEFILE: 2847 case MACRO_TEMPFILE: 2848 case MACRO_LOGFILE: 2849 case MACRO_RESOURCEFILE: 2850 case MACRO_COMMANDFILE: 2851 case MACRO_HOSTPERFDATAFILE: 2852 case MACRO_SERVICEPERFDATAFILE: 2853 case MACRO_PROCESSSTARTTIME: 2854 case MACRO_TEMPPATH: 2855 case MACRO_EVENTSTARTTIME: 2856 /* these don't change during the course of monitoring, so no need to free them */ 2857 break; 2858 default: 2859 my_free(mac->x[x]); 2860 break; 2861 } 2862 } 2863 2864 /* contact address macros */ 2865 for(x = 0; x < MAX_CONTACT_ADDRESSES; x++) 2866 my_free(mac->contactaddress[x]); 2867 2868 /* clear macro pointers */ 2869 mac->host_ptr = NULL; 2870 mac->hostgroup_ptr = NULL; 2871 mac->service_ptr = NULL; 2872 mac->servicegroup_ptr = NULL; 2873 mac->contact_ptr = NULL; 2874 mac->contactgroup_ptr = NULL; 2875 2876 /* clear on-demand macro */ 2877 my_free(mac->ondemand); 2878 2879 /* clear ARGx macros */ 2880 clear_argv_macros_r(mac); 2881 2882 /* clear custom host variables */ 2883 for(this_customvariablesmember = mac->custom_host_vars; this_customvariablesmember != NULL; this_customvariablesmember = next_customvariablesmember) { 2884 next_customvariablesmember = this_customvariablesmember->next; 2885 my_free(this_customvariablesmember->variable_name); 2886 my_free(this_customvariablesmember->variable_value); 2887 my_free(this_customvariablesmember); 2888 } 2889 mac->custom_host_vars = NULL; 2890 2891 /* clear custom service variables */ 2892 for(this_customvariablesmember = mac->custom_service_vars; this_customvariablesmember != NULL; this_customvariablesmember = next_customvariablesmember) { 2893 next_customvariablesmember = this_customvariablesmember->next; 2894 my_free(this_customvariablesmember->variable_name); 2895 my_free(this_customvariablesmember->variable_value); 2896 my_free(this_customvariablesmember); 2897 } 2898 mac->custom_service_vars = NULL; 2899 2900 /* clear custom contact variables */ 2901 for(this_customvariablesmember = mac->custom_contact_vars; this_customvariablesmember != NULL; this_customvariablesmember = next_customvariablesmember) { 2902 next_customvariablesmember = this_customvariablesmember->next; 2903 my_free(this_customvariablesmember->variable_name); 2904 my_free(this_customvariablesmember->variable_value); 2905 my_free(this_customvariablesmember); 2906 } 2907 mac->custom_contact_vars = NULL; 2908 2909 return OK; 2910 } 2911 2912 2913 int clear_volatile_macros(void) { 2914 return clear_volatile_macros_r(&global_macros); 2915 } 2916 2917 2918 /* clear service macros */ 2919 int clear_service_macros_r(nagios_macros *mac) { 2920 customvariablesmember *this_customvariablesmember = NULL; 2921 customvariablesmember *next_customvariablesmember = NULL; 2922 2923 /* FIXME: strings. make these not be strdup()'s anymore */ 2924 my_free(mac->x[MACRO_SERVICEDESC]); 2925 my_free(mac->x[MACRO_SERVICEDISPLAYNAME]); 2926 my_free(mac->x[MACRO_SERVICEOUTPUT]); 2927 my_free(mac->x[MACRO_LONGSERVICEOUTPUT]); 2928 my_free(mac->x[MACRO_SERVICEPERFDATA]); 2929 2930 /* these are recursive but persistent. what to do? */ 2931 my_free(mac->x[MACRO_SERVICECHECKCOMMAND]); 2932 my_free(mac->x[MACRO_SERVICEACTIONURL]); 2933 my_free(mac->x[MACRO_SERVICENOTESURL]); 2934 my_free(mac->x[MACRO_SERVICENOTES]); 2935 2936 my_free(mac->x[MACRO_SERVICECHECKTYPE]); 2937 my_free(mac->x[MACRO_SERVICESTATETYPE]); 2938 my_free(mac->x[MACRO_SERVICESTATE]); 2939 my_free(mac->x[MACRO_SERVICEISVOLATILE]); 2940 my_free(mac->x[MACRO_SERVICESTATEID]); 2941 my_free(mac->x[MACRO_SERVICEATTEMPT]); 2942 my_free(mac->x[MACRO_MAXSERVICEATTEMPTS]); 2943 my_free(mac->x[MACRO_SERVICEEXECUTIONTIME]); 2944 my_free(mac->x[MACRO_SERVICELATENCY]); 2945 my_free(mac->x[MACRO_LASTSERVICECHECK]); 2946 my_free(mac->x[MACRO_LASTSERVICESTATECHANGE]); 2947 my_free(mac->x[MACRO_LASTSERVICEOK]); 2948 my_free(mac->x[MACRO_LASTSERVICEWARNING]); 2949 my_free(mac->x[MACRO_LASTSERVICEUNKNOWN]); 2950 my_free(mac->x[MACRO_LASTSERVICECRITICAL]); 2951 my_free(mac->x[MACRO_SERVICEDOWNTIME]); 2952 my_free(mac->x[MACRO_SERVICEPERCENTCHANGE]); 2953 my_free(mac->x[MACRO_SERVICEDURATIONSEC]); 2954 my_free(mac->x[MACRO_SERVICEDURATION]); 2955 my_free(mac->x[MACRO_SERVICENOTIFICATIONNUMBER]); 2956 my_free(mac->x[MACRO_SERVICENOTIFICATIONID]); 2957 my_free(mac->x[MACRO_SERVICEEVENTID]); 2958 my_free(mac->x[MACRO_LASTSERVICEEVENTID]); 2959 my_free(mac->x[MACRO_SERVICEGROUPNAMES]); 2960 my_free(mac->x[MACRO_SERVICEPROBLEMID]); 2961 my_free(mac->x[MACRO_LASTSERVICEPROBLEMID]); 2962 2963 /* clear custom service variables */ 2964 for(this_customvariablesmember = mac->custom_service_vars; this_customvariablesmember != NULL; this_customvariablesmember = next_customvariablesmember) { 2965 next_customvariablesmember = this_customvariablesmember->next; 2966 my_free(this_customvariablesmember->variable_name); 2967 my_free(this_customvariablesmember->variable_value); 2968 my_free(this_customvariablesmember); 2969 } 2970 mac->custom_service_vars = NULL; 2971 2972 /* clear pointers */ 2973 mac->service_ptr = NULL; 2974 2975 return OK; 2976 } 2977 2978 int clear_service_macros(void) { 2979 return clear_service_macros_r(&global_macros); 2980 } 2981 2982 /* clear host macros */ 2983 int clear_host_macros_r(nagios_macros *mac) { 2984 customvariablesmember *this_customvariablesmember = NULL; 2985 customvariablesmember *next_customvariablesmember = NULL; 2986 2987 /* FIXME: strings; Fix these to not be strdup()'s anymore */ 2988 my_free(mac->x[MACRO_HOSTNAME]); 2989 my_free(mac->x[MACRO_HOSTDISPLAYNAME]); 2990 my_free(mac->x[MACRO_HOSTALIAS]); 2991 my_free(mac->x[MACRO_HOSTADDRESS]); 2992 my_free(mac->x[MACRO_HOSTOUTPUT]); 2993 my_free(mac->x[MACRO_LONGHOSTOUTPUT]); 2994 my_free(mac->x[MACRO_HOSTPERFDATA]); 2995 2996 /* these are recursive but persistent. what to do? */ 2997 my_free(mac->x[MACRO_HOSTCHECKCOMMAND]); 2998 my_free(mac->x[MACRO_HOSTACTIONURL]); 2999 my_free(mac->x[MACRO_HOSTNOTESURL]); 3000 my_free(mac->x[MACRO_HOSTNOTES]); 3001 3002 /* numbers or by necessity autogenerated strings */ 3003 my_free(mac->x[MACRO_HOSTSTATE]); 3004 my_free(mac->x[MACRO_HOSTSTATEID]); 3005 my_free(mac->x[MACRO_HOSTCHECKTYPE]); 3006 my_free(mac->x[MACRO_HOSTSTATETYPE]); 3007 my_free(mac->x[MACRO_HOSTATTEMPT]); 3008 my_free(mac->x[MACRO_MAXHOSTATTEMPTS]); 3009 my_free(mac->x[MACRO_HOSTDOWNTIME]); 3010 my_free(mac->x[MACRO_HOSTPERCENTCHANGE]); 3011 my_free(mac->x[MACRO_HOSTDURATIONSEC]); 3012 my_free(mac->x[MACRO_HOSTDURATION]); 3013 my_free(mac->x[MACRO_HOSTEXECUTIONTIME]); 3014 my_free(mac->x[MACRO_HOSTLATENCY]); 3015 my_free(mac->x[MACRO_LASTHOSTCHECK]); 3016 my_free(mac->x[MACRO_LASTHOSTSTATECHANGE]); 3017 my_free(mac->x[MACRO_LASTHOSTUP]); 3018 my_free(mac->x[MACRO_LASTHOSTDOWN]); 3019 my_free(mac->x[MACRO_LASTHOSTUNREACHABLE]); 3020 my_free(mac->x[MACRO_HOSTNOTIFICATIONNUMBER]); 3021 my_free(mac->x[MACRO_HOSTNOTIFICATIONID]); 3022 my_free(mac->x[MACRO_HOSTEVENTID]); 3023 my_free(mac->x[MACRO_LASTHOSTEVENTID]); 3024 my_free(mac->x[MACRO_HOSTGROUPNAMES]); 3025 my_free(mac->x[MACRO_TOTALHOSTSERVICES]); 3026 my_free(mac->x[MACRO_TOTALHOSTSERVICESOK]); 3027 my_free(mac->x[MACRO_TOTALHOSTSERVICESWARNING]); 3028 my_free(mac->x[MACRO_TOTALHOSTSERVICESUNKNOWN]); 3029 my_free(mac->x[MACRO_TOTALHOSTSERVICESCRITICAL]); 3030 my_free(mac->x[MACRO_HOSTPROBLEMID]); 3031 my_free(mac->x[MACRO_LASTHOSTPROBLEMID]); 3032 3033 3034 /* clear custom host variables */ 3035 for(this_customvariablesmember = mac->custom_host_vars; this_customvariablesmember != NULL; this_customvariablesmember = next_customvariablesmember) { 3036 next_customvariablesmember = this_customvariablesmember->next; 3037 my_free(this_customvariablesmember->variable_name); 3038 my_free(this_customvariablesmember->variable_value); 3039 my_free(this_customvariablesmember); 3040 } 3041 mac->custom_host_vars = NULL; 3042 3043 /* clear pointers */ 3044 mac->host_ptr = NULL; 3045 3046 return OK; 3047 } 3048 3049 int clear_host_macros(void) { 3050 return clear_host_macros_r(&global_macros); 3051 } 3052 3053 3054 /* clear hostgroup macros */ 3055 int clear_hostgroup_macros_r(nagios_macros *mac) { 3056 /* FIXME: make these not strdup()'s */ 3057 my_free(mac->x[MACRO_HOSTGROUPNAME]); 3058 my_free(mac->x[MACRO_HOSTGROUPALIAS]); 3059 3060 /* generated but persistent. what to do? */ 3061 my_free(mac->x[MACRO_HOSTGROUPACTIONURL]); 3062 my_free(mac->x[MACRO_HOSTGROUPNOTESURL]); 3063 my_free(mac->x[MACRO_HOSTGROUPNOTES]); 3064 3065 /* generated */ 3066 my_free(mac->x[MACRO_HOSTGROUPMEMBERS]); 3067 3068 /* clear pointers */ 3069 mac->hostgroup_ptr = NULL; 3070 3071 return OK; 3072 } 3073 3074 int clear_hostgroup_macros(void) { 3075 return clear_hostgroup_macros_r(&global_macros); 3076 } 3077 3078 3079 /* clear servicegroup macros */ 3080 int clear_servicegroup_macros_r(nagios_macros *mac) { 3081 /* FIXME: these should not be strdup()'s */ 3082 my_free(mac->x[MACRO_SERVICEGROUPNAME]); 3083 my_free(mac->x[MACRO_SERVICEGROUPALIAS]); 3084 3085 /* generated but persistent. what to do? */ 3086 my_free(mac->x[MACRO_SERVICEGROUPACTIONURL]); 3087 my_free(mac->x[MACRO_SERVICEGROUPNOTESURL]); 3088 my_free(mac->x[MACRO_SERVICEGROUPNOTES]); 3089 3090 /* generated */ 3091 my_free(mac->x[MACRO_SERVICEGROUPMEMBERS]); 3092 3093 /* clear pointers */ 3094 mac->servicegroup_ptr = NULL; 3095 3096 return OK; 3097 } 3098 3099 int clear_servicegroup_macros(void) { 3100 return clear_servicegroup_macros_r(&global_macros); 3101 } 3102 3103 3104 /* clear contact macros */ 3105 int clear_contact_macros_r(nagios_macros *mac) { 3106 register int x; 3107 customvariablesmember *this_customvariablesmember = NULL; 3108 customvariablesmember *next_customvariablesmember = NULL; 3109 3110 /* FIXME: these should not be strdup()'d */ 3111 my_free(mac->x[MACRO_CONTACTNAME]); 3112 my_free(mac->x[MACRO_CONTACTALIAS]); 3113 my_free(mac->x[MACRO_CONTACTEMAIL]); 3114 my_free(mac->x[MACRO_CONTACTPAGER]); 3115 3116 /* generated per contact */ 3117 my_free(mac->x[MACRO_CONTACTGROUPNAMES]); 3118 3119 /* clear contact addresses */ 3120 for(x = 0; x < MAX_CONTACT_ADDRESSES; x++) 3121 my_free(mac->contactaddress[x]); 3122 3123 /* clear custom contact variables */ 3124 for(this_customvariablesmember = mac->custom_contact_vars; this_customvariablesmember != NULL; this_customvariablesmember = next_customvariablesmember) { 3125 next_customvariablesmember = this_customvariablesmember->next; 3126 my_free(this_customvariablesmember->variable_name); 3127 my_free(this_customvariablesmember->variable_value); 3128 my_free(this_customvariablesmember); 3129 } 3130 mac->custom_contact_vars = NULL; 3131 3132 /* clear pointers */ 3133 mac->contact_ptr = NULL; 3134 3135 return OK; 3136 } 3137 3138 int clear_contact_macros(void) { 3139 return clear_contact_macros_r(&global_macros); 3140 } 3141 3142 3143 /* clear contactgroup macros */ 3144 int clear_contactgroup_macros_r(nagios_macros *mac) { 3145 my_free(mac->x[MACRO_CONTACTGROUPNAME]); 3146 my_free(mac->x[MACRO_CONTACTGROUPALIAS]); 3147 my_free(mac->x[MACRO_CONTACTGROUPMEMBERS]); 3148 3149 /* clear pointers */ 3150 mac->contactgroup_ptr = NULL; 3151 3152 return OK; 3153 } 3154 3155 int clear_contactgroup_macros(void) { 3156 return clear_contactgroup_macros_r(&global_macros); 3157 } 3158 3159 3160 /* clear summary macros */ 3161 int clear_summary_macros_r(nagios_macros *mac) { 3162 register int x; 3163 3164 for(x = MACRO_TOTALHOSTSUP; x <= MACRO_TOTALSERVICEPROBLEMSUNHANDLED; x++) 3165 my_free(mac->x[x]); 3166 3167 return OK; 3168 } 3169 3170 int clear_summary_macros(void) { 3171 return clear_summary_macros_r(&global_macros); 3172 } 3173 3174 3175 /******************************************************************/ 3176 /****************** ENVIRONMENT MACRO FUNCTIONS *******************/ 3177 /******************************************************************/ 3178 3179 #ifdef NSCORE 3180 3181 /* sets or unsets all macro environment variables */ 3182 int set_all_macro_environment_vars_r(nagios_macros *mac, int set) { 3183 if(enable_environment_macros == FALSE) 3184 return ERROR; 3185 3186 set_macrox_environment_vars_r(mac, set); 3187 set_argv_macro_environment_vars_r(mac, set); 3188 set_custom_macro_environment_vars_r(mac, set); 3189 set_contact_address_environment_vars_r(mac, set); 3190 3191 return OK; 3192 } 3193 3194 int set_all_macro_environment_vars(int set) { 3195 return set_all_macro_environment_vars_r(&global_macros, set); 3196 } 3197 3198 3199 /* sets or unsets macrox environment variables */ 3200 int set_macrox_environment_vars_r(nagios_macros *mac, int set) { 3201 register int x = 0; 3202 int free_macro = FALSE; 3203 int generate_macro = TRUE; 3204 3205 /* set each of the macrox environment variables */ 3206 for(x = 0; x < MACRO_X_COUNT; x++) { 3207 3208 free_macro = FALSE; 3209 3210 /* generate the macro value if it hasn't already been done */ 3211 /* THIS IS EXPENSIVE */ 3212 if(set == TRUE) { 3213 3214 generate_macro = TRUE; 3215 3216 /* skip summary macro generation if lage installation tweaks are enabled */ 3217 if((x >= MACRO_TOTALHOSTSUP && x <= MACRO_TOTALSERVICEPROBLEMSUNHANDLED) && use_large_installation_tweaks == TRUE) 3218 generate_macro = FALSE; 3219 3220 if(mac->x[x] == NULL && generate_macro == TRUE) 3221 grab_macrox_value_r(mac, x, NULL, NULL, &mac->x[x], &free_macro); 3222 } 3223 3224 /* set the value */ 3225 set_macro_environment_var(macro_x_names[x], mac->x[x], set); 3226 } 3227 3228 return OK; 3229 } 3230 3231 int set_macrox_environment_vars(int set) { 3232 return set_macrox_environment_vars_r(&global_macros, set); 3233 } 3234 3235 3236 /* sets or unsets argv macro environment variables */ 3237 int set_argv_macro_environment_vars_r(nagios_macros *mac, int set) { 3238 char *macro_name = NULL; 3239 register int x = 0; 3240 3241 /* set each of the argv macro environment variables */ 3242 for(x = 0; x < MAX_COMMAND_ARGUMENTS; x++) { 3243 asprintf(¯o_name, "ARG%d", x + 1); 3244 set_macro_environment_var(macro_name, mac->argv[x], set); 3245 my_free(macro_name); 3246 } 3247 3248 return OK; 3249 } 3250 3251 int set_argv_macro_environment_vars(int set) { 3252 return set_argv_macro_environment_vars_r(&global_macros, set); 3253 } 3254 3255 3256 /* sets or unsets custom host/service/contact macro environment variables */ 3257 int set_custom_macro_environment_vars_r(nagios_macros *mac, int set) { 3258 customvariablesmember *temp_customvariablesmember = NULL; 3259 host *temp_host = NULL; 3260 service *temp_service = NULL; 3261 contact *temp_contact = NULL; 3262 char *customvarname = NULL; 3263 3264 /***** CUSTOM HOST VARIABLES *****/ 3265 /* generate variables and save them for later */ 3266 if((temp_host = mac->host_ptr) && set == TRUE) { 3267 for(temp_customvariablesmember = temp_host->custom_variables; temp_customvariablesmember != NULL; temp_customvariablesmember = temp_customvariablesmember->next) { 3268 asprintf(&customvarname, "_HOST%s", temp_customvariablesmember->variable_name); 3269 add_custom_variable_to_object(&mac->custom_host_vars, customvarname, temp_customvariablesmember->variable_value); 3270 my_free(customvarname); 3271 } 3272 } 3273 /* set variables */ 3274 for(temp_customvariablesmember = mac->custom_host_vars; temp_customvariablesmember != NULL; temp_customvariablesmember = temp_customvariablesmember->next) { 3275 set_macro_environment_var(temp_customvariablesmember->variable_name, clean_macro_chars(temp_customvariablesmember->variable_value, STRIP_ILLEGAL_MACRO_CHARS | ESCAPE_MACRO_CHARS), set); 3276 } 3277 3278 /***** CUSTOM SERVICE VARIABLES *****/ 3279 /* generate variables and save them for later */ 3280 if((temp_service = mac->service_ptr) && set == TRUE) { 3281 for(temp_customvariablesmember = temp_service->custom_variables; temp_customvariablesmember != NULL; temp_customvariablesmember = temp_customvariablesmember->next) { 3282 asprintf(&customvarname, "_SERVICE%s", temp_customvariablesmember->variable_name); 3283 add_custom_variable_to_object(&mac->custom_service_vars, customvarname, temp_customvariablesmember->variable_value); 3284 my_free(customvarname); 3285 } 3286 } 3287 /* set variables */ 3288 for(temp_customvariablesmember = mac->custom_service_vars; temp_customvariablesmember != NULL; temp_customvariablesmember = temp_customvariablesmember->next) 3289 set_macro_environment_var(temp_customvariablesmember->variable_name, clean_macro_chars(temp_customvariablesmember->variable_value, STRIP_ILLEGAL_MACRO_CHARS | ESCAPE_MACRO_CHARS), set); 3290 3291 /***** CUSTOM CONTACT VARIABLES *****/ 3292 /* generate variables and save them for later */ 3293 if((temp_contact = mac->contact_ptr) && set == TRUE) { 3294 for(temp_customvariablesmember = temp_contact->custom_variables; temp_customvariablesmember != NULL; temp_customvariablesmember = temp_customvariablesmember->next) { 3295 asprintf(&customvarname, "_CONTACT%s", temp_customvariablesmember->variable_name); 3296 add_custom_variable_to_object(&mac->custom_contact_vars, customvarname, temp_customvariablesmember->variable_value); 3297 my_free(customvarname); 3298 } 3299 } 3300 /* set variables */ 3301 for(temp_customvariablesmember = mac->custom_contact_vars; temp_customvariablesmember != NULL; temp_customvariablesmember = temp_customvariablesmember->next) 3302 set_macro_environment_var(temp_customvariablesmember->variable_name, clean_macro_chars(temp_customvariablesmember->variable_value, STRIP_ILLEGAL_MACRO_CHARS | ESCAPE_MACRO_CHARS), set); 3303 3304 return OK; 3305 } 3306 3307 int set_custom_macro_environment_vars(int set) { 3308 return set_custom_macro_environment_vars_r(&global_macros, set); 3309 } 3310 3311 3312 /* sets or unsets contact address environment variables */ 3313 int set_contact_address_environment_vars_r(nagios_macros *mac, int set) { 3314 char *varname = NULL; 3315 register int x; 3316 3317 /* these only get set during notifications */ 3318 if(mac->contact_ptr == NULL) 3319 return OK; 3320 3321 for(x = 0; x < MAX_CONTACT_ADDRESSES; x++) { 3322 asprintf(&varname, "CONTACTADDRESS%d", x); 3323 set_macro_environment_var(varname, mac->contact_ptr->address[x], set); 3324 my_free(varname); 3325 } 3326 3327 return OK; 3328 } 3329 3330 int set_contact_address_environment_vars(int set) { 3331 return set_contact_address_environment_vars_r(&global_macros, set); 3332 } 3333 3334 3335 /* sets or unsets a macro environment variable */ 3336 int set_macro_environment_var(char *name, char *value, int set) { 3337 char *env_macro_name = NULL; 3338 3339 /* we won't mess with null variable names */ 3340 if(name == NULL) 3341 return ERROR; 3342 3343 /* create environment var name */ 3344 asprintf(&env_macro_name, "%s%s", MACRO_ENV_VAR_PREFIX, name); 3345 3346 /* set or unset the environment variable */ 3347 set_environment_var(env_macro_name, value, set); 3348 3349 /* free allocated memory */ 3350 my_free(env_macro_name); 3351 3352 return OK; 3353 } 3354 3355 3356 #endif 3357