src/collectd-nagios.c: Improve handling of lines returned from `GETVAL'.
[collectd.git] / src / collectd-nagios.c
index 160412c..ca72a68 100644 (file)
@@ -1,3 +1,5 @@
+#include "config.h"
+
 #include <stdlib.h>
 #include <unistd.h>
 #include <stdio.h>
 #include <sys/un.h>
 
 /*
- * This weird macro cascade forces the glibc to define `NAN'. I don't know
- * another way to solve this, so more intelligent solutions are welcome. -octo
+ * This is copied directly from collectd.h. Make changes there!
  */
-#ifndef __USE_ISOC99
-# define DISABLE__USE_ISOC99 1
-# define __USE_ISOC99 1
-#endif
-#include <math.h>
-#ifdef DISABLE__USE_ISOC99
-# undef DISABLE__USE_ISOC99
-# undef __USE_ISOC99
-#endif
+#if NAN_STATIC_DEFAULT
+# include <math.h>
+/* #endif NAN_STATIC_DEFAULT*/
+#elif NAN_STATIC_ISOC
+# ifndef __USE_ISOC99
+#  define DISABLE_ISOC99 1
+#  define __USE_ISOC99 1
+# endif /* !defined(__USE_ISOC99) */
+# include <math.h>
+# if DISABLE_ISOC99
+#  undef DISABLE_ISOC99
+#  undef __USE_ISOC99
+# endif /* DISABLE_ISOC99 */
+/* #endif NAN_STATIC_ISOC */
+#elif NAN_ZERO_ZERO
+# include <math.h>
+# ifdef NAN
+#  undef NAN
+# endif
+# define NAN (0.0 / 0.0)
+# ifndef isnan
+#  define isnan(f) ((f) != (f))
+# endif /* !defined(isnan) */
+#endif /* NAN_ZERO_ZERO */
 
 #define RET_OKAY     0
 #define RET_WARNING  1
@@ -112,9 +128,9 @@ int match_range (range_t *range, double value)
 {
        int ret = 0;
 
-       if ((range->min != NAN) && (range->min > value))
+       if (!isnan (range->min) && (range->min > value))
                ret = 1;
-       if ((range->max != NAN) && (range->max < value))
+       if (!isnan (range->max) && (range->max < value))
                ret = 1;
 
        return (((ret - range->invert) == 0) ? 0 : 1);
@@ -126,7 +142,7 @@ static int get_values (int *ret_values_num, double **ret_values,
        struct sockaddr_un sa;
        int status;
        int fd;
-       FILE *fh;
+       FILE *fh_in, *fh_out;
        char buffer[4096];
 
        int values_num;
@@ -134,6 +150,7 @@ static int get_values (int *ret_values_num, double **ret_values,
        char **values_names;
 
        int i;
+       int j;
 
        fd = socket (PF_UNIX, SOCK_STREAM, 0);
        if (fd < 0)
@@ -156,8 +173,8 @@ static int get_values (int *ret_values_num, double **ret_values,
                return (-1);
        }
 
-       fh = fdopen (fd, "r+");
-       if (fh == NULL)
+       fh_in = fdopen (fd, "r");
+       if (fh_in == NULL)
        {
                fprintf (stderr, "fdopen failed: %s\n",
                                strerror (errno));
@@ -165,21 +182,37 @@ static int get_values (int *ret_values_num, double **ret_values,
                return (-1);
        }
 
-       fprintf (fh, "GETVAL %s/%s\n", hostname_g, value_string_g);
-       fflush (fh);
+       fh_out = fdopen (fd, "w");
+       if (fh_out == NULL)
+       {
+               fprintf (stderr, "fdopen failed: %s\n",
+                               strerror (errno));
+               fclose (fh_in);
+               return (-1);
+       }
+
+       fprintf (fh_out, "GETVAL %s/%s\n", hostname_g, value_string_g);
+       fflush (fh_out);
 
-       if (fgets (buffer, sizeof (buffer), fh) == NULL)
+       if (fgets (buffer, sizeof (buffer), fh_in) == NULL)
        {
                fprintf (stderr, "fgets failed: %s\n",
                                strerror (errno));
-               close (fd);
+               fclose (fh_in);
+               fclose (fh_out);
                return (-1);
        }
-       close (fd); fd = -1;
 
-       values_num = atoi (buffer);
-       if (values_num < 1)
-               return (-1);
+       {
+               char *ptr = strchr (buffer, ' ');
+
+               if (ptr != NULL)
+                       *ptr = '\0';
+
+               values_num = atoi (buffer);
+               if (values_num < 1)
+                       return (-1);
+       }
 
        values = (double *) malloc (values_num * sizeof (double));
        if (values == NULL)
@@ -197,33 +230,61 @@ static int get_values (int *ret_values_num, double **ret_values,
                free (values);
                return (-1);
        }
+       memset (values_names, 0, values_num * sizeof (char *));
 
+       i = 0; /* index of the values returned by the server */
+       j = 0; /* number of values in `values_names' and `values' */
+       while (fgets (buffer, sizeof (buffer), fh_in) != NULL)
        {
-               char *ptr = strchr (buffer, ' ') + 1;
-               char *key;
-               char *value;
-
-               i = 0;
-               while ((key = strtok (ptr, " \t")) != NULL)
+               do /* while (0) */
                {
-                       ptr = NULL;
+                       char *key;
+                       char *value;
+                       char *endptr;
+
+                       key = buffer;
+
                        value = strchr (key, '=');
                        if (value == NULL)
-                               continue;
-                       *value = '\0'; value++;
+                       {
+                               fprintf (stderr, "Cannot parse line: %s\n", buffer);
+                               break;
+                       }
+                       *value = 0;
+                       value++;
 
                        if (ignore_ds (key) != 0)
-                               continue;
+                               break;
 
-                       values_names[i] = strdup (key);
-                       values[i] = atof (value);
+                       endptr = NULL;
+                       errno = 0;
+                       values[j] = strtod (value, &endptr);
+                       if ((endptr == value) || (errno != 0))
+                       {
+                               fprintf (stderr, "Could not parse buffer "
+                                               "as number: %s\n", value);
+                               break;
+                       }
 
-                       i++;
-                       if (i >= values_num)
+                       values_names[j] = strdup (key);
+                       if (values_names[j] == NULL)
+                       {
+                               fprintf (stderr, "strdup failed.\n");
                                break;
-               }
-               values_num = i;
+                       }
+                       j++;
+               } while (0);
+
+               i++;
+               if (i >= values_num)
+                       break;
        }
+       /* Set `values_num' to the number of values actually stored in the
+        * array. */
+       values_num = j;
+
+       fclose (fh_in); fh_in = NULL; fd = -1;
+       fclose (fh_out); fh_out = NULL;
 
        *ret_values_num = values_num;
        *ret_values = values;
@@ -268,7 +329,7 @@ int do_check_con_none (int values_num, double *values, char **values_names)
 
        for (i = 0; i < values_num; i++)
        {
-               if (values[i] == NAN)
+               if (isnan (values[i]))
                        num_warning++;
                else if (match_range (&range_critical_g, values[i]) != 0)
                        num_critical++;
@@ -278,25 +339,22 @@ int do_check_con_none (int values_num, double *values, char **values_names)
                        num_okay++;
        }
 
-       if ((num_critical != 0) || (values_num == 0))
+       printf ("%i critical, %i warning, %i okay",
+                       num_critical, num_warning, num_okay);
+       if (values_num > 0)
        {
-               printf ("CRITICAL: %i critical, %i warning, %i okay\n",
-                               num_critical, num_warning, num_okay);
-               return (RET_CRITICAL);
+               printf (" |");
+               for (i = 0; i < values_num; i++)
+                       printf (" %s=%lf;;;;", values_names[i], values[i]);
        }
+       printf ("\n");
+
+       if ((num_critical != 0) || (values_num == 0))
+               return (RET_CRITICAL);
        else if (num_warning != 0)
-       {
-               printf ("WARNING: %i warning, %i okay\n",
-                               num_warning, num_okay);
                return (RET_WARNING);
-       }
-       else
-       {
-               printf ("OKAY: %i okay\n", num_okay);
-               return (RET_OKAY);
-       }
 
-       return (RET_UNKNOWN);
+       return (RET_OKAY);
 } /* int do_check_con_none */
 
 int do_check_con_average (int values_num, double *values, char **values_names)
@@ -304,12 +362,13 @@ int do_check_con_average (int values_num, double *values, char **values_names)
        int i;
        double total;
        int total_num;
+       double average;
 
        total = 0.0;
        total_num = 0;
        for (i = 0; i < values_num; i++)
        {
-               if (values[i] != NAN)
+               if (!isnan (values[i]))
                {
                        total += values[i];
                        total_num++;
@@ -317,31 +376,23 @@ int do_check_con_average (int values_num, double *values, char **values_names)
        }
 
        if (total_num == 0)
-       {
-               printf ("WARNING: No defined values found\n");
+               average = NAN;
+       else
+               average = total / total_num;
+       printf ("%lf average |", average);
+       for (i = 0; i < values_num; i++)
+               printf (" %s=%lf;;;;", values_names[i], values[i]);
+
+       if (total_num == 0)
                return (RET_WARNING);
-       }
 
-       if (match_range (&range_critical_g, total / total_num) != 0)
-       {
-               printf ("CRITICAL: Average = %lf\n",
-                               (double) (total / total_num));
+       if (isnan (average)
+                       || match_range (&range_critical_g, average))
                return (RET_CRITICAL);
-       }
-       else if (match_range (&range_warning_g, total / total_num) != 0)
-       {
-               printf ("WARNING: Average = %lf\n",
-                               (double) (total / total_num));
+       else if (match_range (&range_warning_g, average) != 0)
                return (RET_WARNING);
-       }
-       else
-       {
-               printf ("OKAY: Average = %lf\n",
-                               (double) (total / total_num));
-               return (RET_OKAY);
-       }
 
-       return (RET_UNKNOWN);
+       return (RET_OKAY);
 } /* int do_check_con_average */
 
 int do_check_con_sum (int values_num, double *values, char **values_names)
@@ -354,7 +405,7 @@ int do_check_con_sum (int values_num, double *values, char **values_names)
        total_num = 0;
        for (i = 0; i < values_num; i++)
        {
-               if (values[i] != NAN)
+               if (!isnan (values[i]))
                {
                        total += values[i];
                        total_num++;
@@ -406,7 +457,7 @@ int do_check (void)
                return (do_check_con_sum (values_num, values, values_names));
 
        free (values);
-       free (values_names);
+       free (values_names); /* FIXME? */
 
        return (RET_UNKNOWN);
 }