* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* Authors:
- * Florian octo Forster <octo at verplant.org>
+ * Florian octo Forster <octo at collectd.org>
* Sebastian Harl <sh at tokkee.org>
* Peter Holik <peter at holik.at>
**/
+#define _DEFAULT_SOURCE
#define _BSD_SOURCE /* For setgroups */
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
#include <grp.h>
#include <signal.h>
-#include <pthread.h>
-
#define PL_NORMAL 0x01
#define PL_NOTIF_ACTION 0x02
return (-1);
}
- pl = (program_list_t *) malloc (sizeof (program_list_t));
+ pl = calloc (1, sizeof (*pl));
if (pl == NULL)
{
- ERROR ("exec plugin: malloc failed.");
+ ERROR ("exec plugin: calloc failed.");
return (-1);
}
- memset (pl, '\0', sizeof (program_list_t));
if (strcasecmp ("NotificationExec", ci->key) == 0)
pl->flags |= PL_NOTIF_ACTION;
return (-1);
}
- pl->argv = (char **) malloc (ci->values_num * sizeof (char *));
+ pl->argv = calloc (ci->values_num, sizeof (*pl->argv));
if (pl->argv == NULL)
{
- ERROR ("exec plugin: malloc failed.");
+ ERROR ("exec plugin: calloc failed.");
sfree (pl->exec);
sfree (pl->user);
sfree (pl);
return (-1);
}
- memset (pl->argv, '\0', ci->values_num * sizeof (char *));
{
char *tmp = strrchr (ci->values[1].value.string, '/');
pl->argv[0] = strdup (buffer);
if (pl->argv[0] == NULL)
{
- ERROR ("exec plugin: malloc failed.");
+ ERROR ("exec plugin: strdup failed.");
sfree (pl->argv);
sfree (pl->exec);
sfree (pl->user);
static int exec_config (oconfig_item_t *ci) /* {{{ */
{
- int i;
-
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
if ((strcasecmp ("Exec", child->key) == 0)
exit (-1);
}
- status = execvp (pl->exec, pl->argv);
+ execvp (pl->exec, pl->argv);
ERROR ("exec plugin: Failed to execute ``%s'': %s",
pl->exec, sstrerror (errno, errbuf, sizeof (errbuf)));
{
sigset_t ss;
- memset (&ss, 0, sizeof (ss));
sigemptyset (&ss);
sigprocmask (SIG_SETMASK, &ss, /* old mask = */ NULL);
} /* }}} void reset_signal_mask */
+static int create_pipe (int fd_pipe[2]) /* {{{ */
+{
+ char errbuf[1024];
+ int status;
+
+ status = pipe (fd_pipe);
+ if (status != 0)
+ {
+ ERROR ("exec plugin: pipe failed: %s",
+ sstrerror (errno, errbuf, sizeof (errbuf)));
+ return (-1);
+ }
+
+ return 0;
+} /* }}} int create_pipe */
+
+static void close_pipe (int fd_pipe[2]) /* {{{ */
+{
+ if (fd_pipe[0] != -1)
+ close (fd_pipe[0]);
+
+ if (fd_pipe[1] != -1)
+ close (fd_pipe[1]);
+} /* }}} void close_pipe */
+
/*
* 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
*/
static int fork_child (program_list_t *pl, int *fd_in, int *fd_out, int *fd_err) /* {{{ */
{
- int fd_pipe_in[2];
- int fd_pipe_out[2];
- int fd_pipe_err[2];
+ int fd_pipe_in[2] = {-1, -1};
+ int fd_pipe_out[2] = {-1, -1};
+ int fd_pipe_err[2] = {-1, -1};
char errbuf[1024];
int status;
int pid;
if (pl->pid != 0)
return (-1);
- status = pipe (fd_pipe_in);
- if (status != 0)
- {
- ERROR ("exec plugin: pipe failed: %s",
- sstrerror (errno, errbuf, sizeof (errbuf)));
- return (-1);
- }
-
- status = pipe (fd_pipe_out);
- if (status != 0)
- {
- ERROR ("exec plugin: pipe failed: %s",
- sstrerror (errno, errbuf, sizeof (errbuf)));
- return (-1);
- }
-
- status = pipe (fd_pipe_err);
- if (status != 0)
- {
- ERROR ("exec plugin: pipe failed: %s",
- sstrerror (errno, errbuf, sizeof (errbuf)));
- return (-1);
- }
+ if ((create_pipe(fd_pipe_in) == -1)
+ || (create_pipe(fd_pipe_out) == -1)
+ || (create_pipe(fd_pipe_err) == -1))
+ goto failed;
sp_ptr = NULL;
status = getpwnam_r (pl->user, &sp, nambuf, sizeof (nambuf), &sp_ptr);
{
ERROR ("exec plugin: Failed to get user information for user ``%s'': %s",
pl->user, sstrerror (errno, errbuf, sizeof (errbuf)));
- return (-1);
+ goto failed;
}
+
if (sp_ptr == NULL)
{
ERROR ("exec plugin: No such user: `%s'", pl->user);
- return (-1);
+ goto failed;
}
uid = sp.pw_uid;
if (uid == 0)
{
ERROR ("exec plugin: Cowardly refusing to exec program as root.");
- return (-1);
+ goto failed;
}
/* The group configured in the configfile is set as effective group, because
ERROR ("exec plugin: Failed to get group information "
"for group ``%s'': %s", pl->group,
sstrerror (errno, errbuf, sizeof (errbuf)));
- return (-1);
+ goto failed;
}
if (NULL == gr_ptr)
{
ERROR ("exec plugin: No such group: `%s'", pl->group);
- return (-1);
+ goto failed;
}
egid = gr.gr_gid;
{
ERROR ("exec plugin: fork failed: %s",
sstrerror (errno, errbuf, sizeof (errbuf)));
- return (-1);
+ goto failed;
}
else if (pid == 0)
{
int fd_num;
- int fd;
/* Close all file descriptors but the pipe end we need. */
fd_num = getdtablesize ();
- for (fd = 0; fd < fd_num; fd++)
+ for (int fd = 0; fd < fd_num; fd++)
{
if ((fd == fd_pipe_in[0])
|| (fd == fd_pipe_out[1])
close (fd_pipe_err[0]);
return (pid);
+
+failed:
+ close_pipe(fd_pipe_in);
+ close_pipe(fd_pipe_out);
+ close_pipe(fd_pipe_err);
+
+ return (-1);
} /* int fork_child }}} */
static int parse_line (char *buffer) /* {{{ */
{
program_list_t *pl = ((program_list_and_notification_t *) arg)->pl;
notification_t *n = &((program_list_and_notification_t *) arg)->n;
- notification_meta_t *meta;
int fd;
FILE *fh;
int pid;
char errbuf[1024];
ERROR ("exec plugin: fdopen (%i) failed: %s", fd,
sstrerror (errno, errbuf, sizeof (errbuf)));
- kill (pl->pid, SIGTERM);
- pl->pid = 0;
+ kill (pid, SIGTERM);
close (fd);
sfree (arg);
pthread_exit ((void *) 1);
if (strlen (n->type_instance) > 0)
fprintf (fh, "TypeInstance: %s\n", n->type_instance);
- for (meta = n->meta; meta != NULL; meta = meta->next)
+ for (notification_meta_t *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);
static int exec_init (void) /* {{{ */
{
- struct sigaction sa;
+ struct sigaction sa = {
+ .sa_handler = sigchld_handler
+ };
- memset (&sa, '\0', sizeof (sa));
- sa.sa_handler = sigchld_handler;
sigaction (SIGCHLD, &sa, NULL);
return (0);
static int exec_read (void) /* {{{ */
{
- program_list_t *pl;
-
- for (pl = pl_head; pl != NULL; pl = pl->next)
+ for (program_list_t *pl = pl_head; pl != NULL; pl = pl->next)
{
pthread_t t;
pthread_attr_t attr;
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 = pl_head; pl != NULL; pl = pl->next)
+ for (program_list_t *pl = pl_head; pl != NULL; pl = pl->next)
{
pthread_t t;
pthread_attr_t attr;
if (pl->pid != 0)
continue;
- pln = (program_list_and_notification_t *) malloc (sizeof
- (program_list_and_notification_t));
+ pln = malloc (sizeof (*pln));
if (pln == NULL)
{
ERROR ("exec plugin: malloc failed.");