diff options
Diffstat (limited to 'plugins/check_hpjd.c')
-rw-r--r-- | plugins/check_hpjd.c | 571 |
1 files changed, 571 insertions, 0 deletions
diff --git a/plugins/check_hpjd.c b/plugins/check_hpjd.c new file mode 100644 index 00000000..8234abdf --- /dev/null +++ b/plugins/check_hpjd.c | |||
@@ -0,0 +1,571 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * CHECK_HPJD.C | ||
4 | * | ||
5 | * Program: HP printer plugin for Nagios | ||
6 | * License: GPL | ||
7 | * Copyright (c) 1999 Ethan Galstad (nagios@nagios.org) | ||
8 | * | ||
9 | * Last Modified: $Date$ | ||
10 | * | ||
11 | * Command line: CHECK_HPJD <ip_address> [community] | ||
12 | * | ||
13 | * Description: | ||
14 | * | ||
15 | * This plugin will attempt to check the status of an HP printer. The | ||
16 | * printer must have a JetDirect card installed and TCP/IP protocol | ||
17 | * stack enabled. This plugin has only been tested on a few printers | ||
18 | * and may not work well on all models of JetDirect cards. Multiple | ||
19 | * port JetDirect devices must have an IP address assigned to each | ||
20 | * port in order to be monitored. | ||
21 | * | ||
22 | * Dependencies: | ||
23 | * | ||
24 | * This plugin used the 'snmpget' command included with the UCD-SNMP | ||
25 | * package. If you don't have the package installed you will need to | ||
26 | * download it from http://ucd-snmp.ucdavis.edu before you can use | ||
27 | * this plugin. | ||
28 | * | ||
29 | * Return Values: | ||
30 | * | ||
31 | * UNKNOWN = The plugin could not read/process the output from the printer | ||
32 | * OK = Printer looks normal | ||
33 | * WARNING = Low toner, paper jam, intervention required, paper out, etc. | ||
34 | * CRITICAL = The printer could not be reached (it's probably turned off) | ||
35 | * | ||
36 | * Acknowledgements: | ||
37 | * | ||
38 | * The idea for the plugin (as well as some code) were taken from Jim | ||
39 | * Trocki's pinter alert script in his "mon" utility, found at | ||
40 | * http://www.kernel.org/software/mon | ||
41 | * | ||
42 | * Notes: | ||
43 | * 'JetDirect' is copyrighted by Hewlett-Packard. | ||
44 | * HP, please don't sue me... :-) | ||
45 | * | ||
46 | * License Information: | ||
47 | * | ||
48 | * This program is free software; you can redistribute it and/or modify | ||
49 | * it under the terms of the GNU General Public License as published by | ||
50 | * the Free Software Foundation; either version 2 of the License, or | ||
51 | * (at your option) any later version. | ||
52 | * | ||
53 | * This program is distributed in the hope that it will be useful, | ||
54 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
55 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
56 | * GNU General Public License for more details. | ||
57 | * | ||
58 | * You should have received a copy of the GNU General Public License | ||
59 | * along with this program; if not, write to the Free Software | ||
60 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
61 | * | ||
62 | *****************************************************************************/ | ||
63 | |||
64 | #include "common.h" | ||
65 | #include "popen.h" | ||
66 | #include "utils.h" | ||
67 | |||
68 | #define PROGNAME "check_hpjd" | ||
69 | |||
70 | #define HPJD_LINE_STATUS ".1.3.6.1.4.1.11.2.3.9.1.1.2.1" | ||
71 | #define HPJD_PAPER_STATUS ".1.3.6.1.4.1.11.2.3.9.1.1.2.2" | ||
72 | #define HPJD_INTERVENTION_REQUIRED ".1.3.6.1.4.1.11.2.3.9.1.1.2.3" | ||
73 | #define HPJD_GD_PERIPHERAL_ERROR ".1.3.6.1.4.1.11.2.3.9.1.1.2.6" | ||
74 | #define HPJD_GD_PAPER_JAM ".1.3.6.1.4.1.11.2.3.9.1.1.2.8" | ||
75 | #define HPJD_GD_PAPER_OUT ".1.3.6.1.4.1.11.2.3.9.1.1.2.9" | ||
76 | #define HPJD_GD_TONER_LOW ".1.3.6.1.4.1.11.2.3.9.1.1.2.10" | ||
77 | #define HPJD_GD_PAGE_PUNT ".1.3.6.1.4.1.11.2.3.9.1.1.2.11" | ||
78 | #define HPJD_GD_MEMORY_OUT ".1.3.6.1.4.1.11.2.3.9.1.1.2.12" | ||
79 | #define HPJD_GD_DOOR_OPEN ".1.3.6.1.4.1.11.2.3.9.1.1.2.17" | ||
80 | #define HPJD_GD_PAPER_OUTPUT ".1.3.6.1.4.1.11.2.3.9.1.1.2.19" | ||
81 | #define HPJD_GD_STATUS_DISPLAY ".1.3.6.1.4.1.11.2.3.9.1.1.3" | ||
82 | |||
83 | #define ONLINE 0 | ||
84 | #define OFFLINE 1 | ||
85 | |||
86 | int process_arguments (int, char **); | ||
87 | int call_getopt (int, char **); | ||
88 | int validate_arguments (void); | ||
89 | void print_help (void); | ||
90 | void print_usage (void); | ||
91 | |||
92 | char *community = NULL; | ||
93 | char *address = NULL; | ||
94 | |||
95 | int | ||
96 | main (int argc, char **argv) | ||
97 | { | ||
98 | char command_line[1024]; | ||
99 | int result; | ||
100 | int line; | ||
101 | char input_buffer[MAX_INPUT_BUFFER]; | ||
102 | char query_string[512]; | ||
103 | char error_message[MAX_INPUT_BUFFER]; | ||
104 | char *temp_buffer; | ||
105 | int line_status = ONLINE; | ||
106 | int paper_status = 0; | ||
107 | int intervention_required = 0; | ||
108 | int peripheral_error = 0; | ||
109 | int paper_jam = 0; | ||
110 | int paper_out = 0; | ||
111 | int toner_low = 0; | ||
112 | int page_punt = 0; | ||
113 | int memory_out = 0; | ||
114 | int door_open = 0; | ||
115 | int paper_output = 0; | ||
116 | char display_message[MAX_INPUT_BUFFER]; | ||
117 | |||
118 | if (process_arguments (argc, argv) != OK) | ||
119 | usage ("Invalid command arguments supplied\n"); | ||
120 | |||
121 | /* removed ' 2>1' at end of command 10/27/1999 - EG */ | ||
122 | /* create the query string */ | ||
123 | sprintf | ||
124 | (query_string, | ||
125 | "%s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0", | ||
126 | HPJD_LINE_STATUS, | ||
127 | HPJD_PAPER_STATUS, | ||
128 | HPJD_INTERVENTION_REQUIRED, | ||
129 | HPJD_GD_PERIPHERAL_ERROR, | ||
130 | HPJD_GD_PAPER_JAM, | ||
131 | HPJD_GD_PAPER_OUT, | ||
132 | HPJD_GD_TONER_LOW, | ||
133 | HPJD_GD_PAGE_PUNT, | ||
134 | HPJD_GD_MEMORY_OUT, | ||
135 | HPJD_GD_DOOR_OPEN, HPJD_GD_PAPER_OUTPUT, HPJD_GD_STATUS_DISPLAY); | ||
136 | |||
137 | /* get the command to run */ | ||
138 | sprintf (command_line, "%s -v 1 %s %s %s", PATH_TO_SNMPGET, address, | ||
139 | community, query_string); | ||
140 | |||
141 | /* run the command */ | ||
142 | child_process = spopen (command_line); | ||
143 | if (child_process == NULL) { | ||
144 | printf ("Could not open pipe: %s\n", command_line); | ||
145 | return STATE_UNKNOWN; | ||
146 | } | ||
147 | |||
148 | child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r"); | ||
149 | if (child_stderr == NULL) { | ||
150 | printf ("Could not open stderr for %s\n", command_line); | ||
151 | } | ||
152 | |||
153 | result = STATE_OK; | ||
154 | |||
155 | line = 0; | ||
156 | while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) { | ||
157 | |||
158 | /* strip the newline character from the end of the input */ | ||
159 | if (input_buffer[strlen (input_buffer) - 1] == '\n') | ||
160 | input_buffer[strlen (input_buffer) - 1] = 0; | ||
161 | |||
162 | line++; | ||
163 | |||
164 | temp_buffer = strtok (input_buffer, "="); | ||
165 | temp_buffer = strtok (NULL, "="); | ||
166 | |||
167 | switch (line) { | ||
168 | |||
169 | case 1: /* 1st line should contain the line status */ | ||
170 | if (temp_buffer != NULL) | ||
171 | line_status = atoi (temp_buffer); | ||
172 | else { | ||
173 | result = STATE_UNKNOWN; | ||
174 | strcpy (error_message, input_buffer); | ||
175 | } | ||
176 | break; | ||
177 | |||
178 | case 2: /* 2nd line should contain the paper status */ | ||
179 | if (temp_buffer != NULL) | ||
180 | paper_status = atoi (temp_buffer); | ||
181 | else { | ||
182 | result = STATE_UNKNOWN; | ||
183 | strcpy (error_message, input_buffer); | ||
184 | } | ||
185 | break; | ||
186 | |||
187 | case 3: /* 3rd line should be intervention required */ | ||
188 | if (temp_buffer != NULL) | ||
189 | intervention_required = atoi (temp_buffer); | ||
190 | else { | ||
191 | result = STATE_UNKNOWN; | ||
192 | strcpy (error_message, input_buffer); | ||
193 | } | ||
194 | break; | ||
195 | |||
196 | case 4: /* 4th line should be peripheral error */ | ||
197 | if (temp_buffer != NULL) | ||
198 | peripheral_error = atoi (temp_buffer); | ||
199 | else { | ||
200 | result = STATE_UNKNOWN; | ||
201 | strcpy (error_message, input_buffer); | ||
202 | } | ||
203 | break; | ||
204 | |||
205 | case 5: /* 5th line should contain the paper jam status */ | ||
206 | if (temp_buffer != NULL) | ||
207 | paper_jam = atoi (temp_buffer); | ||
208 | else { | ||
209 | result = STATE_UNKNOWN; | ||
210 | strcpy (error_message, input_buffer); | ||
211 | } | ||
212 | break; | ||
213 | |||
214 | case 6: /* 6th line should contain the paper out status */ | ||
215 | if (temp_buffer != NULL) | ||
216 | paper_out = atoi (temp_buffer); | ||
217 | else { | ||
218 | result = STATE_UNKNOWN; | ||
219 | strcpy (error_message, input_buffer); | ||
220 | } | ||
221 | break; | ||
222 | |||
223 | case 7: /* 7th line should contain the toner low status */ | ||
224 | if (temp_buffer != NULL) | ||
225 | toner_low = atoi (temp_buffer); | ||
226 | else { | ||
227 | result = STATE_UNKNOWN; | ||
228 | strcpy (error_message, input_buffer); | ||
229 | } | ||
230 | break; | ||
231 | |||
232 | case 8: /* did data come too slow for engine */ | ||
233 | if (temp_buffer != NULL) | ||
234 | page_punt = atoi (temp_buffer); | ||
235 | else { | ||
236 | result = STATE_UNKNOWN; | ||
237 | strcpy (error_message, input_buffer); | ||
238 | } | ||
239 | break; | ||
240 | |||
241 | case 9: /* did we run out of memory */ | ||
242 | if (temp_buffer != NULL) | ||
243 | memory_out = atoi (temp_buffer); | ||
244 | else { | ||
245 | result = STATE_UNKNOWN; | ||
246 | strcpy (error_message, input_buffer); | ||
247 | } | ||
248 | break; | ||
249 | |||
250 | case 10: /* is there a door open */ | ||
251 | if (temp_buffer != NULL) | ||
252 | door_open = atoi (temp_buffer); | ||
253 | else { | ||
254 | result = STATE_UNKNOWN; | ||
255 | strcpy (error_message, input_buffer); | ||
256 | } | ||
257 | break; | ||
258 | |||
259 | case 11: /* is output tray full */ | ||
260 | if (temp_buffer != NULL) | ||
261 | paper_output = atoi (temp_buffer); | ||
262 | else { | ||
263 | result = STATE_UNKNOWN; | ||
264 | strcpy (error_message, input_buffer); | ||
265 | } | ||
266 | break; | ||
267 | |||
268 | case 12: /* display panel message */ | ||
269 | if (temp_buffer != NULL) | ||
270 | strcpy (display_message, temp_buffer + 1); | ||
271 | else { | ||
272 | result = STATE_UNKNOWN; | ||
273 | strcpy (error_message, input_buffer); | ||
274 | } | ||
275 | break; | ||
276 | |||
277 | default: | ||
278 | break; | ||
279 | } | ||
280 | |||
281 | /* break out of the read loop if we encounter an error */ | ||
282 | if (result != STATE_OK) | ||
283 | break; | ||
284 | } | ||
285 | |||
286 | /* WARNING if output found on stderr */ | ||
287 | if (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) | ||
288 | result = max (result, STATE_WARNING); | ||
289 | |||
290 | /* close stderr */ | ||
291 | (void) fclose (child_stderr); | ||
292 | |||
293 | /* close the pipe */ | ||
294 | if (spclose (child_process)) | ||
295 | result = max (result, STATE_WARNING); | ||
296 | |||
297 | /* if there wasn't any output, display an error */ | ||
298 | if (line == 0) { | ||
299 | |||
300 | /* | ||
301 | result=STATE_UNKNOWN; | ||
302 | strcpy(error_message,"Error: Could not read plugin output\n"); | ||
303 | */ | ||
304 | |||
305 | /* might not be the problem, but most likely is.. */ | ||
306 | result = STATE_UNKNOWN; | ||
307 | sprintf (error_message, "Timeout: No response from %s\n", address); | ||
308 | } | ||
309 | |||
310 | /* if we had no read errors, check the printer status results... */ | ||
311 | if (result == STATE_OK) { | ||
312 | |||
313 | if (paper_jam) { | ||
314 | result = STATE_WARNING; | ||
315 | strcpy (error_message, "Paper Jam"); | ||
316 | } | ||
317 | else if (paper_out) { | ||
318 | result = STATE_WARNING; | ||
319 | strcpy (error_message, "Out of Paper"); | ||
320 | } | ||
321 | else if (line_status == OFFLINE) { | ||
322 | if (strcmp (error_message, "POWERSAVE ON") != 0) { | ||
323 | result = STATE_WARNING; | ||
324 | strcpy (error_message, "Printer Offline"); | ||
325 | } | ||
326 | } | ||
327 | else if (peripheral_error) { | ||
328 | result = STATE_WARNING; | ||
329 | strcpy (error_message, "Peripheral Error"); | ||
330 | } | ||
331 | else if (intervention_required) { | ||
332 | result = STATE_WARNING; | ||
333 | strcpy (error_message, "Intervention Required"); | ||
334 | } | ||
335 | else if (toner_low) { | ||
336 | result = STATE_WARNING; | ||
337 | strcpy (error_message, "Toner Low"); | ||
338 | } | ||
339 | else if (memory_out) { | ||
340 | result = STATE_WARNING; | ||
341 | strcpy (error_message, "Insufficient Memory"); | ||
342 | } | ||
343 | else if (door_open) { | ||
344 | result = STATE_WARNING; | ||
345 | strcpy (error_message, "A Door is Open"); | ||
346 | } | ||
347 | else if (paper_output) { | ||
348 | result = STATE_WARNING; | ||
349 | strcpy (error_message, "Output Tray is Full"); | ||
350 | } | ||
351 | else if (page_punt) { | ||
352 | result = STATE_WARNING; | ||
353 | strcpy (error_message, "Data too Slow for Engine"); | ||
354 | } | ||
355 | else if (paper_status) { | ||
356 | result = STATE_WARNING; | ||
357 | strcpy (error_message, "Unknown Paper Error"); | ||
358 | } | ||
359 | } | ||
360 | |||
361 | if (result == STATE_OK) | ||
362 | printf ("Printer ok - (%s)\n", display_message); | ||
363 | |||
364 | else if (result == STATE_UNKNOWN) { | ||
365 | |||
366 | printf ("%s\n", error_message); | ||
367 | |||
368 | /* if printer could not be reached, escalate to critical */ | ||
369 | if (strstr (error_message, "Timeout")) | ||
370 | result = STATE_CRITICAL; | ||
371 | } | ||
372 | |||
373 | else if (result == STATE_WARNING) | ||
374 | printf ("%s (%s)\n", error_message, display_message); | ||
375 | |||
376 | return result; | ||
377 | } | ||
378 | |||
379 | |||
380 | |||
381 | |||
382 | |||
383 | /* process command-line arguments */ | ||
384 | int | ||
385 | process_arguments (int argc, char **argv) | ||
386 | { | ||
387 | int c; | ||
388 | |||
389 | if (argc < 2) | ||
390 | return ERROR; | ||
391 | |||
392 | for (c = 1; c < argc; c++) { | ||
393 | if (strcmp ("-to", argv[c]) == 0) | ||
394 | strcpy (argv[c], "-t"); | ||
395 | else if (strcmp ("-wt", argv[c]) == 0) | ||
396 | strcpy (argv[c], "-w"); | ||
397 | else if (strcmp ("-ct", argv[c]) == 0) | ||
398 | strcpy (argv[c], "-c"); | ||
399 | } | ||
400 | |||
401 | |||
402 | |||
403 | c = 0; | ||
404 | while ((c += (call_getopt (argc - c, &argv[c]))) < argc) { | ||
405 | |||
406 | if (is_option (argv[c])) | ||
407 | continue; | ||
408 | |||
409 | if (address == NULL) { | ||
410 | if (is_host (argv[c])) { | ||
411 | address = argv[c]; | ||
412 | } | ||
413 | else { | ||
414 | usage ("Invalid host name"); | ||
415 | } | ||
416 | } | ||
417 | else if (community == NULL) { | ||
418 | community = argv[c]; | ||
419 | } | ||
420 | } | ||
421 | |||
422 | if (address == NULL) | ||
423 | address = strscpy (NULL, "127.0.0.1"); | ||
424 | |||
425 | return validate_arguments (); | ||
426 | } | ||
427 | |||
428 | |||
429 | |||
430 | |||
431 | |||
432 | |||
433 | int | ||
434 | call_getopt (int argc, char **argv) | ||
435 | { | ||
436 | int c, i = 0; | ||
437 | |||
438 | #ifdef HAVE_GETOPT_H | ||
439 | int option_index = 0; | ||
440 | static struct option long_options[] = { | ||
441 | {"hostname", required_argument, 0, 'H'}, | ||
442 | {"expect", required_argument, 0, 'e'}, | ||
443 | /* {"critical", required_argument,0,'c'}, */ | ||
444 | /* {"warning", required_argument,0,'w'}, */ | ||
445 | /* {"port", required_argument,0,'P'}, */ | ||
446 | {"verbose", no_argument, 0, 'v'}, | ||
447 | {"version", no_argument, 0, 'V'}, | ||
448 | {"help", no_argument, 0, 'h'}, | ||
449 | {0, 0, 0, 0} | ||
450 | }; | ||
451 | #endif | ||
452 | |||
453 | while (1) { | ||
454 | #ifdef HAVE_GETOPT_H | ||
455 | c = getopt_long (argc, argv, "+hVH:C:", long_options, &option_index); | ||
456 | #else | ||
457 | c = getopt (argc, argv, "+?hVH:C:"); | ||
458 | #endif | ||
459 | |||
460 | i++; | ||
461 | |||
462 | if (c == -1 || c == EOF || c == 1) | ||
463 | break; | ||
464 | |||
465 | switch (c) { | ||
466 | case 'H': | ||
467 | case 'C': | ||
468 | i++; | ||
469 | } | ||
470 | |||
471 | switch (c) { | ||
472 | case 'H': /* hostname */ | ||
473 | if (is_host (optarg)) { | ||
474 | address = optarg; | ||
475 | } | ||
476 | else { | ||
477 | usage ("Invalid host name\n"); | ||
478 | } | ||
479 | break; | ||
480 | case 'C': /* community */ | ||
481 | community = optarg; | ||
482 | break; | ||
483 | case 'V': /* version */ | ||
484 | print_revision (PROGNAME, "$Revision$"); | ||
485 | exit (STATE_OK); | ||
486 | case 'h': /* help */ | ||
487 | print_help (); | ||
488 | exit (STATE_OK); | ||
489 | case '?': /* help */ | ||
490 | usage ("Invalid argument\n"); | ||
491 | } | ||
492 | } | ||
493 | return i; | ||
494 | } | ||
495 | |||
496 | |||
497 | |||
498 | |||
499 | |||
500 | int | ||
501 | validate_arguments (void) | ||
502 | { | ||
503 | return OK; | ||
504 | } | ||
505 | |||
506 | |||
507 | |||
508 | |||
509 | |||
510 | void | ||
511 | print_help (void) | ||
512 | { | ||
513 | print_revision (PROGNAME, "$Revision$"); | ||
514 | printf | ||
515 | ("Copyright (c) 2000 Ethan Galstad/Karl DeBisschop\n\n" | ||
516 | "This plugin tests the STATUS of an HP printer with a JetDirect card.\n" | ||
517 | "Ucd-snmp must be installed on the computer running the plugin.\n\n"); | ||
518 | print_usage (); | ||
519 | printf | ||
520 | ("\nOptions:\n" | ||
521 | " -H, --hostname=STRING or IPADDRESS\n" | ||
522 | " Check server on the indicated host\n" | ||
523 | " -C, --community=STRING\n" | ||
524 | " The SNMP community name\n" | ||
525 | " -h, --help\n" | ||
526 | " Print detailed help screen\n" | ||
527 | " -V, --version\n" " Print version information\n\n"); | ||
528 | support (); | ||
529 | } | ||
530 | |||
531 | |||
532 | |||
533 | |||
534 | |||
535 | void | ||
536 | print_usage (void) | ||
537 | { | ||
538 | printf | ||
539 | ("Usage: %s -H host [-C community]\n" | ||
540 | " %s --help\n" | ||
541 | " %s --version\n", PROGNAME, PROGNAME, PROGNAME); | ||
542 | } | ||
543 | |||
544 | |||
545 | /* | ||
546 | if(argc<2||argc>3){ | ||
547 | printf("Incorrect number of arguments supplied\n"); | ||
548 | printf("\n"); | ||
549 | print_revision(argv[0],"$Revision$"); | ||
550 | printf("Copyright (c) 1999 Ethan Galstad (nagios@nagios.org)\n"); | ||
551 | printf("License: GPL\n"); | ||
552 | printf("\n"); | ||
553 | printf("Usage: %s <ip_address> [community]\n",argv[0]); | ||
554 | printf("\n"); | ||
555 | printf("Note:\n"); | ||
556 | printf(" <ip_address> = The IP address of the JetDirect card\n"); | ||
557 | printf(" [community] = An optional community string used for SNMP communication\n"); | ||
558 | printf(" with the JetDirect card. The default is 'public'.\n"); | ||
559 | printf("\n"); | ||
560 | return STATE_UNKNOWN; | ||
561 | } | ||
562 | |||
563 | // get the IP address of the JetDirect device | ||
564 | strcpy(address,argv[1]); | ||
565 | |||
566 | // get the community name to use for SNMP communication | ||
567 | if(argc>=3) | ||
568 | strcpy(community,argv[2]); | ||
569 | else | ||
570 | strcpy(community,"public"); | ||
571 | */ | ||