automatically create the home directory on startup
authorRichard Kettlewell <rjk@greenend.org.uk>
Wed, 17 Oct 2007 19:31:37 +0000 (20:31 +0100)
committerRichard Kettlewell <rjk@greenend.org.uk>
Wed, 17 Oct 2007 19:31:37 +0000 (20:31 +0100)
README
doc/disorder_config.5.in
lib/configuration.c
lib/user.c
lib/user.h
server/disorderd.c

diff --git a/README b/README
index 5be8716..350d7a2 100644 (file)
--- a/README
+++ b/README
@@ -146,16 +146,7 @@ NOTE: If you are upgrading from an earlier version, see README.upgrades.
    suitable; install it in /etc/init.d, adapting it as necessary, and make
    appropriate links from /etc/rc[0-6].d.
 
    suitable; install it in /etc/init.d, adapting it as necessary, and make
    appropriate links from /etc/rc[0-6].d.
 
-7. Make sure the state directory (/var/disorder or /usr/local/var/disorder or
-   as determined by configure) exists and is writable by the jukebox user.
-
-     mkdir -m 755 /var/disorder
-     chown disorder:root /var/disorder
-
-   If you want to use some other directory you must put use the 'home' command
-   in the configuration file.
-
-8. Start the server.
+7. Start the server.
 
    On Linux systems with sysv-style init:
 
 
    On Linux systems with sysv-style init:
 
@@ -166,35 +157,35 @@ NOTE: If you are upgrading from an earlier version, see README.upgrades.
    start up correctly there should be an error message.  Correct the problem
    and try again.
 
    start up correctly there should be an error message.  Correct the problem
    and try again.
 
-9. After a minute it should start to play something.  Try scratching it, as any
+8. After a minute it should start to play something.  Try scratching it, as any
    of the users you set up in step 5:
 
      disorder scratch
 
    The track should stop playing, and (if you set any up) a scratch sound play.
 
    of the users you set up in step 5:
 
      disorder scratch
 
    The track should stop playing, and (if you set any up) a scratch sound play.
 
-10. Add any other users you want to config.private.  Each user's password
-    should be stored in a file in their home directory, ~/.disorder/passwd,
-    which should be readable only by them, and should take the form of a single
-    line:
+9. Add any other users you want to config.private.  Each user's password
+   should be stored in a file in their home directory, ~/.disorder/passwd,
+   which should be readable only by them, and should take the form of a single
+   line:
 
 
-      password MYPASSWORD
+     password MYPASSWORD
 
 
-    (root doesn't need this as the client can read it out of config.private
-    when running as root.)
+   (root doesn't need this as the client can read it out of config.private
+   when running as root.)
 
 
-    Note that the server must be reloaded (e.g. by 'disorder reconfigure')
-    when new users are added.
+   Note that the server must be reloaded (e.g. by 'disorder reconfigure')
+   when new users are added.
 
 
-    Alternatively the administrator can create /etc/disorder/config.USERNAME
-    containing the same thing as above.  It can either be owned by the user and
-    mode 400, or owned by root and the user's group (if you have per-user
-    groups) and mode 440.
+   Alternatively the administrator can create /etc/disorder/config.USERNAME
+   containing the same thing as above.  It can either be owned by the user and
+   mode 400, or owned by root and the user's group (if you have per-user
+   groups) and mode 440.
 
 
-    You can use 'disorder authorize' to automatically pick passwords and
-    create these files.
+   You can use 'disorder authorize' to automatically pick passwords and
+   create these files.
 
 
-11. Optionally source completion.bash from /etc/profile or similar, for
+10. Optionally source completion.bash from /etc/profile or similar, for
     example:
 
       . /usr/local/share/disorder/completion.bash
     example:
 
       . /usr/local/share/disorder/completion.bash
index 26b1efc..aeaef98 100644 (file)
@@ -117,6 +117,7 @@ start up without a valid config file.)
 .B home \fIDIRECTORY\fR
 The home directory for state files.  Defaults to
 .IR pkgstatedir .
 .B home \fIDIRECTORY\fR
 The home directory for state files.  Defaults to
 .IR pkgstatedir .
+The server will create this directory on startup if it does not exist.
 .TP
 .B plugin \fIPATH\fR
 Adds a directory to the plugin path.  (This is also used by the web
 .TP
 .B plugin \fIPATH\fR
 Adds a directory to the plugin path.  (This is also used by the web
index a506ee9..35573c5 100644 (file)
@@ -593,6 +593,19 @@ static const struct conftype
   }                                                            \
 } while(0)
 
   }                                                            \
 } while(0)
 
+static int validate_isabspath(const struct config_state *cs,
+                             int nvec, char **vec) {
+  int n;
+
+  for(n = 0; n < nvec; ++n)
+    if(vec[n][0] != '/') {
+      error(errno, "%s:%d: %s: not an absolute path", 
+           cs->path, cs->line, vec[n]);
+      return -1;
+    }
+  return 0;
+}
+
 static int validate_isdir(const struct config_state *cs,
                          int nvec, char **vec) {
   VALIDATE_FILE(S_ISDIR, "directory");
 static int validate_isdir(const struct config_state *cs,
                          int nvec, char **vec) {
   VALIDATE_FILE(S_ISDIR, "directory");
@@ -863,7 +876,7 @@ static const struct conf conf[] = {
   { C(device),           &type_string,           validate_any },
   { C(gap),              &type_integer,          validate_non_negative },
   { C(history),          &type_integer,          validate_positive },
   { C(device),           &type_string,           validate_any },
   { C(gap),              &type_integer,          validate_non_negative },
   { C(history),          &type_integer,          validate_positive },
-  { C(home),             &type_string,           validate_isdir },
+  { C(home),             &type_string,           validate_isabspath },
   { C(listen),           &type_stringlist,       validate_port },
   { C(lock),             &type_boolean,          validate_any },
   { C(mixer),            &type_string,           validate_ischr },
   { C(listen),           &type_stringlist,       validate_port },
   { C(lock),             &type_boolean,          validate_any },
   { C(mixer),            &type_string,           validate_ischr },
index 2616de3..ec01a33 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * This file is part of DisOrder
 /*
  * This file is part of DisOrder
- * Copyright (C) 2005 Richard Kettlewell
+ * Copyright (C) 2005, 2007 Richard Kettlewell
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
  * USA
  */
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
  * USA
  */
+/** @file lib/user.c
+ * @brief Jukebox user management
+ */
 
 #include <config.h>
 #include "types.h"
 
 #include <sys/types.h>
 
 #include <config.h>
 #include "types.h"
 
 #include <sys/types.h>
+#include <sys/stat.h>
 #include <errno.h>
 #include <pwd.h>
 #include <grp.h>
 #include <errno.h>
 #include <pwd.h>
 #include <grp.h>
 #include "user.h"
 #include "log.h"
 #include "configuration.h"
 #include "user.h"
 #include "log.h"
 #include "configuration.h"
+#include "mem.h"
 
 
+/** @brief Become the jukebox user
+ *
+ * If a jukebox user is configured then becomes that user.
+ */
 void become_mortal(void) {
   struct passwd *pw;
   
 void become_mortal(void) {
   struct passwd *pw;
   
@@ -54,6 +63,41 @@ void become_mortal(void) {
   }
 }
 
   }
 }
 
+/** @brief Create the jukebox state directory
+ *
+ * If the home directory does not exist then creates it and assigns
+ * it suitable permissions.
+ */
+void make_home(void) {
+  struct stat sb;
+  struct passwd *pw;
+  char *home, *p;
+  
+  if(stat(config->home, &sb) < 0) {
+    /* create parent directories */
+    home = xstrdup(config->home);
+    p = home;
+    while(*p) {
+      if(*p == '/' && p > home) {
+        *p = 0;
+        mkdir(home, 0755);
+        *p = '/';
+      }
+      ++p;
+    }
+    /* create the directory itself */
+    if(mkdir(config->home, 02755) < 0)
+      fatal(errno, "error creating %s", config->home);
+    /* make sure it has the right ownership */
+    if(config->user) {
+      if(!(pw = getpwnam(config->user)))
+        fatal(0, "cannot find user %s", config->user);
+      if(chown(config->home, pw->pw_uid, pw->pw_gid) < 0)
+        fatal(errno, "error chowning %s", config->home);
+    }
+  }
+}
+
 /*
 Local Variables:
 c-basic-offset:2
 /*
 Local Variables:
 c-basic-offset:2
index be28a51..8996032 100644 (file)
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
  * USA
  */
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
  * USA
  */
+/** @file lib/user.h
+ * @brief Jukebox user management
+ */
 
 #ifndef USER_H
 #define USER_H
 
 void become_mortal(void);
 
 #ifndef USER_H
 #define USER_H
 
 void become_mortal(void);
+void make_home(void);
 
 #endif /* USER_H */
 
 
 #endif /* USER_H */
 
index f4a1a62..fb31087 100644 (file)
@@ -246,6 +246,8 @@ int main(int argc, char **argv) {
   /* read config */
   if(config_read(1))
     fatal(0, "cannot read configuration");
   /* read config */
   if(config_read(1))
     fatal(0, "cannot read configuration");
+  /* make sure the home directory exists and has suitable permissions */
+  make_home();
   /* Start the speaker process (as root! - so it can choose its nice value) */
   speaker_setup(ev);
   /* set server nice value _after_ starting the speaker, so that they
   /* Start the speaker process (as root! - so it can choose its nice value) */
   speaker_setup(ev);
   /* set server nice value _after_ starting the speaker, so that they