collectd.conf(5): Moved information about ``special'' plugins from collectd(1) to...
[collectd.git] / src / exec.c
index 836c881..518efc8 100644 (file)
 #include "collectd.h"
 #include "common.h"
 #include "plugin.h"
-#include "utils_debug.h"
 
 #include <sys/types.h>
 #include <pwd.h>
+#include <signal.h>
 
 #include <pthread.h>
 
@@ -45,26 +45,6 @@ struct program_list_s
 /*
  * Private variables
  */
-static data_source_t dsrc_counter[1] =
-{
-  {"value", DS_TYPE_COUNTER, NAN, NAN}
-};
-
-static data_set_t ds_counter =
-{
-  "counter", STATIC_ARRAY_SIZE (dsrc_counter), dsrc_counter
-};
-
-static data_source_t dsrc_gauge[1] =
-{
-  {"value", DS_TYPE_GAUGE, NAN, NAN}
-};
-
-static data_set_t ds_gauge =
-{
-  "gauge", STATIC_ARRAY_SIZE (dsrc_gauge), dsrc_gauge
-};
-
 static const char *config_keys[] =
 {
   "Exec"
@@ -129,14 +109,14 @@ static void submit_counter (const char *type_instance, counter_t value)
   value_t values[1];
   value_list_t vl = VALUE_LIST_INIT;
 
-  DBG ("type_instance = %s; value = %llu;", type_instance, value);
+  DEBUG ("type_instance = %s; value = %llu;", type_instance, value);
 
   values[0].counter = value;
 
   vl.values = values;
   vl.values_len = 1;
   vl.time = time (NULL);
-  strcpy (vl.host, hostname);
+  strcpy (vl.host, hostname_g);
   strcpy (vl.plugin, "exec");
   strcpy (vl.plugin_instance, "");
   strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
@@ -149,14 +129,14 @@ static void submit_gauge (const char *type_instance, gauge_t value)
   value_t values[1];
   value_list_t vl = VALUE_LIST_INIT;
 
-  DBG ("type_instance = %s; value = %lf;", type_instance, value);
+  DEBUG ("type_instance = %s; value = %lf;", type_instance, value);
 
   values[0].gauge = value;
 
   vl.values = values;
   vl.values_len = 1;
   vl.time = time (NULL);
-  strcpy (vl.host, hostname);
+  strcpy (vl.host, hostname_g);
   strcpy (vl.plugin, "exec");
   strcpy (vl.plugin_instance, "");
   strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
@@ -166,30 +146,41 @@ static void submit_gauge (const char *type_instance, gauge_t value)
 
 static void exec_child (program_list_t *pl)
 {
-  struct passwd *sp;
   int status;
   int uid;
   char *arg0;
 
-  /* FIXME: Not thread safe! */
-  sp = getpwnam (pl->user);
-  if (sp == NULL)
+  struct passwd *sp_ptr;
+  struct passwd sp;
+  char pwnambuf[2048];
+  char errbuf[1024];
+
+  sp_ptr = NULL;
+  status = getpwnam_r (pl->user, &sp, pwnambuf, sizeof (pwnambuf), &sp_ptr);
+  if (status != 0)
+  {
+    ERROR ("exec plugin: getpwnam_r failed: %s",
+       sstrerror (errno, errbuf, sizeof (errbuf)));
+    exit (-1);
+  }
+  if (sp_ptr == NULL)
   {
-    syslog (LOG_ERR, "exec plugin: getpwnam failed: %s", strerror (errno));
+    ERROR ("exec plugin: No such user: `%s'", pl->user);
     exit (-1);
   }
 
-  uid = sp->pw_uid;
+  uid = sp.pw_uid;
   if (uid == 0)
   {
-    syslog (LOG_ERR, "exec plugin: Cowardly refusing to exec program as root.");
+    ERROR ("exec plugin: Cowardly refusing to exec program as root.");
     exit (-1);
   }
 
   status = setuid (uid);
   if (status != 0)
   {
-    syslog (LOG_ERR, "exec plugin: setuid failed: %s", strerror (errno));
+    ERROR ("exec plugin: setuid failed: %s",
+       sstrerror (errno, errbuf, sizeof (errbuf)));
     exit (-1);
   }
 
@@ -201,7 +192,8 @@ static void exec_child (program_list_t *pl)
 
   status = execlp (pl->exec, arg0, (char *) 0);
 
-  syslog (LOG_ERR, "exec plugin: exec failed: %s", strerror (errno));
+  ERROR ("exec plugin: exec failed: %s",
+      sstrerror (errno, errbuf, sizeof (errbuf)));
   exit (-1);
 } /* void exec_child */
 
@@ -216,14 +208,18 @@ static int fork_child (program_list_t *pl)
   status = pipe (fd_pipe);
   if (status != 0)
   {
-    syslog (LOG_ERR, "exec plugin: pipe failed: %s", strerror (errno));
+    char errbuf[1024];
+    ERROR ("exec plugin: pipe failed: %s",
+       sstrerror (errno, errbuf, sizeof (errbuf)));
     return (-1);
   }
 
   pl->pid = fork ();
   if (pl->pid < 0)
   {
-    syslog (LOG_ERR, "exec plugin: fork failed: %s", strerror (errno));
+    char errbuf[1024];
+    ERROR ("exec plugin: fork failed: %s",
+       sstrerror (errno, errbuf, sizeof (errbuf)));
     return (-1);
   }
   else if (pl->pid == 0)
@@ -262,8 +258,9 @@ static void *exec_read_one (void *arg)
   fh = fdopen (fd, "r");
   if (fh == NULL)
   {
-    syslog (LOG_ERR, "exec plugin: fdopen (%i) failed: %s", fd,
-       strerror (errno));
+    char errbuf[1024];
+    ERROR ("exec plugin: fdopen (%i) failed: %s", fd,
+       sstrerror (errno, errbuf, sizeof (errbuf)));
     kill (pl->pid, SIGTERM);
     close (fd);
     pthread_exit ((void *) 1);
@@ -276,7 +273,7 @@ static void *exec_read_one (void *arg)
     char *type_instance;
     char *value;
 
-    DBG ("buffer = %s", buffer);
+    DEBUG ("buffer = %s", buffer);
 
     len = strlen (buffer);
     if (len < 5)
@@ -296,7 +293,7 @@ static void *exec_read_one (void *arg)
     if ((strcasecmp ("counter", type) != 0)
        && (strcasecmp ("gauge", type) != 0))
     {
-      syslog (LOG_WARNING, "exec plugin: Received invalid type: %s", type);
+      WARNING ("exec plugin: Received invalid type: %s", type);
       continue;
     }
 
@@ -306,7 +303,7 @@ static void *exec_read_one (void *arg)
     *value = '\0';
     value++;
 
-    DBG ("value = %s", value);
+    DEBUG ("value = %s", value);
 
     if (strcasecmp ("counter", type) == 0)
       submit_counter (type_instance, atoll (value));
@@ -318,6 +315,7 @@ static void *exec_read_one (void *arg)
   pl->pid = 0;
 
   pthread_exit ((void *) 0);
+  return (NULL);
 } /* void *exec_read_one */
 
 static int exec_read (void)
@@ -340,12 +338,37 @@ static int exec_read (void)
   return (0);
 } /* int exec_read */
 
+static int exec_shutdown (void)
+{
+  program_list_t *pl;
+  program_list_t *next;
+
+  pl = pl_head;
+  while (pl != NULL)
+  {
+    next = pl->next;
+
+    if (pl->pid > 0)
+    {
+      kill (pl->pid, SIGTERM);
+      INFO ("exec plugin: Sent SIGTERM to %hu", (unsigned short int) pl->pid);
+    }
+
+    sfree (pl->user);
+    sfree (pl);
+
+    pl = next;
+  } /* while (pl) */
+  pl_head = NULL;
+
+  return (0);
+} /* int exec_shutdown */
+
 void module_register (void)
 {
-  plugin_register_data_set (&ds_counter);
-  plugin_register_data_set (&ds_gauge);
   plugin_register_config ("exec", exec_config, config_keys, config_keys_num);
   plugin_register_read ("exec", exec_read);
+  plugin_register_shutdown ("exec", exec_shutdown);
 } /* void module_register */
 
 /*