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