Merge branch 'collectd-4.10' into collectd-5.0
[collectd.git] / src / exec.c
index 4405985..0d33b29 100644 (file)
@@ -1,6 +1,6 @@
 /**
  * collectd - src/exec.c
- * Copyright (C) 2007-2009  Florian octo Forster
+ * Copyright (C) 2007-2010  Florian octo Forster
  * Copyright (C) 2007-2009  Sebastian Harl
  * Copyright (C) 2008       Peter Holik
  *
@@ -265,6 +265,27 @@ static int exec_config (oconfig_item_t *ci) /* {{{ */
   return (0);
 } /* int exec_config }}} */
 
+static void set_environment (void) /* {{{ */
+{
+  char buffer[1024];
+
+#ifdef HAVE_SETENV
+  ssnprintf (buffer, sizeof (buffer), "%.3f", CDTIME_T_TO_DOUBLE (interval_g));
+  setenv ("COLLECTD_INTERVAL", buffer, /* overwrite = */ 1);
+
+  ssnprintf (buffer, sizeof (buffer), "%s", hostname_g);
+  setenv ("COLLECTD_HOSTNAME", buffer, /* overwrite = */ 1);
+#else
+  ssnprintf (buffer, sizeof (buffer), "COLLECTD_INTERVAL=%.3f",
+      CDTIME_T_TO_DOUBLE (interval_g));
+  putenv (buffer);
+
+  ssnprintf (buffer, sizeof (buffer), "COLLECTD_HOSTNAME=%s", hostname_g);
+  putenv (buffer);
+#endif
+} /* }}} void set_environment */
+
+__attribute__((noreturn))
 static void exec_child (program_list_t *pl) /* {{{ */
 {
   int status;
@@ -281,8 +302,8 @@ static void exec_child (program_list_t *pl) /* {{{ */
   status = getpwnam_r (pl->user, &sp, nambuf, sizeof (nambuf), &sp_ptr);
   if (status != 0)
   {
-    ERROR ("exec plugin: getpwnam_r failed: %s",
-       sstrerror (errno, errbuf, sizeof (errbuf)));
+    ERROR ("exec plugin: Failed to get user information for user ``%s'': %s",
+       pl->user, sstrerror (errno, errbuf, sizeof (errbuf)));
     exit (-1);
   }
   if (sp_ptr == NULL)
@@ -311,7 +332,8 @@ static void exec_child (program_list_t *pl) /* {{{ */
       status = getgrnam_r (pl->group, &gr, nambuf, sizeof (nambuf), &gr_ptr);
       if (0 != status)
       {
-       ERROR ("exec plugin: getgrnam_r failed: %s",
+       ERROR ("exec plugin: Failed to get group information "
+           "for group ``%s'': %s", pl->group,
            sstrerror (errno, errbuf, sizeof (errbuf)));
        exit (-1);
       }
@@ -377,11 +399,20 @@ static void exec_child (program_list_t *pl) /* {{{ */
 
   status = execvp (pl->exec, pl->argv);
 
-  ERROR ("exec plugin: exec failed: %s",
-      sstrerror (errno, errbuf, sizeof (errbuf)));
+  ERROR ("exec plugin: Failed to execute ``%s'': %s",
+      pl->exec, sstrerror (errno, errbuf, sizeof (errbuf)));
   exit (-1);
 } /* void exec_child }}} */
 
+static void reset_signal_mask (void) /* {{{ */
+{
+  sigset_t ss;
+
+  memset (&ss, 0, sizeof (ss));
+  sigemptyset (&ss);
+  sigprocmask (SIG_SETMASK, &ss, /* old mask = */ NULL);
+} /* }}} void reset_signal_mask */
+
 /*
  * Creates three pipes (one for reading, one for writing and one for errors),
  * forks a child, sets up the pipes so that fd_in is connected to STDIN of
@@ -468,6 +499,11 @@ static int fork_child (program_list_t *pl, int *fd_in, int *fd_out, int *fd_err)
       close (fd_pipe_err[1]);
     }
 
+    set_environment ();
+
+    /* Unblock all signals */
+    reset_signal_mask ();
+
     exec_child (pl);
     /* does not return */
   }
@@ -502,12 +538,9 @@ static int parse_line (char *buffer) /* {{{ */
     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));
+    ERROR ("exec plugin: Unable to parse command, ignoring line: \"%s\"",
+       buffer);
+    return (-1);
   }
 } /* int parse_line }}} */
 
@@ -524,7 +557,13 @@ static void *exec_read_one (void *arg) /* {{{ */
 
   status = fork_child (pl, NULL, &fd, &fd_err);
   if (status < 0)
+  {
+    /* Reset the "running" flag */
+    pthread_mutex_lock (&pl_lock);
+    pl->flags &= ~PL_RUNNING;
+    pthread_mutex_unlock (&pl_lock);
     pthread_exit ((void *) 1);
+  }
   pl->pid = status;
 
   assert (pl->pid != 0);
@@ -730,7 +769,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);
+  if (n->meta != NULL)
+    plugin_notification_meta_free (n->meta);
   n->meta = NULL;
   sfree (arg);
   pthread_exit ((void *) 0);
@@ -779,7 +819,7 @@ static int exec_read (void) /* {{{ */
   return (0);
 } /* int exec_read }}} */
 
-static int exec_notification (const notification_t *n,
+static int exec_notification (const notification_t *n, /* {{{ */
     user_data_t __attribute__((unused)) *user_data)
 {
   program_list_t *pl;