Merge branch 'collectd-4.5' into collectd-4.6
[collectd.git] / src / exec.c
index ac0175c..ea31b30 100644 (file)
@@ -1,6 +1,8 @@
 /**
  * collectd - src/exec.c
- * Copyright (C) 2007,2008  Florian octo Forster
+ * Copyright (C) 2007-2009  Florian octo Forster
+ * Copyright (C) 2007-2009  Sebastian Harl
+ * Copyright (C) 2008       Peter Holik
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
@@ -17,6 +19,8 @@
  *
  * Authors:
  *   Florian octo Forster <octo at verplant.org>
+ *   Sebastian Harl <sh at tokkee.org>
+ *   Peter Holik <peter at holik.at>
  **/
 
 #include "collectd.h"
@@ -78,7 +82,7 @@ static pthread_mutex_t pl_lock = PTHREAD_MUTEX_INITIALIZER;
 /*
  * Functions
  */
-static void sigchld_handler (int signal) /* {{{ */
+static void sigchld_handler (int __attribute__((unused)) signal) /* {{{ */
 {
   pid_t pid;
   int status;
@@ -490,19 +494,19 @@ static int fork_child (program_list_t *pl, int *fd_in, int *fd_out, int *fd_err)
 
 static int parse_line (char *buffer) /* {{{ */
 {
-  char *fields[256];
-  int fields_num;
-
-  fields[0] = "PUTVAL";
-  fields_num = strsplit (buffer, fields + 1, STATIC_ARRAY_SIZE(fields) - 1);
-
-  if (strcasecmp (fields[1], "putval") == 0)
-    return (handle_putval (stdout, fields + 1, fields_num));
-  else if (strcasecmp (fields[1], "putnotif") == 0)
-    return (handle_putnotif (stdout, fields + 1, fields_num));
-
-  /* compatibility code */
-  return (handle_putval (stdout, fields, fields_num + 1));
+  if (strncasecmp ("PUTVAL", buffer, strlen ("PUTVAL")) == 0)
+    return (handle_putval (stdout, buffer));
+  else if (strncasecmp ("PUTNOTIF", buffer, strlen ("PUTNOTIF")) == 0)
+    return (handle_putnotif (stdout, buffer));
+  else
+  {
+    /* For backwards compatibility */
+    char tmp[1220];
+    /* Let's annoy the user a bit.. */
+    INFO ("exec plugin: Prepending `PUTVAL' to this line: %s", buffer);
+    ssnprintf (tmp, sizeof (tmp), "PUTVAL %s", buffer);
+    return (handle_putval (stdout, tmp));
+  }
 } /* int parse_line }}} */
 
 static void *exec_read_one (void *arg) /* {{{ */
@@ -585,7 +589,17 @@ static void *exec_read_one (void *arg) /* {{{ */
         if (errno == EAGAIN || errno == EINTR)  continue;
         break;
       }
-      else if (len == 0) break;  /* We've reached EOF */
+      else if (len == 0)
+      {
+       /* We've reached EOF */
+       NOTICE ("exec plugin: Program `%s' has closed STDERR.",
+           pl->exec);
+       close (fd_err);
+       FD_CLR (fd_err, &fdset);
+       highest_fd = fd;
+       fd_err = -1;
+       continue;
+      }
 
       pbuffer_err[len] = '\0';
 
@@ -615,6 +629,7 @@ static void *exec_read_one (void *arg) /* {{{ */
     copy = fdset;
   }
 
+  DEBUG ("exec plugin: exec_read_one: Waiting for `%s' to exit.", pl->exec);
   if (waitpid (pl->pid, &status, 0) > 0)
     pl->status = status;
 
@@ -628,7 +643,8 @@ static void *exec_read_one (void *arg) /* {{{ */
   pthread_mutex_unlock (&pl_lock);
 
   close (fd);
-  close (fd_err);
+  if (fd_err >= 0)
+    close (fd_err);
 
   pthread_exit ((void *) 0);
   return (NULL);
@@ -637,7 +653,8 @@ static void *exec_read_one (void *arg) /* {{{ */
 static void *exec_notification_one (void *arg) /* {{{ */
 {
   program_list_t *pl = ((program_list_and_notification_t *) arg)->pl;
-  const notification_t *n = &((program_list_and_notification_t *) arg)->n;
+  notification_t *n = &((program_list_and_notification_t *) arg)->n;
+  notification_meta_t *meta;
   int fd;
   FILE *fh;
   int pid;
@@ -686,6 +703,21 @@ static void *exec_notification_one (void *arg) /* {{{ */
   if (strlen (n->type_instance) > 0)
     fprintf (fh, "TypeInstance: %s\n", n->type_instance);
 
+  for (meta = n->meta; meta != NULL; meta = meta->next)
+  {
+    if (meta->type == NM_TYPE_STRING)
+      fprintf (fh, "%s: %s\n", meta->name, meta->nm_value.nm_string);
+    else if (meta->type == NM_TYPE_SIGNED_INT)
+      fprintf (fh, "%s: %"PRIi64"\n", meta->name, meta->nm_value.nm_signed_int);
+    else if (meta->type == NM_TYPE_UNSIGNED_INT)
+      fprintf (fh, "%s: %"PRIu64"\n", meta->name, meta->nm_value.nm_unsigned_int);
+    else if (meta->type == NM_TYPE_DOUBLE)
+      fprintf (fh, "%s: %e\n", meta->name, meta->nm_value.nm_double);
+    else if (meta->type == NM_TYPE_BOOLEAN)
+      fprintf (fh, "%s: %s\n", meta->name,
+         meta->nm_value.nm_boolean ? "true" : "false");
+  }
+
   fprintf (fh, "\n%s\n", n->message);
 
   fflush (fh);
@@ -696,6 +728,8 @@ static void *exec_notification_one (void *arg) /* {{{ */
   DEBUG ("exec plugin: Child %i exited with status %i.",
       pid, status);
 
+  plugin_notification_meta_free (n->meta);
+  n->meta = NULL;
   sfree (arg);
   pthread_exit ((void *) 0);
   return (NULL);
@@ -772,6 +806,11 @@ static int exec_notification (const notification_t *n)
     pln->pl = pl;
     memcpy (&pln->n, n, sizeof (notification_t));
 
+    /* Set the `meta' member to NULL, otherwise `plugin_notification_meta_copy'
+     * will run into an endless loop. */
+    pln->n.meta = NULL;
+    plugin_notification_meta_copy (&pln->n, n);
+
     pthread_attr_init (&attr);
     pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
     pthread_create (&t, &attr, exec_notification_one, (void *) pln);