Code

Add newline after "Usage:" in --help
[nagiosplug.git] / plugins / check_snmp.c
index bb3d295e0f31fe0a14b822a7ccfeaf5f72648d1e..2bc6024f42bab4ca06475ab69473f3d1fc64e729 100644 (file)
@@ -59,6 +59,25 @@ const char *email = "nagiosplug-devel@lists.sourceforge.net";
 
 #define MAX_OIDS 8
 
+/* Gobble to string - stop incrementing c when c[0] match one of the
+ * characters in s */
+#define GOBBLE_TOS(c, s) while(c[0]!='\0' && strchr(s, c[0])==NULL) { c++; }
+/* Given c, keep track of backslashes (bk) and double-quotes (dq)
+ * from c[0] */
+#define COUNT_SEQ(c, bk, dq) switch(c[0]) {\
+       case '\\': \
+               if (bk) bk--; \
+               else bk++; \
+               break; \
+       case '"': \
+               if (!dq) { dq++; } \
+               else if(!bk) { dq--; } \
+               else { bk--; } \
+               break; \
+       }
+
+
+
 int process_arguments (int, char **);
 int validate_arguments (void);
 char *thisarg (char *str);
@@ -117,7 +136,8 @@ int needmibs = FALSE;
 int
 main (int argc, char **argv)
 {
-       int i;
+       int i, len, line;
+       unsigned int bk_count = 0, dq_count = 0;
        int iresult = STATE_UNKNOWN;
        int result = STATE_UNKNOWN;
        int return_code = 0;
@@ -126,6 +146,7 @@ main (int argc, char **argv)
        char *cl_hidden_auth = NULL;
        char *oidname = NULL;
        char *response = NULL;
+       char *mult_resp = NULL;
        char *outbuff;
        char *ptr = NULL;
        char *show = NULL;
@@ -186,7 +207,7 @@ main (int argc, char **argv)
        }else{
                snmpcmd = strdup (PATH_TO_SNMPGET);
        }
-       
+
        /* 9 arguments to pass before authpriv options + 1 for host and numoids. Add one for terminating NULL */
        command_line = calloc (9 + numauthpriv + 1 + numoids + 1, sizeof (char *));
        command_line[0] = snmpcmd;
@@ -249,21 +270,23 @@ main (int argc, char **argv)
                }
        }
 
-       for (i = 0; i < chld_out.lines; i++) {
+       for (line=0, i=0; line < chld_out.lines; line++, i++) {
                const char *conv = "%.0f";
 
-               ptr = chld_out.line[i];
+               ptr = chld_out.line[line];
                oidname = strpcpy (oidname, ptr, delimiter);
                response = strstr (ptr, delimiter);
+               if (response == NULL)
+                       break;
+
                if (verbose > 2) {
-                       printf("Processing line %i\n  oidname: %s\n  response: %s\n", i+1, oidname, response);
+                       printf("Processing oid %i (line %i)\n  oidname: %s\n  response: %s\n", i+1, line+1, oidname, response);
                }
 
-               /* We strip out the datatype indicator for PHBs */
-
                /* Clean up type array - Sol10 does not necessarily zero it out */
                bzero(type, sizeof(type));
 
+               /* We strip out the datatype indicator for PHBs */
                if (strstr (response, "Gauge: "))
                        show = strstr (response, "Gauge: ") + 7;
                else if (strstr (response, "Gauge32: "))
@@ -281,6 +304,39 @@ main (int argc, char **argv)
                else if (strstr (response, "STRING: ")) {
                        show = strstr (response, "STRING: ") + 8;
                        conv = "%.10g";
+
+                       /* Get the rest of the string on multi-line strings */
+                       ptr = show;
+                       COUNT_SEQ(ptr, bk_count, dq_count)
+                       while (dq_count && ptr[0] != '\n' && ptr[0] != '\0') {
+                               ptr++;
+                               GOBBLE_TOS(ptr, "\n\"\\")
+                               COUNT_SEQ(ptr, bk_count, dq_count)
+                       }
+
+                       if (dq_count) { /* unfinished line */
+                               /* copy show verbatim first */
+                               if (!mult_resp) mult_resp = strdup("");
+                               asprintf (&mult_resp, "%s%s:\n%s\n", mult_resp, oids[i], show);
+                               /* then strip out unmatched double-quote from single-line output */
+                               if (show[0] == '"') show++;
+
+                               /* Keep reading until we match end of double-quoted string */
+                               for (line++; line < chld_out.lines; line++) {
+                                       ptr = chld_out.line[line];
+                                       asprintf (&mult_resp, "%s%s\n", mult_resp, ptr);
+
+                                       COUNT_SEQ(ptr, bk_count, dq_count)
+                                       while (dq_count && ptr[0] != '\n' && ptr[0] != '\0') {
+                                               ptr++;
+                                               GOBBLE_TOS(ptr, "\n\"\\")
+                                               COUNT_SEQ(ptr, bk_count, dq_count)
+                                       }
+                                       /* Break for loop before next line increment when done */
+                                       if (!dq_count) break;
+                               }
+                       }
+
                }
                else if (strstr (response, "Timeticks: "))
                        show = strstr (response, "Timeticks: ");
@@ -349,10 +405,14 @@ main (int argc, char **argv)
                if (nunits > (size_t)0 && (size_t)i < nunits && unitv[i] != NULL)
                        asprintf (&outbuff, "%s %s", outbuff, unitv[i]);
 
-               if (is_numeric(show)) {
+               /* Write perfdata with whatever can be parsed by strtod, if possible */
+               ptr = NULL;
+               strtod(show, &ptr);
+               if (ptr > show) {
                        strncat(perfstr, oidname, sizeof(perfstr)-strlen(perfstr)-1);
                        strncat(perfstr, "=", sizeof(perfstr)-strlen(perfstr)-1);
-                       strncat(perfstr, show, sizeof(perfstr)-strlen(perfstr)-1);
+                       len = sizeof(perfstr)-strlen(perfstr)-1;
+                       strncat(perfstr, show, len>ptr-show ? ptr-show : len);
 
                        if (type)
                                strncat(perfstr, type, sizeof(perfstr)-strlen(perfstr)-1);
@@ -360,7 +420,8 @@ main (int argc, char **argv)
                }
        }
 
-       printf ("%s %s -%s %s \n", label, state_text (result), outbuff, perfstr);
+       printf ("%s %s -%s %s\n", label, state_text (result), outbuff, perfstr);
+       if (mult_resp) printf ("%s", mult_resp);
 
        return result;
 }
@@ -504,7 +565,7 @@ process_arguments (int argc, char **argv)
                                         */
                                        needmibs = TRUE;
                        }
-                       oids = calloc(MAX_OIDS, sizeof (char *));
+                       if (!oids) oids = calloc(MAX_OIDS, sizeof (char *));
                        for (ptr = strtok(optarg, ", "); ptr != NULL && j < MAX_OIDS; ptr = strtok(NULL, ", "), j++) {
                                oids[j] = strdup(ptr);
                        }
@@ -800,10 +861,10 @@ print_help (void)
 
        print_usage ();
 
-       printf (_(UT_HELP_VRSN));
-       printf (_(UT_EXTRA_OPTS));
+       printf (UT_HELP_VRSN);
+       printf (UT_EXTRA_OPTS);
 
-       printf (_(UT_HOST_PORT), 'p', DEFAULT_PORT);
+       printf (UT_HOST_PORT, 'p', DEFAULT_PORT);
 
        /* SNMP and Authentication Protocol */
        printf (" %s\n", "-n, --next");
@@ -861,11 +922,11 @@ print_help (void)
        printf (" %s\n", "-D, --output-delimiter=STRING");
        printf ("    %s\n", _("Separates output on multiple OID requests"));
 
-       printf (_(UT_TIMEOUT), DEFAULT_SOCKET_TIMEOUT);
+       printf (UT_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
        printf (" %s\n", "-e, --retries=INTEGER");
        printf ("    %s\n", _("Number of retries to be used in the requests"));
 
-       printf (_(UT_VERBOSE));
+       printf (UT_VERBOSE);
 
        printf ("\n");
        printf ("%s\n", _("This plugin uses the 'snmpget' command included with the NET-SNMP package."));
@@ -877,17 +938,14 @@ print_help (void)
        printf (" %s\n", _("- Multiple OIDs may be indicated by a comma- or space-delimited list (lists with"));
        printf ("   %s\n", _("internal spaces must be quoted) [max 8 OIDs]"));
 
-       printf(" -%s", _(UT_THRESHOLDS_NOTES));
+       printf(" -%s", UT_THRESHOLDS_NOTES);
 
        printf (" %s\n", _("- When checking multiple OIDs, separate ranges by commas like '-w 1:10,1:,:20'"));
        printf (" %s\n", _("- Note that only one string and one regex may be checked at present"));
        printf (" %s\n", _("- All evaluation methods other than PR, STR, and SUBSTR expect that the value"));
        printf ("   %s\n", _("returned from the SNMP query is an unsigned integer."));
-#ifdef NP_EXTRA_OPTS
-       printf (" -%s", _(UT_EXTRA_OPTS_NOTES));
-#endif
 
-       printf (_(UT_SUPPORT));
+       printf (UT_SUPPORT);
 }
 
 
@@ -895,7 +953,7 @@ print_help (void)
 void
 print_usage (void)
 {
-       printf (_("Usage:"));
+       printf ("%s\n", _("Usage:"));
        printf ("%s -H <ip_address> -o <OID> [-w warn_range] [-c crit_range]\n",progname);
        printf ("[-C community] [-s string] [-r regex] [-R regexi] [-t timeout] [-e retries]\n");
        printf ("[-l label] [-u units] [-p port-number] [-d delimiter] [-D output-delimiter]\n");