277 lines
6.5 KiB
C
277 lines
6.5 KiB
C
#include "config.h"
|
|
#include "common.h"
|
|
#include "locations.h"
|
|
#include "cgiutils.h"
|
|
#include "getcgi.h"
|
|
#ifdef HAVE_GETOPT_H
|
|
#include <getopt.h>
|
|
#endif
|
|
#include <stdarg.h>
|
|
|
|
#define CHARLEN 256
|
|
#define max(a,b) ((a)>(b))?(a):(b)
|
|
|
|
static void document_header(void);
|
|
//static void document_footer(void);
|
|
static int process_cgivars(void);
|
|
|
|
static char *strscpy(char *dest, const char *src);
|
|
static char *ssprintf(char *str, const char *fmt, ...);
|
|
static void terminate(int result, const char *fmt, ...);
|
|
static void get_expire_time_string(time_t *raw_time, char *buffer, int buffer_length);
|
|
|
|
int main(int argc, char **argv) {
|
|
FILE *fp;
|
|
char *status_file = NULL;
|
|
char *lock_file = NULL;
|
|
char *proc_file = NULL;
|
|
char input_buffer[CHARLEN];
|
|
int c, age, pid, testpid, found;
|
|
int wt = -1;
|
|
int ct = -1;
|
|
struct stat statbuf;
|
|
time_t current_time;
|
|
|
|
#ifdef DEFAULT_STATUS_FILE
|
|
status_file = strscpy(status_file, DEFAULT_STATUS_FILE);
|
|
#else
|
|
status_file = strscpy(status_file, "/var/log/nagios/status.log");
|
|
#endif
|
|
|
|
#ifdef DEFAULT_LOCK_FILE
|
|
lock_file = strscpy(lock_file, DEFAULT_LOCK_FILE);
|
|
#else
|
|
lock_file = strscpy(lock_file, "/tmp/nagios.lock");
|
|
#endif
|
|
|
|
if(getenv("REQUEST_METHOD")) {
|
|
process_cgivars();
|
|
document_header();
|
|
}
|
|
else { /* get arguments */
|
|
while((c = getopt(argc, argv, "+c:w:s:l:")) != EOF) {
|
|
switch(c) {
|
|
case 'c':
|
|
ct = atoi(optarg);
|
|
break;
|
|
case 'w':
|
|
wt = atoi(optarg);
|
|
break;
|
|
case 's':
|
|
status_file = optarg;
|
|
break;
|
|
case 'l':
|
|
lock_file = optarg;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* find status file, get lastmod time */
|
|
if(stat(status_file, &statbuf) == -1) {
|
|
printf("NAGIOS CRITICAL - could not find status log: %s\n", status_file);
|
|
exit(STATE_CRITICAL);
|
|
}
|
|
time(¤t_time);
|
|
age = (int)(current_time - statbuf.st_mtime);
|
|
|
|
/* find lock file. get pid if it exists */
|
|
if(stat(lock_file, &statbuf) == -1) {
|
|
printf("NAGIOS CRITICAL - could not find lock file: %s\n", lock_file);
|
|
exit(STATE_CRITICAL);
|
|
}
|
|
fp = fopen(lock_file, "r");
|
|
fscanf(fp, "%d", &pid);
|
|
fclose(fp);
|
|
proc_file = ssprintf(proc_file, "/proc/%d", pid);
|
|
|
|
if(stat("/proc", &statbuf) == 0) {
|
|
if(stat(proc_file, &statbuf) == -1) {
|
|
printf("NAGIOS CRITICAL - could not find proc file: %s\n", proc_file);
|
|
exit(STATE_CRITICAL);
|
|
}
|
|
}
|
|
else if(snprintf(proc_file, CHARLEN - 1, "/bin/ps -o pid -p %d", pid) &&
|
|
(fp = popen(proc_file, "r")) != NULL) {
|
|
fgets(input_buffer, CHARLEN - 1, fp);
|
|
fgets(input_buffer, CHARLEN - 1, fp);
|
|
if(sscanf(input_buffer, "%d", &testpid) == 1) {
|
|
if(testpid != pid) {
|
|
printf("NAGIOS CRITICAL - could not find process(1): %d\n", pid);
|
|
exit(STATE_CRITICAL);
|
|
}
|
|
}
|
|
}
|
|
else if(snprintf(proc_file, CHARLEN - 1, "/bin/ps -eo pid") &&
|
|
(fp = popen(proc_file, "r")) != NULL) {
|
|
found = FALSE;
|
|
fgets(input_buffer, CHARLEN - 1, fp);
|
|
while(fgets(input_buffer, CHARLEN - 1, fp)) {
|
|
if(sscanf(input_buffer, "%d", &testpid) == 1)
|
|
if(testpid == pid) found = TRUE;
|
|
}
|
|
if(!found) {
|
|
printf("NAGIOS CRITICAL - could not find process(2): %d\n", pid);
|
|
exit(STATE_CRITICAL);
|
|
}
|
|
}
|
|
else if(snprintf(proc_file, CHARLEN - 1, "/bin/ps -Ao pid") &&
|
|
(fp = popen(proc_file, "r")) != NULL) {
|
|
found = FALSE;
|
|
fgets(input_buffer, CHARLEN - 1, fp);
|
|
while(fgets(input_buffer, CHARLEN - 1, fp)) {
|
|
if(sscanf(input_buffer, "%d", &testpid) == 1)
|
|
if(testpid == pid) found = TRUE;
|
|
}
|
|
if(!found) {
|
|
printf("NAGIOS CRITICAL - could not find process(2): %d\n", pid);
|
|
exit(STATE_CRITICAL);
|
|
}
|
|
}
|
|
|
|
if(ct > 0 && ct < age) {
|
|
printf("NAGIOS CRITICAL - status written %d seconds ago\n", age);
|
|
exit(STATE_CRITICAL);
|
|
}
|
|
else if(wt > 0 && wt < age) {
|
|
printf("NAGIOS WARNING - status written %d seconds ago\n", age);
|
|
exit(STATE_WARNING);
|
|
}
|
|
else {
|
|
printf("NAGIOS ok - status written %d seconds ago\n", age);
|
|
exit(STATE_OK);
|
|
}
|
|
|
|
}
|
|
|
|
static void document_header(void) {
|
|
char date_time[48];
|
|
time_t current_time;
|
|
|
|
printf("Cache-Control: no-store\nPragma: no-cache\n");
|
|
|
|
time(¤t_time);
|
|
get_expire_time_string(¤t_time, date_time, (int)sizeof(date_time));
|
|
printf("Last-Modified: %s\n", date_time);
|
|
printf("Expires: %s\n", date_time);
|
|
|
|
printf("Content-type: text/html\n\n");
|
|
|
|
printf("<html>\n<head>\n<title>Nagios Daemon Status</title>\n</head>\n");
|
|
printf("<body onunload=\"if (window.wnd && wnd.close) wnd.close(); return true;\">\n");
|
|
|
|
return;
|
|
}
|
|
|
|
static int process_cgivars(void) {
|
|
char **variables;
|
|
int error = FALSE;
|
|
int x;
|
|
|
|
variables = getcgivars();
|
|
|
|
for(x = 0; variables[x] != NULL; x++) {
|
|
|
|
/* do some basic length checking on the variable identifier to prevent buffer overflows */
|
|
if(strlen(variables[x]) >= MAX_INPUT_BUFFER - 1) {
|
|
continue;
|
|
}
|
|
}
|
|
return error;
|
|
}
|
|
|
|
/* get date/time string used in META tags for page expiration */
|
|
static void get_expire_time_string(time_t *raw_time, char *buffer, int buffer_length) {
|
|
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"};
|
|
|
|
if(raw_time == NULL)
|
|
time(&t);
|
|
else
|
|
t = *raw_time;
|
|
|
|
tm_ptr = gmtime(&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;
|
|
|
|
snprintf(buffer, buffer_length, "%s, %d %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;
|
|
}
|
|
|
|
static char *strscpy(char *dest, const char *src) {
|
|
int len;
|
|
|
|
if(src != NULL)
|
|
len = strlen(src) + 1;
|
|
else
|
|
return dest;
|
|
|
|
if(dest == NULL || strlen(dest) < len)
|
|
dest = realloc(dest, len);
|
|
if(dest == NULL)
|
|
terminate(STATE_UNKNOWN, "failed realloc in strscpy\n");
|
|
|
|
strncpy(dest, src, len);
|
|
|
|
return dest;
|
|
}
|
|
|
|
static char *ssprintf(char *str, const char *fmt, ...) {
|
|
va_list ap;
|
|
int nchars;
|
|
int size;
|
|
|
|
if(str == NULL)
|
|
str = malloc(CHARLEN);
|
|
if(str == NULL)
|
|
terminate(STATE_UNKNOWN, "malloc failed in ssprintf");
|
|
|
|
size = max(strlen(str), CHARLEN);
|
|
|
|
va_start(ap, fmt);
|
|
|
|
while(1) {
|
|
|
|
nchars = vsnprintf(str, size, fmt, ap);
|
|
|
|
if(nchars > -1)
|
|
if(nchars < size) {
|
|
va_end(ap);
|
|
return str;
|
|
}
|
|
else {
|
|
size = nchars + 1;
|
|
}
|
|
|
|
else
|
|
size *= 2;
|
|
|
|
str = realloc(str, nchars + 1);
|
|
|
|
if(str == NULL)
|
|
terminate(STATE_UNKNOWN, "realloc failed in ssprintf");
|
|
}
|
|
|
|
}
|
|
|
|
static void terminate(int result, const char *fmt, ...) {
|
|
va_list ap;
|
|
va_start(ap, fmt);
|
|
vprintf(fmt, ap);
|
|
va_end(ap);
|
|
exit(result);
|
|
}
|