Merge branch 'collectd-4.10' into collectd-5.1
[collectd.git] / src / exec.c
index 681b94d..ee37c60 100644 (file)
@@ -93,7 +93,7 @@ static void sigchld_handler (int __attribute__((unused)) signal) /* {{{ */
     program_list_t *pl;
     for (pl = pl_head; pl != NULL; pl = pl->next)
       if (pl->pid == pid)
-       break;
+        break;
     if (pl != NULL)
       pl->status = status;
   } /* while (waitpid) */
@@ -108,20 +108,20 @@ static int exec_config_exec (oconfig_item_t *ci) /* {{{ */
   if (ci->children_num != 0)
   {
     WARNING ("exec plugin: The config option `%s' may not be a block.",
-       ci->key);
+        ci->key);
     return (-1);
   }
   if (ci->values_num < 2)
   {
     WARNING ("exec plugin: The config option `%s' needs at least two "
-       "arguments.", ci->key);
+        "arguments.", ci->key);
     return (-1);
   }
   if ((ci->values[0].type != OCONFIG_TYPE_STRING)
       || (ci->values[1].type != OCONFIG_TYPE_STRING))
   {
     WARNING ("exec plugin: The first two arguments to the `%s' option must "
-       "be string arguments.", ci->key);
+        "be string arguments.", ci->key);
     return (-1);
   }
 
@@ -201,15 +201,15 @@ static int exec_config_exec (oconfig_item_t *ci) /* {{{ */
     {
       if (ci->values[i + 1].type == OCONFIG_TYPE_NUMBER)
       {
-       ssnprintf (buffer, sizeof (buffer), "%lf",
-           ci->values[i + 1].value.number);
+        ssnprintf (buffer, sizeof (buffer), "%lf",
+            ci->values[i + 1].value.number);
       }
       else
       {
-       if (ci->values[i + 1].value.boolean)
-         sstrncpy (buffer, "true", sizeof (buffer));
-       else
-         sstrncpy (buffer, "false", sizeof (buffer));
+        if (ci->values[i + 1].value.boolean)
+          sstrncpy (buffer, "true", sizeof (buffer));
+        else
+          sstrncpy (buffer, "false", sizeof (buffer));
       }
 
       pl->argv[i] = strdup (buffer);
@@ -254,7 +254,7 @@ static int exec_config (oconfig_item_t *ci) /* {{{ */
   {
     oconfig_item_t *child = ci->children + i;
     if ((strcasecmp ("Exec", child->key) == 0)
-       || (strcasecmp ("NotificationExec", child->key) == 0))
+        || (strcasecmp ("NotificationExec", child->key) == 0))
       exec_config_exec (child);
     else
     {
@@ -269,11 +269,20 @@ static void set_environment (void) /* {{{ */
 {
   char buffer[1024];
 
-  ssnprintf (buffer, sizeof (buffer), "%i", interval_g);
+#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))
@@ -294,7 +303,7 @@ static void exec_child (program_list_t *pl) /* {{{ */
   if (status != 0)
   {
     ERROR ("exec plugin: Failed to get user information for user ``%s'': %s",
-       pl->user, sstrerror (errno, errbuf, sizeof (errbuf)));
+        pl->user, sstrerror (errno, errbuf, sizeof (errbuf)));
     exit (-1);
   }
   if (sp_ptr == NULL)
@@ -323,15 +332,15 @@ 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: Failed to get group information "
-           "for group ``%s'': %s", pl->group,
-           sstrerror (errno, errbuf, sizeof (errbuf)));
-       exit (-1);
+        ERROR ("exec plugin: Failed to get group information "
+            "for group ``%s'': %s", pl->group,
+            sstrerror (errno, errbuf, sizeof (errbuf)));
+        exit (-1);
       }
       if (NULL == gr_ptr)
       {
-       ERROR ("exec plugin: No such group: `%s'", pl->group);
-       exit (-1);
+        ERROR ("exec plugin: No such group: `%s'", pl->group);
+        exit (-1);
       }
 
       egid = gr.gr_gid;
@@ -365,7 +374,7 @@ static void exec_child (program_list_t *pl) /* {{{ */
   if (status != 0)
   {
     ERROR ("exec plugin: setgid (%i) failed: %s",
-       gid, sstrerror (errno, errbuf, sizeof (errbuf)));
+        gid, sstrerror (errno, errbuf, sizeof (errbuf)));
     exit (-1);
   }
 
@@ -375,7 +384,7 @@ static void exec_child (program_list_t *pl) /* {{{ */
     if (status != 0)
     {
       ERROR ("exec plugin: setegid (%i) failed: %s",
-         egid, sstrerror (errno, errbuf, sizeof (errbuf)));
+          egid, sstrerror (errno, errbuf, sizeof (errbuf)));
       exit (-1);
     }
   }
@@ -384,7 +393,7 @@ static void exec_child (program_list_t *pl) /* {{{ */
   if (status != 0)
   {
     ERROR ("exec plugin: setuid (%i) failed: %s",
-       uid, sstrerror (errno, errbuf, sizeof (errbuf)));
+        uid, sstrerror (errno, errbuf, sizeof (errbuf)));
     exit (-1);
   }
 
@@ -426,7 +435,7 @@ static int fork_child (program_list_t *pl, int *fd_in, int *fd_out, int *fd_err)
   if (status != 0)
   {
     ERROR ("exec plugin: pipe failed: %s",
-       sstrerror (errno, errbuf, sizeof (errbuf)));
+        sstrerror (errno, errbuf, sizeof (errbuf)));
     return (-1);
   }
 
@@ -434,7 +443,7 @@ static int fork_child (program_list_t *pl, int *fd_in, int *fd_out, int *fd_err)
   if (status != 0)
   {
     ERROR ("exec plugin: pipe failed: %s",
-       sstrerror (errno, errbuf, sizeof (errbuf)));
+        sstrerror (errno, errbuf, sizeof (errbuf)));
     return (-1);
   }
 
@@ -442,7 +451,7 @@ static int fork_child (program_list_t *pl, int *fd_in, int *fd_out, int *fd_err)
   if (status != 0)
   {
     ERROR ("exec plugin: pipe failed: %s",
-       sstrerror (errno, errbuf, sizeof (errbuf)));
+        sstrerror (errno, errbuf, sizeof (errbuf)));
     return (-1);
   }
 
@@ -450,7 +459,7 @@ static int fork_child (program_list_t *pl, int *fd_in, int *fd_out, int *fd_err)
   if (pid < 0)
   {
     ERROR ("exec plugin: fork failed: %s",
-       sstrerror (errno, errbuf, sizeof (errbuf)));
+        sstrerror (errno, errbuf, sizeof (errbuf)));
     return (-1);
   }
   else if (pid == 0)
@@ -463,9 +472,9 @@ static int fork_child (program_list_t *pl, int *fd_in, int *fd_out, int *fd_err)
     for (fd = 0; fd < fd_num; fd++)
     {
       if ((fd == fd_pipe_in[0])
-         || (fd == fd_pipe_out[1])
-         || (fd == fd_pipe_err[1]))
-       continue;
+          || (fd == fd_pipe_out[1])
+          || (fd == fd_pipe_err[1]))
+        continue;
       close (fd);
     }
 
@@ -483,7 +492,7 @@ static int fork_child (program_list_t *pl, int *fd_in, int *fd_out, int *fd_err)
       close (fd_pipe_out[1]);
     }
 
-    /* Now connect the `out' pipe to STDOUT */
+    /* Now connect the `err' pipe to STDERR */
     if (fd_pipe_err[1] != STDERR_FILENO)
     {
       dup2 (fd_pipe_err[1], STDERR_FILENO);
@@ -529,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 }}} */
 
@@ -572,10 +578,18 @@ static void *exec_read_one (void *arg) /* {{{ */
   /* We use a copy of fdset, as select modifies it */
   copy = fdset;
 
-  while (select(highest_fd + 1, &copy, NULL, NULL, NULL ) > 0)
+  while (1)
   {
     int len;
 
+    status = select (highest_fd + 1, &copy, NULL, NULL, NULL);
+    if (status < 0)
+    {
+      if (errno == EINTR)
+        continue;
+      break;
+    }
+
     if (FD_ISSET(fd, &copy))
     {
       char *pnl;
@@ -621,19 +635,24 @@ static void *exec_read_one (void *arg) /* {{{ */
 
       if (len < 0)
       {
-        if (errno == EAGAIN || errno == EINTR)  continue;
+        if (errno == EAGAIN || errno == EINTR)
+          continue;
         break;
       }
       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;
+        /* We've reached EOF */
+        NOTICE ("exec plugin: Program `%s' has closed STDERR.", pl->exec);
+
+        /* Remove file descriptor form select() set. */
+        FD_CLR (fd_err, &fdset);
+        copy = fdset;
+        highest_fd = fd;
+
+        /* Clean up file descriptor */
+        close (fd_err);
+        fd_err = -1;
+        continue;
       }
 
       pbuffer_err[len] = '\0';
@@ -707,7 +726,7 @@ static void *exec_notification_one (void *arg) /* {{{ */
   {
     char errbuf[1024];
     ERROR ("exec plugin: fdopen (%i) failed: %s", fd,
-       sstrerror (errno, errbuf, sizeof (errbuf)));
+        sstrerror (errno, errbuf, sizeof (errbuf)));
     kill (pl->pid, SIGTERM);
     pl->pid = 0;
     close (fd);
@@ -723,8 +742,8 @@ static void *exec_notification_one (void *arg) /* {{{ */
 
   fprintf (fh,
       "Severity: %s\n"
-      "Time: %u\n",
-      severity, (unsigned int) n->time);
+      "Time: %.3f\n",
+      severity, CDTIME_T_TO_DOUBLE (n->time));
 
   /* Print the optional fields */
   if (strlen (n->host) > 0)
@@ -750,7 +769,7 @@ static void *exec_notification_one (void *arg) /* {{{ */
       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");
+          meta->nm_value.nm_boolean ? "true" : "false");
   }
 
   fprintf (fh, "\n%s\n", n->message);
@@ -808,6 +827,7 @@ static int exec_read (void) /* {{{ */
     pthread_attr_init (&attr);
     pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
     pthread_create (&t, &attr, exec_read_one, (void *) pl);
+    pthread_attr_destroy (&attr);
   } /* for (pl) */
 
   return (0);
@@ -833,7 +853,7 @@ static int exec_notification (const notification_t *n, /* {{{ */
       continue;
 
     pln = (program_list_and_notification_t *) malloc (sizeof
-       (program_list_and_notification_t));
+        (program_list_and_notification_t));
     if (pln == NULL)
     {
       ERROR ("exec plugin: malloc failed.");
@@ -851,6 +871,7 @@ static int exec_notification (const notification_t *n, /* {{{ */
     pthread_attr_init (&attr);
     pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
     pthread_create (&t, &attr, exec_notification_one, (void *) pln);
+    pthread_attr_destroy (&attr);
   } /* for (pl) */
 
   return (0);