X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fexec.c;h=b8b538b8c765d1f09ea5312b39e384b11306c92b;hb=b5c5890955fa19651ad8b3f48d99364d270a0d8f;hp=63401bec3c4c53f79b6206cf81a3bea3fb870d63;hpb=18e6a1883e6eb739d448e60b9028334c83e0f4d6;p=collectd.git diff --git a/src/exec.c b/src/exec.c index 63401bec..b8b538b8 100644 --- a/src/exec.c +++ b/src/exec.c @@ -22,10 +22,12 @@ #include "collectd.h" #include "common.h" #include "plugin.h" -#include "utils_debug.h" +#include "utils_cmd_putval.h" #include #include +#include +#include #include @@ -37,6 +39,7 @@ typedef struct program_list_s program_list_t; struct program_list_s { char *user; + char *group; char *exec; int pid; program_list_t *next; @@ -45,26 +48,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" @@ -115,6 +98,12 @@ static int exec_config (const char *key, const char *value) pl->next = pl_head; pl_head = pl; + + pl->group = strchr (pl->user, ':'); + if (NULL != pl->group) { + *pl->group = '\0'; + pl->group++; + } } else { @@ -124,80 +113,114 @@ static int exec_config (const char *key, const char *value) return (0); } /* int exec_config */ -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); - - values[0].counter = value; - - vl.values = values; - vl.values_len = 1; - vl.time = time (NULL); - strcpy (vl.host, hostname_g); - strcpy (vl.plugin, "exec"); - strcpy (vl.plugin_instance, ""); - strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance)); - - plugin_dispatch_values ("counter", &vl); -} /* void submit_counter */ - -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); - - values[0].gauge = value; - - vl.values = values; - vl.values_len = 1; - vl.time = time (NULL); - strcpy (vl.host, hostname_g); - strcpy (vl.plugin, "exec"); - strcpy (vl.plugin_instance, ""); - strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance)); - - plugin_dispatch_values ("gauge", &vl); -} /* void submit_counter */ - static void exec_child (program_list_t *pl) { int status; int uid; + int gid; + int egid; char *arg0; struct passwd *sp_ptr; struct passwd sp; - char pwnambuf[2048]; + char nambuf[2048]; + char errbuf[1024]; sp_ptr = NULL; - status = getpwnam_r (pl->user, &sp, pwnambuf, sizeof (pwnambuf), &sp_ptr); + status = getpwnam_r (pl->user, &sp, nambuf, sizeof (nambuf), &sp_ptr); if (status != 0) { - syslog (LOG_ERR, "exec plugin: getpwnam_r failed: %s", strerror (status)); + ERROR ("exec plugin: getpwnam_r failed: %s", + sstrerror (errno, errbuf, sizeof (errbuf))); exit (-1); } if (sp_ptr == NULL) { - syslog (LOG_ERR, "exec plugin: No such user: `%s'", pl->user); + ERROR ("exec plugin: No such user: `%s'", pl->user); exit (-1); } uid = sp.pw_uid; + gid = sp.pw_gid; 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); } + /* 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) { + struct group *gr_ptr = NULL; + struct group gr; + + status = getgrnam_r (pl->group, &gr, nambuf, sizeof (nambuf), &gr_ptr); + if (0 != status) + { + ERROR ("exec plugin: getgrnam_r failed: %s", + sstrerror (errno, errbuf, sizeof (errbuf))); + exit (-1); + } + if (NULL == gr_ptr) + { + ERROR ("exec plugin: No such group: `%s'", pl->group); + exit (-1); + } + + egid = gr.gr_gid; + } + else + { + egid = gid; + } + } /* if (pl->group == NULL) */ + +#if HAVE_SETGROUPS + if (getuid () == 0) + { + gid_t glist[2]; + size_t glist_len; + + glist[0] = gid; + glist_len = 1; + + if (gid != egid) + { + glist[1] = egid; + glist_len = 2; + } + + setgroups (glist_len, glist); + } +#endif /* HAVE_SETGROUPS */ + + status = setgid (gid); + if (status != 0) + { + ERROR ("exec plugin: setgid (%i) failed: %s", + gid, sstrerror (errno, errbuf, sizeof (errbuf))); + exit (-1); + } + + if (egid != -1) + { + status = setegid (egid); + if (status != 0) + { + ERROR ("exec plugin: setegid (%i) failed: %s", + egid, sstrerror (errno, errbuf, sizeof (errbuf))); + exit (-1); + } + } + status = setuid (uid); if (status != 0) { - syslog (LOG_ERR, "exec plugin: setuid failed: %s", strerror (errno)); + ERROR ("exec plugin: setuid (%i) failed: %s", + uid, sstrerror (errno, errbuf, sizeof (errbuf))); exit (-1); } @@ -209,7 +232,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 */ @@ -224,14 +248,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) @@ -254,6 +282,18 @@ static int fork_child (program_list_t *pl) return (fd_pipe[0]); } /* int fork_child */ +static int parse_line (char *buffer) +{ + char *fields[256]; + int fields_num; + + fields[0] = "PUTVAL"; + fields_num = strsplit (buffer, &fields[1], STATIC_ARRAY_SIZE(fields) - 1); + + handle_putval (stdout, fields, fields_num + 1); + return (0); +} /* int parse_line */ + static void *exec_read_one (void *arg) { program_list_t *pl = (program_list_t *) arg; @@ -270,9 +310,11 @@ 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); + pl->pid = 0; close (fd); pthread_exit ((void *) 1); } @@ -280,52 +322,24 @@ static void *exec_read_one (void *arg) while (fgets (buffer, sizeof (buffer), fh) != NULL) { int len; - char *type; - char *type_instance; - char *value; - - DBG ("buffer = %s", buffer); len = strlen (buffer); - if (len < 5) - continue; - - if (buffer[0] == '#') - continue; - - type = buffer; - - type_instance = strchr (type, ','); - if (type_instance == NULL) - continue; - *type_instance = '\0'; - type_instance++; - - if ((strcasecmp ("counter", type) != 0) - && (strcasecmp ("gauge", type) != 0)) - { - syslog (LOG_WARNING, "exec plugin: Received invalid type: %s", type); - continue; - } - value = strchr (type_instance, ','); - if (value == NULL) - continue; - *value = '\0'; - value++; + /* Remove newline from end. */ + while ((len > 0) && ((buffer[len - 1] == '\n') + || (buffer[len - 1] == '\r'))) + buffer[--len] = '\0'; - DBG ("value = %s", value); + DEBUG ("exec plugin: exec_read_one: buffer = %s", buffer); - if (strcasecmp ("counter", type) == 0) - submit_counter (type_instance, atoll (value)); - else - submit_gauge (type_instance, atof (value)); + parse_line (buffer); } /* while (fgets) */ fclose (fh); pl->pid = 0; pthread_exit ((void *) 0); + return (NULL); } /* void *exec_read_one */ static int exec_read (void) @@ -348,12 +362,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 */ /*