1 #include "config.h"
2 #include "common.h"
3 #include "locations.h"
4 #include "cgiutils.h"
5 #include "getcgi.h"
6 #ifdef HAVE_GETOPT_H
7 #include <getopt.h>
8 #endif
9 #include <stdarg.h>
10 
11 #define CHARLEN 256
12 #define max(a,b) ((a)>(b))?(a):(b)
13 
14 static void document_header(void);
15 //static void document_footer(void);
16 static int process_cgivars(void);
17 
18 static char *strscpy(char *dest, const char *src);
19 static char *ssprintf(char *str, const char *fmt, ...);
20 static void terminate(int result, const char *fmt, ...);
21 static void get_expire_time_string(time_t *raw_time, char *buffer, int buffer_length);
22 
main(int argc,char ** argv)23 int main(int argc, char **argv) {
24 	FILE *fp;
25 	char *status_file = NULL;
26 	char *lock_file = NULL;
27 	char *proc_file = NULL;
28 	char input_buffer[CHARLEN];
29 	int c, age, pid, testpid, found;
30 	int wt = -1;
31 	int ct = -1;
32 	struct stat statbuf;
33 	time_t current_time;
34 
35 #ifdef DEFAULT_STATUS_FILE
36 	status_file = strscpy(status_file, DEFAULT_STATUS_FILE);
37 #else
38 	status_file = strscpy(status_file, "/var/log/nagios/status.log");
39 #endif
40 
41 #ifdef DEFAULT_LOCK_FILE
42 	lock_file = strscpy(lock_file, DEFAULT_LOCK_FILE);
43 #else
44 	lock_file = strscpy(lock_file, "/tmp/nagios.lock");
45 #endif
46 
47 	if(getenv("REQUEST_METHOD")) {
48 		process_cgivars();
49 		document_header();
50 		}
51 	else {   /* get arguments */
52 		while((c = getopt(argc, argv, "+c:w:s:l:")) != EOF) {
53 			switch(c) {
54 				case 'c':
55 					ct = atoi(optarg);
56 					break;
57 				case 'w':
58 					wt = atoi(optarg);
59 					break;
60 				case 's':
61 					status_file = optarg;
62 					break;
63 				case 'l':
64 					lock_file = optarg;
65 					break;
66 				}
67 			}
68 		}
69 
70 	/* find status file, get lastmod time */
71 	if(stat(status_file, &statbuf) == -1) {
72 		printf("NAGIOS CRITICAL - could not find status log: %s\n", status_file);
73 		exit(STATE_CRITICAL);
74 		}
75 	time(&current_time);
76 	age = (int)(current_time - statbuf.st_mtime);
77 
78 	/* find lock file.  get pid if it exists */
79 	if(stat(lock_file, &statbuf) == -1) {
80 		printf("NAGIOS CRITICAL - could not find lock file: %s\n", lock_file);
81 		exit(STATE_CRITICAL);
82 		}
83 	fp = fopen(lock_file, "r");
84 	fscanf(fp, "%d", &pid);
85 	fclose(fp);
86 	proc_file = ssprintf(proc_file, "/proc/%d", pid);
87 
88 	if(stat("/proc", &statbuf) == 0) {
89 		if(stat(proc_file, &statbuf) == -1) {
90 			printf("NAGIOS CRITICAL - could not find proc file: %s\n", proc_file);
91 			exit(STATE_CRITICAL);
92 			}
93 		}
94 	else if(snprintf(proc_file, CHARLEN - 1, "/bin/ps -o pid -p %d", pid) &&
95 	        (fp = popen(proc_file, "r")) != NULL) {
96 		fgets(input_buffer, CHARLEN - 1, fp);
97 		fgets(input_buffer, CHARLEN - 1, fp);
98 		if(sscanf(input_buffer, "%d", &testpid) == 1) {
99 			if(testpid != pid) {
100 				printf("NAGIOS CRITICAL - could not find process(1): %d\n", pid);
101 				exit(STATE_CRITICAL);
102 				}
103 			}
104 		}
105 	else if(snprintf(proc_file, CHARLEN - 1, "/bin/ps -eo pid") &&
106 	        (fp = popen(proc_file, "r")) != NULL) {
107 		found = FALSE;
108 		fgets(input_buffer, CHARLEN - 1, fp);
109 		while(fgets(input_buffer, CHARLEN - 1, fp)) {
110 			if(sscanf(input_buffer, "%d", &testpid) == 1)
111 				if(testpid == pid) found = TRUE;
112 			}
113 		if(!found) {
114 			printf("NAGIOS CRITICAL - could not find process(2): %d\n", pid);
115 			exit(STATE_CRITICAL);
116 			}
117 		}
118 	else if(snprintf(proc_file, CHARLEN - 1, "/bin/ps -Ao pid") &&
119 	        (fp = popen(proc_file, "r")) != NULL) {
120 		found = FALSE;
121 		fgets(input_buffer, CHARLEN - 1, fp);
122 		while(fgets(input_buffer, CHARLEN - 1, fp)) {
123 			if(sscanf(input_buffer, "%d", &testpid) == 1)
124 				if(testpid == pid) found = TRUE;
125 			}
126 		if(!found) {
127 			printf("NAGIOS CRITICAL - could not find process(2): %d\n", pid);
128 			exit(STATE_CRITICAL);
129 			}
130 		}
131 
132 	if(ct > 0 && ct < age) {
133 		printf("NAGIOS CRITICAL - status written %d seconds ago\n", age);
134 		exit(STATE_CRITICAL);
135 		}
136 	else if(wt > 0 && wt < age) {
137 		printf("NAGIOS WARNING - status written %d seconds ago\n", age);
138 		exit(STATE_WARNING);
139 		}
140 	else {
141 		printf("NAGIOS ok - status written %d seconds ago\n", age);
142 		exit(STATE_OK);
143 		}
144 
145 	}
146 
document_header(void)147 static void document_header(void) {
148 	char date_time[48];
149 	time_t current_time;
150 
151 	printf("Cache-Control: no-store\nPragma: no-cache\n");
152 
153 	time(&current_time);
154 	get_expire_time_string(&current_time, date_time, (int)sizeof(date_time));
155 	printf("Last-Modified: %s\n", date_time);
156 	printf("Expires: %s\n", date_time);
157 
158 	printf("Content-type: text/html\n\n");
159 
160 	printf("<html>\n<head>\n<title>Nagios Daemon Status</title>\n</head>\n");
161 	printf("<body onunload=\"if (window.wnd && wnd.close) wnd.close(); return true;\">\n");
162 
163 	return;
164 	}
165 
process_cgivars(void)166 static int process_cgivars(void) {
167 	char **variables;
168 	int error = FALSE;
169 	int x;
170 
171 	variables = getcgivars();
172 
173 	for(x = 0; variables[x] != NULL; x++) {
174 
175 		/* do some basic length checking on the variable identifier to prevent buffer overflows */
176 		if(strlen(variables[x]) >= MAX_INPUT_BUFFER - 1) {
177 			continue;
178 			}
179 		}
180 	return error;
181 	}
182 
183 /* get date/time string used in META tags for page expiration */
get_expire_time_string(time_t * raw_time,char * buffer,int buffer_length)184 static void get_expire_time_string(time_t *raw_time, char *buffer, int buffer_length) {
185 	time_t t;
186 	struct tm *tm_ptr;
187 	int day;
188 	int hour;
189 	int minute;
190 	int second;
191 	int year;
192 	char *weekdays[7] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
193 	char *months[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
194 
195 	if(raw_time == NULL)
196 		time(&t);
197 	else
198 		t = *raw_time;
199 
200 	tm_ptr = gmtime(&t);
201 
202 	hour = tm_ptr->tm_hour;
203 	minute = tm_ptr->tm_min;
204 	second = tm_ptr->tm_sec;
205 	day = tm_ptr->tm_mday;
206 	year = tm_ptr->tm_year + 1900;
207 
208 	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);
209 	buffer[buffer_length - 1] = '\x0';
210 
211 	return;
212 	}
213 
strscpy(char * dest,const char * src)214 static char *strscpy(char *dest, const char *src) {
215 	int len;
216 
217 	if(src != NULL)
218 		len = strlen(src) + 1;
219 	else
220 		return dest;
221 
222 	if(dest == NULL || strlen(dest) < len)
223 		dest = realloc(dest, len);
224 	if(dest == NULL)
225 		terminate(STATE_UNKNOWN, "failed realloc in strscpy\n");
226 
227 	strncpy(dest, src, len);
228 
229 	return dest;
230 	}
231 
ssprintf(char * str,const char * fmt,...)232 static char *ssprintf(char *str, const char *fmt, ...) {
233 	va_list ap;
234 	int nchars;
235 	int size;
236 
237 	if(str == NULL)
238 		str = malloc(CHARLEN);
239 	if(str == NULL)
240 		terminate(STATE_UNKNOWN, "malloc failed in ssprintf");
241 
242 	size = max(strlen(str), CHARLEN);
243 
244 	va_start(ap, fmt);
245 
246 	while(1) {
247 
248 		nchars = vsnprintf(str, size, fmt, ap);
249 
250 		if(nchars > -1)
251 			if(nchars < size) {
252 				va_end(ap);
253 				return str;
254 				}
255 			else {
256 				size = nchars + 1;
257 				}
258 
259 		else
260 			size *= 2;
261 
262 		str = realloc(str, nchars + 1);
263 
264 		if(str == NULL)
265 			terminate(STATE_UNKNOWN, "realloc failed in ssprintf");
266 		}
267 
268 	}
269 
terminate(int result,const char * fmt,...)270 static void terminate(int result, const char *fmt, ...) {
271 	va_list ap;
272 	va_start(ap, fmt);
273 	vprintf(fmt, ap);
274 	va_end(ap);
275 	exit(result);
276 	}
277