#include <sys/time.h>
#include <time.h>
#include <libgen.h>
+#include <grp.h>
#include <glib-2.0/glib.h>
/* }}} */
static listen_socket_t *listen_fds = NULL;
static size_t listen_fds_num = 0;
+static gboolean set_socket_group = FALSE;
+static gid_t socket_group;
+
enum {
RUNNING, /* normal operation */
FLUSHING, /* flushing remaining values */
static pthread_mutex_t stats_lock = PTHREAD_MUTEX_INITIALIZER;
/* Journaled updates */
+#define JOURNAL_REPLAY(s) ((s) == NULL)
#define JOURNAL_BASE "rrd.journal"
static journal_set *journal_cur = NULL;
static journal_set *journal_old = NULL;
char buffer[CMD_MAX];
int len;
- if (sock == NULL) return 0; /* journal replay mode */
+ if (JOURNAL_REPLAY(sock)) return 0;
if (sock->batch_start) return 0; /* no extra info returned when in BATCH */
va_start(argp, fmt);
ssize_t wrote;
int rclen, len;
- if (sock == NULL) return rc; /* journal replay mode */
+ if (JOURNAL_REPLAY(sock)) return rc;
if (sock->batch_start)
{
assert(file != NULL);
if (!config_write_base_only
- || sock == NULL /* journal replay */
+ || JOURNAL_REPLAY(sock)
|| config_base_dir == NULL)
return 1;
if (found == TRUE)
{
- if (sock != NULL)
+ if (!JOURNAL_REPLAY(sock))
journal_write("forget", file);
return send_response(sock, RESP_OK, "Gone!\n");
cache_item_t *ci;
/* save it for the journal later */
- strncpy(orig_buf, buffer, sizeof(orig_buf)-1);
+ if (!JOURNAL_REPLAY(sock))
+ strncpy(orig_buf, buffer, buffer_size);
status = buffer_get_field (&buffer, &buffer_size, &file);
if (status != 0)
assert (ci != NULL);
/* don't re-write updates in replay mode */
- if (sock != NULL)
+ if (!JOURNAL_REPLAY(sock))
journal_write("update", orig_buf);
while (buffer_size > 0)
{
ssize_t i;
- if (sock == NULL) /* journal replay */
+ if (JOURNAL_REPLAY(sock))
return (1);
if (cmd == NULL)
/* check whether commands are received in the expected context */
static int command_check_context(listen_socket_t *sock, command_t *cmd)
{
- if (sock == NULL)
+ if (JOURNAL_REPLAY(sock))
return (cmd->context & CMD_CONTEXT_JOURNAL);
else if (sock->batch_start)
return (cmd->context & CMD_CONTEXT_BATCH);
return send_response(sock, RESP_OK, resp_txt);
} /* }}} int handle_request_help */
-/* if sock==NULL, we are in journal replay mode */
static int handle_request (DISPATCH_PROTO) /* {{{ */
{
char *buffer_ptr = buffer;
return (-1);
}
+ /* tweak the sockets group ownership */
+ if (set_socket_group)
+ {
+ if ( (chown(path, getuid(), socket_group) != 0) ||
+ (chmod(path, (S_IRUSR|S_IWUSR|S_IXUSR | S_IRGRP|S_IWGRP)) != 0) )
+ {
+ fprintf(stderr, "rrdcached: failed to set socket group permissions (%s)\n", strerror(errno));
+ }
+ }
+
status = listen (fd, /* backlog = */ 10);
if (status != 0)
{
char **permissions = NULL;
size_t permissions_len = 0;
- while ((option = getopt(argc, argv, "gl:P:f:w:z:t:Bb:p:Fj:h?")) != -1)
+ while ((option = getopt(argc, argv, "gl:s:P:f:w:z:t:Bb:p:Fj:h?")) != -1)
{
switch (option)
{
}
break;
+ /* set socket group permissions */
+ case 's':
+ {
+ gid_t group_gid;
+ struct group *grp;
+
+ group_gid = strtoul(optarg, NULL, 10);
+ if (errno != EINVAL && group_gid>0)
+ {
+ /* we were passed a number */
+ grp = getgrgid(group_gid);
+ }
+ else
+ {
+ grp = getgrnam(optarg);
+ }
+
+ if (grp)
+ {
+ socket_group = grp->gr_gid;
+ set_socket_group = TRUE;
+ }
+ else
+ {
+ /* no idea what the user wanted... */
+ fprintf (stderr, "read_options: couldn't map \"%s\" to a group, Sorry\n", optarg);
+ return (5);
+ }
+ }
+ break;
+
case 'P':
{
char *optcopy;
" -g Do not fork and run in the foreground.\n"
" -j <dir> Directory in which to create the journal files.\n"
" -F Always flush all updates at shutdown\n"
+ " -s <id|name> Make socket g+rw to named group\n"
"\n"
"For more information and a detailed description of all options "
"please refer\n"