1 /*****************************************************************************
2 *
3 * Monitoring check_hpjd plugin
4 *
5 * License: GPL
6 * Copyright (c) 2000-2007 Monitoring Plugins Development Team
7 *
8 * Description:
9 *
10 * This file contains the check_hpjd plugin
11 *
12 * This plugin tests the STATUS of an HP printer with a JetDirect card.
13 * Net-SNMP must be installed on the computer running the plugin.
14 *
15 *
16 * This program is free software: you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation, either version 3 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
28 *
29 *
30 *****************************************************************************/
31 
32 const char *progname = "check_hpjd";
33 const char *copyright = "2000-2007";
34 const char *email = "devel@monitoring-plugins.org";
35 
36 #include "common.h"
37 #include "popen.h"
38 #include "utils.h"
39 #include "netutils.h"
40 
41 #define DEFAULT_COMMUNITY "public"
42 #define DEFAULT_PORT "161"
43 
44 const char *option_summary = "-H host [-C community]\n";
45 
46 #define HPJD_LINE_STATUS           ".1.3.6.1.4.1.11.2.3.9.1.1.2.1"
47 #define HPJD_PAPER_STATUS          ".1.3.6.1.4.1.11.2.3.9.1.1.2.2"
48 #define HPJD_INTERVENTION_REQUIRED ".1.3.6.1.4.1.11.2.3.9.1.1.2.3"
49 #define HPJD_GD_PERIPHERAL_ERROR   ".1.3.6.1.4.1.11.2.3.9.1.1.2.6"
50 #define HPJD_GD_PAPER_OUT          ".1.3.6.1.4.1.11.2.3.9.1.1.2.8"
51 #define HPJD_GD_PAPER_JAM          ".1.3.6.1.4.1.11.2.3.9.1.1.2.9"
52 #define HPJD_GD_TONER_LOW          ".1.3.6.1.4.1.11.2.3.9.1.1.2.10"
53 #define HPJD_GD_PAGE_PUNT          ".1.3.6.1.4.1.11.2.3.9.1.1.2.11"
54 #define HPJD_GD_MEMORY_OUT         ".1.3.6.1.4.1.11.2.3.9.1.1.2.12"
55 #define HPJD_GD_DOOR_OPEN          ".1.3.6.1.4.1.11.2.3.9.1.1.2.17"
56 #define HPJD_GD_PAPER_OUTPUT       ".1.3.6.1.4.1.11.2.3.9.1.1.2.19"
57 #define HPJD_GD_STATUS_DISPLAY     ".1.3.6.1.4.1.11.2.3.9.1.1.3"
58 
59 #define ONLINE		0
60 #define OFFLINE		1
61 
62 int process_arguments (int, char **);
63 int validate_arguments (void);
64 void print_help (void);
65 void print_usage (void);
66 
67 char *community = NULL;
68 char *address = NULL;
69 char *port = NULL;
70 int  check_paper_out = 1;
71 
72 int
main(int argc,char ** argv)73 main (int argc, char **argv)
74 {
75 	char command_line[1024];
76 	int result = STATE_UNKNOWN;
77 	int line;
78 	char input_buffer[MAX_INPUT_BUFFER];
79 	char query_string[512];
80 	char *errmsg;
81 	char *temp_buffer;
82 	int line_status = ONLINE;
83 	int paper_status = 0;
84 	int intervention_required = 0;
85 	int peripheral_error = 0;
86 	int paper_jam = 0;
87 	int paper_out = 0;
88 	int toner_low = 0;
89 	int page_punt = 0;
90 	int memory_out = 0;
91 	int door_open = 0;
92 	int paper_output = 0;
93 	char display_message[MAX_INPUT_BUFFER];
94 
95 	errmsg = malloc(MAX_INPUT_BUFFER);
96 
97 	setlocale (LC_ALL, "");
98 	bindtextdomain (PACKAGE, LOCALEDIR);
99 	textdomain (PACKAGE);
100 
101 	/* Parse extra opts if any */
102 	argv=np_extra_opts (&argc, argv, progname);
103 
104 	if (process_arguments (argc, argv) == ERROR)
105 		usage4 (_("Could not parse arguments"));
106 
107 	/* removed ' 2>1' at end of command 10/27/1999 - EG */
108 	/* create the query string */
109 	sprintf
110 		(query_string,
111 		 "%s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0",
112 		 HPJD_LINE_STATUS,
113 		 HPJD_PAPER_STATUS,
114 		 HPJD_INTERVENTION_REQUIRED,
115 		 HPJD_GD_PERIPHERAL_ERROR,
116 		 HPJD_GD_PAPER_JAM,
117 		 HPJD_GD_PAPER_OUT,
118 		 HPJD_GD_TONER_LOW,
119 		 HPJD_GD_PAGE_PUNT,
120 		 HPJD_GD_MEMORY_OUT,
121 		 HPJD_GD_DOOR_OPEN, HPJD_GD_PAPER_OUTPUT, HPJD_GD_STATUS_DISPLAY);
122 
123 	/* get the command to run */
124 	sprintf (command_line, "%s -OQa -m : -v 1 -c %s %s:%hd %s", PATH_TO_SNMPGET, community,
125 									address, port, query_string);
126 
127 	/* run the command */
128 	child_process = spopen (command_line);
129 	if (child_process == NULL) {
130 		printf (_("Could not open pipe: %s\n"), command_line);
131 		return STATE_UNKNOWN;
132 	}
133 
134 	child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
135 	if (child_stderr == NULL) {
136 		printf (_("Could not open stderr for %s\n"), command_line);
137 	}
138 
139 	result = STATE_OK;
140 
141 	line = 0;
142 	while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
143 
144 		/* strip the newline character from the end of the input */
145 		if (input_buffer[strlen (input_buffer) - 1] == '\n')
146 			input_buffer[strlen (input_buffer) - 1] = 0;
147 
148 		line++;
149 
150 		temp_buffer = strtok (input_buffer, "=");
151 		temp_buffer = strtok (NULL, "=");
152 
153 		if (temp_buffer == NULL && line < 13) {
154 
155 				result = STATE_UNKNOWN;
156 				strcpy (errmsg, input_buffer);
157 
158 		} else {
159 
160 			switch (line) {
161 
162 			case 1:										/* 1st line should contain the line status */
163 				line_status = atoi (temp_buffer);
164 				break;
165 			case 2:										/* 2nd line should contain the paper status */
166 				paper_status = atoi (temp_buffer);
167 				break;
168 			case 3:										/* 3rd line should be intervention required */
169 				intervention_required = atoi (temp_buffer);
170 				break;
171 			case 4:										/* 4th line should be peripheral error */
172 				peripheral_error = atoi (temp_buffer);
173 				break;
174 			case 5:										/* 5th line should contain the paper jam status */
175 				paper_jam = atoi (temp_buffer);
176 				break;
177 			case 6:										/* 6th line should contain the paper out status */
178 				paper_out = atoi (temp_buffer);
179 				break;
180 			case 7:										/* 7th line should contain the toner low status */
181 				toner_low = atoi (temp_buffer);
182 				break;
183 			case 8:										/* did data come too slow for engine */
184 				page_punt = atoi (temp_buffer);
185 				break;
186 			case 9:										/* did we run out of memory */
187 				memory_out = atoi (temp_buffer);
188 				break;
189 			case 10:										/* is there a door open */
190 				door_open = atoi (temp_buffer);
191 				break;
192 			case 11:										/* is output tray full */
193 				paper_output = atoi (temp_buffer);
194 				break;
195 			case 12:										/* display panel message */
196 				strcpy (display_message, temp_buffer + 1);
197 				break;
198 			default:										/* fold multiline message */
199 				strncat (display_message, input_buffer,
200 						sizeof (display_message) - strlen (display_message) - 1);
201 			}
202 
203 		}
204 
205 		/* break out of the read loop if we encounter an error */
206 		if (result != STATE_OK)
207 			break;
208 	}
209 
210 	/* WARNING if output found on stderr */
211 	if (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) {
212 		result = max_state (result, STATE_WARNING);
213 		/* remove CRLF */
214 		if (input_buffer[strlen (input_buffer) - 1] == '\n')
215 			input_buffer[strlen (input_buffer) - 1] = 0;
216 		sprintf (errmsg, "%s", input_buffer );
217 
218 	}
219 
220 	/* close stderr */
221 	(void) fclose (child_stderr);
222 
223 	/* close the pipe */
224 	if (spclose (child_process))
225 		result = max_state (result, STATE_WARNING);
226 
227 	/* if there wasn't any output, display an error */
228 	if (line == 0) {
229 
230 		/* might not be the problem, but most likely is. */
231 		result = STATE_UNKNOWN ;
232 		xasprintf (&errmsg, "%s : Timeout from host %s\n", errmsg, address );
233 
234 	}
235 
236 	/* if we had no read errors, check the printer status results... */
237 	if (result == STATE_OK) {
238 
239 		if (paper_jam) {
240 			result = STATE_WARNING;
241 			strcpy (errmsg, _("Paper Jam"));
242 		}
243 		else if (paper_out) {
244 			if (check_paper_out)
245 				result = STATE_WARNING;
246 			strcpy (errmsg, _("Out of Paper"));
247 		}
248 		else if (line_status == OFFLINE) {
249 			if (strcmp (errmsg, "POWERSAVE ON") != 0) {
250 				result = STATE_WARNING;
251 				strcpy (errmsg, _("Printer Offline"));
252 			}
253 		}
254 		else if (peripheral_error) {
255 			result = STATE_WARNING;
256 			strcpy (errmsg, _("Peripheral Error"));
257 		}
258 		else if (intervention_required) {
259 			result = STATE_WARNING;
260 			strcpy (errmsg, _("Intervention Required"));
261 		}
262 		else if (toner_low) {
263 			result = STATE_WARNING;
264 			strcpy (errmsg, _("Toner Low"));
265 		}
266 		else if (memory_out) {
267 			result = STATE_WARNING;
268 			strcpy (errmsg, _("Insufficient Memory"));
269 		}
270 		else if (door_open) {
271 			result = STATE_WARNING;
272 			strcpy (errmsg, _("A Door is Open"));
273 		}
274 		else if (paper_output) {
275 			result = STATE_WARNING;
276 			strcpy (errmsg, _("Output Tray is Full"));
277 		}
278 		else if (page_punt) {
279 			result = STATE_WARNING;
280 			strcpy (errmsg, _("Data too Slow for Engine"));
281 		}
282 		else if (paper_status) {
283 			result = STATE_WARNING;
284 			strcpy (errmsg, _("Unknown Paper Error"));
285 		}
286 	}
287 
288 	if (result == STATE_OK)
289 		printf (_("Printer ok - (%s)\n"), display_message);
290 
291 	else if (result == STATE_UNKNOWN) {
292 
293 		printf ("%s\n", errmsg);
294 
295 		/* if printer could not be reached, escalate to critical */
296 		if (strstr (errmsg, "Timeout"))
297 			result = STATE_CRITICAL;
298 	}
299 
300 	else if (result == STATE_WARNING)
301 		printf ("%s (%s)\n", errmsg, display_message);
302 
303 	return result;
304 }
305 
306 
307 /* process command-line arguments */
308 int
process_arguments(int argc,char ** argv)309 process_arguments (int argc, char **argv)
310 {
311 	int c;
312 
313 	int option = 0;
314 	static struct option longopts[] = {
315 		{"hostname", required_argument, 0, 'H'},
316 		{"community", required_argument, 0, 'C'},
317 /*  		{"critical",       required_argument,0,'c'}, */
318 /*  		{"warning",        required_argument,0,'w'}, */
319   		{"port", required_argument,0,'p'},
320 		{"version", no_argument, 0, 'V'},
321 		{"help", no_argument, 0, 'h'},
322 		{0, 0, 0, 0}
323 	};
324 
325 	if (argc < 2)
326 		return ERROR;
327 
328 
329 	while (1) {
330 		c = getopt_long (argc, argv, "+hVH:C:p:D", longopts, &option);
331 
332 		if (c == -1 || c == EOF || c == 1)
333 			break;
334 
335 		switch (c) {
336 		case 'H':									/* hostname */
337 			if (is_host (optarg)) {
338 				address = strscpy(address, optarg) ;
339 			}
340 			else {
341 				usage2 (_("Invalid hostname/address"), optarg);
342 			}
343 			break;
344 		case 'C':									/* community */
345 			community = strscpy (community, optarg);
346 			break;
347 		case 'p':
348 			if (!is_intpos(optarg))
349 				usage2 (_("Port must be a positive short integer"), optarg);
350 			else
351 				port = atoi(optarg);
352 		case 'D':									/* disable paper out check*/
353 			check_paper_out = 0;
354 			break;
355 		case 'V':									/* version */
356 			print_revision (progname, NP_VERSION);
357 			exit (STATE_UNKNOWN);
358 		case 'h':									/* help */
359 			print_help ();
360 			exit (STATE_UNKNOWN);
361 		case '?':									/* help */
362 			usage5 ();
363 		}
364 	}
365 
366 	c = optind;
367 	if (address == NULL) {
368 		if (is_host (argv[c])) {
369 			address = argv[c++];
370 		}
371 		else {
372 			usage2 (_("Invalid hostname/address"), argv[c]);
373 		}
374 	}
375 
376 	if (community == NULL) {
377 		if (argv[c] != NULL )
378 			community = argv[c];
379 		else
380 			community = strdup (DEFAULT_COMMUNITY);
381 	}
382 
383 	if (port == NULL) {
384 		if (argv[c] != NULL )
385 			port = argv[c];
386 		else
387 			port = atoi (DEFAULT_PORT);
388 	}
389 
390 	return validate_arguments ();
391 }
392 
393 
394 int
validate_arguments(void)395 validate_arguments (void)
396 {
397 	return OK;
398 }
399 
400 
401 void
print_help(void)402 print_help (void)
403 {
404 	print_revision (progname, NP_VERSION);
405 
406 	printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
407 	printf (COPYRIGHT, copyright, email);
408 
409 	printf ("%s\n", _("This plugin tests the STATUS of an HP printer with a JetDirect card."));
410 	printf ("%s\n", _("Net-snmp must be installed on the computer running the plugin."));
411 
412 	printf ("\n\n");
413 
414 	print_usage ();
415 
416 	printf (UT_HELP_VRSN);
417 	printf (UT_EXTRA_OPTS);
418 
419 	printf (" %s\n", "-C, --community=STRING");
420 	printf ("    %s", _("The SNMP community name "));
421 	printf (_("(default=%s)"), DEFAULT_COMMUNITY);
422 	printf ("\n");
423 	printf (" %s\n", "-p, --port=STRING");
424 	printf ("    %s", _("Specify the port to check "));
425 	printf (_("(default=%s)"), DEFAULT_PORT);
426 	printf ("\n");
427 	printf (" %s\n", "-D");
428 	printf ("    %s", _("Disable paper check "));
429 
430 	printf (UT_SUPPORT);
431 }
432 
433 
434 
435 void
print_usage(void)436 print_usage (void)
437 {
438   printf ("%s\n", _("Usage:"));
439 	printf ("%s -H host [-C community] [-p port] [-D]\n", progname);
440 }
441