X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fexec.c;h=2c99ce2a7f296395b3e682d2f85ada85af95a5a9;hb=436dacdb577300ad6ed4692c95089f22ae98de3c;hp=246584b71436b907da46e40d0de803e8a63950a6;hpb=55ffaf9ad7c8b180ac0192adb1a6ff6adc72c5a3;p=collectd.git diff --git a/src/exec.c b/src/exec.c index 246584b7..2c99ce2a 100644 --- a/src/exec.c +++ b/src/exec.c @@ -39,6 +39,7 @@ #include #include +#include #ifdef HAVE_SYS_CAPABILITY_H #include #endif @@ -78,9 +79,14 @@ typedef struct program_list_and_notification_s { } program_list_and_notification_t; /* + * constants + */ +const long int MAX_GRBUF_SIZE = 65536; + +/* * Private variables */ -static program_list_t *pl_head = NULL; +static program_list_t *pl_head; static pthread_mutex_t pl_lock = PTHREAD_MUTEX_INITIALIZER; /* @@ -108,26 +114,26 @@ 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); - return (-1); + return -1; } if (ci->values_num < 2) { WARNING("exec plugin: The config option `%s' needs at least two " "arguments.", ci->key); - return (-1); + 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); - return (-1); + return -1; } pl = calloc(1, sizeof(*pl)); if (pl == NULL) { ERROR("exec plugin: calloc failed."); - return (-1); + return -1; } if (strcasecmp("NotificationExec", ci->key) == 0) @@ -139,7 +145,7 @@ static int exec_config_exec(oconfig_item_t *ci) /* {{{ */ if (pl->user == NULL) { ERROR("exec plugin: strdup failed."); sfree(pl); - return (-1); + return -1; } pl->group = strchr(pl->user, ':'); @@ -153,7 +159,7 @@ static int exec_config_exec(oconfig_item_t *ci) /* {{{ */ ERROR("exec plugin: strdup failed."); sfree(pl->user); sfree(pl); - return (-1); + return -1; } pl->argv = calloc(ci->values_num, sizeof(*pl->argv)); @@ -162,7 +168,7 @@ static int exec_config_exec(oconfig_item_t *ci) /* {{{ */ sfree(pl->exec); sfree(pl->user); sfree(pl); - return (-1); + return -1; } { @@ -179,7 +185,7 @@ static int exec_config_exec(oconfig_item_t *ci) /* {{{ */ sfree(pl->exec); sfree(pl->user); sfree(pl); - return (-1); + return -1; } for (i = 1; i < (ci->values_num - 1); i++) { @@ -187,8 +193,7 @@ static int exec_config_exec(oconfig_item_t *ci) /* {{{ */ pl->argv[i] = strdup(ci->values[i + 1].value.string); } else { if (ci->values[i + 1].type == OCONFIG_TYPE_NUMBER) { - ssnprintf(buffer, sizeof(buffer), "%lf", - ci->values[i + 1].value.number); + snprintf(buffer, sizeof(buffer), "%lf", ci->values[i + 1].value.number); } else { if (ci->values[i + 1].value.boolean) sstrncpy(buffer, "true", sizeof(buffer)); @@ -213,7 +218,7 @@ static int exec_config_exec(oconfig_item_t *ci) /* {{{ */ sfree(pl->exec); sfree(pl->user); sfree(pl); - return (-1); + return -1; } for (i = 0; pl->argv[i] != NULL; i++) { @@ -223,7 +228,7 @@ static int exec_config_exec(oconfig_item_t *ci) /* {{{ */ pl->next = pl_head; pl_head = pl; - return (0); + return 0; } /* int exec_config_exec }}} */ static int exec_config(oconfig_item_t *ci) /* {{{ */ @@ -238,7 +243,7 @@ static int exec_config(oconfig_item_t *ci) /* {{{ */ } } /* for (i) */ - return (0); + return 0; } /* int exec_config }}} */ static void set_environment(void) /* {{{ */ @@ -246,18 +251,18 @@ static void set_environment(void) /* {{{ */ char buffer[1024]; #ifdef HAVE_SETENV - ssnprintf(buffer, sizeof(buffer), "%.3f", - CDTIME_T_TO_DOUBLE(plugin_get_interval())); + 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 - ssnprintf(buffer, sizeof(buffer), "COLLECTD_INTERVAL=%.3f", - CDTIME_T_TO_DOUBLE(plugin_get_interval())); + snprintf(buffer, sizeof(buffer), "COLLECTD_INTERVAL=%.3f", + CDTIME_T_TO_DOUBLE(plugin_get_interval())); putenv(buffer); - ssnprintf(buffer, sizeof(buffer), "COLLECTD_HOSTNAME=%s", hostname_g); + snprintf(buffer, sizeof(buffer), "COLLECTD_HOSTNAME=%s", hostname_g); putenv(buffer); #endif } /* }}} void set_environment */ @@ -266,7 +271,6 @@ __attribute__((noreturn)) static void exec_child(program_list_t *pl, int uid, int gid, int egid) /* {{{ */ { int status; - char errbuf[1024]; #if HAVE_SETGROUPS if (getuid() == 0) { @@ -287,31 +291,27 @@ __attribute__((noreturn)) static void exec_child(program_list_t *pl, int uid, status = setgid(gid); if (status != 0) { - ERROR("exec plugin: setgid (%i) failed: %s", gid, - sstrerror(errno, errbuf, sizeof(errbuf))); + ERROR("exec plugin: setgid (%i) failed: %s", gid, STRERRNO); exit(-1); } if (egid != -1) { status = setegid(egid); if (status != 0) { - ERROR("exec plugin: setegid (%i) failed: %s", egid, - sstrerror(errno, errbuf, sizeof(errbuf))); + ERROR("exec plugin: setegid (%i) failed: %s", egid, STRERRNO); exit(-1); } } status = setuid(uid); if (status != 0) { - ERROR("exec plugin: setuid (%i) failed: %s", uid, - sstrerror(errno, errbuf, sizeof(errbuf))); + ERROR("exec plugin: setuid (%i) failed: %s", uid, STRERRNO); exit(-1); } execvp(pl->exec, pl->argv); - ERROR("exec plugin: Failed to execute ``%s'': %s", pl->exec, - sstrerror(errno, errbuf, sizeof(errbuf))); + ERROR("exec plugin: Failed to execute ``%s'': %s", pl->exec, STRERRNO); exit(-1); } /* void exec_child }}} */ @@ -325,14 +325,12 @@ static void reset_signal_mask(void) /* {{{ */ 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); + ERROR("exec plugin: pipe failed: %s", STRERRNO); + return -1; } return 0; @@ -359,7 +357,6 @@ static int fork_child(program_list_t *pl, int *fd_in, int *fd_out, 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; @@ -371,7 +368,7 @@ static int fork_child(program_list_t *pl, int *fd_in, int *fd_out, struct passwd sp; if (pl->pid != 0) - return (-1); + return -1; long int nambuf_size = sysconf(_SC_GETPW_R_SIZE_MAX); if (nambuf_size <= 0) @@ -388,7 +385,7 @@ static int fork_child(program_list_t *pl, int *fd_in, int *fd_out, status = getpwnam_r(pl->user, &sp, nambuf, sizeof(nambuf), &sp_ptr); if (status != 0) { ERROR("exec plugin: Failed to get user information for user ``%s'': %s", - pl->user, sstrerror(status, errbuf, sizeof(errbuf))); + pl->user, STRERROR(status)); goto failed; } @@ -407,8 +404,8 @@ static int fork_child(program_list_t *pl, int *fd_in, int *fd_out, /* The group configured in the configfile is set as effective group, because * this way the forked process can (re-)gain the user's primary group. */ egid = -1; - if (NULL != pl->group) { - if ('\0' != *pl->group) { + if (pl->group != NULL) { + if (*pl->group != '\0') { struct group *gr_ptr = NULL; struct group gr; @@ -417,21 +414,65 @@ static int fork_child(program_list_t *pl, int *fd_in, int *fd_out, grbuf_size = sysconf(_SC_PAGESIZE); if (grbuf_size <= 0) grbuf_size = 4096; - char grbuf[grbuf_size]; - status = getgrnam_r(pl->group, &gr, grbuf, sizeof(grbuf), &gr_ptr); - if (0 != status) { - ERROR("exec plugin: Failed to get group information " - "for group ``%s'': %s", - pl->group, sstrerror(status, errbuf, sizeof(errbuf))); - goto failed; + long int size; + size = grbuf_size; + char *temp = NULL; + char *grbuf = NULL; + int getgr_failed = 0; + grbuf = malloc(size); + if (grbuf == NULL) { + ERROR("exec plugin: get group information for '%s' failed: buffer " + "malloc() failed", + pl->group); + getgr_failed = 1; + goto gr_finally; + } + int status; + while ((status = getgrnam_r(pl->group, &gr, grbuf, size, &gr_ptr)) != 0) { + switch (errno) { + case ERANGE: + if ((size + grbuf_size) < size || + (size + grbuf_size) > MAX_GRBUF_SIZE) { + ERROR("exec plugin: get group information for '%s' max buffer " + "limit (%ld) reached \n", + pl->group, MAX_GRBUF_SIZE); + getgr_failed = 1; + goto gr_finally; + } + /* grow the buffer by 'grbuf_size' each time getgrnamr fails */ + size += grbuf_size; + temp = realloc(grbuf, size); + if (temp == NULL) { + ERROR("exec plugin: get group information for '%s' realloc() " + "buffer to (%ld) failed ", + pl->group, size); + getgr_failed = 1; + goto gr_finally; + } + grbuf = temp; + break; + default: + ERROR("exec plugin: default errno: get group information for '%s' " + "failed : %s", + pl->group, sstrerror(status, errbuf, sizeof(errbuf))); + getgr_failed = 1; + goto gr_finally; + } } - if (NULL == gr_ptr) { + if (gr_ptr == NULL) { ERROR("exec plugin: No such group: `%s'", pl->group); - goto failed; + getgr_failed = 1; + goto gr_finally; } - egid = gr.gr_gid; + gr_finally: + free(grbuf); + DEBUG("exec plugin: release grbuf memory "); + grbuf = NULL; + if (getgr_failed > 0) { + goto failed; + } } else { egid = gid; } @@ -439,8 +480,7 @@ static int fork_child(program_list_t *pl, int *fd_in, int *fd_out, pid = fork(); if (pid < 0) { - ERROR("exec plugin: fork failed: %s", - sstrerror(errno, errbuf, sizeof(errbuf))); + ERROR("exec plugin: fork failed: %s", STRERRNO); goto failed; } else if (pid == 0) { int fd_num; @@ -500,26 +540,26 @@ static int fork_child(program_list_t *pl, int *fd_in, int *fd_out, else close(fd_pipe_err[0]); - return (pid); + return pid; failed: close_pipe(fd_pipe_in); close_pipe(fd_pipe_out); close_pipe(fd_pipe_err); - return (-1); + return -1; } /* int fork_child }}} */ static int parse_line(char *buffer) /* {{{ */ { if (strncasecmp("PUTVAL", buffer, strlen("PUTVAL")) == 0) - return (cmd_handle_putval(stdout, buffer)); + return cmd_handle_putval(stdout, buffer); else if (strncasecmp("PUTNOTIF", buffer, strlen("PUTNOTIF")) == 0) - return (handle_putnotif(stdout, buffer)); + return handle_putnotif(stdout, buffer); else { ERROR("exec plugin: Unable to parse command, ignoring line: \"%s\"", buffer); - return (-1); + return -1; } } /* int parse_line }}} */ @@ -668,7 +708,7 @@ static void *exec_read_one(void *arg) /* {{{ */ close(fd_err); pthread_exit((void *)0); - return (NULL); + return NULL; } /* void *exec_read_one }}} */ static void *exec_notification_one(void *arg) /* {{{ */ @@ -689,9 +729,7 @@ static void *exec_notification_one(void *arg) /* {{{ */ fh = fdopen(fd, "w"); if (fh == NULL) { - char errbuf[1024]; - ERROR("exec plugin: fdopen (%i) failed: %s", fd, - sstrerror(errno, errbuf, sizeof(errbuf))); + ERROR("exec plugin: fdopen (%i) failed: %s", fd, STRERRNO); kill(pid, SIGTERM); close(fd); sfree(arg); @@ -750,7 +788,7 @@ static void *exec_notification_one(void *arg) /* {{{ */ n->meta = NULL; sfree(arg); pthread_exit((void *)0); - return (NULL); + return NULL; } /* void *exec_notification_one }}} */ static int exec_init(void) /* {{{ */ @@ -776,7 +814,7 @@ static int exec_init(void) /* {{{ */ } #endif - return (0); + return 0; } /* int exec_init }}} */ static int exec_read(void) /* {{{ */ @@ -800,11 +838,15 @@ static int exec_read(void) /* {{{ */ pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - plugin_thread_create(&t, &attr, exec_read_one, (void *)pl, "exec read"); + int status = + plugin_thread_create(&t, &attr, exec_read_one, (void *)pl, "exec read"); + if (status != 0) { + ERROR("exec plugin: plugin_thread_create failed."); + } pthread_attr_destroy(&attr); } /* for (pl) */ - return (0); + return 0; } /* int exec_read }}} */ static int exec_notification(const notification_t *n, /* {{{ */ @@ -839,12 +881,15 @@ static int exec_notification(const notification_t *n, /* {{{ */ pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - plugin_thread_create(&t, &attr, exec_notification_one, (void *)pln, - "exec notify"); + int status = plugin_thread_create(&t, &attr, exec_notification_one, + (void *)pln, "exec notify"); + if (status != 0) { + ERROR("exec plugin: plugin_thread_create failed."); + } pthread_attr_destroy(&attr); } /* for (pl) */ - return (0); + return 0; } /* }}} int exec_notification */ static int exec_shutdown(void) /* {{{ */ @@ -868,7 +913,7 @@ static int exec_shutdown(void) /* {{{ */ } /* while (pl) */ pl_head = NULL; - return (0); + return 0; } /* int exec_shutdown }}} */ void module_register(void) { @@ -879,7 +924,3 @@ void module_register(void) { /* user_data = */ NULL); plugin_register_shutdown("exec", exec_shutdown); } /* void module_register */ - -/* - * vim:shiftwidth=2:softtabstop=2:tabstop=8:fdm=marker - */