Obviously this will only work if rrdcached is running as root which in
authoroetiker <oetiker@a5681a0c-68f1-0310-ab6d-d61299d08faa>
Mon, 8 Mar 2010 17:13:16 +0000 (17:13 +0000)
committeroetiker <oetiker@a5681a0c-68f1-0310-ab6d-d61299d08faa>
Mon, 8 Mar 2010 17:13:16 +0000 (17:13 +0000)
my case it has to be (as upstart can't currently monitor non-root
daemons). As you may have RRD data sources (data loggers) and RRD
consumers (e.g. CGI scripts) that both need to talk to the cache
daemon one solution is to set the group permissions of the socket.

This offer some flexibility over trying to get every RRD user/daemon
running under the same user context. -- Alex Bennee  ajb pitcairn.cambridgebroadband.com

git-svn-id: svn://svn.oetiker.ch/rrdtool/trunk/program@2029 a5681a0c-68f1-0310-ab6d-d61299d08faa

doc/rrdcached.pod
src/rrd_daemon.c

index 0fa12ca..22a74e9 100644 (file)
@@ -9,6 +9,7 @@ rrdcached - Data caching daemon for rrdtool
 B<rrdcached>
 [B<-P>E<nbsp>I<permissions>]
 [B<-l>E<nbsp>I<address>]
+[B<-s>E<nbsp>I<group>]
 [B<-w>E<nbsp>I<timeout>]
 [B<-z>E<nbsp>I<delay>]
 [B<-f>E<nbsp>I<timeout>]
@@ -65,6 +66,15 @@ domain socket B<must> start with a slash in the second case!
 If the B<-l> option is not specified the default address,
 C<unix:/tmp/rrdcached.sock>, will be used.
 
+=item B<-s> I<id>
+
+Set the group permissions of the UNIX domain socket. The option accepts either
+a numeric group id or group name. That group will then have both read and write
+permissions to the socket and therefore able to send commands to the daemon. This
+may be useful in cases where you cannot easily run all RRD processes with the same
+user privileges (e.g. graph generating CGI scripts that typically run in the
+permission context of the web server).
+
 =item B<-P> I<command>[,I<command>[,...]]
 
 Specifies the commands accepted via a network socket. This allows
index 4c84f19..d4cfa94 100644 (file)
 #include <sys/time.h>
 #include <time.h>
 #include <libgen.h>
+#include <grp.h>
 
 #include <glib-2.0/glib.h>
 /* }}} */
@@ -220,6 +221,9 @@ static uid_t daemon_uid;
 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 */
@@ -2326,6 +2330,16 @@ static int open_listen_socket_unix (const listen_socket_t *sock) /* {{{ */
     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)
   {
@@ -2746,7 +2760,7 @@ static int read_options (int argc, char **argv) /* {{{ */
   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)
     {
@@ -2811,6 +2825,37 @@ static int read_options (int argc, char **argv) /* {{{ */
       }
       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;
@@ -3024,6 +3069,7 @@ static int read_options (int argc, char **argv) /* {{{ */
             "  -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"