Tighter input checking in scripts/setup
[disorder] / scripts / setup.in
1 #! /bin/bash
2 #
3 # This file is part of DisOrder
4 # Copyright (C) 2008 Richard Kettlewell
5 #
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful, but
12 # WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 # General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19 # USA
20 #
21
22 set -e
23
24 while [ $# -gt 0 ]; do
25 opt="$1"
26 shift
27 case "$opt" in
28 -h | --help )
29 cat <<EOF
30
31 Usage:
32 scripts/setup [OPTIONS]
33
34 Options:
35 --root ROOT Add a root (can be used multiple times)
36 --encoding ENCODING Filename encoding
37 --port PORT TCP port to listen on or 'none'
38 --smtp-server HOSTNAME SMTP server
39 --email ADDRESS Origin email address
40 --register y|n Enable/disable online registration
41 --play local|network Choose local or network play
42 --mcast ADDRESS PORT Set multicast address and port for --play network
43 -h, --help Display this message
44
45 Sets up a basic DisOrder installation. You must have run 'make install'
46 first. Use scripts/teardown to stop the server and deconfigure.
47
48 EOF
49 exit 0
50 ;;
51 --version | -V )
52 echo "DisOrder scripts/setup _version_"
53 exit 0
54 ;;
55 --root )
56 roots="$roots $1"
57 shift
58 ;;
59 --encoding )
60 encoding="$1"
61 shift
62 ;;
63 --port )
64 port="$1"
65 shift
66 ;;
67 --smtp-server )
68 smtp_server="$1"
69 shift
70 ;;
71 --email )
72 mail_sender="$1"
73 shift
74 ;;
75 --register )
76 register="$1"
77 shift
78 ;;
79 --play )
80 play="$1"
81 shift
82 ;;
83 --mcast )
84 play=network
85 mcast_address="$1"
86 shift
87 mcast_port="$1"
88 shift
89 ;;
90 * )
91 echo >&2 "ERROR: unknown option '$opt'"
92 exit 1
93 ;;
94 esac
95 done
96
97 echo
98 echo ------------------------------------------------------------------------
99 echo "DisOrder setup script"
100
101 case $(uname -s) in
102 Darwin )
103 echo "Mac OS X detected"
104 os=Mac
105 user=jukebox
106 group=jukebox
107 ;;
108 FreeBSD )
109 echo "FreeBSD detected"
110 os=FreeBSD
111 user=jukebox
112 group=jukebox
113 ;;
114 Linux )
115 if grep Debian /etc/issue >/dev/null 2>&1; then
116 echo "You appear to be running Debian - please use .debs instead"
117 echo
118 elif grep Ubuntu /etc/issue >/dev/null 2>&1; then
119 echo "You appear to be running Ubuntu - please use .debs instead"
120 echo
121 fi
122 echo "Linux detected"
123 os=Linux
124 user=jukebox
125 group=jukebox
126 ;;
127 * )
128 echo
129 echo "WARNING: unknown operating system '$(uname -s)'"
130 echo "This script won't be able to do all setup on this platform"
131 os=unknown
132 user=daemon
133 group=daemon
134 ;;
135 esac
136
137 echo
138 echo "This script will:"
139 echo " - overwrite any existing configuration"
140 echo " - set the server up to be run at boot time"
141 echo " - start the server"
142 echo " - set up the web interface"
143 echo
144 echo "If this is not what you want, press ^C."
145 echo ------------------------------------------------------------------------
146
147 if [ -z "$roots" ]; then
148 while :; do
149 echo
150 echo "What directory or directories contain your music files:"
151 echo "(enter one or more directories separated by spaces)"
152 read -r roots
153 ok=true
154 anyroots=false
155 for root in $roots; do
156 if [ ! -d $root ]; then
157 echo "'$root' does not exist"
158 ok=false
159 else
160 anyroots=true
161 fi
162 done
163 if $anyroots && $ok; then
164 break
165 fi
166 done
167 fi
168
169 if [ -z "$encoding" ]; then
170 while :; do
171 echo
172 echo "What filesystem encoding should I assume for track names?"
173 echo "(e.g. UTF-8, ISO-8859-1, ...)"
174 read -r encoding
175 if [ ! -z "$encoding" ]; then
176 break
177 fi
178 done
179 fi
180
181 if [ -z "$port" ]; then
182 while :; do
183 echo
184 echo "What TCP port should DisOrder listen on?"
185 echo "(enter 'none' for none)"
186 read -r port
187 case $port in
188 none )
189 break
190 ;;
191 [^0-9] | "" )
192 echo "'$port' is not a valid port number"
193 continue
194 ;;
195 * )
196 break
197 ;;
198 esac
199 done
200 fi
201
202 if [ -z "$play" ]; then
203 while :; do
204 echo
205 echo "How do you want to play sound? Enter 'local' to use a local sound"
206 echo "device or 'network' to multicast sound across your network."
207 read -r play
208 case $play in
209 'local' | network )
210 break
211 ;;
212 * )
213 echo "Enter 'local' or 'network'"
214 continue
215 ;;
216 esac
217 done
218 fi
219
220 if [ "x$play" = xnetwork ]; then
221 if [ -z "$mcast_address" ]; then
222 echo
223 echo "Enter destination address for network transmission"
224 echo "(e.g. a multicast address)"
225 read -r mcast_address
226 fi
227 if [ -z "$mcast_port" ]; then
228 while :; do
229 echo
230 echo "Enter destination port for network transmission"
231 read -r mcast_port
232 case $mcast_port in
233 none )
234 break
235 ;;
236 [^0-9] | "" )
237 echo "'$mcast_port' is not a valid port number"
238 continue
239 ;;
240 * )
241 break
242 ;;
243 esac
244 done
245 fi
246 fi
247
248 if [ -z "$mail_sender" ]; then
249 while :; do
250 echo
251 echo "What address should mail from DisOrder come from?"
252 read -r mail_sender
253 case "$mail_sender" in
254 *@* )
255 break
256 ;;
257 * )
258 echo "Email address must contain an '@' sign"
259 ;;
260 esac
261 done
262 fi
263
264 if [ -z "$register" ]; then
265 while :; do
266 echo
267 echo "Do you want to enable online registration? (Enter 'y' or 'n')"
268 read -r register
269 case $register in
270 y | n )
271 break
272 ;;
273 esac
274 done
275 fi
276
277 echo
278 echo "Proposed DisOrder setup:"
279 echo " Music directory: $roots"
280 if [ "$port" = none ]; then
281 echo " Do not listen on a TCP port"
282 else
283 echo " TCP port to listen on: $port"
284 fi
285 if [ ! -z "$smtp_server" ]; then
286 echo " SMTP Server: $smtp_server"
287 fi
288 echo " Sender address: $mail_sender"
289 echo " Online registration: $register"
290 if [ $play = network ]; then
291 echo " Send sound to: $mcast_address port $mcast_port"
292 fi
293
294 echo "Is this OK? (Enter 'y' or 'n')"
295 read -r ok
296 case $ok in
297 y )
298 ;;
299 * )
300 echo
301 echo "OK, didn't change anything."
302 exit 0
303 ;;
304 esac
305
306 mkdir -p pkgconfdir
307
308 rm -f pkgconfdir/config.new
309 for root in $roots; do
310 echo "collection fs $encoding $root" >> pkgconfdir/config.new
311 done
312 for scratch in slap.ogg scratch.ogg; do
313 echo "scratch pkgdatadir/$scratch" >> pkgconfdir/config.new
314 done
315 echo "user $user" >> pkgconfdir/config.new
316 if [ $port != none ]; then
317 echo "listen 0.0.0.0 $port" >> pkgconfdir/config.new
318 fi
319 if [ $play = network ]; then
320 echo "broadcast $mcast_address $mcast_port" >> pkgconfdir/config.new
321 fi
322 if [ ! -z "$smtp_server" ]; then
323 echo "smtp_server $smtp_server" >> pkgconfdir/config.new
324 fi
325 echo "mail_sender $mail_sender" >> pkgconfdir/config.new
326
327 echo
328 echo "Proposed pkgconfdir/config:"
329 sed < pkgconfdir/config.new 's/^/ /'
330 echo
331 echo "Is this OK? (Enter 'y' or 'n')"
332 read -r ok
333 case $ok in
334 y )
335 ;;
336 * )
337 echo
338 echo "OK, not installing it."
339 rm -f pkgconfdir/config.new
340 exit 0
341 ;;
342 esac
343 echo
344 echo "Installing pkgconfdir/config"
345 mv pkgconfdir/config.new pkgconfdir/config
346
347 if [ ! -f pkgconfdir/options.user ]; then
348 echo "Making sure pkgconfdir/options.user exists"
349 touch pkgconfdir/options.user
350 fi
351
352 # pick ID1 ID2 ... IDn
353 # Echoes an ID matching none of ID1..IDn
354 pick() {
355 local n
356 n=250 # better not choose 0!
357 while :; do
358 ok=true
359 for k in "$@"; do
360 if [ $n = $k ]; then
361 ok=false
362 break
363 fi
364 done
365 if $ok; then
366 echo $n
367 return
368 fi
369 n=$((1+$n))
370 done
371 }
372
373 case $os in
374 Mac )
375 # Apple don't seem to believe in creating a user as a discrete operation
376 if dscl . -read /Groups/$group >/dev/null 2>&1; then
377 echo "$group group already exists"
378 else
379 echo "Creating $group group"
380 gids=$(dscl . -list /Groups PrimaryGroupID|awk '{print $2}')
381 gid=$(pick $gids)
382 echo "(picked gid $gid)"
383 dscl . -create /Groups/$group
384 dscl . -create /Groups/$group PrimaryGroupID $gid
385 dscl . -create /Groups/$group Password \*
386 fi
387 if dscl . -read /Users/$user >/dev/null 2>&1; then
388 echo "$user user already exists"
389 else
390 echo "Creating $user user"
391 uids=$(dscl . -list /Users UniqueID|awk '{print $2}')
392 uid=$(pick $uids)
393 echo "(picked uid $uid)"
394 gid=$(dscl . -read /Groups/$group PrimaryGroupID | awk '{print $2}')
395 dscl . -create /Users/$user
396 dscl . -create /Users/$user UniqueID $uid
397 dscl . -create /Users/$user UserShell /usr/bin/false
398 dscl . -create /Users/$user RealName 'DisOrder server'
399 dscl . -create /Users/$user NFSHomeDirectory pkgstatedir
400 dscl . -create /Users/$user PrimaryGroupID $gid
401 dscl . -create /Users/$user Password \*
402 fi
403 ;;
404 FreeBSD )
405 # FreeBSD has a simple well-documented interface
406 if pw groupshow $group >/dev/null 2>&1; then
407 echo "$group group already exists"
408 else
409 echo "Creating $group group"
410 pw groupadd $group
411 fi
412 if pw usershow $user >/dev/null 2>&1; then
413 echo "$user user already exists"
414 else
415 echo "Creating $user user"
416 pw useradd $user -w no -d pkgstatedir -g $group -c 'DisOrder user'
417 fi
418 ;;
419 Linux )
420 if grep ^$group: /etc/group >/dev/null; then
421 echo "$group group already exists"
422 else
423 echo "Creating $group group"
424 groupadd $group
425 fi
426 if grep ^$user: /etc/passwd >/dev/null; then
427 echo "$user user already exists"
428 else
429 echo "Creating $user user"
430 useradd -d pkgstatedir -g $group $user -c 'DisOrder user'
431 fi
432 ;;
433 esac
434
435 echo "Making sure that pkgstatedir exists"
436 mkdir -p pkgstatedir
437 chown $user:$group pkgstatedir
438 chmod 2755 pkgstatedir
439
440 case $os in
441 Mac )
442 echo "Installing the plist into /Library/LaunchDaemons"
443 cp examples/uk.org.greenend.rjk.disorder.plist /Library/LaunchDaemons/.
444 echo "Reloading launchd"
445 launchctl load /Library/LaunchDaemons
446 echo "Starting DisOrder server"
447 launchctl start uk.org.greenend.rjk.disorder
448 server_running=true
449 ;;
450 FreeBSD )
451 echo "Installing startup script into /etc/rc.d"
452 install -m 555 examples/disorder.rc /etc/rc.d/disorder
453 echo "Starting DisOrder server"
454 /etc/rc.d/disorder start
455 server_running=true
456 ;;
457 Linux )
458 echo "Looking for init scripts directory"
459 for d in /etc/rc.d /etc; do
460 if [ -d $d/init.d ]; then
461 RC_D=$d
462 break
463 fi
464 done
465 if [ -z "$RC_D" ]; then
466 echo "Cannot find your init scripts directory"
467 else
468 echo "Installing init script into $RC_D/init.d"
469 install -m 755 examples/disorder.init $RC_D/init.d/disorder
470 echo "Linking init script into $RC_D/rc*.d"
471 for n in 2 3 4 5; do
472 echo " $RC_D/rc$n.d/S99disorder -> $RC_D/init.d/disorder"
473 rm -f $RC_D/rc$n.d/S99disorder
474 ln -s $RC_D/init.d/disorder $RC_D/rc$n.d/S99disorder
475 done
476 for n in 0 1 6; do
477 echo " $RC_D/rc$n.d/K01disorder -> $RC_D/init.d/disorder"
478 rm -f $RC_D/rc$n.d/K01disorder
479 ln -s $RC_D/init.d/disorder $RC_D/rc$n.d/K01disorder
480 done
481 echo "Starting DisOrder server"
482 $RC_D/init.d/disorder start
483 fi
484 server_running=true
485 ;;
486 * )
487 echo
488 echo "Sorry, I don't know how to install the server on this platform."
489 echo "You will have to do that by hand."
490 server_running=false
491 ;;
492 esac
493
494 if $server_running; then
495 first=true
496 sleep 5
497 while ! disorder version >/dev/null 2>&1; do
498 if $first; then
499 echo "Waiting for server startup to complete..."
500 first=false
501 fi
502 sleep 1
503 done
504 if [ $register = y ]; then
505 echo "Creating guest user with 'register' right"
506 disorder setup-guest
507 else
508 echo "Creating guest user without 'register' right"
509 disorder setup-guest --no-online-registration
510 fi
511 fi
512
513 echo
514 echo Done