/**
* 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
*
* Peter Holik <peter at holik.at>
**/
+#define _BSD_SOURCE /* For setgroups */
+
#include "collectd.h"
#include "common.h"
#include "plugin.h"
/*
* Functions
*/
-static void sigchld_handler (int signal) /* {{{ */
+static void sigchld_handler (int __attribute__((unused)) signal) /* {{{ */
{
pid_t pid;
int status;
return (0);
} /* int exec_config }}} */
+static void set_environment (void) /* {{{ */
+{
+ char buffer[1024];
+
+#ifdef HAVE_SETENV
+ ssnprintf (buffer, sizeof (buffer), "%i", 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=%i", 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;
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)
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);
}
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
close (fd_pipe_err[1]);
}
+ set_environment ();
+
+ /* Unblock all signals */
+ reset_signal_mask ();
+
exec_child (pl);
/* does not return */
}
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);
DEBUG ("exec plugin: Child %i exited with status %i.",
pid, status);
- plugin_notification_meta_free (n);
+ if (n->meta != NULL)
+ plugin_notification_meta_free (n->meta);
+ n->meta = NULL;
sfree (arg);
pthread_exit ((void *) 0);
return (NULL);
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;
program_list_and_notification_t *pln;
} /* for (pl) */
return (0);
-} /* int exec_notification */
+} /* }}} int exec_notification */
static int exec_shutdown (void) /* {{{ */
{
plugin_register_complex_config ("exec", exec_config);
plugin_register_init ("exec", exec_init);
plugin_register_read ("exec", exec_read);
- plugin_register_notification ("exec", exec_notification);
+ plugin_register_notification ("exec", exec_notification,
+ /* user_data = */ NULL);
plugin_register_shutdown ("exec", exec_shutdown);
} /* void module_register */