/*********************************************************************** * * CGIUTILS.C - Common utilities for Nagios CGIs * * Copyright (c) 1999-2007 Ethan Galstad (nagios@nagios.org) * Last Modified: 10-21-2007 * * 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. ***********************************************************************/ #include "../include/config.h" #include "../include/common.h" #include "../include/locations.h" #include "../include/objects.h" #include "../include/statusdata.h" #include "../include/cgiutils.h" char main_config_file[MAX_FILENAME_LENGTH]; char log_file[MAX_FILENAME_LENGTH]; char log_archive_path[MAX_FILENAME_LENGTH]; char command_file[MAX_FILENAME_LENGTH]; char physical_html_path[MAX_FILENAME_LENGTH]; char physical_images_path[MAX_FILENAME_LENGTH]; char physical_ssi_path[MAX_FILENAME_LENGTH]; char url_html_path[MAX_FILENAME_LENGTH]; char url_docs_path[MAX_FILENAME_LENGTH]; char url_context_help_path[MAX_FILENAME_LENGTH]; char url_images_path[MAX_FILENAME_LENGTH]; char url_logo_images_path[MAX_FILENAME_LENGTH]; char url_stylesheets_path[MAX_FILENAME_LENGTH]; char url_media_path[MAX_FILENAME_LENGTH]; char *service_critical_sound=NULL; char *service_warning_sound=NULL; char *service_unknown_sound=NULL; char *host_down_sound=NULL; char *host_unreachable_sound=NULL; char *normal_sound=NULL; char *statusmap_background_image=NULL; char *statuswrl_include=NULL; char *ping_syntax=NULL; char nagios_check_command[MAX_INPUT_BUFFER]=""; char nagios_process_info[MAX_INPUT_BUFFER]=""; int nagios_process_state=STATE_OK; extern time_t program_start; extern int nagios_pid; extern int daemon_mode; extern int enable_notifications; extern int execute_service_checks; extern int accept_passive_service_checks; extern int enable_event_handlers; extern int obsess_over_services; extern int enable_failure_prediction; extern int process_performance_data; extern time_t last_command_check; extern time_t last_log_rotation; int check_external_commands=0; int date_format=DATE_FORMAT_US; int log_rotation_method=LOG_ROTATION_NONE; time_t this_scheduled_log_rotation=0L; time_t last_scheduled_log_rotation=0L; time_t next_scheduled_log_rotation=0L; int use_authentication=TRUE; int interval_length=60; int show_context_help=FALSE; int hosts_have_been_read=FALSE; int hostgroups_have_been_read=FALSE; int servicegroups_have_been_read=FALSE; int contacts_have_been_read=FALSE; int contactgroups_have_been_read=FALSE; int services_have_been_read=FALSE; int timeperiods_have_been_read=FALSE; int commands_have_been_read=FALSE; int servicedependencies_have_been_read=FALSE; int serviceescalations_have_been_read=FALSE; int hostdependencies_have_been_read=FALSE; int hostescalations_have_been_read=FALSE; int hostextinfo_have_been_read=FALSE; int serviceextinfo_have_been_read=FALSE; int host_status_has_been_read=FALSE; int service_status_has_been_read=FALSE; int program_status_has_been_read=FALSE; int refresh_rate=DEFAULT_REFRESH_RATE; int default_statusmap_layout_method=0; int default_statuswrl_layout_method=0; extern hostgroup *hostgroup_list; extern contactgroup *contactgroup_list; extern command *command_list; extern timeperiod *timeperiod_list; extern contact *contact_list; extern serviceescalation *serviceescalation_list; extern hoststatus *hoststatus_list; extern servicestatus *servicestatus_list; lifo *lifo_list=NULL; char *my_strtok_buffer=NULL; char *original_my_strtok_buffer=NULL; char encoded_url_string[MAX_INPUT_BUFFER]; char encoded_html_string[MAX_INPUT_BUFFER]; #ifdef HAVE_TZNAME #ifdef CYGWIN extern char *_tzname[2] __declspec(dllimport); #else extern char *tzname[2]; #endif #endif /********************************************************** ***************** CLEANUP FUNCTIONS ********************** **********************************************************/ /* reset all variables used by the CGIs */ void reset_cgi_vars(void){ strcpy(main_config_file,""); strcpy(physical_html_path,""); strcpy(physical_images_path,""); strcpy(physical_ssi_path,""); strcpy(url_html_path,""); strcpy(url_docs_path,""); strcpy(url_context_help_path,""); strcpy(url_stylesheets_path,""); strcpy(url_media_path,""); strcpy(url_images_path,""); strcpy(log_file,""); strcpy(log_archive_path,DEFAULT_LOG_ARCHIVE_PATH); if(log_archive_path[strlen(log_archive_path)-1]!='/' && strlen(log_archive_path)0) return 1; else if(result<0) return -1; else return strcmp(val1b,val2b); } /********************************************************** ******************* LIFO FUNCTIONS *********************** **********************************************************/ /* reads contents of file into the lifo struct */ int read_file_into_lifo(char *filename){ char *input=NULL; mmapfile *thefile; int lifo_result; if((thefile=mmap_fopen(filename))==NULL) return LIFO_ERROR_FILE; while(1){ free(input); if((input=mmap_fgets(thefile))==NULL) break; lifo_result=push_lifo(input); if(lifo_result!=LIFO_OK){ free_lifo_memory(); free(input); mmap_fclose(thefile); return lifo_result; } } mmap_fclose(thefile); return LIFO_OK; } /* frees all memory allocated to lifo */ void free_lifo_memory(void){ lifo *temp_lifo; lifo *next_lifo; if(lifo_list==NULL) return; temp_lifo=lifo_list; while(temp_lifo!=NULL){ next_lifo=temp_lifo->next; if(temp_lifo->data!=NULL) free((void *)temp_lifo->data); free((void *)temp_lifo); temp_lifo=next_lifo; } return; } /* adds an item to lifo */ int push_lifo(char *buffer){ lifo *temp_lifo; temp_lifo=(lifo *)malloc(sizeof(lifo)); if(temp_lifo==NULL) return LIFO_ERROR_MEMORY; if(buffer==NULL) temp_lifo->data=(char *)strdup(""); else temp_lifo->data=(char *)strdup(buffer); if(temp_lifo->data==NULL){ free(temp_lifo); return LIFO_ERROR_MEMORY; } /* add item to front of lifo... */ temp_lifo->next=lifo_list; lifo_list=temp_lifo; return LIFO_OK; } /* returns/clears an item from lifo */ char *pop_lifo(void){ lifo *temp_lifo; char *buf; if(lifo_list==NULL || lifo_list->data==NULL) return NULL; buf=strdup(lifo_list->data); temp_lifo=lifo_list->next; if(lifo_list->data!=NULL) free((void *)lifo_list->data); free((void *)lifo_list); lifo_list=temp_lifo; return buf; } /********************************************************** *************** MISC UTILITY FUNCTIONS ******************* **********************************************************/ /* strip newline, carriage return, and tab characters from beginning and end of a string */ void strip(char *buffer){ register int x; register int y; register int z; if(buffer==NULL || buffer[0]=='\x0') return; /* strip end of string */ y=(int)strlen(buffer); for(x=y-1;x>=0;x--){ if(buffer[x]==' ' || buffer[x]=='\n' || buffer[x]=='\r' || buffer[x]=='\t' || buffer[x]==13) buffer[x]='\x0'; else break; } /* strip beginning of string (by shifting) */ y=(int)strlen(buffer); for(x=0;x0){ for(z=x;z'){ in_html=FALSE; continue; } /* skip everything inside HTML tags */ else if(in_html==TRUE) continue; /* strip single and double quotes */ else if(buffer[x]=='\'' || buffer[x]=='\"') new_buffer[y++]=' '; /* strip semicolons (replace with colons) */ else if(buffer[x]==';') new_buffer[y++]=':'; /* strip pipe and ampersand */ else if(buffer[x]=='&' || buffer[x]=='|') new_buffer[y++]=' '; /* normal character */ else new_buffer[y++]=buffer[x]; } /* terminate sanitized buffer */ new_buffer[y++]='\x0'; /* copy the sanitized buffer back to the original */ strcpy(buffer,new_buffer); /* free memory allocated to the new buffer */ free(new_buffer); return; } /* get date/time string */ void get_time_string(time_t *raw_time,char *buffer,int buffer_length,int type){ time_t t; struct tm *tm_ptr; int day; int hour; int minute; int second; int year; char *weekdays[7]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"}; char *months[12]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"}; char *tzone=""; if(raw_time==NULL) time(&t); else t=*raw_time; if(type==HTTP_DATE_TIME) tm_ptr=gmtime(&t); else tm_ptr=localtime(&t); hour=tm_ptr->tm_hour; minute=tm_ptr->tm_min; second=tm_ptr->tm_sec; day=tm_ptr->tm_mday; year=tm_ptr->tm_year+1900; #ifdef HAVE_TM_ZONE tzone=(char *)tm_ptr->tm_zone; #else tzone=(tm_ptr->tm_isdst)?tzname[1]:tzname[0]; #endif /* ctime() style */ if(type==LONG_DATE_TIME) snprintf(buffer,buffer_length,"%s %s %d %02d:%02d:%02d %s %d",weekdays[tm_ptr->tm_wday],months[tm_ptr->tm_mon],day,hour,minute,second,tzone,year); /* short style */ else if(type==SHORT_DATE_TIME){ if(date_format==DATE_FORMAT_EURO) snprintf(buffer,buffer_length,"%02d-%02d-%04d %02d:%02d:%02d",tm_ptr->tm_mday,tm_ptr->tm_mon+1,tm_ptr->tm_year+1900,tm_ptr->tm_hour,tm_ptr->tm_min,tm_ptr->tm_sec); else if(date_format==DATE_FORMAT_ISO8601 || date_format==DATE_FORMAT_STRICT_ISO8601) snprintf(buffer,buffer_length,"%04d-%02d-%02d%c%02d:%02d:%02d",tm_ptr->tm_year+1900,tm_ptr->tm_mon+1,tm_ptr->tm_mday,(date_format==DATE_FORMAT_STRICT_ISO8601)?'T':' ',tm_ptr->tm_hour,tm_ptr->tm_min,tm_ptr->tm_sec); else snprintf(buffer,buffer_length,"%02d-%02d-%04d %02d:%02d:%02d",tm_ptr->tm_mon+1,tm_ptr->tm_mday,tm_ptr->tm_year+1900,tm_ptr->tm_hour,tm_ptr->tm_min,tm_ptr->tm_sec); } /* expiration date/time for HTTP headers */ else if(type==HTTP_DATE_TIME) snprintf(buffer,buffer_length,"%s, %02d %s %d %02d:%02d:%02d GMT",weekdays[tm_ptr->tm_wday],day,months[tm_ptr->tm_mon],year,hour,minute,second); buffer[buffer_length-1]='\x0'; return; } /* get time string for an interval of time */ void get_interval_time_string(int time_units,char *buffer,int buffer_length){ unsigned long total_seconds; int hours=0; int minutes=0; int seconds=0; total_seconds=(unsigned long)(time_units*interval_length); hours=(int)total_seconds/3600; total_seconds%=3600; minutes=(int)total_seconds/60; total_seconds%=60; seconds=(int)total_seconds; snprintf(buffer,buffer_length,"%dh %dm %ds",hours,minutes,seconds); buffer[buffer_length-1]='\x0'; return; } /* fix the problem with strtok() skipping empty options between tokens */ char *my_strtok(char *buffer,char *tokens){ char *token_position; char *sequence_head; if(buffer!=NULL){ if(original_my_strtok_buffer!=NULL) free(original_my_strtok_buffer); my_strtok_buffer=malloc(strlen(buffer)+1); if(my_strtok_buffer==NULL) return NULL; original_my_strtok_buffer=my_strtok_buffer; strcpy(my_strtok_buffer,buffer); } sequence_head=my_strtok_buffer; if(sequence_head[0]=='\x0') return NULL; token_position=index(my_strtok_buffer,tokens[0]); if(token_position==NULL){ my_strtok_buffer=index(my_strtok_buffer,'\x0'); return sequence_head; } token_position[0]='\x0'; my_strtok_buffer=token_position+1; return sequence_head; } /* fixes compiler problems under Solaris, since strsep() isn't included */ /* this code is taken from the glibc source */ char *my_strsep (char **stringp, const char *delim){ char *begin, *end; begin = *stringp; if (begin == NULL) return NULL; /* A frequent case is when the delimiter string contains only one character. Here we don't need to call the expensive `strpbrk' function and instead work using `strchr'. */ if(delim[0]=='\0' || delim[1]=='\0'){ char ch = delim[0]; if(ch=='\0') end=NULL; else{ if(*begin==ch) end=begin; else end=strchr(begin+1,ch); } } else /* Find the end of the token. */ end = strpbrk (begin, delim); if(end){ /* Terminate the token and set *STRINGP past NUL character. */ *end++='\0'; *stringp=end; } else /* No more delimiters; this is the last token. */ *stringp=NULL; return begin; } /* open a file read-only via mmap() */ mmapfile *mmap_fopen(char *filename){ mmapfile *new_mmapfile; int fd; void *mmap_buf; struct stat statbuf; int mode=O_RDONLY; /* allocate memory */ if((new_mmapfile=(mmapfile *)malloc(sizeof(mmapfile)))==NULL) return NULL; /* open the file */ if((fd=open(filename,mode))==-1) return NULL; /* get file info */ if((fstat(fd,&statbuf))==-1){ close(fd); free(new_mmapfile); return NULL; } /* mmap() the file */ if((mmap_buf=(void *)mmap(0,statbuf.st_size,PROT_READ,MAP_PRIVATE,fd,0))==MAP_FAILED){ close(fd); free(new_mmapfile); return NULL; } /* populate struct info for later use */ new_mmapfile->path=strdup(filename); new_mmapfile->fd=fd; new_mmapfile->file_size=(unsigned long)(statbuf.st_size); new_mmapfile->current_position=0L; new_mmapfile->current_line=0L; new_mmapfile->mmap_buf=mmap_buf; return new_mmapfile; } /* close a file originally opened via mmap() */ int mmap_fclose(mmapfile *temp_mmapfile){ if(temp_mmapfile==NULL) return ERROR; /* un-mmap() the file */ munmap(temp_mmapfile->mmap_buf,temp_mmapfile->file_size); /* close the file */ close(temp_mmapfile->fd); /* free memory */ free(temp_mmapfile); return OK; } /* gets one line of input from an mmap()'ed file */ char *mmap_fgets(mmapfile *temp_mmapfile){ char *buf=NULL; unsigned long x=0L; int len=0; if(temp_mmapfile==NULL) return NULL; /* we've reached the end of the file */ if(temp_mmapfile->current_position>=temp_mmapfile->file_size) return NULL; /* find the end of the string (or buffer) */ for(x=temp_mmapfile->current_position;xfile_size;x++){ if(*((char *)(temp_mmapfile->mmap_buf)+x)=='\n'){ x++; break; } } /* calculate length of line we just read */ len=(int)(x-temp_mmapfile->current_position); /* allocate memory for the new line */ if((buf=(char *)malloc(len+1))==NULL) return NULL; /* copy string to newly allocated memory and terminate the string */ memcpy(buf,((char *)(temp_mmapfile->mmap_buf)+temp_mmapfile->current_position),len); buf[len]='\x0'; /* update the current position */ temp_mmapfile->current_position=x; /* increment the current line */ temp_mmapfile->current_line++; return buf; } /* gets one line of input from an mmap()'ed file (may be contained on more than one line in the source file) */ char *mmap_fgets_multiline(mmapfile *temp_mmapfile){ char *buf=NULL; char *tempbuf=NULL; int len; int len2; if(temp_mmapfile==NULL) return NULL; while(1){ free(tempbuf); if((tempbuf=mmap_fgets(temp_mmapfile))==NULL) break; if(buf==NULL){ len=strlen(tempbuf); if((buf=(char *)malloc(len+1))==NULL) break; memcpy(buf,tempbuf,len); buf[len]='\x0'; } else{ len=strlen(tempbuf); len2=strlen(buf); if((buf=(char *)realloc(buf,len+len2+1))==NULL) break; strcat(buf,tempbuf); len+=len2; buf[len]='\x0'; } /* we shouldn't continue to the next line... */ if(!(len>0 && buf[len-1]=='\\' && (len==1 || buf[len-2]!='\\'))) break; } free(tempbuf); return buf; } /* get days, hours, minutes, and seconds from a raw time_t format or total seconds */ void get_time_breakdown(unsigned long raw_time,int *days,int *hours,int *minutes,int *seconds){ unsigned long temp_time; int temp_days; int temp_hours; int temp_minutes; int temp_seconds; temp_time=raw_time; temp_days=temp_time/86400; temp_time-=(temp_days * 86400); temp_hours=temp_time/3600; temp_time-=(temp_hours * 3600); temp_minutes=temp_time/60; temp_time-=(temp_minutes * 60); temp_seconds=(int)temp_time; *days=temp_days; *hours=temp_hours; *minutes=temp_minutes; *seconds=temp_seconds; return; } /* encodes a string in proper URL format */ char * url_encode(char *input){ int len,output_len; int x,y; char temp_expansion[4]; len=(int)strlen(input); output_len=(int)sizeof(encoded_url_string); encoded_url_string[0]='\x0'; for(x=0,y=0;x<=len && y='0' && (char)input[x]<='9') || ((char)input[x]>='A' && (char)input[x]<='Z') || ((char)input[x]>=(char)'a' && (char)input[x]<=(char)'z') || (char)input[x]==(char)'.' || (char)input[x]==(char)'-' || (char)input[x]==(char)'_'){ encoded_url_string[y]=input[x]; y++; } /* spaces are pluses */ else if((char)input[x]<=(char)' '){ encoded_url_string[y]='+'; y++; } /* anything else gets represented by its hex value */ else{ encoded_url_string[y]='\x0'; if((int)strlen(encoded_url_string)<(output_len-3)){ sprintf(temp_expansion,"%%%02X",(unsigned int)input[x]); strcat(encoded_url_string,temp_expansion); y+=3; } } } encoded_url_string[sizeof(encoded_url_string)-1]='\x0'; return &encoded_url_string[0]; } /* escapes a string used in HTML */ char * html_encode(char *input){ int len,output_len; int x,y; char temp_expansion[7]; len=(int)strlen(input); output_len=(int)sizeof(encoded_html_string); encoded_html_string[0]='\x0'; for(x=0,y=0;x<=len && y='0' && (char)input[x]<='9') || ((char)input[x]>='A' && (char)input[x]<='Z') || ((char)input[x]>=(char)'a' && (char)input[x]<=(char)'z')){ encoded_html_string[y]=input[x]; y++; } #ifdef NOT_SO_SURE_ABOUT_THIS /* spaces are encoded as non-breaking spaces */ else if((char)input[x]==(char)' '){ encoded_html_string[y]='\x0'; if((int)strlen(encoded_html_string)<(output_len-6)){ strcat(encoded_html_string," "); y+=6; } } #endif else if((char)input[x]==(char)'<'){ encoded_html_string[y]='\x0'; if((int)strlen(encoded_html_string)<(output_len-4)){ strcat(encoded_html_string,"<"); y+=4; } } else if((char)input[x]==(char)'>'){ encoded_html_string[y]='\x0'; if((int)strlen(encoded_html_string)<(output_len-4)){ strcat(encoded_html_string,">"); y+=4; } } /* for simplicity, everything else gets represented by its numeric value */ else{ encoded_html_string[y]='\x0'; sprintf(temp_expansion,"&#%d;",(unsigned int)input[x]); if((int)strlen(encoded_html_string)<(output_len-strlen(temp_expansion))){ strcat(encoded_html_string,temp_expansion); y+=strlen(temp_expansion); } } } encoded_html_string[sizeof(encoded_html_string)-1]='\x0'; return &encoded_html_string[0]; } /* strips dangerous HTML from plugin output */ char * strip_plugin_html(char *input){ /* TODO */ return input; } /* strip > and < from string */ void strip_html_brackets(char *buffer){ register int x; register int y; register int z; if(buffer==NULL || buffer[0]=='\x0') return; /* remove all occurances in string */ z=(int)strlen(buffer); for(x=0,y=0;x') continue; buffer[y++]=buffer[x]; } buffer[y++]='\x0'; return; } /* determines the log file we should use (from current time) */ void get_log_archive_to_use(int archive,char *buffer,int buffer_length){ struct tm *t; /* determine the time at which the log was rotated for this archive # */ determine_log_rotation_times(archive); /* if we're not rotating the logs or if we want the current log, use the main one... */ if(log_rotation_method==LOG_ROTATION_NONE || archive<=0){ strncpy(buffer,log_file,buffer_length); buffer[buffer_length-1]='\x0'; return; } t=localtime(&this_scheduled_log_rotation); /* use the time that the log rotation occurred to figure out the name of the log file */ snprintf(buffer,buffer_length,"%snagios-%02d-%02d-%d-%02d.log",log_archive_path,t->tm_mon+1,t->tm_mday,t->tm_year+1900,t->tm_hour); buffer[buffer_length-1]='\x0'; return; } /* determines log archive to use, given a specific time */ int determine_archive_to_use_from_time(time_t target_time){ time_t current_time; int current_archive=0; /* if log rotation is disabled, we don't have archives */ if(log_rotation_method==LOG_ROTATION_NONE) return 0; /* make sure target time is rational */ current_time=time(NULL); if(target_time>=current_time) return 0; /* backtrack through archives to find the one we need for this time */ /* start with archive of 1, subtract one when we find the right time period to compensate for current (non-rotated) log */ for(current_archive=1;;current_archive++){ /* determine time at which the log rotation occurred for this archive number */ determine_log_rotation_times(current_archive); /* if the target time falls within the times encompassed by this archive, we have the right archive! */ if(target_time>=this_scheduled_log_rotation) return current_archive-1; } return 0; } /* determines the log rotation times - past, present, future */ void determine_log_rotation_times(int archive){ struct tm *t; int current_month; int is_dst_now=FALSE; time_t current_time; /* negative archive numbers don't make sense */ /* if archive=0 (current log), this_scheduled_log_rotation time is set to next rotation time */ if(archive<0) return; time(¤t_time); t=localtime(¤t_time); is_dst_now=(t->tm_isdst>0)?TRUE:FALSE; t->tm_min=0; t->tm_sec=0; switch(log_rotation_method){ case LOG_ROTATION_HOURLY: this_scheduled_log_rotation=mktime(t); this_scheduled_log_rotation=(time_t)(this_scheduled_log_rotation-((archive-1)*3600)); last_scheduled_log_rotation=(time_t)(this_scheduled_log_rotation-3600); break; case LOG_ROTATION_DAILY: t->tm_hour=0; this_scheduled_log_rotation=mktime(t); this_scheduled_log_rotation=(time_t)(this_scheduled_log_rotation-((archive-1)*86400)); last_scheduled_log_rotation=(time_t)(this_scheduled_log_rotation-86400); break; case LOG_ROTATION_WEEKLY: t->tm_hour=0; this_scheduled_log_rotation=mktime(t); this_scheduled_log_rotation=(time_t)(this_scheduled_log_rotation-(86400*t->tm_wday)); this_scheduled_log_rotation=(time_t)(this_scheduled_log_rotation-((archive-1)*604800)); last_scheduled_log_rotation=(time_t)(this_scheduled_log_rotation-604800); break; case LOG_ROTATION_MONTHLY: t=localtime(¤t_time); t->tm_mon++; t->tm_mday=1; t->tm_hour=0; t->tm_min=0; t->tm_sec=0; for(current_month=0;current_month<=archive;current_month++){ if(t->tm_mon==0){ t->tm_mon=11; t->tm_year--; } else t->tm_mon--; } last_scheduled_log_rotation=mktime(t); t=localtime(¤t_time); t->tm_mon++; t->tm_mday=1; t->tm_hour=0; t->tm_min=0; t->tm_sec=0; for(current_month=0;current_monthtm_mon==0){ t->tm_mon=11; t->tm_year--; } else t->tm_mon--; } this_scheduled_log_rotation=mktime(t); break; default: break; } /* adjust this rotation time for daylight savings time */ t=localtime(&this_scheduled_log_rotation); if(t->tm_isdst>0 && is_dst_now==FALSE) this_scheduled_log_rotation=(time_t)(this_scheduled_log_rotation-3600); else if(t->tm_isdst==0 && is_dst_now==TRUE) this_scheduled_log_rotation=(time_t)(this_scheduled_log_rotation+3600); /* adjust last rotation time for daylight savings time */ t=localtime(&last_scheduled_log_rotation); if(t->tm_isdst>0 && is_dst_now==FALSE) last_scheduled_log_rotation=(time_t)(last_scheduled_log_rotation-3600); else if(t->tm_isdst==0 && is_dst_now==TRUE) last_scheduled_log_rotation=(time_t)(last_scheduled_log_rotation+3600); return; } /********************************************************** *************** COMMON HTML FUNCTIONS ******************** **********************************************************/ void display_info_table(char *title,int refresh, authdata *current_authdata){ time_t current_time; char date_time[MAX_DATETIME_LENGTH]; int result; /* read program status */ result=read_all_status_data(get_cgi_config_location(),READ_PROGRAM_STATUS); printf("\n"); printf("\n"); printf("
\n"); printf("
%s
\n",title); time(¤t_time); get_time_string(¤t_time,date_time,(int)sizeof(date_time),LONG_DATE_TIME); printf("Last Updated: %s
\n",date_time); if(refresh==TRUE) printf("Updated every %d seconds
\n",refresh_rate); printf("Nagios® %s - www.nagios.org
\n",PROGRAM_VERSION); if(current_authdata!=NULL) printf("Logged in as %s
\n",(!strcmp(current_authdata->username,""))?"?":current_authdata->username); if(nagios_process_state!=STATE_OK) printf("
Warning: Monitoring process may not be running!
Click here for more info.
",EXTINFO_CGI,DISPLAY_PROCESS_INFO); if(result==ERROR) printf("
Warning: Could not read program status information!
"); else{ if(enable_notifications==FALSE) printf("
- Notifications are disabled
"); if(execute_service_checks==FALSE) printf("
- Service checks are disabled
"); } printf("
\n"); return; } void display_nav_table(char *url,int archive){ char date_time[MAX_DATETIME_LENGTH]; char archive_file[MAX_INPUT_BUFFER]; char *archive_basename; if(log_rotation_method!=LOG_ROTATION_NONE){ printf("\n"); printf("\n"); printf("\n"); printf("\n"); printf("\n"); printf("\n"); if(archive!=0){ printf("\n"); } else printf("\n",url_images_path,EMPTY_ICON); printf("\n"); printf("\n"); } /* get archive to use */ get_log_archive_to_use(archive,archive_file,sizeof(archive_file)-1); /* cut the pathname for security, and the remaining slash for clarity */ archive_basename=(char *)&archive_file; if(strrchr((char *)&archive_basename,'/')!=NULL) archive_basename=strrchr((char *)&archive_file,'/')+1; /* now it's safe to print the filename */ printf("
\n",archive_basename); return; } /* prints the additional notes or action url for a host (with macros substituted) */ void print_extra_host_url(char *host_name, char *url){ char input_buffer[MAX_INPUT_BUFFER]=""; char output_buffer[MAX_INPUT_BUFFER]=""; char *temp_buffer; int in_macro=FALSE; host *temp_host; if(host_name==NULL || url==NULL) return; temp_host=find_host(host_name); if(temp_host==NULL){ printf("%s",url); return; } strncpy(input_buffer,url,sizeof(input_buffer)-1); output_buffer[sizeof(input_buffer)-1]='\x0'; for(temp_buffer=my_strtok(input_buffer,"$");temp_buffer!=NULL;temp_buffer=my_strtok(NULL,"$")){ if(in_macro==FALSE){ if(strlen(output_buffer)+strlen(temp_buffer)name),sizeof(output_buffer)-strlen(output_buffer)-1); else if(!strcmp(temp_buffer,"HOSTADDRESS")) strncat(output_buffer,(temp_host->address==NULL)?"":url_encode(temp_host->address),sizeof(output_buffer)-strlen(output_buffer)-1); } in_macro=FALSE; } } printf("%s",output_buffer); return; } /* prints the additional notes or action url for a service (with macros substituted) */ void print_extra_service_url(char *host_name, char *svc_description, char *url){ char input_buffer[MAX_INPUT_BUFFER]=""; char output_buffer[MAX_INPUT_BUFFER]=""; char *temp_buffer; int in_macro=FALSE; service *temp_service; host *temp_host; if(host_name==NULL || svc_description==NULL || url==NULL) return; temp_service=find_service(host_name,svc_description); if(temp_service==NULL){ printf("%s",url); return; } temp_host=find_host(host_name); strncpy(input_buffer,url,sizeof(input_buffer)-1); input_buffer[sizeof(input_buffer)-1]='\x0'; for(temp_buffer=my_strtok(input_buffer,"$");temp_buffer!=NULL;temp_buffer=my_strtok(NULL,"$")){ if(in_macro==FALSE){ if(strlen(output_buffer)+strlen(temp_buffer)host_name),sizeof(output_buffer)-strlen(output_buffer)-1); else if(!strcmp(temp_buffer,"HOSTADDRESS") && temp_host!=NULL) strncat(output_buffer,(temp_host->address==NULL)?"":url_encode(temp_host->address),sizeof(output_buffer)-strlen(output_buffer)-1); else if(!strcmp(temp_buffer,"SERVICEDESC")) strncat(output_buffer,url_encode(temp_service->description),sizeof(output_buffer)-strlen(output_buffer)-1); } in_macro=FALSE; } } printf("%s",output_buffer); return; } /* include user-defined SSI footers or headers */ void include_ssi_files(char *cgi_name, int type){ char common_ssi_file[MAX_INPUT_BUFFER]; char cgi_ssi_file[MAX_INPUT_BUFFER]; char raw_cgi_name[MAX_INPUT_BUFFER]; char *stripped_cgi_name; int x; /* common header or footer */ snprintf(common_ssi_file,sizeof(common_ssi_file)-1,"%scommon-%s.ssi",physical_ssi_path,(type==SSI_HEADER)?"header":"footer"); common_ssi_file[sizeof(common_ssi_file)-1]='\x0'; /* CGI-specific header or footer */ strncpy(raw_cgi_name,cgi_name,sizeof(raw_cgi_name)-1); raw_cgi_name[sizeof(raw_cgi_name)-1]='\x0'; stripped_cgi_name=strtok(raw_cgi_name,"."); snprintf(cgi_ssi_file,sizeof(cgi_ssi_file)-1,"%s%s-%s.ssi",physical_ssi_path,(stripped_cgi_name==NULL)?"":stripped_cgi_name,(type==SSI_HEADER)?"header":"footer"); cgi_ssi_file[sizeof(cgi_ssi_file)-1]='\x0'; for(x=0;x\n"); include_ssi_file(common_ssi_file); include_ssi_file(cgi_ssi_file); } else{ include_ssi_file(cgi_ssi_file); include_ssi_file(common_ssi_file); printf("\n\n"); } return; } /* include user-defined SSI footer or header */ void include_ssi_file(char *filename){ char buffer[MAX_INPUT_BUFFER]; FILE *fp; struct stat stat_result; int call_return; /* if file is executable, we want to run it rather than print it */ call_return=stat(filename,&stat_result); /* file is executable */ if(call_return==0 && (stat_result.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))){ /* must flush output stream first so that output from script shows up in correct place. Other choice is to open program under pipe and copy the data from the program to our output stream. */ fflush(stdout); /* ignore return status from system call. */ call_return=system(filename); return; } /* an error occurred trying to stat() the file */ else if(call_return!=0){ /* Handle error conditions. Assume that standard posix error codes and errno are available. If not, comment this section out. */ switch(errno){ case ENOTDIR: /* - A component of the path is not a directory. */ case ELOOP: /* Too many symbolic links encountered while traversing the path. */ case EFAULT: /* Bad address. */ case ENOMEM: /* Out of memory (i.e. kernel memory). */ case ENAMETOOLONG: /* File name too long. */ printf("
A stat call returned %d while looking for the file %s.
", errno, filename); return; case EACCES: /* Permission denied. -- The file should be accessible by nagios. */ printf("
A stat call returned a permissions error(%d) while looking for the file %s.
", errno, filename); return; case ENOENT: /* A component of the path file_name does not exist, or the path is an empty string. Just return if the file doesn't exist. */ return; default: return; } } fp=fopen(filename,"r"); if(fp==NULL) return; /* print all lines in the SSI file */ while(fgets(buffer,(int)(sizeof(buffer)-1),fp)!=NULL) printf("%s",buffer); fclose(fp); return; } /* displays an error if CGI config file could not be read */ void cgi_config_file_error(char *config_file){ printf("

Whoops!

\n"); printf("

Error: Could not open CGI config file '%s' for reading!

\n",config_file); printf("

\n"); printf("Here are some things you should check in order to resolve this error:\n"); printf("

\n"); printf("

\n"); printf("

    \n"); printf("
  1. Make sure you've installed a CGI config file in its proper location. See the error message about for details on where the CGI is expecting to find the configuration file. A sample CGI configuration file (named cgi.cfg) can be found in the sample-config/ subdirectory of the Nagios source code distribution.\n"); printf("
  2. Make sure the user your web server is running as has permission to read the CGI config file.\n"); printf("
\n"); printf("

\n"); printf("

\n"); printf("Make sure you read the documentation on installing and configuring Nagios thoroughly before continuing. If all else fails, try sending a message to one of the mailing lists. More information can be found at http://www.nagios.org.\n"); printf("

\n"); return; } /* displays an error if main config file could not be read */ void main_config_file_error(char *config_file){ printf("

Whoops!

\n"); printf("

Error: Could not open main config file '%s' for reading!

\n",config_file); printf("

\n"); printf("Here are some things you should check in order to resolve this error:\n"); printf("

\n"); printf("

\n"); printf("

    \n"); printf("
  1. Make sure you've installed a main config file in its proper location. See the error message about for details on where the CGI is expecting to find the configuration file. A sample main configuration file (named nagios.cfg) can be found in the sample-config/ subdirectory of the Nagios source code distribution.\n"); printf("
  2. Make sure the user your web server is running as has permission to read the main config file.\n"); printf("
\n"); printf("

\n"); printf("

\n"); printf("Make sure you read the documentation on installing and configuring Nagios thoroughly before continuing. If all else fails, try sending a message to one of the mailing lists. More information can be found at http://www.nagios.org.\n"); printf("

\n"); return; } /* displays an error if object data could not be read */ void object_data_error(void){ printf("

Whoops!

\n"); printf("

Error: Could not read object configuration data!

\n"); printf("

\n"); printf("Here are some things you should check in order to resolve this error:\n"); printf("

\n"); printf("

\n"); printf("

    \n"); printf("
  1. Verify configuration options using the -v command-line option to check for errors.\n"); printf("
  2. Check the Nagios log file for messages relating to startup or status data errors.\n"); printf("
  3. Make sure you've compiled the main program and the CGIs to use the same object data storage options (i.e. default text file or template-based file).\n"); printf("
\n"); printf("

\n"); printf("

\n"); printf("Make sure you read the documentation on installing, configuring and running Nagios thoroughly before continuing. If all else fails, try sending a message to one of the mailing lists. More information can be found at http://www.nagios.org.\n"); printf("

\n"); return; } /* displays an error if status data could not be read */ void status_data_error(void){ printf("

Whoops!

\n"); printf("

Error: Could not read host and service status information!

\n"); printf("

\n"); printf("The most common cause of this error message (especially for new users), is the fact that Nagios is not actually running. If Nagios is indeed not running, this is a normal error message. It simply indicates that the CGIs could not obtain the current status of hosts and services that are being monitored. If you've just installed things, make sure you read the documentation on starting Nagios.\n"); printf("

\n"); printf("

\n"); printf("Some other things you should check in order to resolve this error include:\n"); printf("

\n"); printf("

\n"); printf("

    \n"); printf("
  1. Check the Nagios log file for messages relating to startup or status data errors.\n"); printf("
  2. Always verify configuration options using the -v command-line option before starting or restarting Nagios!\n"); printf("
  3. Make sure you've compiled the main program and the CGIs to use the same status data storage options (i.e. text file or database). If the main program is storing status data in a text file and the CGIs are trying to read status data from a database, you'll have problems.\n"); printf("
\n"); printf("

\n"); printf("

\n"); printf("Make sure you read the documentation on installing, configuring and running Nagios thoroughly before continuing. If all else fails, try sending a message to one of the mailing lists. More information can be found at http://www.nagios.org.\n"); printf("

\n"); return; } /* displays context-sensitive help window */ void display_context_help(char *chid){ char *icon=CONTEXT_HELP_ICON1; if(show_context_help==FALSE) return; /* change icon if necessary */ if(!strcmp(chid,CONTEXTHELP_TAC)) icon=CONTEXT_HELP_ICON2; printf("Display context-sensitive help for this screen\n",url_context_help_path,chid,url_context_help_path,chid,url_images_path,icon); return; }