X-Git-Url: https://git.octo.it/?p=collectd.git;a=blobdiff_plain;f=src%2Fexec.c;h=f8707d4181269d82d4a87d1afb9b496ef0914a8f;hp=162565224b2fdc9d5237bc91e3c026ddc25c9bb0;hb=48efd3deb4c9139fd060ff3d289896e9031bcc7c;hpb=41532dee9fc88023e67d6a7e73d7d99617f5148f diff --git a/src/exec.c b/src/exec.c index 16256522..f8707d41 100644 --- a/src/exec.c +++ b/src/exec.c @@ -26,13 +26,16 @@ #define _DEFAULT_SOURCE #define _BSD_SOURCE /* For setgroups */ +/* _GNU_SOURCE is needed in Linux to use execvpe */ +#define _GNU_SOURCE + #include "collectd.h" -#include "common.h" #include "plugin.h" +#include "utils/common/common.h" -#include "utils_cmd_putnotif.h" -#include "utils_cmd_putval.h" +#include "utils/cmds/putnotif.h" +#include "utils/cmds/putval.h" #include #include @@ -43,6 +46,8 @@ #include #endif +extern char **environ; + #define PL_NORMAL 0x01 #define PL_NOTIF_ACTION 0x02 @@ -245,29 +250,9 @@ static int exec_config(oconfig_item_t *ci) /* {{{ */ return 0; } /* int exec_config }}} */ -static void set_environment(void) /* {{{ */ -{ - char buffer[1024]; - -#ifdef HAVE_SETENV - snprintf(buffer, sizeof(buffer), "%.3f", - CDTIME_T_TO_DOUBLE(plugin_get_interval())); - setenv("COLLECTD_INTERVAL", buffer, /* overwrite = */ 1); - - sstrncpy(buffer, hostname_g, sizeof(buffer)); - setenv("COLLECTD_HOSTNAME", buffer, /* overwrite = */ 1); -#else - snprintf(buffer, sizeof(buffer), "COLLECTD_INTERVAL=%.3f", - CDTIME_T_TO_DOUBLE(plugin_get_interval())); - putenv(buffer); - - snprintf(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 uid, - int gid, int egid) /* {{{ */ +__attribute__((noreturn)) static void exec_child(program_list_t *pl, + char **envp, int uid, int gid, + int egid) /* {{{ */ { int status; @@ -308,7 +293,12 @@ __attribute__((noreturn)) static void exec_child(program_list_t *pl, int uid, exit(-1); } +#ifdef HAVE_EXECVPE + execvpe(pl->exec, pl->argv, envp); +#else + environ = envp; execvp(pl->exec, pl->argv); +#endif ERROR("exec plugin: Failed to execute ``%s'': %s", pl->exec, STRERRNO); exit(-1); @@ -359,8 +349,8 @@ static int getegr_id(program_list_t *pl, int gid) /* {{{ */ if (pl->group == NULL) { return -1; } - if (strcmp(pl->group,"") == 0) { - return gid; + if (strcmp(pl->group, "") == 0) { + return gid; } struct group *gr_ptr = NULL; struct group gr; @@ -376,22 +366,22 @@ static int getegr_id(program_list_t *pl, int gid) /* {{{ */ do { temp = realloc(grbuf, grbuf_size); - if ( temp == NULL ) { + if (temp == NULL) { ERROR("exec plugin: getegr_id for %s: realloc buffer[%ld] failed ", - pl->group, grbuf_size); + pl->group, grbuf_size); sfree(grbuf); return -2; } grbuf = temp; - if(getgrnam_r(pl->group, &gr, grbuf, grbuf_size, &gr_ptr) == 0) { + if (getgrnam_r(pl->group, &gr, grbuf, grbuf_size, &gr_ptr) == 0) { sfree(grbuf); if (gr_ptr == NULL) { - ERROR("exec plugin: No such group: `%s'", pl->group); + ERROR("exec plugin: No such group: `%s'", pl->group); return -1; } return gr.gr_gid; - } else if ( errno == ERANGE) { - grbuf_size += grbuf_size; // increment buffer size and try again + } else if (errno == ERANGE) { + grbuf_size += grbuf_size; // increment buffer size and try again } else { ERROR("exec plugin: getegr_id failed %s", STRERRNO); sfree(grbuf); @@ -466,15 +456,42 @@ static int fork_child(program_list_t *pl, int *fd_in, int *fd_out, goto failed; } + double interval = CDTIME_T_TO_DOUBLE(plugin_get_interval()); + pid = fork(); if (pid < 0) { ERROR("exec plugin: fork failed: %s", STRERRNO); goto failed; } else if (pid == 0) { - int fd_num; + char interval_buf[128]; + snprintf(interval_buf, sizeof(interval_buf), "COLLECTD_INTERVAL=%.3f", + interval); + + /* max hostname len is 255, so this should be enough */ + char hostname_buf[300]; + snprintf(hostname_buf, sizeof(hostname_buf), "COLLECTD_HOSTNAME=%s", + hostname_g); + + size_t env_size = 0; + while (environ[env_size] != NULL) { + ++env_size; + } + + /* Copy the environment variables */ + char *envp[env_size + 3]; + size_t envp_idx; + for (envp_idx = 0; environ[envp_idx] != NULL && envp_idx < env_size; + ++envp_idx) { + envp[envp_idx] = environ[envp_idx]; + } + + /* Add the collectd environment variables */ + envp[envp_idx++] = interval_buf; + envp[envp_idx++] = hostname_buf; + envp[envp_idx++] = NULL; /* Close all file descriptors but the pipe end we need. */ - fd_num = getdtablesize(); + int fd_num = getdtablesize(); for (int fd = 0; fd < fd_num; fd++) { if ((fd == fd_pipe_in[0]) || (fd == fd_pipe_out[1]) || (fd == fd_pipe_err[1])) @@ -500,12 +517,10 @@ static int fork_child(program_list_t *pl, int *fd_in, int *fd_out, close(fd_pipe_err[1]); } - set_environment(); - /* Unblock all signals */ reset_signal_mask(); - exec_child(pl, uid, gid, egid); + exec_child(pl, envp, uid, gid, egid); /* does not return */ } @@ -730,8 +745,9 @@ static void *exec_notification_one(void *arg) /* {{{ */ else if (n->severity == NOTIF_OKAY) severity = "OKAY"; - fprintf(fh, "Severity: %s\n" - "Time: %.3f\n", + fprintf(fh, + "Severity: %s\n" + "Time: %.3f\n", severity, CDTIME_T_TO_DOUBLE(n->time)); /* Print the optional fields */ @@ -894,6 +910,11 @@ static int exec_shutdown(void) /* {{{ */ INFO("exec plugin: Sent SIGTERM to %hu", (unsigned short int)pl->pid); } + for (int i = 0; pl->argv[i] != NULL; i++) { + sfree(pl->argv[i]); + } + sfree(pl->argv); + sfree(pl->exec); sfree(pl->user); sfree(pl);