chiark / gitweb /
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 5be87163166ca66028d7c1f85ea6feecf378a2ac..350d7a274a5accb57417eca6fb9a9a11994c09d6 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 26b1efc5841eb48e150e374a775501c4c4a0f46b..aeaef98cd9fbf377490f6e0fb6eb8808daa1375f 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 a506ee948fe8439167324c928017c341aca36d93..35573c5c15dc6d03c26248315cc509132f21facb 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 2616de3494f97b2ca6f0a3b50e7a69d02b4eb44a..ec01a339bc6a7259294b07d9b98d8d51ce426672 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 be28a5146cf4c2d45f77ad5edd05d987745beaa8..8996032e55065c1c63327f408743d5de5073711b 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 f4a1a627176bce3f219ecf65b40a8d49e799f2d2..fb31087ba94ef4f1f8f8ef46df078bbeaa1b0e5a 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