diff -urN ./plugins/check_hpjd.c ../plugins/plugins/check_hpjd.c --- ./plugins/check_hpjd.c 2005-01-05 21:53:13.000000000 +0100 +++ ../plugins/plugins/check_hpjd.c 2005-02-18 13:02:58.000000000 +0100 @@ -44,6 +44,7 @@ #define HPJD_GD_DOOR_OPEN ".1.3.6.1.4.1.11.2.3.9.1.1.2.17" #define HPJD_GD_PAPER_OUTPUT ".1.3.6.1.4.1.11.2.3.9.1.1.2.19" #define HPJD_GD_STATUS_DISPLAY ".1.3.6.1.4.1.11.2.3.9.1.1.3" +#define SNMP_VARS 12 #define ONLINE 0 #define OFFLINE 1 @@ -61,23 +62,30 @@ { char command_line[1024]; int result = STATE_UNKNOWN; - int line; + int line, val = 0; char input_buffer[MAX_INPUT_BUFFER]; char query_string[512]; char *errmsg; char *temp_buffer; int line_status = ONLINE; - int paper_status = 0; - int intervention_required = 0; - int peripheral_error = 0; - int paper_jam = 0; - int paper_out = 0; - int toner_low = 0; - int page_punt = 0; - int memory_out = 0; - int door_open = 0; - int paper_output = 0; - char display_message[MAX_INPUT_BUFFER]; + int errorflag = 0; /* bitflag error tracker */ + char *display_message; + char *errmsg_strings[11]; + int i; + + /* get the error messages. Will complain about discarded qualifiers + * with --disable-nls, but that doesn't matter since they're immutable */ + errmsg_strings[0] = _("Paper Jam"); + errmsg_strings[1] = _("Out of Paper"); + errmsg_strings[2] = _("Printer Offline"); + errmsg_strings[3] = _("Peripheral Error"); + errmsg_strings[4] = _("Intervention Required"); + errmsg_strings[5] = _("Toner Low"); + errmsg_strings[6] = _("Insufficient Memory"); + errmsg_strings[7] = _("A Door is Open"); + errmsg_strings[8] = _("Output Tray is Full"); + errmsg_strings[9] = _("Data too Slow for Engine"); + errmsg_strings[10] = _("Unknown Paper Error"); errmsg = malloc(MAX_INPUT_BUFFER); @@ -90,9 +98,12 @@ /* removed ' 2>1' at end of command 10/27/1999 - EG */ /* create the query string */ + /* get status display line first, so we can match line status against + * powersave as we parse it */ sprintf (query_string, "%s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0", + HPJD_GD_STATUS_DISPLAY, HPJD_LINE_STATUS, HPJD_PAPER_STATUS, HPJD_INTERVENTION_REQUIRED, @@ -102,11 +113,11 @@ HPJD_GD_TONER_LOW, HPJD_GD_PAGE_PUNT, HPJD_GD_MEMORY_OUT, - HPJD_GD_DOOR_OPEN, HPJD_GD_PAPER_OUTPUT, HPJD_GD_STATUS_DISPLAY); + HPJD_GD_DOOR_OPEN, HPJD_GD_PAPER_OUTPUT); /* get the command to run */ - sprintf (command_line, "%s -OQa -m : -v 1 -c %s %s %s", PATH_TO_SNMPGET, community, - address, query_string); + sprintf (command_line, "%s -Oqa -m : -v 1 -c %s %s %s", PATH_TO_SNMPGET, community, + address, query_string); /* run the command */ child_process = spopen (command_line); @@ -117,170 +128,98 @@ child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r"); if (child_stderr == NULL) { - printf (_("Could not open stderr for %s\n"), command_line); + /* don't print newline here, or we might return OK while + * only printing an error message (highly confusing) */ + printf (_("Could not open stderr for %s :: "), command_line); } result = STATE_OK; line = 0; + /* end parsing when we have display_message, since we won't know + * what to do with line 13 or more anyway */ while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) { + /* strip the newline character from the end of the input, if any */ + temp_buffer = strrchr(input_buffer, '\n'); + if(temp_buffer) *temp_buffer = '\0'; + + if(line == 0) { + display_message = strdup(input_buffer); + continue; + } + val = (int)strtol(input_buffer, NULL, 0); + if(!val) continue; /* no errors here, so don't handle it */ + errorflag |= 1 << (line - 1); /* set the error flag */ + + /* this switch statement is largely for adding additional + * exception handling (POWERSAVE and such) */ + switch (line) { + case 1: /* line status */ + /* clear the flag if it's powersaving */ + if(!strstr("POWERSAVE ON", display_message) != 0) + errorflag ^= 1 << (line - 1); + break; - /* strip the newline character from the end of the input */ - if (input_buffer[strlen (input_buffer) - 1] == '\n') - input_buffer[strlen (input_buffer) - 1] = 0; - - line++; - - temp_buffer = strtok (input_buffer, "="); - temp_buffer = strtok (NULL, "="); - - if (temp_buffer == NULL) { - - result = STATE_UNKNOWN; - strcpy (errmsg, input_buffer); - - } else { - - switch (line) { - - case 1: /* 1st line should contain the line status */ - line_status = atoi (temp_buffer); - break; - case 2: /* 2nd line should contain the paper status */ - paper_status = atoi (temp_buffer); - break; - case 3: /* 3rd line should be intervention required */ - intervention_required = atoi (temp_buffer); - break; - case 4: /* 4th line should be peripheral error */ - peripheral_error = atoi (temp_buffer); - break; - case 5: /* 5th line should contain the paper jam status */ - paper_jam = atoi (temp_buffer); - break; - case 6: /* 6th line should contain the paper out status */ - paper_out = atoi (temp_buffer); - break; - case 7: /* 7th line should contain the toner low status */ - toner_low = atoi (temp_buffer); - break; - case 8: /* did data come too slow for engine */ - page_punt = atoi (temp_buffer); - break; - case 9: /* did we run out of memory */ - memory_out = atoi (temp_buffer); - break; - case 10: /* is there a door open */ - door_open = atoi (temp_buffer); - break; - case 11: /* is output tray full */ - paper_output = atoi (temp_buffer); - break; - case 12: /* display panel message */ - strcpy (display_message, temp_buffer + 1); - break; - default: - break; - } - + case 2: /* paper status */ + case 3: /* intervention required */ + case 4: /* peripheral error */ + case 5: /* paper jam */ + case 6: /* paper out */ + case 7: /* toner low */ + case 8: /* data came too slow for engine */ + case 9: /* out of memory */ + case 10: /* is there a door open */ + case 11: /* is output tray full */ + default: /* notreached */ + break; } - /* break out of the read loop if we encounter an error */ - if (result != STATE_OK) + if(++line >= SNMP_VARS) break; } - /* WARNING if output found on stderr */ - if (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) { + /* WARNING if output found on stderr, but only if we + * haven't already found an error condition */ + if (!errorflag && fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) { result = max_state (result, STATE_WARNING); /* remove CRLF */ if (input_buffer[strlen (input_buffer) - 1] == '\n') input_buffer[strlen (input_buffer) - 1] = 0; - sprintf (errmsg, "%s", input_buffer ); - + strncpy(errmsg, input_buffer, sizeof(errmsg)); } - + /* close stderr */ (void) fclose (child_stderr); - /* close the pipe */ + /* close the pipe. set warning at least if snmpget didn't return 0 */ if (spclose (child_process)) - result = max_state (result, STATE_WARNING); + result = STATE_WARNING; /* if there wasn't any output, display an error */ if (line == 0) { - - /* might not be the problem, but most likely is. */ - result = STATE_UNKNOWN ; - asprintf (&errmsg, "%s : Timeout from host %s\n", errmsg, address ); - - } - - /* if we had no read errors, check the printer status results... */ - if (result == STATE_OK) { - - if (paper_jam) { - result = STATE_WARNING; - strcpy (errmsg, _("Paper Jam")); - } - else if (paper_out) { - result = STATE_WARNING; - strcpy (errmsg, _("Out of Paper")); - } - else if (line_status == OFFLINE) { - if (strcmp (errmsg, "POWERSAVE ON") != 0) { - result = STATE_WARNING; - strcpy (errmsg, _("Printer Offline")); - } - } - else if (peripheral_error) { - result = STATE_WARNING; - strcpy (errmsg, _("Peripheral Error")); - } - else if (intervention_required) { - result = STATE_WARNING; - strcpy (errmsg, _("Intervention Required")); - } - else if (toner_low) { - result = STATE_WARNING; - strcpy (errmsg, _("Toner Low")); - } - else if (memory_out) { - result = STATE_WARNING; - strcpy (errmsg, _("Insufficient Memory")); - } - else if (door_open) { - result = STATE_WARNING; - strcpy (errmsg, _("A Door is Open")); - } - else if (paper_output) { - result = STATE_WARNING; - strcpy (errmsg, _("Output Tray is Full")); - } - else if (page_punt) { - result = STATE_WARNING; - strcpy (errmsg, _("Data too Slow for Engine")); - } - else if (paper_status) { - result = STATE_WARNING; - strcpy (errmsg, _("Unknown Paper Error")); - } + /* timeout is not necessarily the problem, and produces wildly + * inaccurate error messages when it isn't, so just say + * the host didn't return anything and return immediately + * (old plugin unconditionally escalated STATE_UNKNOWN to + * STATE_CRITICAL at the end, so this just saves a bit of + * indentation. */ + printf (_("%s : No data returned from %s\n"), errmsg, address ); + return STATE_CRITICAL; } - if (result == STATE_OK) + /* obviously no read errors, so check the printer status results... */ + if (!errors) { + result = STATE_OK; printf (_("Printer ok - (%s)\n"), display_message); - - else if (result == STATE_UNKNOWN) { - - printf ("%s\n", errmsg); - - /* if printer could not be reached, escalate to critical */ - if (strstr (errmsg, "Timeout")) - result = STATE_CRITICAL; } - - else if (result == STATE_WARNING) - printf ("%s (%s)\n", errmsg, display_message); + else { + /* some error occured, so print them all */ + while(i < SNMP_VARS) { + printf ("%s (%s)\n", errmsg ? errmsg : "", display_message); + if((errorflag >> i) & 1) /* only print if flag is set */ + printf(":: %s", errmsg_strings[i++]); + } + } return result; } @@ -346,12 +285,12 @@ usage2 (_("Invalid hostname/address"), argv[c]); } } - + if (community == NULL) { if (argv[c] != NULL ) community = argv[c]; else - community = strdup (DEFAULT_COMMUNITY); + community = DEFAULT_COMMUNITY; } return validate_arguments ();