/***************************************************************************** * * XCDDEFAULT.C - Default external comment data routines for Nagios * * Copyright (c) 2000-2006 Ethan Galstad (nagios@nagios.org) * Last Modified: 05-20-2006 * * License: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * *****************************************************************************/ /*********** COMMON HEADER FILES ***********/ #include "../include/config.h" #include "../include/common.h" #include "../include/locations.h" #include "../include/comments.h" #ifdef NSCORE #include "../include/objects.h" #include "../include/nagios.h" #endif #ifdef NSCGI #include "../include/cgiutils.h" #endif /**** IMPLEMENTATION SPECIFIC HEADER FILES ****/ #include "xcddefault.h" char xcddefault_comment_file[MAX_FILENAME_LENGTH]=""; char xcddefault_temp_file[MAX_FILENAME_LENGTH]=""; #ifdef NSCORE unsigned long current_comment_id=0; extern comment *comment_list; extern char *macro_x[MACRO_X_COUNT]; #endif /******************************************************************/ /***************** COMMON CONFIG INITIALIZATION ******************/ /******************************************************************/ /* grab configuration information from appropriate config file(s) */ int xcddefault_grab_config_info(char *config_file){ char *input=NULL; mmapfile *thefile; #ifdef NSCGI char *input2=NULL; mmapfile *thefile2; char *temp_buffer; #endif /*** CORE PASSES IN MAIN CONFIG FILE, CGIS PASS IN CGI CONFIG FILE! ***/ /* initialize the location of the comment and temp */ strncpy(xcddefault_comment_file,DEFAULT_COMMENT_FILE,sizeof(xcddefault_comment_file)-1); strncpy(xcddefault_temp_file,DEFAULT_TEMP_FILE,sizeof(xcddefault_temp_file)-1); xcddefault_comment_file[sizeof(xcddefault_comment_file)-1]='\x0'; xcddefault_temp_file[sizeof(xcddefault_temp_file)-1]='\x0'; /* open the config file for reading */ if((thefile=mmap_fopen(config_file))==NULL) return ERROR; /* read in all lines from the config file */ while(1){ /* free memory */ free(input); /* read the next line */ if((input=mmap_fgets(thefile))==NULL) break; strip(input); /* skip blank lines and comments */ if(input[0]=='#' || input[0]=='\x0') continue; #ifdef NSCGI /* CGI needs to find and read contents of main config file, since it was passed the name of the CGI config file */ if(strstr(input,"main_config_file")==input){ temp_buffer=strtok(input,"="); temp_buffer=strtok(NULL,"\n"); if(temp_buffer==NULL) continue; if((thefile2=mmap_fopen(temp_buffer))==NULL) continue; /* read in all lines from the main config file */ while(1){ /* free memory */ free(input2); /* read the next line */ if((input2=mmap_fgets(thefile2))==NULL) break; strip(input2); /* skip blank lines and comments */ if(input2[0]=='#' || input2[0]=='\x0') continue; xcddefault_grab_config_directives(input2); } /* free memory and close the file */ free(input2); mmap_fclose(thefile2); } #endif #ifdef NSCORE /* core read variables directly from the main config file */ xcddefault_grab_config_directives(input); #endif } /* free memory and close the file */ free(input); mmap_fclose(thefile); /* we didn't find the comment file */ if(!strcmp(xcddefault_comment_file,"")) return ERROR; /* we didn't find the temp file */ if(!strcmp(xcddefault_temp_file,"")) return ERROR; #ifdef NSCORE /* save the comment data file macro */ if(macro_x[MACRO_COMMENTDATAFILE]!=NULL) free(macro_x[MACRO_COMMENTDATAFILE]); macro_x[MACRO_COMMENTDATAFILE]=(char *)strdup(xcddefault_comment_file); if(macro_x[MACRO_COMMENTDATAFILE]!=NULL) strip(macro_x[MACRO_COMMENTDATAFILE]); #endif return OK; } void xcddefault_grab_config_directives(char *input_buffer){ char *temp_buffer; /* comment file definition */ if((strstr(input_buffer,"comment_file")==input_buffer) || (strstr(input_buffer,"xcddefault_comment_file")==input_buffer)){ temp_buffer=strtok(input_buffer,"="); temp_buffer=strtok(NULL,"\n"); if(temp_buffer==NULL) return; strncpy(xcddefault_comment_file,temp_buffer,sizeof(xcddefault_comment_file)-1); xcddefault_comment_file[sizeof(xcddefault_comment_file)-1]='\x0'; } /* status log definition */ if((strstr(input_buffer,"temp_file")==input_buffer) || (strstr(input_buffer,"xcddefault_temp_file")==input_buffer)){ temp_buffer=strtok(input_buffer,"="); temp_buffer=strtok(NULL,"\n"); if(temp_buffer==NULL) return; strncpy(xcddefault_temp_file,temp_buffer,sizeof(xcddefault_temp_file)-1); xcddefault_temp_file[sizeof(xcddefault_temp_file)-1]='\x0'; } return; } #ifdef NSCORE /******************************************************************/ /************ COMMENT INITIALIZATION/CLEANUP FUNCTIONS ************/ /******************************************************************/ /* initialize comment data */ int xcddefault_initialize_comment_data(char *main_config_file){ /* grab configuration information */ if(xcddefault_grab_config_info(main_config_file)==ERROR) return ERROR; /* create comment file if necessary */ xcddefault_create_comment_file(); /* read comment data */ xcddefault_read_comment_data(main_config_file); /* clean up the old comment data */ xcddefault_validate_comment_data(); return OK; } /* creates an empty comment data file if one doesn't already exist */ int xcddefault_create_comment_file(void){ struct stat statbuf; /* bail out if file already exists */ if(!stat(xcddefault_comment_file,&statbuf)) return OK; /* create an empty file */ xcddefault_save_comment_data(); return OK; } /* removes invalid and old comments from the comment file */ int xcddefault_validate_comment_data(void){ comment *temp_comment; comment *next_comment; int update_file=FALSE; int save=TRUE; /* remove stale comments */ for(temp_comment=comment_list;temp_comment!=NULL;temp_comment=next_comment){ next_comment=temp_comment->next; save=TRUE; /* delete comments with invalid host names */ if(find_host(temp_comment->host_name)==NULL) save=FALSE; /* delete comments with invalid service descriptions */ if(temp_comment->comment_type==SERVICE_COMMENT && find_service(temp_comment->host_name,temp_comment->service_description)==NULL) save=FALSE; /* delete non-persistent comments */ if(temp_comment->persistent==FALSE) save=FALSE; /* delete the comment */ if(save==FALSE){ update_file=TRUE; delete_comment(temp_comment->comment_type,temp_comment->comment_id); } } /* update comment file */ if(update_file==TRUE) xcddefault_save_comment_data(); /* reset the current comment counter */ current_comment_id=0; /* find the new starting index for comment id */ for(temp_comment=comment_list;temp_comment!=NULL;temp_comment=temp_comment->next){ if(temp_comment->comment_id>current_comment_id) current_comment_id=temp_comment->comment_id; } return OK; } /* removes invalid and old comments from the comment file */ int xcddefault_cleanup_comment_data(char *main_config_file){ /* we don't need to do any cleanup... */ return OK; } /******************************************************************/ /***************** DEFAULT DATA OUTPUT FUNCTIONS ******************/ /******************************************************************/ /* adds a new host comment */ int xcddefault_add_new_host_comment(int entry_type, char *host_name, time_t entry_time, char *author_name, char *comment_data, int persistent, int source, int expires, time_t expire_time, unsigned long *comment_id){ /* find the next valid comment id */ do{ current_comment_id++; if(current_comment_id==0) current_comment_id++; }while(find_host_comment(current_comment_id)!=NULL); /* add comment to list in memory */ add_host_comment(entry_type,host_name,entry_time,author_name,comment_data,current_comment_id,persistent,expires,expire_time,source); /* update comment file */ xcddefault_save_comment_data(); /* return the id for the comment we are about to add (this happens in the main code) */ if(comment_id!=NULL) *comment_id=current_comment_id; return OK; } /* adds a new service comment */ int xcddefault_add_new_service_comment(int entry_type, char *host_name, char *svc_description, time_t entry_time, char *author_name, char *comment_data, int persistent, int source, int expires, time_t expire_time, unsigned long *comment_id){ /* find the next valid comment id */ do{ current_comment_id++; if(current_comment_id==0) current_comment_id++; }while(find_service_comment(current_comment_id)!=NULL); /* add comment to list in memory */ add_service_comment(entry_type,host_name,svc_description,entry_time,author_name,comment_data,current_comment_id,persistent,expires,expire_time,source); /* update comment file */ xcddefault_save_comment_data(); /* return the id for the comment we are about to add (this happens in the main code) */ if(comment_id!=NULL) *comment_id=current_comment_id; return OK; } /******************************************************************/ /**************** COMMENT DELETION FUNCTIONS **********************/ /******************************************************************/ /* deletes a host comment */ int xcddefault_delete_host_comment(unsigned long comment_id){ /* update comment file */ xcddefault_save_comment_data(); return OK; } /* deletes a service comment */ int xcddefault_delete_service_comment(unsigned long comment_id){ /* update comment file */ xcddefault_save_comment_data(); return OK; } /* deletes all comments for a particular host */ int xcddefault_delete_all_host_comments(char *host_name){ /* update comment file */ xcddefault_save_comment_data(); return OK; } /* deletes all comments for a particular service */ int xcddefault_delete_all_service_comments(char *host_name, char *svc_description){ /* update comment file */ xcddefault_save_comment_data(); return OK; } /******************************************************************/ /****************** COMMENT OUTPUT FUNCTIONS **********************/ /******************************************************************/ /* writes comment data to file */ int xcddefault_save_comment_data(void){ char temp_file[MAX_FILENAME_LENGTH]; time_t current_time; comment *temp_comment; int fd=0; FILE *fp=NULL; /* open a safe temp file for output */ snprintf(temp_file,sizeof(temp_file)-1,"%sXXXXXX",xcddefault_temp_file); temp_file[sizeof(temp_file)-1]='\x0'; if((fd=mkstemp(temp_file))==-1) return ERROR; fp=fdopen(fd,"w"); if(fp==NULL){ close(fd); unlink(temp_file); return ERROR; } /* write header */ fprintf(fp,"########################################\n"); fprintf(fp,"# NAGIOS COMMENT FILE\n"); fprintf(fp,"#\n"); fprintf(fp,"# THIS FILE IS AUTOMATICALLY GENERATED\n"); fprintf(fp,"# BY NAGIOS. DO NOT MODIFY THIS FILE!\n"); fprintf(fp,"########################################\n\n"); time(¤t_time); /* write file info */ fprintf(fp,"info {\n"); fprintf(fp,"\tcreated=%lu\n",current_time); fprintf(fp,"\tversion=%s\n",PROGRAM_VERSION); fprintf(fp,"\t}\n\n"); /* save all comments */ for(temp_comment=comment_list;temp_comment!=NULL;temp_comment=temp_comment->next){ if(temp_comment->comment_type==HOST_COMMENT) fprintf(fp,"hostcomment {\n"); else fprintf(fp,"servicecomment {\n"); fprintf(fp,"\thost_name=%s\n",temp_comment->host_name); if(temp_comment->comment_type==SERVICE_COMMENT) fprintf(fp,"\tservice_description=%s\n",temp_comment->service_description); fprintf(fp,"\tentry_type=%d\n",temp_comment->entry_type); fprintf(fp,"\tcomment_id=%lu\n",temp_comment->comment_id); fprintf(fp,"\tsource=%d\n",temp_comment->source); fprintf(fp,"\tpersistent=%d\n",temp_comment->persistent); fprintf(fp,"\tentry_time=%lu\n",temp_comment->entry_time); fprintf(fp,"\texpires=%d\n",temp_comment->expires); fprintf(fp,"\texpire_time=%lu\n",temp_comment->expire_time); fprintf(fp,"\tauthor=%s\n",temp_comment->author); fprintf(fp,"\tcomment_data=%s\n",temp_comment->comment_data); fprintf(fp,"\t}\n\n"); } /* reset file permissions */ fchmod(fd,S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); /* close the temp file */ fclose(fp); /* move the temp file to the comment file (overwrite the old comment file) */ if(my_rename(temp_file,xcddefault_comment_file)) return ERROR; return OK; } #endif /******************************************************************/ /****************** COMMENT INPUT FUNCTIONS ***********************/ /******************************************************************/ /* read the comment file */ int xcddefault_read_comment_data(char *main_config_file){ #ifdef BAD_MMAP char *input=NULL; mmapfile *thefile; #else char input[2048]=""; FILE *fp=NULL; #endif int data_type=XCDDEFAULT_NO_DATA; char *var; char *val; int result; unsigned long comment_id=0; int persistent=FALSE; int expires=FALSE; time_t expire_time=0L; int entry_type=USER_COMMENT; int source=COMMENTSOURCE_INTERNAL; time_t entry_time=0L; char *host_name=NULL; char *service_description=NULL; char *author=NULL; char *comment_data=NULL; /* grab configuration data */ result=xcddefault_grab_config_info(main_config_file); if(result==ERROR) return ERROR; /* open the comment file for reading */ #ifdef BAD_MMAP if((thefile=mmap_fopen(xcddefault_comment_file))==NULL) return ERROR; #else if((fp=fopen(xcddefault_comment_file,"r"))==NULL) return ERROR; #endif /* read all lines in the comment file */ while(1){ #ifdef BAD_MMAP /* free memory */ free(input); /* read the next line */ if((input=mmap_fgets(thefile))==NULL) break; #else strcpy(input,""); if(fgets(input,sizeof(input),fp)==NULL) break; #endif strip(input); /* skip blank lines and comments */ if(input[0]=='#' || input[0]=='\x0') continue; else if(!strcmp(input,"info {")) data_type=XCDDEFAULT_INFO_DATA; else if(!strcmp(input,"hostcomment {")) data_type=XCDDEFAULT_HOST_DATA; else if(!strcmp(input,"servicecomment {")) data_type=XCDDEFAULT_SERVICE_DATA; else if(!strcmp(input,"}")){ switch(data_type){ case XCDDEFAULT_INFO_DATA: break; case XCDDEFAULT_HOST_DATA: case XCDDEFAULT_SERVICE_DATA: add_comment((data_type==XCDDEFAULT_HOST_DATA)?HOST_COMMENT:SERVICE_COMMENT,entry_type,host_name,service_description,entry_time,author,comment_data,comment_id,persistent,expires,expire_time,source); break; default: break; } data_type=XCDDEFAULT_NO_DATA; /* free temp memory */ free(host_name); free(service_description); free(author); free(comment_data); /* reset defaults */ host_name=NULL; service_description=NULL; author=NULL; comment_data=NULL; entry_type=USER_COMMENT; comment_id=0; source=COMMENTSOURCE_INTERNAL; persistent=FALSE; entry_time=0L; expires=FALSE; expire_time=0L; } else if(data_type!=XCDDEFAULT_NO_DATA){ var=strtok(input,"="); val=strtok(NULL,"\n"); if(val==NULL) continue; switch(data_type){ case XCDDEFAULT_INFO_DATA: break; case XCDDEFAULT_HOST_DATA: case XCDDEFAULT_SERVICE_DATA: if(!strcmp(var,"host_name")) host_name=strdup(val); else if(!strcmp(var,"service_description")) service_description=strdup(val); else if(!strcmp(var,"entry_type")) entry_type=atoi(val); else if(!strcmp(var,"comment_id")) comment_id=strtoul(val,NULL,10); else if(!strcmp(var,"source")) source=atoi(val); else if(!strcmp(var,"persistent")) persistent=(atoi(val)>0)?TRUE:FALSE; else if(!strcmp(var,"entry_time")) entry_time=strtoul(val,NULL,10); else if(!strcmp(var,"expires")) expires=(atoi(val)>0)?TRUE:FALSE; else if(!strcmp(var,"expire_time")) expire_time=strtoul(val,NULL,10); else if(!strcmp(var,"author")) author=strdup(val); else if(!strcmp(var,"comment_data")) comment_data=strdup(val); break; default: break; } } } /* free memory and close the file */ #ifdef BAD_MMAP free(input); mmap_fclose(thefile); #else fclose(fp); #endif return OK; }