chiark / gitweb /
Merge MDW's one-pass track picker
[disorder] / scripts / setup.in
index 921cedf40a63512dae74653e3f374781f5ce7647..3bc0b45ae8d3b56b79b885abee76ba58ab499c12 100755 (executable)
 
 set -e
 
+while [ $# -gt 0 ]; do
+  opt="$1"
+  shift
+  case "$opt" in
+  -h | --help )
+    cat  <<EOF
+
+Usage:
+  scripts/setup [OPTIONS]
+
+Options:
+  --root ROOT             Add a root (can be used multiple times)
+  --encoding ENCODING     Filename encoding
+  --port PORT             TCP port to listen on or 'none'
+  --smtp-server HOSTNAME  SMTP server
+  --email ADDRESS         Origin email address
+  --register y|n          Enable/disable online registration
+  --play local|network    Choose local or network play
+  --mcast ADDRESS PORT    Set multicast address and port for --play network
+  -h, --help              Display this message
+
+Sets up a basic DisOrder installation.  You must have run 'make install'
+first.  Use scripts/teardown to stop the server and deconfigure.
+
+EOF
+    exit 0
+    ;;
+  --version | -V )
+    echo "DisOrder scripts/setup _version_"
+    exit 0
+    ;;
+  --root )
+    roots="$roots $1"
+    shift
+    ;;
+  --encoding )
+    encoding="$1"
+    shift
+    ;;
+  --port )
+    port="$1"
+    shift
+    ;;
+  --smtp-server )
+    smtp_server="$1"
+    shift
+    ;;
+  --email )
+    mail_sender="$1"
+    shift
+    ;;
+  --register )
+    register="$1"
+    shift
+    ;;
+  --play )
+    play="$1"
+    shift
+    ;;
+  --mcast )
+    play=network
+    mcast_address="$1"
+    shift
+    mcast_port="$1"
+    shift
+    ;;
+  * )
+    echo >&2 "ERROR: unknown option '$opt'"
+    exit 1
+    ;;
+  esac
+done
+
 echo
 echo ------------------------------------------------------------------------
 echo "DisOrder setup script"
 
 case $(uname -s) in
 Darwin )
-  os=mac
-  user=daemon
-  group=daemon
+  echo "Mac OS X detected"
+  os=Mac
+  user=jukebox
+  group=jukebox
+  ;;
+FreeBSD )
+  echo "FreeBSD detected"
+  os=FreeBSD
+  user=jukebox
+  group=jukebox
+  ;;
+Linux )
+  if grep Debian /etc/issue >/dev/null 2>&1; then
+    echo "You appear to be running Debian - please use .debs instead"
+    echo
+  elif grep Ubuntu /etc/issue >/dev/null 2>&1; then
+    echo "You appear to be running Ubuntu - please use .debs instead"
+    echo
+  fi
+  echo "Linux detected"
+  os=Linux
+  user=jukebox
+  group=jukebox
   ;;
 * )
+  echo 
+  echo "WARNING: unknown operating system '$(uname -s)'"
+  echo "This script won't be able to do all setup on this platform"
   os=unknown
   user=daemon
   group=daemon
@@ -41,32 +137,31 @@ esac
 echo
 echo "This script will:"
 echo " - overwrite any existing configuration"
-case $os in
-mac )
-  echo " - set the server up to be run at boot time"
-  echo " - start the server"
-  ;;
-esac
+echo " - set the server up to be run at boot time"
+echo " - start the server"
+echo " - set up the web interface"
 echo
 echo "If this is not what you want, press ^C."
 echo ------------------------------------------------------------------------
 
-while :; do
-  echo
-  echo "What directory or directories contain your music files:"
-  echo "(enter one or more directories separated by spaces)"
-  read -r roots
-  ok=true
-  for root in $roots; do
-    if [ ! -d $root ]; then
-      echo "'$root' does not exist"
-      ok=false
+if [ -z "$roots" ]; then
+  while :; do
+    echo
+    echo "What directory or directories contain your music files:"
+    echo "(enter one or more directories separated by spaces)"
+    read -r roots
+    ok=true
+    for root in $roots; do
+      if [ ! -d $root ]; then
+       echo "'$root' does not exist"
+       ok=false
+      fi
+    done
+    if $ok; then
+      break
     fi
   done
-  if $ok; then
-    break
-  fi
-done
+fi
 
 if [ -z "$encoding" ]; then
   echo 
@@ -75,32 +170,107 @@ if [ -z "$encoding" ]; then
   read -r encoding
 fi
 
-while :; do
+if [ -z "$port" ]; then
+  while :; do
+    echo
+    echo "What TCP port should DisOrder listen on?"
+    echo "(enter 'none' for none)"
+    read -r port
+    case $port in
+    none )
+      break
+      ;;
+    [^0-9] )
+      echo "'$port' is not a valid port number"
+      continue
+      ;;
+    * )
+      break
+      ;;
+    esac
+  done
+fi
+
+if [ -z "$play" ]; then
+  while :; do
+    echo
+    echo "How do you want to play sound?  Enter 'local' to use a local sound"
+    echo "device or 'network' to multicast sound across your network."
+    read -r play
+    case $play in
+    'local' | network )
+      break
+      ;;
+    * )
+      echo "Enter 'local' or 'network'"
+      continue
+      ;;
+    esac
+  done
+fi
+
+if [ "x$play" = xnetwork ]; then
+  if [ -z "$mcast_address" ]; then
+    echo
+    echo "Enter destination address for network transmission"
+    echo "(e.g. a multicast address)"
+    read -r mcast_address
+  fi
+  if [ -z "$mcast_port" ]; then
+    while :; do
+      echo
+      echo "Enter destination port for network transmission"
+      read -r mcast_port
+      case $mcast_port in
+      none )
+       break
+       ;;
+      [^0-9] )
+       echo "'$mcast_port' is not a valid port number"
+       continue
+       ;;
+      * )
+       break
+       ;;
+      esac
+    done
+  fi
+fi
+
+if [ -z "$smtp_server" ]; then
   echo
-  echo "What TCP port should DisOrder listen on?"
-  echo "(enter 'none' for none)"
-  read -r port
-  case $port in
-  none )
-    break
-    ;;
-  [^0-9] )
-    echo "'$port' is not a valid port number"
-    continue
-    ;;
-  * )
-    break
-    ;;
-  esac
-done
+  echo "What host should DisOrder use as an SMTP server?"
+  read -r smtp_server
+fi
 
-echo
-echo "What host should DisOrder use as an SMTP server?"
-read -r smtp_server
-  
-echo
-echo "What address should mail from DisOrder come from?"
-read -r mail_sender
+if [ -z "$mail_sender" ]; then
+  while :; do
+    echo
+    echo "What address should mail from DisOrder come from?"
+    read -r mail_sender
+    case "$mail_sender" in
+    *@* )
+      break
+      ;;
+    * )
+      echo "Email address must contain an '@' sign"
+      ;;
+    esac
+  done
+fi
+
+if [ -z "$register" ]; then
+  while :; do
+    echo
+    echo "Do you want to enable online registration?  (Enter 'y' or 'n')"
+    read -r register
+    case $reguser in
+    y | n )
+      break
+      ;;
+    esac
+  done
+fi
 
 echo
 echo "Proposed DisOrder setup:"
@@ -112,6 +282,10 @@ else
 fi
 echo " SMTP Server:           $smtp_server"
 echo " Sender address:        $mail_sender"
+echo " Online registration:   $register"
+if [ $play = network ]; then
+  echo " Send sound to:         $mcast_address port $mcast_port"
+fi
 
 echo "Is this OK?  (Enter 'y' or 'n')"
 read -r ok
@@ -138,6 +312,9 @@ echo "user $user" >> pkgconfdir/config.new
 if [ $port != none ]; then
   echo "listen 0.0.0.0 $port" >> pkgconfdir/config.new
 fi
+if [ $play = network ]; then
+  echo "broadcast $mcast_address $mcast_port" >> pkgconfdir/config.new
+fi
 echo "smtp_server $smtp_server" >> pkgconfdir/config.new
 echo "mail_sender $mail_sender" >> pkgconfdir/config.new
 
@@ -166,33 +343,220 @@ if [ ! -f pkgconfdir/options.user ]; then
   touch pkgconfdir/options.user
 fi
 
+# pick ID1 ID2 ... IDn
+# Echoes an ID matching none of ID1..IDn
+pick() {
+  local n
+  n=250                                # better not choose 0!
+  while :; do
+    ok=true
+    for k in "$@"; do
+      if [ $n = $k ]; then
+        ok=false
+        break
+      fi
+    done
+    if $ok; then
+      echo $n
+      return
+    fi
+    n=$((1+$n))
+  done
+}
+
+case $os in
+Mac )
+  # Apple don't seem to believe in creating a user as a discrete operation
+  if dscl . -read /Groups/$group >/dev/null 2>&1; then
+    echo "$group group already exists"
+  else
+    echo "Creating $group group"
+    gids=$(dscl . -list /Groups PrimaryGroupID|awk '{print $2}')
+    gid=$(pick $gids)
+    echo "(picked gid $gid)"
+    dscl . -create /Groups/$group
+    dscl . -create /Groups/$group PrimaryGroupID $gid
+    dscl . -create /Groups/$group Password \*
+  fi
+  if dscl . -read /Users/$user >/dev/null 2>&1; then
+    echo "$user user already exists"
+  else
+    echo "Creating $user user"
+    uids=$(dscl . -list /Users UniqueID|awk '{print $2}')
+    uid=$(pick $uids)
+    echo "(picked uid $uid)"
+    gid=$(dscl . -read /Groups/$group PrimaryGroupID | awk '{print $2}')
+    dscl . -create /Users/$user
+    dscl . -create /Users/$user UniqueID $uid
+    dscl . -create /Users/$user UserShell /usr/bin/false
+    dscl . -create /Users/$user RealName 'DisOrder server'
+    dscl . -create /Users/$user NFSHomeDirectory pkgstatedir
+    dscl . -create /Users/$user PrimaryGroupID $gid
+    dscl . -create /Users/$user Password \*
+  fi
+  ;;
+FreeBSD )
+  # FreeBSD has a simple well-documented interface
+  if pw groupshow $group >/dev/null 2>&1; then
+    echo "$group group already exists"
+  else
+    echo "Creating $group group"
+    pw groupadd $group
+  fi
+  if pw usershow $user >/dev/null 2>&1; then
+    echo "$user user already exists"
+  else
+    echo "Creating $user user"
+    pw useradd $user -w no -d pkgstatedir -g $group -c 'DisOrder user'
+  fi
+  ;;
+Linux )
+  if grep ^$group: /etc/group >/dev/null; then
+    echo "$group group already exists"
+  else
+    echo "Creating $group group"
+    groupadd $group
+  fi
+  if grep ^$user: /etc/passwd >/dev/null; then
+    echo "$user user already exists"
+  else
+    echo "Creating $user user"
+    useradd -d pkgstatedir -g $group $user -c 'DisOrder user'
+  fi
+  ;;
+esac
+
 echo "Making sure that pkgstatedir exists"
 mkdir -p pkgstatedir
 chown $user:$group pkgstatedir
 chmod 2755 pkgstatedir
 
 case $os in
-mac )
-  echo "Installing the plist into /Library/LaunchDaemons/"
-  cp server/uk.org.greenend.rjk.disorder.plist /Library/LaunchDaemons/.
+Mac )
+  echo "Installing the plist into /Library/LaunchDaemons"
+  cp examples/uk.org.greenend.rjk.disorder.plist /Library/LaunchDaemons/.
   echo "Reloading launchd"
   launchctl load /Library/LaunchDaemons
   echo "Starting DisOrder server"
   launchctl start uk.org.greenend.rjk.disorder
-  echo "Installing CGI"
-  install -m 555 server/disorder.cgi /Library/WebServer/CGI-Executables/disorder
-  echo "Setting up link to CGI resources"
-  rm /etc/httpd/users/disorder.conf.new
-  echo Alias /disorder/ pkgdatadir/static/ >> /etc/httpd/users/disorder.conf.new
-  mv /etc/httpd/users/disorder.conf.new /etc/httpd/users/disorder.conf
-  echo "Reloading web server"
-  sudo apachectl graceful
-  echo
-  echo "You must sudo disorder setup-guest [--no-online-registration] next."
+  CGIBIN=/Library/WebServer/CGI-Executables
+  DOCROOT=/Library/WebServer/Documents
+  sever_running=true
+  ;;
+FreeBSD )
+  echo "Installing startup script into /etc/rc.d"
+  install -m 555 examples/disorder.rc /etc/rc.d/disorder
+  echo "Starting DisOrder server"
+  /etc/rc.d/disorder start
+  echo "Identifying web server"
+  set /usr/local/www/*
+  case $# in
+  0 )
+    echo
+    echo "Could not find a web server"
+    exit 1
+    ;;
+  1 )
+    ;;
+  * )
+    echo
+    echo "Yikes!  There seems to be more than one web server here."
+    echo "Guessing that you want $1."
+    echo
+    ;;
+  esac
+  web=$1
+  echo "Found $web"
+  CGIBIN=$web/cgi-bin
+  DOCROOT=$web/data
+  server_running=true
+  ;;
+Linux )
+  echo "Looking for init scripts directory"
+  for d in /etc/rc.d /etc; do
+    if [ -d $d/init.d ]; then
+      RC_D=$d
+      break
+    fi
+  done
+  if [ -z "$RC_D" ]; then
+    echo "Cannot find your init scripts directory"
+  else
+    echo "Installing init script into $RC_D/init.d"
+    install -m 755 examples/disorder.init $RC_D/init.d/disorder
+    echo "Linking init script into $RC_D/rc*.d"
+    for n in 2 3 4 5; do
+      echo " $RC_D/rc$n.d/S99disorder -> $RC_D/init.d/disorder"
+      rm -f $RC_D/rc$n.d/S99disorder
+      ln -s $RC_D/init.d/disorder $RC_D/rc$n.d/S99disorder
+    done
+    for n in 0 1 6; do
+      echo " $RC_D/rc$n.d/K01disorder -> $RC_D/init.d/disorder"
+      rm -f $RC_D/rc$n.d/K01disorder
+      ln -s $RC_D/init.d/disorder $RC_D/rc$n.d/K01disorder
+    done
+    echo "Starting DisOrder server"
+    $RC_D/init.d/disorder start
+  fi
+  echo "Looking for web server document root"
+  for d in /var/www/html /var/www; do
+    if [ -d $d ]; then
+      DOCROOT=$d
+      break
+    fi
+  done
+  echo "Looking for cgi-bin directory"
+  for d in /var/www/cgi-bin /usr/lib/cgi-bin; do
+    if [ -d $d ]; then
+      CGIBIN=$d
+      break
+    fi
+  done
+  server_running=true
   ;;
 * )
+  echo
   echo "Sorry, I don't know how to install the server on this platform."
   echo "You will have to do that by hand."
-  exit 1
+  server_running=false
   ;;
 esac
+
+echo
+if [ -z "$DOCROOT" ]; then
+  echo "Cannot find your web server's document root"
+else
+  echo "Setting up link to CGI's dependencies in $DOCROOT"
+  rm -f $DOCROOT/disorder
+  ln -s pkgdatadir/static $DOCROOT/disorder
+fi
+
+echo
+if [ -z "$CGIBIN" ]; then
+  echo "Cannot find your web server's cgi-bin directory"
+else
+  echo "Installing CGI in $CGIBIN"
+  install -m 555 server/disorder.cgi $CGIBIN/disorder
+fi
+
+if $server_running; then
+  first=true
+  sleep 5
+  while ! disorder version >/dev/null 2>&1; do
+    if $first; then
+      echo "Waiting for server startup to complete..."
+      first=false
+    fi
+    sleep 1
+  done
+  if [ $register = y ]; then
+    echo "Creating guest user with 'register' right"
+    disorder setup-guest
+  else
+    echo "Creating guest user without 'register' right"
+    disorder setup-guest --no-online-registration
+  fi
+fi
+
+echo
+echo Done