src/collectd-nagios.c: Improve handling of lines returned from `GETVAL'.
[collectd.git] / src / collectd-nagios.c
index 63effd5..ca72a68 100644 (file)
@@ -142,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;
@@ -150,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)
@@ -172,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));
@@ -181,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)
@@ -213,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;