initial commit

This commit is contained in:
ahriman 2018-12-24 20:51:52 +01:00
commit b36960f50e
58 changed files with 4724 additions and 0 deletions

4
.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
\#*
.#*
logs/
crawl-git-repository/

90
README Normal file
View File

@ -0,0 +1,90 @@
dgamelaunch-config
------------------
This is a collection of scripts to manage a dgamelaunch
(http://nethackwiki.com/wiki/Dgamelaunch) install, all run from an
umbrella `dgl` script.
These are still very incomplete, WIP.
Currently available commands:
1. Update your dgamelaunch config from the repository:
$ sudo dgl publish --confirm
2. Change a dgl user's password:
$ sudo dgl passwd johndoe
3. Update Crawl alpha build from git master:
$ dgl update-trunk
4. Remove stale Crawl alpha versions:
$ dgl remove-trunks
5. Run dgl-whereis inotify daemon:
$ sudo dgl crawl-inotify-dglwhere
This inotify daemon monitors the dgamelaunch in-progress dirs to keep
track of active players, and monitors their morgue directories for
changes to their .where files. When a .where changes, the daemon reads
it and writes a human-readable .dglwhere file in the same directory.
You may configure dgamelaunch to show this .dglwhere information
using the dgamelaunch extra_info_file option.
You may also run the crawl-inotify-dglwhere script standalone (without
the rest of the dgamelaunch-config setup) by starting it as:
sudo -u dgl perl crawl-inotify-dglwhere.pl <dgldir> <morguedir>
Note: Some of these commands will probably change names soon.
The ultimate goal for this project is to become a one-stop shop for
all your dgamelaunch+Crawl needs, starting from installing dgamelaunch
itself
TODO
----
1. `dgl install-dgl` command to fetch and install the latest dgamelaunch.
2. `dgl create-chroot` command to set up a basic chroot jail with all the
fixtures dgamelaunch wants (dgamelaunch already has a skeleton script
that can serve as a basis, although this is unfortunately NetHack-biased).
3. Support for installing different games, including fetching their sources
from their respective source repositories, compiling, installing into the
chroot, etc.
`dgl install crawl master`,
`dgl install nethack 3.4.3` etc.)
Installing a game should also (eventually) add a suitable entry to
the various menu files and update the dgamelaunch config
appropriately.
4. Support for tracking development versions of games (such as Crawl
master) using a system similar to CDO's for creating versioned
directories, migrating saves to newer versions, and deleting old
versions with no remaining save games.
5. Module system so that management of say, crawl-git is a
self-contained module. Each module should be able to contribute dgl
commands and provide files that will be installed to the chroot or
root filesystem.
6. Each dgl command that affects the machine or chroot should update a
manifest. The manifest could be a file or a directory containing
multiple manifest files.
Given a manifest, I should be able to install dgamelaunch-config
on a brand new machine and use one dgl command to recreate the manifest.
For instance, something like:
`dgl replicate-manifest <path-to-manifest>`
The manifest should include information like this:
* What dgamelaunch version is installed, and from where (install-dgl module)
* chroot configuration: what binaries and libraries have been installed
into the chroot, with the exception of game binaries, i.e. the state of
the chroot minus games (chroot module)
* Game configuration (handled by the various game modules)

95
bin/admin.sh Normal file
View File

@ -0,0 +1,95 @@
#! /bin/bash
help <<EOF
$SCRIPT_NAME: Manages dgamelaunch admin users.
Usage: $SCRIPT_NAME ls List admin users
$SCRIPT_NAME add <user> Make <user> an admin
$SCRIPT_NAME rm <user> Make <user> a regular (non-admin) user.
EOF
assert-login-db-exists
SUBCOMMAND=$1
shift
[[ -z "$SUBCOMMAND" ]] && SUBCOMMAND=ls
admin-ls() {
echo "Existing admin users:"
login-query <<EOF
SELECT username, email FROM dglusers
WHERE (flags & 1) = 1
ORDER BY username;
EOF
}
dgl-user-make-admin() {
local user="$1"
login-query <<EOF
UPDATE dglusers
SET flags = flags | 1
WHERE username='$user';
EOF
}
dgl-user-unmake-admin() {
local user="$1"
login-query <<EOF
UPDATE dglusers
SET flags = flags & ~1
WHERE username='$user';
EOF
}
admin-add() {
local new_admin="$1"
dgl-user-exists "$new_admin" || \
abort-saying "Cannot find user $new_admin in dgl login db"
if dgl-user-is-admin "$new_admin"; then
echo -e "User $new_admin is already an admin"
exit 0
fi
assert-running-as-root
dgl-user-make-admin "$new_admin"
if dgl-user-is-admin "$new_admin"; then
printf "\nDone, $new_admin is now a DGL admin.\n"
exit 0
else
echo -e "Oops, couldn't make $new_admin a DGL admin.\n"
exit 1
fi
}
admin-rm() {
local ex_admin="$1"
dgl-user-exists "$ex_admin" || \
abort-saying "Cannot find user $ex_admin in dgl login db"
if ! dgl-user-is-admin "$ex_admin"; then
echo -e "User $ex_admin is not an admin, nothing to do"
exit 0
fi
assert-running-as-root
dgl-user-unmake-admin "$ex_admin"
if ! dgl-user-is-admin "$ex_admin"; then
printf "\nDone, $ex_admin is now a regular DGL non-admin user.\n"
exit 0
else
echo -e "Oops, couldn't make $ex_admin a regular DGL non-admin user."
exit 1
fi
}
case $SUBCOMMAND in
ls) admin-ls "$@" ;;
add) each-do admin-add "$@" ;;
rm) each-do admin-rm "$@" ;;
*) abort-saying "Unknown usage: $SCRIPT_NAME $SUBCOMMAND"
esac

54
bin/compress-ttyrecs.sh Executable file
View File

@ -0,0 +1,54 @@
#! /bin/bash
source $DGL_CONF_HOME/crawl-git.conf
if [[ $UID != 0 ]]; then
echo "$0 must be run as root!"
exit 1
fi
if [[ $1 == -v || $1 == --verbose ]]; then
verbose=1
else
verbose=0
fi
verbiate() {
((verbose)) && echo "$@" >&2
}
quietly() {
"$@" >/dev/null 2>&1
}
failures=()
skip=0 succ=0 fail=0
shopt -s nullglob
for ttyrec in "$TTYRECDIR"/*/*.ttyrec; do
# If anyone has it open, skip it.
if quietly lsof "$ttyrec"; then
verbiate -n "."
let ++skip
continue
fi
if bzip2 "$ttyrec"; then
let ++succ
verbiate -n "+"
else
let ++fail
verbiate -n "X"
failures+=( "$ttyrec" )
fi
done
verbiate
if (( failed || verbose )); then
printf "%d succeeded\t%d failed\t%d skipped\n" "$succ" "$fail" "$skip"
if (( failed )); then
printf "\nFailing files:\n"
printf " %s\n" "${failures[@]}"
exit 1
fi
fi
exit 0

View File

@ -0,0 +1,312 @@
#! /usr/bin/perl
#
# Monitors dgamelaunch inprogress-dirs to detect active games, and then
# monitors those active games to find .where updates and converts them to
# .dglwhere files that dgamelaunch can consume.
#
# Assumption: inprogress dirs are directly under DGLDIR/inprogress*
# Assumption: player .where files are under TTYRECDIR/<playername>/
# Assumption: the script runs with permissions to create .dglwhere alongside
# the player .where
use strict;
use warnings;
use Linux::Inotify2;
use POSIX;
use Fcntl qw/:flock/;
use Getopt::Long;
my $DAEMON = 1;
GetOptions("daemon!" => \$DAEMON)
or die "Bad command line: @ARGV\n";
my $DGLDIR = $ARGV[0] || '';
my $TTYRECDIR = $ARGV[1] || '';
$ENV{DGLDIR} = $DGLDIR;
$ENV{TTYRECDIR} = $TTYRECDIR;
my $LOCKFILE = "$DGLDIR/.crawl-inotify.lock";
my $LOGFILE = "$DGLDIR/crawl-inotify-where.log";
my $inotify;
my %MONITORED_PLAYERS;
sub say($) {
print STDERR "@_\n";
}
sub assert_dir_exists($) {
my $dir = shift;
die "$dir not set\n" unless $ENV{$dir};
die "Can't find $dir ($ENV{$dir})\n" unless -d $ENV{$dir};
}
sub assert_environment_exists() {
assert_dir_exists('DGLDIR');
assert_dir_exists('TTYRECDIR');
}
sub player_where_dir($$) {
my ($player, $dir) = @_;
for my $candidate ("$TTYRECDIR/$dir/morgue/$player") {
return $candidate if -d $candidate;
}
"$TTYRECDIR/$player"
}
sub player_where_file($$) {
my ($player, $where_dir) = @_;
player_where_dir($player, $where_dir) . "/$player.where"
}
sub player_dglwhere_file($$) {
my ($player, $morgue_dir) = @_;
player_where_dir($player, $morgue_dir) . "/$player.dglwhere"
}
sub whereis_read($) {
my $whereis_file = shift;
open my $inf, '<', $whereis_file or do {
warn "Could not read whereis file: $whereis_file: $!\n";
return;
};
chomp(my $text = <$inf>);
close $inf;
$text =~ s/::/\n/g;
my %hash = map {
my ($key, $value) = /(\w+)=(.*)/s;
$value =~ s/\n/:/gs;
($key, $value)
} split(/:/s, $text);
\%hash
}
sub whereis_human_readable($) {
my $w = shift;
# No more than 18 characters, empty string for saved/dead characters:
return '' if $$w{status} ne 'active';
my $weight = $$w{xl} * 100 + $$w{lvl};
sprintf("$weight|%-3s $$w{char}, $$w{place}",
"L$$w{xl}")
}
sub write_dglwhere_file($$) {
my ($player, $where_dir) = @_;
my $where_dict = whereis_read(player_where_file($player, $where_dir));
if ($where_dict) {
my $human_readable_where = whereis_human_readable($where_dict);
my $dglwhere_file = player_dglwhere_file($player, $where_dir);
open my $outf, '>', $dglwhere_file or do {
say "Could not write $dglwhere_file: $!";
return;
};
print $outf "$human_readable_where\n";
close $outf;
say "Wrote $dglwhere_file: $human_readable_where";
}
}
sub inprog_player($) {
my $ttyrec = shift;
($ttyrec) = $ttyrec =~ m{.*/(.*)} if $ttyrec =~ m{/};
my ($player) = $ttyrec =~ /(.+?):/;
$player
}
sub inprog_morgue_dir($) {
my $dir = shift;
$dir =~ s{/$}{};
($dir) = $dir =~ m{.*/(.*)};
# Strip alt qualifiers:
$dir =~ s/\b(?:spr|zd|tut)-//;
$dir
}
## BEGIN inotify callbacks ##
sub inotify_player_where_file_changed {
my ($player, $where_dir, $event) = @_;
return unless $$event{name} =~ /$player\.where$/;
write_dglwhere_file($player, $where_dir);
}
sub inotify_inprogress_change {
my ($inprog_dir, $event) = @_;
my $file = $$event{name};
return unless $file;
my $player = inprog_player($file);
my $morgue_dir = inprog_morgue_dir($inprog_dir);
my $gone_away = $$event{mask} & IN_DELETE;
if ($player) {
if ($gone_away) {
say "$player went away, unmonitoring.";
unmonitor_player($player);
}
else {
say "$player started game, monitoring";
write_dglwhere_file($player, $morgue_dir);
monitor_player($inotify, $player, $morgue_dir);
}
}
}
## END inotify callbacks ##
sub monitor_player($$$) {
my ($inotify, $player, $morgue_dir) = @_;
return if $MONITORED_PLAYERS{$player};
say "++ MONITOR: $player";
my $watch;
for my $i (1..3) {
my $where_dir = player_where_dir($player, $morgue_dir);
$watch = $inotify->watch($where_dir,
IN_CLOSE_WRITE,
sub {
inotify_player_where_file_changed($player,
$morgue_dir,
@_)
});
last if $watch;
say " xx RETRY: $i";
sleep 1;
}
if ($watch) {
$MONITORED_PLAYERS{$player} = $watch;
} else {
say "[ERR] Watch object is false for $player: $!"
}
}
sub unmonitor_player($) {
my $player = shift;
my $watch = $MONITORED_PLAYERS{$player};
if (defined $watch) {
say "-- MONITOR: $player";
$watch->cancel;
delete $MONITORED_PLAYERS{$player};
}
else {
say "$player was not being monitored, ignoring unmonitor request"
}
}
sub inprogress_dirs() {
my $inprog_glob = $DGLDIR;
if (-d "$DGLDIR/inprogress") {
$inprog_glob = "$DGLDIR/inprogress/*";
}
else {
$inprog_glob = "$DGLDIR/inprogress*";
}
my @dirs = grep(-d, glob($inprog_glob));
die "No inprogress dirs under $DGLDIR!\n" unless @dirs;
@dirs
}
sub monitor_active_player_where($) {
my $inotify = shift;
my %monitorees;
my @inprog_dirs = inprogress_dirs();
for my $dir (@inprog_dirs) {
my @ttyrecs = glob("$dir/*.ttyrec");
my $morgue_dir = inprog_morgue_dir($dir);
for my $ttyrec (@ttyrecs) {
my $player = inprog_player($ttyrec);
write_dglwhere_file($player, $morgue_dir);
monitor_player($inotify, $player, $morgue_dir);
}
}
}
sub monitor_inprogress_dirs($) {
my $inotify = shift;
my @inprog_dirs = inprogress_dirs();
for my $inprog (@inprog_dirs) {
$inotify->watch($inprog, IN_CREATE | IN_DELETE,
sub {
my $event = shift;
inotify_inprogress_change($inprog, $event)
});
}
}
sub lock_or_exit {
my ($exitcode, $lockf) = @_;
$exitcode ||= 0;
open LOCKFILE, '>', $lockf or die "Couldn't open $lockf: $!\n";
flock(LOCKFILE, LOCK_EX | LOCK_NB)
or do {
warn "Cannot start: $lockf is held by another process\n";
exit($exitcode);
};
}
sub daemonify {
my $log = shift;
defined(my $pid = fork) or die "Unable to fork: $!";
exit if $pid;
setsid or die "Unable to start a new session: $!";
print "Started daemon.\n";
open STDOUT, '>', $log or die "Can't write $log: $!\n";
open STDERR, '>&', \*STDOUT;
# Done daemonifying.
}
sub ps_list($) {
my $process_name = shift;
my @processes = map([split],
qx/ps -ef | grep \Q$process_name\E | grep -v grep/);
grep($_->[1] != $$, @processes);
}
sub ps_pid($) {
my $process_name = shift;
my @processes = ps_list($process_name);
return unless @processes == 1;
return $processes[0][1];
}
sub pid_describe($) {
my $pid = shift;
my @lines = qx/ps -f -p \Q$pid\E/;
join('', @lines)
}
sub supersede_existing_daemon() {
my $name = $0;
($name) = $name =~ m{.*/(.*)} if $name =~ m{/};
my $existing_daemon_pid = ps_pid($name);
if ($existing_daemon_pid) {
print "Killing existing daemon ($existing_daemon_pid):\n",
pid_describe($existing_daemon_pid);
kill TERM => $existing_daemon_pid;
sleep 1;
}
}
sub main() {
assert_environment_exists();
supersede_existing_daemon();
lock_or_exit(1, $LOCKFILE);
daemonify($LOGFILE) if $DAEMON;
$inotify = Linux::Inotify2->new;
monitor_active_player_where($inotify);
monitor_inprogress_dirs($inotify);
say "Monitoring and updating where info";
$inotify->poll while 1;
warn "Exiting, WTF?\n";
}
main();

View File

@ -0,0 +1,19 @@
#! /bin/bash
assert-chroot-exists
cat-error <<EOF
$SCRIPT_NAME: Monitors Crawl .where files and creates .dglwhere files for the
dgamelaunch menu to display
EOF
if [[ "$UID" != "0" && "$USER" != "$DGL_USER" ]]; then
abort-saying "This script must be run as root or $DGL_USER"
fi
SUDO=
if [[ "$USER" != "$DGL_USER" ]]; then
SUDO="sudo -u $DGL_USER"
fi
$SUDO perl $DGL_CONF_HOME/bin/crawl-inotify-dglwhere.pl $DGLDIR $MORGUEDIR "$@"

View File

@ -0,0 +1,25 @@
#! /bin/bash
source $DGL_CONF_HOME/crawl-git.conf
set -e
GAME_DIR=$CRAWL_GAMEDIR
echo "Crawl basedir to create: $GAME_DIR"
[[ -d "$GAME_DIR" ]] && abort-saying "Crawl base directory already exists"
assert-chroot-exists
[[ "$UID" != "0" ]] && abort-saying "This script must be run as root"
mkdir -p $DGL_CHROOT/cores
mkdir -p $GAME_DIR/saves/{sprint,zotdef}
( cd $GAME_DIR/saves &&
touch logfile{,-sprint,-zotdef} \
milestones{,-sprint,-zotdef} \
scores{,-sprint,-zotdef} )
# Only the saves dir is chowned games: data dir is not supposed to be
# games writable.
chown -R $CRAWL_UGRP $GAME_DIR/saves
echo "Created $GAME_DIR"

27
bin/create-versions-db.sh Normal file
View File

@ -0,0 +1,27 @@
#! /bin/bash
source ./crawl-git.conf
if [[ -f "$VERSIONS_DB" ]]; then
echo -e "Crawl version db $VERSIONS_DB already exists, aborting."
exit 1
fi
set -e
if [[ -f "$VERSIONS_DB" ]]; then
abort-saying "Versions DB file $VERSIONS_DB already exists"
fi
echo "Creating $VERSIONS_DB"
if [[ "$UID" != "0" ]]; then
echo -e "This script must be run as root"
exit 1
fi
VERSIONS_DB_DIR="$(dirname $VERSIONS_DB)"
if [[ ! -d "$VERSIONS_DB_DIR" ]]; then
say "Version DB directory $VERSIONS_DB_DIR doesn't exist, creating it."
mkdir -p "$VERSIONS_DB_DIR"
fi
cat $CRAWL_BUILD_DIR/version-db-schema.sql | sqlite3 $VERSIONS_DB

108
bin/dgl Executable file
View File

@ -0,0 +1,108 @@
#! /bin/bash
#
# General launcher script for dgamelaunch actions. The idea is to symlink
# this (one) script into $HOME/bin and use it to run the others.
SELF="$0"
SCRIPT_NAME=$(basename $0)
usage() {
echo -e "Usage: $SCRIPT_NAME $@"
}
cat-error() {
cat >&2
}
report-usage() {
printf "Usage: $SCRIPT_NAME " >&2
cat-error
exit 1
}
canonical-name() {
local name=$1
if [[ -d "$name" ]]; then
printf "%s\n" "$(cd $name && echo $PWD)"
else
local dir=$(cd $(dirname $name) && echo $PWD)
printf "%s\n" "$dir/$(basename $name)"
fi
}
test-set-dgl-home() {
if [[ -n "$DGL_CONF_HOME" ]]; then
return 0
fi
local dir=$1
if [[ -d "$dir" && -d "$dir/bin" && -f "$dir/dgamelaunch.conf" \
&& -d "$dir/chroot" ]]; then
export DGL_CONF_HOME="$(canonical-name $dir)"
export DGL_CONF_LOGS="$dir/logs"
mkdir -p "$DGL_CONF_LOGS"
fi
}
find-dgl-home() {
test-set-dgl-home "$HOME/conf-dgamelaunch"
test-set-dgl-home "$(dirname $SELF)/.."
local link_target="$(readlink $0)"
if [[ -n "$link_target" ]]; then
test-set-dgl-home "$(dirname $(readlink $SELF))/.."
fi
if [[ -z "$DGL_CONF_HOME" ]]; then
echo -e "Cannot find dgamelaunch config base directory"
return 1
fi
}
resolve-action() {
local action="$1"
local script="$DGL_CONF_HOME/bin/$action.sh"
if [[ ! -f "$script" ]]; then
cat-error <<EOF
Can't find dgamelaunch action '$action'
Available actions are:
$(list-all-actions)
EOF
exit 1
fi
echo "$script"
}
find-dgl-home || exit 1
ACTION=$1
shift
find-all-actions() {
local -a actions
actions=($DGL_CONF_HOME/bin/*.sh)
actions=(${actions[@]%%.sh})
actions=(${actions[@]##$DGL_CONF_HOME/bin/})
echo "${actions[@]}"
}
list-all-actions() {
find-all-actions | fold -s
}
if [[ -z "$ACTION" ]]; then
usage "<action>"
echo -e "Where <action> is one of:"
list-all-actions >&2
exit 1
fi
ACTION_SCRIPT="$(resolve-action $ACTION)"
[[ -z "$ACTION_SCRIPT" ]] && exit 1
cd "$DGL_CONF_HOME"
source ./sh-utils
SCRIPT_NAME="$SCRIPT_NAME $ACTION"
source "$ACTION_SCRIPT"

24
bin/help.sh Normal file
View File

@ -0,0 +1,24 @@
#! /bin/bash
GIVE_HELP=1
COMMAND="$1"
if [[ -z "$COMMAND" ]]; then
help <<EOF
Gives help on how to use a command.
Usage: $SCRIPT_NAME <command>
Where <command> is one of: $(list-all-actions)
EOF
fi
SCRIPT="$(resolve-action $COMMAND)"
[[ -z "$SCRIPT" ]] && exit 1
HELPFILE="help/$COMMAND.txt"
if [[ ! -f "$HELPFILE" ]]; then
abort-saying "No help available for \"dgl $COMMAND\""
fi
cat "$HELPFILE"

6
bin/ls-users.sh Executable file
View File

@ -0,0 +1,6 @@
#!/bin/bash
assert-login-db-exists
sqlite3 "$LOGIN_DB" <<EOF | sort -f
SELECT username, email FROM dglusers ORDER BY username;
EOF

94
bin/passwd.sh Normal file
View File

@ -0,0 +1,94 @@
#! /bin/bash
assert-login-db-exists
(( $# == 1 )) || \
report-usage <<EOF
<dgl-username / email address>
Gives a password hint for the given username, and (if run as root)
prompts for a new password. You may ^C out at the new password
prompt.
EOF
password-hint() {
local user=$1
sqlite3 "$LOGIN_DB" <<EOF
SELECT SUBSTR(password, 1, 2)
FROM dglusers
WHERE username='$user' OR email='$user';
EOF
}
count-users() {
local user=$1
sqlite3 "$LOGIN_DB" <<EOF
SELECT COUNT(*)
FROM dglusers
WHERE username='$user' OR email='$user';
EOF
}
assert-password-safe() {
local password="$1"
if [[ "$password" =~ \' ]]; then
echo -e "Sorry, I can't handle passwords containing '"
exit 1
fi
}
change-password() {
local user="$1"
local password_clear="$2"
assert-password-safe "$password_clear"
local password_crypt="$(perl -le 'print crypt($ARGV[0], substr($ARGV[0], 0, 2))' "$password_clear")"
sqlite3 "$LOGIN_DB" <<EOF
UPDATE dglusers
SET password='$password_crypt'
WHERE username='$user' OR email='$user';
EOF
}
assert-sane-user-match() {
local user=$1
local count=$(count-users $user)
if (( $count != 1 )); then
if (( $count == 0 )); then
abort-saying "Can't find user matching '$user'"
else
abort-saying "Too many user matches for '$user'"
fi
fi
}
USER=$1
assert-sane-user-match "$USER"
echo "Password hint for $USER: '$(password-hint $USER)'"
if [[ "$UID" == "0" ]]; then
echo
read -s -p "Enter new password for $USER: " PASSWORD
echo
if [[ -z "$PASSWORD" ]]; then
abort-saying "Empty password"
fi
read -s -p "Retype password for $USER: " CONFIRM_PASSWORD
echo
if [[ "$PASSWORD" != "$CONFIRM_PASSWORD" ]]; then
abort-saying "Passwords do not match"
fi
change-password "$USER" "$PASSWORD"
echo "Updated password for $USER"
else
cat <<EOF
If you'd like to change the password for $USER, rerun this command as root:
$SCRIPT_NAME $@
EOF
fi

8
bin/publish-conf.sh Normal file
View File

@ -0,0 +1,8 @@
#! /bin/bash
#
# Publish only the dgamelaunch config file.
#
assert-chroot-exists
set -- "--confirm" "--match" "dgamelaunch.conf" "$@"
source $DGL_CONF_HOME/bin/publish.sh

8
bin/publish-scripts.sh Normal file
View File

@ -0,0 +1,8 @@
#! /bin/bash
#
# Publish everything other than the dgamelaunch.conf file.
#
assert-chroot-exists
set -- "--confirm" "--skip" "dgamelaunch.conf" "$@"
source $DGL_CONF_HOME/bin/publish.sh

302
bin/publish.pl Normal file
View File

@ -0,0 +1,302 @@
#! /usr/bin/env perl
use strict;
use warnings;
use File::Copy;
use File::Path;
use Cwd qw/abs_path/;
use Term::ANSIColor;
use Getopt::Long;
use lib "$ENV{DGL_CONF_HOME}/lib";
use DGLMan;
my %OPT;
GetOptions(\%OPT, "match=s", "skip=s", "confirm", "target=s")
or die "Bad command line: @ARGV\n";
my $CHROOT = $ENV{DGL_CHROOT};
die "DGL chroot not specified in environment\n" unless $CHROOT;
my @COPY_TARGETS = ([ 'dgamelaunch.conf', '//etc' ],
[ 'utils/auth-save-downloader.pl', '//usr/lib/cgi-bin' ],
[ 'utils/trigger-rebuild.pl', '//usr/lib/cgi-bin' ],
[ 'utils/webtiles', '//etc/init.d' ],
[ 'config.py', "/crawl-master/webserver" ],
[ 'chroot/data/menus/*.txt', "/dgldir/data/menus" ],
[ 'chroot/data/*.{rc,macro}', "/dgldir/data" ],
[ 'chroot/bin/*.sh', '/bin' ],
[ 'chroot/sbin/*.sh', '/sbin' ]);
if ($OPT{match}) {
@COPY_TARGETS = grep($$_[0] =~ /\Q$OPT{match}/, @COPY_TARGETS);
}
if ($OPT{skip}) {
@COPY_TARGETS = grep($$_[0] !~ /\Q$OPT{skip}/, @COPY_TARGETS);
}
if ($OPT{target}) {
die "--target specified, but more than one file to publish\n"
if @COPY_TARGETS > 1;
$COPY_TARGETS[0][1] = $OPT{target};
}
sub change_stat($@) {
my ($dst, @src) = @_;
my $changed = 0;
my @changed;
my $new = 0;
my @new;
for my $file (@src) {
my $target = target_file($dst, $file);
if (-l $target) {
return "ERR: $target is a symlink";
}
my $src_text = source_file_text($file);
if (-f $target) {
my $dst_text = file_text($target);
if ($src_text ne $dst_text) {
++$changed;
push @changed, basename($target);
}
} else {
++$new;
push @new, basename($file);
}
}
return { new => \@new,
changed => \@changed };
}
sub change_exists($) {
my $stat = shift;
return @{$$stat{new}} || @{$$stat{changed}};
}
sub change_summary($) {
my $stat = shift;
my @report;
my @new = @{$$stat{new}};
my @changed = @{$$stat{changed}};
my $new = scalar(@new);
my $changed = scalar(@changed);
push @report, neutral_text("$new new: @new") if @new;
push @report, neutral_text("$changed changed: @changed") if @changed;
@report? join(', ', @report) : 'no change'
}
sub publishee_summary($) {
my ($src, $dst) = @{$_[0]};
my @files = glob($src);
$dst = qualify_directory($dst);
my $change_stat = change_stat($dst, @files);
if (@files == 1 && $files[0] eq $src) {
("$src -> $dst (" . change_summary($change_stat) . ")",
$change_stat)
} else {
("$src (" . scalar(@files) . " files) -> $dst (" .
change_summary($change_stat) . ")",
$change_stat)
}
}
sub summarize_publishees() {
my $index = 0;
print "These are the publish copy targets:\n";
my $dirty;
for my $copy_target (@COPY_TARGETS) {
++$index;
my ($summary, $stat) = publishee_summary($copy_target);
print("$index) $summary\n");
$dirty = 1 if change_exists($stat);
}
$dirty
}
my $copy_count = 0;
sub nth_copy() {
++$copy_count . ") ";
}
sub qualify_directory($) {
my $dir = shift;
if ($dir =~ m{^//}) {
$dir =~ s{^/}{};
$dir
} else {
"$CHROOT$dir"
}
}
sub substitute_variable($$) {
my ($file, $var) = @_;
die "$file refers to unknown variable $var.\n" unless $ENV{$var};
$ENV{$var}
}
sub file_needs_banner($) {
my $filename = shift;
$filename =~ /(?:dgamelaunch\.conf|\.sh|\.pl)$/
}
sub file_banner($) {
my $filename = shift;
my $basename = basename($filename);
my $source_file = abs_path($filename);
return <<BANNER;
#############################################################################
#
# WARNING! AUTO-GENERATED FILE, DO NOT EDIT.
#
# This file ($basename) is automatically generated from $source_file.
#
# Do NOT edit this file; edit $source_file instead, and
# use `dgl publish` to publish your changes.
#
#############################################################################
BANNER
}
sub file_add_banner($$) {
my ($filename, $text) = @_;
if ($text =~ /^#!.*\n/) {
$text =~ s/(^#!.*\n)/$1 . file_banner($filename)/e;
} else {
$text =~ s/^/file_banner($filename)/e;
}
$text
}
sub substitute_variables($$) {
my ($filename, $text) = @_;
$text = file_add_banner($filename, $text) if file_needs_banner($filename);
$text =~ s/%%(\w+)%%/ substitute_variable($filename, $1) /ge;
$text
}
sub basename($) {
my $file = shift;
my ($basename) = $file =~ m{.*/(.*)};
$basename || $file
}
sub target_file($$) {
my ($dst, $src) = @_;
my $basename = basename($src);
"$dst/$basename"
}
sub file_text($) {
my $source_file = shift;
open my $inf, '<', $source_file or die "Can't read $source_file: $!\n";
binmode $inf;
my $text = do { local $/; <$inf> };
close $inf;
$text
}
sub source_file_text($) {
my $source_file = shift;
substitute_variables($source_file, file_text($source_file))
}
sub copy_file($$) {
my ($source_file, $dst) = @_;
my $target_file = target_file($dst, $source_file);
if (-l $target_file) {
die "Can't copy $source_file -> $target_file: destination is a symlink\n";
}
my $text = source_file_text($source_file);
my $target_tmp = "$target_file.tmp";
open my $outf, '>', $target_tmp or die "Can't write $target_tmp: $!\n";
print $outf $text;
close $outf;
if (-x $source_file) {
chmod 0755, $target_tmp or
die "Couldn't +x $target_tmp when copying $source_file -> $dst" ;
}
rename $target_tmp, $target_file or
die "Couldn't copy $source_file -> $target_file\n";
}
sub copy_files($$) {
my ($src, $dst) = @_;
my @files = glob($src);
if (!@files) {
die "Can't find files to copy for $src\n";
}
$dst = qualify_directory($dst);
if (!-d($dst)) {
mkpath($dst) or die "Couldn't create $dst\n";
}
my @quoted_files = map("\Q$_", @files);
print(nth_copy() . "@files -> $dst ");
eval {
for my $file (@files) {
copy_file($file, $dst) or
die "Failed to copy $file -> $dst: $!\n";
}
say_good(" [OK]\n");
};
if ($@) {
say_bad(" [ERR]\n\n");
die $@;
}
}
sub copy_targets(@) {
print "Copying files:\n";
for my $copy_target (@_) {
copy_files($copy_target->[0], $copy_target->[1]);
}
}
print "Publishing DGL config files:\n\n";
my $dirty = summarize_publishees();
print "\n";
my $want_publish = $OPT{confirm};
if (!$want_publish) {
if ($dirty) {
warn <<PUBLISH_HOWTO;
To publish the new dgl config, run this command as root:
@{ [ emphasized_text('dgl publish --confirm') ] }
PUBLISH_HOWTO
}
else {
say_coloured('bold green', <<INSYNC);
DGL config is in sync.
INSYNC
}
exit 0;
}
if ($< != 0) {
print STDERR "** This script must be run as root to publish changes **\n";
exit 1;
}
copy_targets(@COPY_TARGETS);
print "\nAll done.\n";

7
bin/publish.sh Normal file
View File

@ -0,0 +1,7 @@
#! /bin/bash
assert-chroot-exists
source $DGL_CONF_HOME/crawl-git.conf
export DGL_CONF_HOME DGL_CHROOT
exec perl $DGL_CONF_HOME/bin/publish.pl "$@"

4
bin/remove-trunks.sh Normal file
View File

@ -0,0 +1,4 @@
#!/bin/bash
sudo -H $DGL_CHROOT/sbin/remove-trunks.sh $*

View File

@ -0,0 +1,32 @@
#!/bin/bash
set -u
source $DGL_CONF_HOME/crawl-git.conf
LATEST_GAME_HASH="$(latest-game-hash)"
PREFIX="$DGL_CHROOT/$CRAWL_GIT_DIR"
SAVEBASE="${PREFIX}/${BINARY_BASE_NAME}-*/saves"
ALL_CHARS="$(ls -1rt $SAVEBASE/*-${DGL_UID}.sav \
$SAVEBASE/*-${DGL_UID}.chr \
$SAVEBASE/*.cs \
$SAVEBASE/sprint/*-${DGL_UID}.chr \
$SAVEBASE/sprint/*.cs \
$SAVEBASE/zotdef/*.cs 2>/dev/null | \
grep -v $LATEST_GAME_HASH | \
sed "s|${PREFIX}/${BINARY_BASE_NAME}-.*/saves/\(.*\)\..*|\1|;s|-${DGL_UID}||" | \
sort -f)"
echo "Trying to transfer these chars to a newer version:"
echo ${ALL_CHARS}
echo
echo "-- Press RETURN to start transfer --"
read
for char in ${ALL_CHARS}
do
dgl savegame-transfer ${char}
done

3
bin/savegame-transfer.sh Normal file
View File

@ -0,0 +1,3 @@
#!/bin/bash
sudo -H $DGL_CHROOT/sbin/savegame-transfer.sh $*

44
bin/test.sh Normal file
View File

@ -0,0 +1,44 @@
#! /bin/bash
set -e
DGAMELAUNCH="$1"
valid-dgl() {
[[ -n "$DGAMELAUNCH" && -x "$DGAMELAUNCH" ]]
}
valid-dgl || DGAMELAUNCH="$(which dgamelaunch 2>/dev/null || true)"
valid-dgl || DGAMELAUNCH=/usr/local/sbin/dgamelaunch
valid-dgl || abort-saying "Cannot find dgamelaunch binary"
STRACE_OUT=strace.out
if not-running-as-root; then
cat-error <<EOF
$SCRIPT_NAME: runs dgamelaunch with the current (testing) configuration
Run this command as root to test your dgamelaunch.conf
Options:
--strace: Run dgamelaunch with strace and dump strace output to $STRACE_OUT
EOF
exit 1
fi
[[ "$1" == "--strace" ]] && STRACE=1 || STRACE=
TEST_FILE=dgamelaunch.conf
TMP_DIR=.tmp
trap "rm $TMP_DIR/$TEST_FILE && rmdir $TMP_DIR" EXIT
mkdir -p $TMP_DIR
dgl-run publish-conf --target /$PWD/$TMP_DIR
if [[ -z "$STRACE" ]]; then
"$DGAMELAUNCH" -f "$TMP_DIR/$TEST_FILE"
else
strace -f "$DGAMELAUNCH" -f "$TMP_DIR/$TEST_FILE" 2>$STRACE_OUT
fi

4
bin/update-stable.sh Normal file
View File

@ -0,0 +1,4 @@
#!/bin/bash
cd $DGL_CONF_HOME/crawl-build
source ./update-crawl-stable-build.sh

4
bin/update-trunk.sh Normal file
View File

@ -0,0 +1,4 @@
#!/bin/bash
cd $DGL_CONF_HOME/crawl-build
source ./update-crawl-trunk-build.sh

304
chroot/bin/crawl-git-launcher.sh Executable file
View File

@ -0,0 +1,304 @@
#! /bin/bash
#
# Must be called as crawl-git -name <playername> [...]; character name
# must always be the second argument.
#
# ===========================================================================
# Copyright (C) 2008, 2009, 2010, 2011 Marc H. Thoben
# Copyright (C) 2011 Darshan Shaligram
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# ===========================================================================
#
# The webtiles binary requires a UTF-8 locale.
export LC_ALL=en_US.UTF-8
set -o nounset
CRAWL_GIT_DIR="%%CHROOT_CRAWL_BASEDIR%%"
USER_DB="%%CHROOT_LOGIN_DB%%"
CRAWL_BINARY_PATH="%%CHROOT_CRAWL_BINARY_PATH%%"
BINARY_BASE_NAME="%%GAME%%"
USER_ID="%%DGL_UID%%"
VERSIONS_DB="%%CHROOT_VERSIONS_DB%%"
export HOME="%%CHROOT_COREDIR%%"
# Word boundary regex; bash's =~ is funny about that.
wb='\b'
JUST_RUN_CRAWL_ALREADY=
# If set, this script will not event report the existence of newer versions.
[[ "$@" =~ -print-charset$wb ]] && JUST_RUN_CRAWL_ALREADY=1
[[ "$@" =~ -print-webtiles-options$wb ]] && JUST_RUN_CRAWL_ALREADY=1
WEBTILES=
[[ "$@" =~ -await-connection$wb ]] && WEBTILES=1
cecho() {
[[ -z "$WEBTILES" ]] && echo "$@"
}
wecho() {
[[ -n "$WEBTILES" ]] && echo "$@"
}
wcat() {
if [[ -n "$WEBTILES" ]]; then
tr '\n' ' ' | sed -e 's/ $//'
echo
else
cat >/dev/null
fi
}
TRANSFER_ENABLED="1"
CHAR_NAME="$2"
NICE=""
[[ $CHAR_NAME = notqw ]] && NICE="nice -n 10 ionice -c 3"
# Clear screen
[[ -z "$JUST_RUN_CRAWL_ALREADY" && -z "$WEBTILES" ]] && printf "\e[2J\e[H"
export LANG="en_US.UTF-8"
export LC_CTYPE="en_US.UTF-8"
SAVES="saves"
[[ "$@" =~ -sprint$wb ]] && SAVES="$SAVES/sprint"
[[ "$@" =~ -zotdef$wb ]] && SAVES="$SAVES/zotdef"
if [[ $# == 0 || -z "$CHAR_NAME" ]]; then
if [[ -z "$JUST_RUN_CRAWL_ALREADY" ]]; then
echo "Parameters missing. Aborting..."
read -n 1 -s -p "--- any key to continue ---"
echo
fi
exit 1
fi
ulimit -S -c 1536000 2>/dev/null
ulimit -S -v 1024000 2>/dev/null
first-real-file() {
for file in "$@"; do
if [[ -f "$file" ]]; then
printf "%s\n" "$file"
return 0
fi
done
}
query() {
sqlite3 "$VERSIONS_DB"
}
hash-description() {
local hash=$1
query <<EOF
SELECT description FROM versions WHERE hash='$hash' LIMIT 1;
EOF
}
latest-game-hash() {
query <<EOF
SELECT hash FROM versions ORDER BY time DESC LIMIT 1;
EOF
}
major-version-for-game() {
local game=$1
query <<EOF
SELECT major FROM versions WHERE hash='$game' LIMIT 1;
EOF
}
newest-version-with-major-version() {
local major_version=$1
query <<EOF
SELECT hash FROM versions WHERE major=$major_version
ORDER BY time DESC
LIMIT 1;
EOF
}
user-is-admin() {
local found="$(echo "SELECT username FROM dglusers
WHERE username='$CHAR_NAME' AND (flags & 1) = 1;" |
sqlite3 "$USER_DB")"
[[ -n "$found" ]]
}
transfer-save() {
local save=$1
local game_hash=$2
local target="$CRAWL_GIT_DIR/$BINARY_BASE_NAME-$game_hash/$SAVES"
local src_save_dir=$(dirname $save)
wecho -n '{"msg":"show_dialog", "html":"'
if [[ -d "$target" ]]; then
# It's okay if moving the .prf fails (it might not exist one day).
mv "$src_save_dir/start-$CHAR_NAME-ns.prf" "$target" 2>/dev/null || true
mv "$src_save_dir/$CHAR_NAME".cs "$target"
if test $? -eq 0
then
wcat <<EOF
<p>Transferring successful!</p>
<input type='button' class='button' data-key=' ' value='Continue' style='float:right;'>
"}
EOF
cecho ": successful!"
cecho
OUR_GAME_HASH="${game_hash}"
cecho -n "--- any key to continue ---"
read -n 1 -t 5 -s
cecho
else
wcat <<EOF
<p>Transferring failed!</p>
<p>Transferring your save failed! Continuing with former version.</p>
<input type='button' class='button' data-key=' ' value='Continue' style='float:right;'>
"}
EOF
cecho ": failed!"
cecho
cecho "Transferring your save failed! Continuing with former version."
cecho -n "--- any key to continue ---"
read -n 1 -s
cecho
fi
else
wcat <<EOF
<p>Transferring failed!</p>
<p>Target version is corrupt! Continuing with former version.</p>
<input type='button' class='button' data-key=' ' value='Continue' style='float:right;'>
"}
EOF
cecho ": failed!"
cecho
cecho "Target version is corrupt! Continuing with former version."
cecho -n "--- any key to continue ---"
read -n 1 -s
cecho
fi
wecho '{"msg":"hide_dialog"}'
}
SAVEGLOB="$CRAWL_GIT_DIR/$BINARY_BASE_NAME-*/$SAVES"
declare -a SAVE_CANDIDATES
SAVE_CANDIDATES=($SAVEGLOB/$CHAR_NAME.cs \
$SAVEGLOB/$CHAR_NAME-$USER_ID.sav \
$SAVEGLOB/$CHAR_NAME-$USER_ID.chr)
SAVE="$(first-real-file "${SAVE_CANDIDATES[@]}")"
LATEST_GAME_HASH="$(latest-game-hash)"
if [[ -n "$SAVE" ]]; then
OUR_GAME_HASH=${SAVE#$CRAWL_GIT_DIR/$BINARY_BASE_NAME-}
OUR_GAME_HASH=${OUR_GAME_HASH%%/*}
if [[ -z "$JUST_RUN_CRAWL_ALREADY" && \
"$OUR_GAME_HASH" != "$LATEST_GAME_HASH" ]]
then
current_ver="$(hash-description $OUR_GAME_HASH)"
cecho "Hi, you have a $current_ver save game:"
cecho
OUR_SGV_MAJOR="$(major-version-for-game $OUR_GAME_HASH)"
NEW_GAME_HASH="$(newest-version-with-major-version $OUR_SGV_MAJOR)"
new_ver="$(hash-description $NEW_GAME_HASH)"
if [[ "$OUR_GAME_HASH" != "$NEW_GAME_HASH" &&
"$TRANSFER_ENABLED" == "1" ]]; then
wecho '{"msg":"layer", "layer":"crt"}'
wecho -n '{"msg":"show_dialog", "html":"'
if [[ "${NEW_GAME_HASH}" != "${LATEST_GAME_HASH}" ]]; then
cecho "There's a newer version ($new_ver) that can load your save."
cecho -n "[T]ransfer your save to this version?"
wcat <<EOF
<p>There's a newer version ($new_ver) that can load your save.</p>
<p>[T]ransfer your save to this version?</p>
<input type='button' class='button' data-key='N' value='No' style='float:right;'>
<input type='button' class='button' data-key='T' value='Yes' style='float:right;'>
"}
EOF
read -n 1 -s REPLY
cecho
else
cecho -n "[T]ransfer your save to the latest version ($new_ver)?"
wcat <<EOF
<p>[T]ransfer your save to the latest version ($new_ver)?</p>
<input type='button' class='button' data-key='N' value='No' style='float:right;'>
<input type='button' class='button' data-key='T' value='Yes' style='float:right;'>
"}
EOF
read -n 1 -s REPLY
cecho
fi
wecho '{"msg":"hide_dialog"}'
if test "$REPLY" = "t" -o "$REPLY" = "T" -o "$REPLY" = "y" -o "$REPLY" = "Y"
then
cecho -n "Transferring..."
transfer-save "$SAVE" "$NEW_GAME_HASH"
fi
else
if test "${TRANSFER_ENABLED}" != "1"
then
cecho "Transfering of saves is currently disabled."
cecho "Finish your game or end your character to play in latest version."
else
cecho "Your save cannot be tranferred though because of incompatibility."
cecho "Finish your game or end your character to play in latest version."
fi
cecho -n "--- any key to continue ---"
[[ -z "$WEBTILES" ]] && read -n 1 -t 5 -s
cecho
fi
fi
else
OUR_GAME_HASH="${LATEST_GAME_HASH}"
fi
if test ${#OUR_GAME_HASH} -eq 0
then
cecho "Could not figure out the right game version. Aborting..."
cecho -n "--- any key to continue ---"
[[ -z "$WEBTILES" ]] && read -n 1 -s -p
cecho
exit 1
fi
BINARY_NAME="$CRAWL_BINARY_PATH/$BINARY_BASE_NAME-$OUR_GAME_HASH"
GAME_FOLDER="$CRAWL_GIT_DIR/$BINARY_BASE_NAME-$OUR_GAME_HASH"
if user-is-admin; then
set -- "$@" -wizard
fi
if test -x "${BINARY_NAME}" -a -d "${GAME_FOLDER}"
then
cd ${HOME}
exec ${NICE} ${BINARY_NAME} "$@"
fi
cecho "Failed starting: ${BINARY_NAME} not found!"
read -n 1 -s -p "--- any key to continue ---"
cecho
exit 1

View File

@ -0,0 +1,115 @@
#! /bin/bash
#
# Must be called as crawl-git -name <playername> [...]; character name
# must always be the second argument.
#
# ===========================================================================
# Copyright (C) 2008, 2009, 2010, 2011 Marc H. Thoben
# Copyright (C) 2011 Darshan Shaligram
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# ===========================================================================
#
# The webtiles binary requires a UTF-8 locale.
export LC_ALL=en_US.UTF-8
set -o nounset
VERSION=$1
shift
CRAWL_GIT_DIR="%%CHROOT_CRAWL_BASEDIR%%"
USER_DB="%%CHROOT_LOGIN_DB%%"
CRAWL_BINARY_PATH="%%CHROOT_CRAWL_BINARY_PATH%%"
BINARY_BASE_NAME="crawl-$VERSION"
USER_ID="%%DGL_UID%%"
export HOME="%%CHROOT_COREDIR%%"
# Word boundary regex; bash's =~ is funny about that.
wb='\b'
JUST_RUN_CRAWL_ALREADY=
# If set, this script will not event report the existence of newer versions.
[[ "$@" =~ -print-charset$wb ]] && JUST_RUN_CRAWL_ALREADY=1
[[ "$@" =~ -print-webtiles-options$wb ]] && JUST_RUN_CRAWL_ALREADY=1
WEBTILES=
[[ "$@" =~ -await-connection$wb ]] && WEBTILES=1
cecho() {
[[ -z "$WEBTILES" ]] && echo "$@"
}
wecho() {
[[ -n "$WEBTILES" ]] && echo "$@"
}
TRANSFER_ENABLED="1"
CHAR_NAME="$2"
NICE=""
[[ $CHAR_NAME = notqw ]] && NICE="nice -n 10 ionice -c 3"
# Clear screen
[[ -z "$JUST_RUN_CRAWL_ALREADY" && -z "$WEBTILES" ]] && printf "\e[2J\e[H"
export LANG="en_US.UTF-8"
export LC_CTYPE="en_US.UTF-8"
if [[ $# == 0 || -z "$CHAR_NAME" ]]; then
if [[ -z "$JUST_RUN_CRAWL_ALREADY" ]]; then
echo "Parameters missing. Aborting..."
read -n 1 -s -p "--- any key to continue ---"
echo
fi;
exit 1
fi
ulimit -S -c 1536000 2>/dev/null
ulimit -S -v 1024000 2>/dev/null
first-real-file() {
for file in "$@"; do
if [[ -f "$file" ]]; then
printf "%s\n" "$file"
return 0
fi
done
}
user-is-admin() {
local found="$(echo "SELECT username FROM dglusers
WHERE username='$CHAR_NAME' AND (flags & 1) = 1;" |
sqlite3 "$USER_DB")"
[[ -n "$found" ]]
}
BINARY_NAME="$CRAWL_BINARY_PATH/$BINARY_BASE_NAME"
GAME_FOLDER="$CRAWL_GIT_DIR/$BINARY_BASE_NAME"
if user-is-admin; then
set -- "$@" -wizard
fi
if test -x "${BINARY_NAME}" -a -d "${GAME_FOLDER}"
then
cd ${HOME}
exec ${NICE} ${BINARY_NAME} "$@"
fi
cecho "Failed starting: ${BINARY_NAME} not found!"
read -n 1 -s -p "--- any key to continue ---"
cecho
exit 1

29
chroot/bin/init-webtiles.sh Executable file
View File

@ -0,0 +1,29 @@
#! /bin/sh
ifnxcp() {
[ -e "$2" ] || cp "$1" "$2";
}
NAME=$1
ifnxcp %%CHROOT_DGLDIR%%/data/crawl-git-settings/init.txt %%CHROOT_RCFILESDIR%%/crawl-git/"$NAME".rc
ifnxcp %%CHROOT_DGLDIR%%/data/crawl-git.macro %%CHROOT_RCFILESDIR%%/crawl-git/"$NAME".macro
ifnxcp %%CHROOT_DGLDIR%%/data/crawl-0.17-settings/init.txt %%CHROOT_RCFILESDIR%%/crawl-0.17/"$NAME".rc
ifnxcp %%CHROOT_DGLDIR%%/data/crawl-git.macro %%CHROOT_RCFILESDIR%%/crawl-0.17/"$NAME".macro
ifnxcp %%CHROOT_DGLDIR%%/data/crawl-0.16-settings/init.txt %%CHROOT_RCFILESDIR%%/crawl-0.16/"$NAME".rc
ifnxcp %%CHROOT_DGLDIR%%/data/crawl-git.macro %%CHROOT_RCFILESDIR%%/crawl-0.16/"$NAME".macro
ifnxcp %%CHROOT_DGLDIR%%/data/crawl-0.15-settings/init.txt %%CHROOT_RCFILESDIR%%/crawl-0.15/"$NAME".rc
ifnxcp %%CHROOT_DGLDIR%%/data/crawl-git.macro %%CHROOT_RCFILESDIR%%/crawl-0.15/"$NAME".macro
ifnxcp %%CHROOT_DGLDIR%%/data/crawl-0.14-settings/init.txt %%CHROOT_RCFILESDIR%%/crawl-0.14/"$NAME".rc
ifnxcp %%CHROOT_DGLDIR%%/data/crawl-git.macro %%CHROOT_RCFILESDIR%%/crawl-0.14/"$NAME".macro
ifnxcp %%CHROOT_DGLDIR%%/data/crawl-0.13-settings/init.txt %%CHROOT_RCFILESDIR%%/crawl-0.13/"$NAME".rc
ifnxcp %%CHROOT_DGLDIR%%/data/crawl-git.macro %%CHROOT_RCFILESDIR%%/crawl-0.13/"$NAME".macro
ifnxcp %%CHROOT_DGLDIR%%/data/crawl-0.12-settings/init.txt %%CHROOT_RCFILESDIR%%/crawl-0.12/"$NAME".rc
ifnxcp %%CHROOT_DGLDIR%%/data/crawl-git.macro %%CHROOT_RCFILESDIR%%/crawl-0.12/"$NAME".macro
ifnxcp %%CHROOT_DGLDIR%%/data/crawl-0.11-settings/init.txt %%CHROOT_RCFILESDIR%%/crawl-0.11/"$NAME".rc
ifnxcp %%CHROOT_DGLDIR%%/data/crawl-git.macro %%CHROOT_RCFILESDIR%%/crawl-0.11/"$NAME".macro
ifnxcp %%CHROOT_DGLDIR%%/data/crawl-0.10-settings/init.txt %%CHROOT_RCFILESDIR%%/crawl-0.10/"$NAME".rc
ifnxcp %%CHROOT_DGLDIR%%/data/crawl-git.macro %%CHROOT_RCFILESDIR%%/crawl-0.10/"$NAME".macro
mkdir -p %%CHROOT_MORGUEDIR%%/"$NAME"
mkdir -p %%CHROOT_TTYRECDIR%%/"$NAME"

144
chroot/bin/savegame-backup.sh Executable file
View File

@ -0,0 +1,144 @@
#!/bin/bash
#
# ===========================================================================
# Copyright (C) 2008, 2009, 2010, 2011 Marc H. Thoben
# Copyright (C) 2011 Darshan Shaligram
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# ===========================================================================
#
set -u
ARGUMENTS=($@)
CHAR_NAME="$(echo ${ARGUMENTS[0]} | sed 's/[$*\/();.|+-]//g')"
BINARY_MAIN_NAME=${ARGUMENTS[1]}
BINARY_SAVE_NAME=$BINARY_MAIN_NAME
PREFIX="${ARGUMENTS[2]}"
trap "read -n 1 -s -p '-- Hit a key to exit --'; exit 0" EXIT
clear
TODAY="$(date +%y%m%d-%H%M)"
TARGET_DIR="%%CHROOT_SAVE_DUMPDIR%%"
HTTP_LINK="%%WEB_SAVEDUMP_URL%%"
USER_ID="%%DGL_UID%%"
existing-files() {
for file in "$@"; do
if [[ -f "$file" ]]; then
printf "%s " "$file"
fi
done
}
first-existing-file() {
for file in "$@"; do
if [[ -f "$file" ]]; then
echo "$file"
fi
done
}
savedir-containing() {
local char="$1"
local -a saves
saves=($PREFIX/$BINARY_SAVE_NAME{,-*}/saves/$char{,-$USER_ID}.{cs,chr,sav})
local savefile="$(first-existing-file "${saves[@]}")"
[[ -n "$savefile" ]] && dirname "$savefile"
return 0
}
SAVES="$(savedir-containing $CHAR_NAME)"
SPRINT_SAVES="$(savedir-containing sprint/$CHAR_NAME)"
ZOTDEF_SAVES="$(savedir-containing zotdef/$CHAR_NAME)"
if [[ -z "$SAVES" && -z "$SPRINT_SAVES" && -z "$ZOTDEF_SAVES" ]]; then
echo "No saves to backup for $CHAR_NAME"
fi
SAVE_QUALIFIER=""
CHAR=Character
C_NORMAL="\033[0m"
C_YELLOW="\033[1;33m"
C_GREEN="\033[1;32m"
C_RED="\033[1;31m"
PROMPT="Backup"
[[ -n "$SAVES" ]] && PROMPT="$PROMPT [n]ormal save"
[[ -n "$SPRINT_SAVES" ]] && PROMPT="$PROMPT [s]print"
[[ -n "$ZOTDEF_SAVES" ]] && PROMPT="$PROMPT [z]otdef"
PROMPT="$PROMPT character?"
read -n 1 -s -p "$PROMPT" REPLY
echo
REPLY="$(echo "$REPLY" | sed 's/\([A-Z]\)/\L\1/g')"
if [[ -n "$SPRINT_SAVES" && ( "$REPLY" = "s" ) ]]; then
SAVE_QUALIFIER="-sprint"
SAVES="$SPRINT_SAVES"
CHAR="Sprint character"
elif [[ -n "$ZOTDEF_SAVES" && ( "$REPLY" = "z" ) ]]; then
SAVE_QUALIFIER="-zotdef"
SAVES="$ZOTDEF_SAVES"
CHAR="Zot Defense character"
elif [[ "$REPLY" != "n" ]]; then
echo -e "Bad choice, aborting."
exit 1
fi
declare -a SAVE_MATCHES
SAVE_MATCHES=(${SAVES}/${CHAR_NAME}{,-${USER_ID}}.{sav,cs,chr}*)
# Get rid of glob patterns that failed to match anything:
SAVE_MATCHES=(${SAVE_MATCHES[@]##*\*})
# And the first remaining entry is the matched save.
SAVE_FOUND=${SAVE_MATCHES[0]}
if [[ -n "$SAVE_FOUND" && -f "$SAVE_FOUND" ]]; then
GAME_NAME=${SAVES%/zotdef}
GAME_NAME=${GAME_NAME%/sprint}
GAME_NAME="$(dirname $GAME_NAME)"
GAME_NAME="${GAME_NAME##*/}"
echo
echo "$CHAR \"${CHAR_NAME}\" in $GAME_NAME. "
echo -n "Backing up:"
cd $SAVES
TARNAME=${CHAR_NAME}${SAVE_QUALIFIER}-$GAME_NAME-${TODAY}.tar.bz2
tar -cjf ${TARGET_DIR}/$TARNAME \
$(existing-files ${CHAR_NAME}{,-${USER_ID}}.*)
if test $? -ne 0
then
echo -e " ${C_RED}failed!${C_NORMAL}"
else
echo -e " ${C_GREEN}successful.${C_NORMAL}"
echo "- ${HTTP_LINK}/$TARNAME"
echo
echo "Please provide this link in your bug-report or give it to a developer."
fi
else
echo "Your character ($CHAR_NAME) was not found in $SAVES."
fi

7
chroot/data/dgl-banner Executable file
View File

@ -0,0 +1,7 @@
Crawl server (Germany) hosted and maintained by Ben Morrison (ahriman).
------------------------------------------------------------------------------
Webtiles: http://crawl.tildeverse.org/
Crawl information: http://crawl.develz.org/
------------------------------------------------------------------------------
** Games on this server are recorded for in-progress viewing and playback! **
------------------------------------------------------------------------------

View File

View File

@ -0,0 +1,420 @@
# Crawl Init file
#
# On Unix systems (such as Mac OS X, Linux and the BSDs), you must copy
# init.txt to ~/.crawlrc or ~/.crawl/init.txt as:
# cp init.txt ~/.crawlrc
#
# Lines beginning with '#' are comments. The basic syntax is:
#
# field = value or field.subfield = value
#
# Only one specification is allowed per line.
#
# The terms are typically case-insensitive except in the fairly obvious
# cases (the character's name and specifying files or directories when
# on a system that has case-sensitive filenames).
#
# White space is stripped from the beginning and end of the line, as
# well as immediately before and after the '='. If the option allows
# multiple comma/semicolon-separated terms (such as
# autopickup_exceptions), all whitespace around the separator is also
# trimmed. All other whitespace is left intact.
#
# For descriptions concerning an option consult the file
# options_guide.txt
# in your /docs directory. Also note that the ordering of the options
# is taken from that file; this is for presentational reasons only.
#
# Note that all boolean options (i.e. values of 'true' or 'false') have
# their non-default value commented out. You can toggle these by just
# uncommenting.
# Options with several values, e.g. drop_mode = (multi | single),
# usually have the first value as default.
#
# The options for monster glyphs and item colours don't matter for Tiles.
# Similarily, tile options are ignored in console games.
##### Ancient versions ##############################################
# If you're used to the interface of ancient versions of Crawl, you may
# get back parts of it by uncommenting the following options:
# include = 034_command_keys.txt
# target_unshifted_dirs = true
# clear_messages = true
#
# And to revert monster glyph and colouring changes:
# include = 034_monster_glyphs.txt
# include = 052_monster_glyphs.txt
# include = 060_monster_glyphs.txt
# include = 071_monster_glyphs.txt
# include = 080_monster_glyphs.txt
# include = 0.9_monster_glyphs.txt
##### 1- Starting Screen ############################################
#
# name = Delilah
# remember_name = false
# weapon = (short sword | falchion | quarterstaff | hand axe | spear | mace
# | trident | unarmed | random)
# species = (Human |...| Vampire | random)
# job = (Fighter |...| Wanderer | random)
# random_pick = true
# good_random = false
# restart_after_game = true
# default_manual_training = true
##### 2- File System ###############################################
#
# crawl_dir = <path>
# morgue_dir = morgue
# save_dir = saves
# macro_dir = settings/
# sound = <regex>:<path to sound file>
##### 3- Lua Files #################################################
#
lua_file = lua/stash.lua
lua_file = lua/wield.lua
lua_file = lua/runrest.lua
lua_file = lua/gearset.lua
lua_file = lua/trapwalk.lua
# kills.lua yields more information at the cost of huge dumps.
# lua_file = lua/kills.lua
# autofight.lua allows binding both movement and attack a single key.
# Use at your own discretion! See options_guide.txt for details.
lua_file = lua/autofight.lua
##### 4- Interface #################################################
#
##### 4-a Picking up and Dropping ###############
#
autopickup = $?!+"/%
# There is a long list of autopickup exceptions in
include = autopickup_exceptions.txt
drop_filter = useless_item
# default_autopickup = false
# autopickup_no_burden = false
# pickup_thrown = false
# chunks_autopickup = false
# assign_item_slot = (forward | backward)
#
# drop_mode = (multi | single)
# pickup_mode = (single | multi | auto:5)
# drop_filter = skeleton, corpse, useless_item
# default_friendly_pickup = (none | friend | player | all)
##### 4-b Targetting ############################
#
# default_target = false
# target_unshifted_dirs = true
# darken_beyond_range = false
##### 4-c Passive Sightings #####################
#
# detected_monster_colour = lightred
# detected_item_colour = green
# remembered_monster_colour = darkgrey
# clean_map = true
##### 4-d Branding ##############################
#
# friend_brand = hi:green
# neutral_brand = hi:lightgrey
# stab_brand = hi:blue
# may_stab_brand = hi:yellow
# heap_brand = reverse
# feature_item_brand = reverse
# trap_item_brand = reverse
##### 4-e Level Map Functions ###################
#
# level_map_cursor_step = 7
# level_map_title = false
# show_waypoints = false
##### 4-f Viewport Options ###################
#
# view_max_width = 33
# view_max_height = 21
# view_lock_x = false
# view_lock_y = false
# view_lock = false
# center_on_scroll = true
# symmetric_scroll = false
# scroll_margin_x = 2
# scroll_margin_y = 2
# scroll_margin = 2
##### 4-g Travel and Exploration #################
#
# travel_delay = 20
# explore_delay = -1
# travel_avoid_terrain = shallow water
#
# explore_greedy = false
# explore_stop = items,greedy_pickup_smart,stairs,shops,altars,gates
# explore_stop += greedy_visited_item_stack
# explore_improved = true
# explore_wall_bias = 0
# travel_key_stop = false
#
# explore_stop_pickup_ignore = curare
auto_exclude = oklob,statue,curse skull,roxanne,hyperactive,lightning spire
# tc_reachable = blue
# tc_dangerous = cyan
# tc_disconnected = darkgrey
# tc_excluded = lightmagenta
# tc_exclude_circle = red
# runrest options (require runrest.lua to be included above)
runrest_ignore_poison = 2:30
runrest_ignore_monster = butterfly:1
# runrest_ignore_monster = swamp worm:3
# The file runrest_messages.txt contains a list of default
# runrest message settings. Add your own before this to override
# later settings.
# runrest_stop_message = You hear a.* slurping noise
# runrest_ignore_message = Jiyva's power touches on your attributes
include = runrest_messages.txt
trapwalk_safe_hp = dart:20,needle:15,arrow:35,bolt:45,spear:40,axe:45,blade:95
#rest_wait_both = true
##### 4-h Stashes ###############################
#
# annotate_item_class = true
# annotate_item_dropped = true
##### 4-i Command Enhancements ##################
#
# auto_list = false
# auto_switch = true
# easy_open = false
# easy_unequip = false
# equip_unequip = true
# easy_confirm = (none | safe | all)
# allow_self_target = (yes | no | prompt)
# confirm_butcher = (auto | always | never)
# prefer_safe_chunks = false
# easy_eat_chunks = true
# easy_eat_gourmand = true
# easy_eat_contaminated = true
# auto_eat_chunks = true
# prompt_for_swap = false
# easy_quit_item_prompts = false
# easy_exit_menu = true
# sort_menus = pickup: true : art, ego, basename, qualname, curse, qty
sort_menus = inv: true : equipped, freshness, charged
# autofight_stop = 30
##### 4-j Messages and Display Enhancements #####
#
# hp_warning = 30
# mp_warning = 0
# hp_colour = 50:yellow, 25:red
# mp_colour = 50:yellow, 25:red
# stat_colour = 1:lightred, 3:red
# status_caption_colour = yellow
# mlist_min_height = 4
# msg_min_height = 7
# msg_max_height = 10
# mlist_allow_alternate_layout = true
# messages_at_top = true
# mlist_targetting = true
# show_gold_turns = true
# show_game_turns = true
# show_newturn_mark = false
# clear_messages = true
# small_more = true
# show_more = false
# show_inventory_weights = true
# item_stack_summary_minimum = 5
# list_rotten = false
# msg_condense_repeats = false
# msg_condense_short = false
# show_no_ctele = false
# skill_focus = false
##### Colours (messages and menus) #####
#
# menu_colour_prefix_class = false
# menu_colour_shops = false
# Food is colour coded in standard_colours.txt as follows:
include = standard_colours.txt
#
# yellow = preferred food ($preferred)
# darkgrey = cannot be eaten at all ($inedible)
# lightred = causes rot ($rot-inducing)
# magenta = dangerous to use, mutagenic ($dangerous, $mutagenic)
# red = considered "evil" by your deity ($evil)
# lightgreen = poisonous ($poisonous)
# brown = contaminated, may cause nausea ($contaminated)
#
# You can change colours by using something like
# $contaminated := magenta
include = food_colouring.txt
# There is elaborate colouring of items in the inventory (and other menus)
# depending on their usefulness, taking species and other criteria into account.
include = menu_colours.txt
# Colouring of autoinscribed god gifts
menu_colour = pickup:green:god gift
# Highlight (partly) selected items
menu_colour = inventory:white:\w \+\s
menu_colour = inventory:white:\w \#\s
# Colouring of messages
# Messages are colour coded in standard_colours.txt as follows:
#
# lightred = really important messages ($danger)
# yellow = significant messages ($warning)
# lightred = item damaged/destroyed ($item_dmg [same as $danger])
# darkgrey = boring, message clutter ($boring)
#
include = messages.txt
# Colouring for the notes
menu_colour = notes:white:Reached XP level
# These lines will suppress extra feedback messages from travel/shift-running.
#
# message_colour = mute:warning:comes into view
# message_colour = mute:You start (searching|resting)
# message_colour = mute:Done searching
# message_colour = mute:(HP|Magic) restored
# message_colour = mute:warning:Not with.*(in view|monsters around)
# You can also enforce a --more-- prompt for messages
## Avoid wasting turns with aborted actions:
# force_more_message = There are no visible monsters within range
# force_more_message = This wand has no charges
force_more_message = You have reached level
force_more_message = Your scales start
force_more_message = You fall through a shaft
## Reduce chance of drowning because levitation or form runs out:
force_more_message = Careful!
# Announcements of timed portal vaults (bazaar, labyrinths):
force_more_message = interdimensional caravan
force_more_message = distant snort
##### 4-k Firing Commands #######################
#
# fire_items_start = a
# fire_order = launcher, return
# fire_order += javelin / dart / stone / rock / spear / net / handaxe / dagger / club
# fire_order += inscribed
##### 4-l Channels ##############################
#
# channel.multiturn = mute
##### 4-m Inscriptions ##########################
#
# autoinscribe = bad_item.*potion:!q
# autoinscribe = potion.*mutation:!q
# autoinscribe = royal jell:=g
# autoinscribe_artefacts = false
# autoinscribe_cursed = false
# autoinscribe = fruit:!e
##### 4-n Macro related Options #################
#
# flush.failure = false
# flush.command = true
# flush.message = true
##### 4-t Tile related Options ##################
# All tiles specific options are in the external file
include = tiles_options.txt
##### 5- Dump File #################################################
#
##### 5-a Items and Kill List ###################
#
# kill_map = friend:you, other:you
# dump_kill_places = (single | all | none)
# dump_item_origins = all,artifacts,ego_arm,ego_weap,jewellery,runes
# dump_item_origin_price = -1
# dump_message_count = 20
# dump_order = header, hiscore, stats, misc, notes, inventory,
# dump_order += turns_by_place, skills, spells, overview, mutations,
# dump_order += messages, screenshot, monlist, kills_by_place, kills
# dump_order += spell_usage, action_counts
# dump_book_spells = false
##### 5-b Notes #################################
#
# user_note_prefix=@@@
ood_interesting = 8
note_hp_percent = 5
note_skill_levels = 1,5,10,15,27
#note_all_skill_levels = true
#note_skill_max = false
#note_all_spells = false
#note_xom_effects = false
note_items = rod of, acquirement, preservation, running, of Zot
note_messages = You pass through the gate
note_messages = cast .* Abyss
note_messages = Your scales start
note_messages = protects you from harm
note_messages = You fall through a shaft
note_monsters = orb of fire, ancient lich, Sigmund
##### 6- Miscellaneous #############################################
#
##### 6-a All OS ################################
#
# mouse_input = true
# wiz_mode = no
# char_set = ascii
# use_fake_player_cursor = false
#
# colour.lightgray = black
# colour.lightcyan = cyan
# colour.yellow = brown
#
# pizza = Sausage
# show_player_species = true
# See options_guide.txt for the options
# cset, feature, mon_glyph
## Highlight the edge of unexplored terrain.
# feature = explore horizon {',,green}
##### 6-b Windows console #######################
#
# dos_use_background_intensity = true
# background = black
##### 6-c Unix console ##########################
#
# use_fake_cursor = false
##### 6-d Alternative keybinding files ##########
#
# Alternative vi bindings for Dvorak users.
# include = dvorak_command_keys.txt
#
# Override the vi movement keys with a non-command.
# include = no_vi_command_keys.txt

View File

@ -0,0 +1,23 @@
Crawl server (Germany) hosted and maintained by Ben Morrison (ahriman)
------------------------------------------------------------------------------
Webtiles: https://crawl.tildeverse.org/
Crawl information: http://crawl.develz.org/
------------------------------------------------------------------------------
** Games on this server are recorded for in-progress viewing and playback! **
------------------------------------------------------------------------------
Logged in as: $USERNAME
Game selected: Dungeon Crawl Stone Soup 0.22
P)lay Crawl S)print T)utorial
o Edit options O) with Virus
m Edit macros M) with Virus
v View changelog V) with Virus
Advanced options
q Return to main menu
=>

View File

@ -0,0 +1,22 @@
Crawl server (Germany) hosted and maintained by Ben Morrison (ahriman)
------------------------------------------------------------------------------
Webtiles: https://crawl.tildeverse.org/
Crawl information: http://crawl.develz.org/
------------------------------------------------------------------------------
** Games on this server are recorded for in-progress viewing and playback! **
------------------------------------------------------------------------------
Logged in as: $USERNAME
Game selected: Dungeon Crawl Stone Soup 0.22
Backup your save-game (for bug reports and debugging)
The next option allows you to reset your options.
ALL CHANGES YOU'VE MADE TO YOUR OPTIONS WILL BE LOST.
O Reset options
q Return to previous menu
=>

View File

@ -0,0 +1,23 @@
Crawl server (Germany) hosted and maintained by Ben Morrison (ahriman)
------------------------------------------------------------------------------
Webtiles: https://crawl.tildeverse.org/
Crawl information: http://crawl.develz.org/
------------------------------------------------------------------------------
** Games on this server are recorded for in-progress viewing and playback! **
------------------------------------------------------------------------------
Logged in as: $USERNAME
Game selected: Dungeon Crawl Stone Soup Trunk
P)lay Crawl S)print T)utorial
o Edit options O) with Virus
m Edit macros M) with Virus
v View changelog V) with Virus
Advanced options
q Return to main menu
=>

View File

@ -0,0 +1,22 @@
Crawl server (Germany) hosted and maintained by Ben Morrison (ahriman)
------------------------------------------------------------------------------
Webtiles: https://crawl.tildeverse.org/
Crawl information: http://crawl.develz.org/
------------------------------------------------------------------------------
** Games on this server are recorded for in-progress viewing and playback! **
------------------------------------------------------------------------------
Logged in as: $USERNAME
Game selected: Dungeon Crawl Stone Soup Trunk
Backup your save-game (for bug reports and debugging)
The next option allows you to reset your options.
ALL CHANGES YOU'VE MADE TO YOUR OPTIONS WILL BE LOST.
O Reset options
q Return to previous menu
=>

View File

@ -0,0 +1,22 @@
Crawl server (Germany) hosted and maintained by Ben Morrison (ahriman)
------------------------------------------------------------------------------
Webtiles: https://crawl.tildeverse.org/
Crawl information: http://crawl.develz.org/
------------------------------------------------------------------------------
** Games on this server are recorded for in-progress viewing and playback! **
------------------------------------------------------------------------------
Logged in as: $USERNAME
Game selected: Dungeon Crawl Stone Soup experimental branches
WARNING: Experimental branches have limited save compatibility! Updates to the
branches may cause the loss of existing games, and branches may be removed
without warning: don't get too attached to your character. Thanks for helping
us evaluate potential new features!
Chunkless
Iashol
Smith God (updated)
q Return to trunk menu
=>

View File

@ -0,0 +1,21 @@
Crawl server (Germany) hosted and maintained by Ben Morrison (ahriman)
------------------------------------------------------------------------------
Webtiles: https://crawl.tildeverse.org
Crawl information: http://crawl.develz.org/
------------------------------------------------------------------------------
** Games on this server are recorded for in-progress viewing and playback! **
------------------------------------------------------------------------------
Logged in as: $USERNAME (admin)
W) Watch games in progress
T) Dungeon Crawl Stone Soup Trunk
0) Dungeon Crawl Stone Soup 0.22
c) Change password e) Change email address
P)lay or S)print in Crawl 0.22 now
Q)uit
=>

View File

@ -0,0 +1,18 @@
Crawl server (Germany) hosted and maintained by Ben Morrison (ahriman)
------------------------------------------------------------------------------
Webtiles: https://crawl.tildeverse.org/
Crawl information: http://crawl.develz.org/
------------------------------------------------------------------------------
** Games on this server are recorded for in-progress viewing and playback! **
------------------------------------------------------------------------------
Not logged in.
W) Watch games in progress
R) Register as new user
L) Login
Q) Quit
=>

View File

@ -0,0 +1,21 @@
Crawl server (Germany) hosted and maintained by Ben Morrison (ahriman)
------------------------------------------------------------------------------
Webtiles: https://crawl.tildeverse.org/
Crawl information: http://crawl.develz.org/
------------------------------------------------------------------------------
** Games on this server are recorded for in-progress viewing and playback! **
------------------------------------------------------------------------------
Logged in as: $USERNAME
W) Watch games in progress
T) Dungeon Crawl Stone Soup Trunk
0) Dungeon Crawl Stone Soup 0.22
c) Change password e) Change email address
P)lay or S)print in Crawl 0.22 now
Q)uit
=>

View File

@ -0,0 +1,22 @@
Help for watching-menu
----------------------
? show this help.
> < next/previous page.
. , change sorting method.
q Q return to main menu.
a-zA-Z select a game to watch.
/ select/search by name a game to watch.
* start showing a randomly selected game.
enter start watching already selected game.
While watching a game
---------------------
q return to the watching menu.
m send mail to the player (requires login.
s toggle charset stripping between Unicode/IBM/none.
r resize your terminal to match the player's terminal.
Press 'q' or space to return.

133
chroot/sbin/install-stable.sh Executable file
View File

@ -0,0 +1,133 @@
#!/bin/bash
#
# This script needs a sudo entry for user crawl to run as root:
# For obvious reasons, this script should not source any other scripts that
# are not owned by root.
#
# ===========================================================================
# Copyright (C) 2008, 2009, 2010, 2011 Marc H. Thoben
# Copyright (C) 2011 Darshan Shaligram
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# ===========================================================================
#
set -e
set -u
# These are not overrideable:
CHROOT="%%DGL_CHROOT%%"
CHROOT_BINARIES="%%CHROOT_CRAWL_BINARY_PATH%%"
CHROOT_CRAWL_BASEDIR="%%CHROOT_CRAWL_BASEDIR%%"
DESTDIR="%%CRAWL_BASEDIR%%"
VERSIONS_DB="%%VERSIONS_DB%%"
CRAWL_UGRP="%%CRAWL_UGRP%%"
DGL_SETTINGS_DIR="%%DGL_SETTINGS_DIR%%"
VERSION="$1"
GAME="crawl-$VERSION"
# Safe path:
PATH=/bin:/sbin:/usr/bin:/usr/sbin
if [[ "$UID" != "0" ]]; then
echo "$0 must be run as root"
exit 1
fi
copy-game-binary() {
echo "Installing game binary ($GAME_BINARY) in $BINARIES_DIR"
mkdir -p $BINARIES_DIR
if [[ -f $BINARIES_DIR/$GAME_BINARY ]]; then
mv $BINARIES_DIR/$GAME_BINARY $BINARIES_DIR/$GAME_BINARY.old
fi
if cp source/$GAME_BINARY $BINARIES_DIR; then
rm $BINARIES_DIR/$GAME_BINARY.old || true
else
local ERR=$?
mv $BINARIES_DIR/$GAME_BINARY.old $BINARIES_DIR/$GAME_BINARY || true
return $ERR
fi
}
copy-data-files() {
echo "Copying game data files to $DATADIR"
cp -r source/dat docs settings $DATADIR
# Only one of these exists, don't error for the other.
cp -r README.txt README.md $DATADIR 2>/dev/null || true
cp -r settings/. $DGL_SETTINGS_DIR/$GAME-settings
cp -r source/webserver/game_data/. $DATADIR/web
mkdir -p "$ABS_COMMON_DIR/data/docs"
cp docs/crawl_changelog.txt "$ABS_COMMON_DIR/data/docs"
}
install-game() {
mkdir -p $SAVEDIR/{,sprint,zotdef}
mkdir -p $DATADIR
copy-game-binary
copy-data-files
chown -R $CRAWL_UGRP $SAVEDIR
}
assert-not-evil() {
local file=$1
if [[ "$file" != "$(echo "$file" |
perl -lpe 's{[.]{2}|[^.a-zA-Z0-9_/-]+}{}g')" ]]
then
echo -e "Path $file contains characters I don't like, aborting."
exit 1
fi
}
if [[ -z "$VERSION" ]]; then
echo -e "Missing version argument"
exit 1
fi
assert-not-evil "$VERSION"
if [[ ! ( "$CRAWL_UGRP" =~ ^[a-z0-9]+:[a-z0-9]+$ ) ]]; then
echo -e "Expected CRAWL_UGRP to be user:group, but got $CRAWL_UGRP"
exit 1
fi
# COMMON_DIR is the absolute path *inside* the chroot jail of the
# directory holding common data for all game versions, viz: saves.
COMMON_DIR=$CHROOT_CRAWL_BASEDIR/$GAME
assert-not-evil "$COMMON_DIR"
# ABS_COMMON_DIR is the absolute path from outside the chroot
# corresponding to COMMON_DIR
ABS_COMMON_DIR=$CHROOT$COMMON_DIR
if [[ ! -d "$ABS_COMMON_DIR" ]]; then
mkdir -p "$ABS_COMMON_DIR"
fi
GAME_BINARY=$GAME
BINARIES_DIR=$CHROOT$CHROOT_BINARIES
GAMEDIR=$CHROOT$CHROOT_CRAWL_BASEDIR/$GAME
# Absolute path to save game directory
SAVEDIR=$GAMEDIR/saves
DATADIR=$GAMEDIR/data
assert-not-evil "$SAVEDIR"
assert-not-evil "$DATADIR"
echo "Installing game"
install-game

175
chroot/sbin/install-trunk.sh Executable file
View File

@ -0,0 +1,175 @@
#!/bin/bash
#
# This script needs a sudo entry for user crawl to run as root:
# For obvious reasons, this script should not source any other scripts that
# are not owned by root.
#
# ===========================================================================
# Copyright (C) 2008, 2009, 2010, 2011 Marc H. Thoben
# Copyright (C) 2011 Darshan Shaligram
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# ===========================================================================
#
set -e
set -u
shopt -s extglob
# These are not overrideable:
CHROOT="%%DGL_CHROOT%%"
CHROOT_BINARIES="%%CHROOT_CRAWL_BINARY_PATH%%"
GAME="%%GAME%%"
CHROOT_CRAWL_BASEDIR="%%CHROOT_CRAWL_BASEDIR%%"
DESTDIR="%%CRAWL_BASEDIR%%"
VERSIONS_DB="%%VERSIONS_DB%%"
CRAWL_UGRP="%%CRAWL_UGRP%%"
DGL_SETTINGS_DIR="%%DGL_SETTINGS_DIR%%"
REVISION="$1"
DESCRIPTION="$2"
SGV_MAJOR="$3"
SGV_MINOR="$4"
# Safe path:
PATH=/bin:/sbin:/usr/bin:/usr/sbin
if [[ "$UID" != "0" ]]; then
echo "$0 must be run as root"
exit 1
fi
copy-game-binary() {
echo "Installing game binary ($GAME_BINARY) in $BINARIES_DIR"
mkdir -p $BINARIES_DIR
cp source/$GAME_BINARY $BINARIES_DIR
ln -sf $GAME_BINARY $BINARIES_DIR/crawl-latest
}
copy-data-files() {
echo "Copying game data files to $DATADIR"
cp -r source/dat docs settings $DATADIR
# Only one of these exists, don't error for the other.
cp -r README.txt README.md $DATADIR 2>/dev/null || true
cp -r settings/. $DGL_SETTINGS_DIR/$GAME-settings
cp -r source/webserver/game_data/. $DATADIR/web
cp -r source/webserver/!(config.py|game_data|templates) $WEBDIR
cp source/webserver/templates/client.html $WEBDIR/templates/
cp source/webserver/templates/game_links.html $WEBDIR/templates/
mkdir -p "$ABS_COMMON_DIR/data/docs"
cp docs/crawl_changelog.txt "$ABS_COMMON_DIR/data/docs"
}
link-logfiles() {
for file in logfile milestones scores; do
ln -sf $COMMON_DIR/saves/$file $SAVEDIR
ln -sf $COMMON_DIR/saves/$file-sprint $SAVEDIR
ln -sf $COMMON_DIR/saves/$file-zotdef $SAVEDIR
done
}
install-game() {
mkdir -p $SAVEDIR/{,sprint,zotdef}
mkdir -p $DATADIR
copy-game-binary
copy-data-files
link-logfiles
chown -R $CRAWL_UGRP $SAVEDIR
ln -snf $GAME_BINARY $CHROOT$CHROOT_CRAWL_BASEDIR/crawl-latest
}
register-game-version() {
echo
echo "Adding version (${SGV_MAJOR}.${SGV_MINOR}) to database..."
sqlite3 ${VERSIONS_DB} <<SQL
INSERT INTO VERSIONS VALUES ('${REVISION}', '$DESCRIPTION', $(date +%s),
${SGV_MAJOR}, ${SGV_MINOR}, 1);
SQL
}
assert-not-evil() {
local file=$1
if [[ "$file" != "$(echo "$file" |
perl -lpe 's{[.]{2}|[^.a-zA-Z0-9_/-]+}{}g')" ]]
then
echo -e "Path $file contains characters I don't like, aborting."
exit 1
fi
}
assert-all-variables-exist() {
local -a broken_variables=()
for variable_name in "$@"; do
eval "value=\"\$$variable_name\""
if [[ -z "$value" ]]; then
broken_variables=(${broken_variables[@]} $variable_name)
fi
done
if (( ${#broken_variables[@]} > 0 )); then
echo -e "These variables are required, but are unset:" \
"${broken_variables[@]}"
exit 1
fi
}
if [[ -z "$REVISION" ]]; then
echo -e "Missing revision argument"
exit 1
fi
assert-not-evil "$REVISION"
if [[ ! ( "$CRAWL_UGRP" =~ ^[a-z0-9]+:[a-z0-9]+$ ) ]]; then
echo -e "Expected CRAWL_UGRP to be user:group, but got $CRAWL_UGRP"
exit 1
fi
if [[ -n "${SGV_MAJOR}" && -n "${SGV_MINOR}" ]]; then
# COMMON_DIR is the absolute path *inside* the chroot jail of the
# directory holding common data for all game versions, viz: saves.
COMMON_DIR=$CHROOT_CRAWL_BASEDIR/$GAME
assert-not-evil "$COMMON_DIR"
# ABS_COMMON_DIR is the absolute path from outside the chroot
# corresponding to COMMON_DIR
ABS_COMMON_DIR=$CHROOT$CHROOT_CRAWL_BASEDIR/$GAME
if [[ ! -d "$CHROOT$COMMON_DIR" ]]; then
echo -e "Expected to find common game dir $ABS_COMMON_DIR but did not find it"
exit 1
fi
GAME_BINARY=$GAME-$REVISION
BINARIES_DIR=$CHROOT$CHROOT_BINARIES
WEBDIR=$CHROOT$CHROOT_CRAWL_BASEDIR/webserver
GAMEDIR=$CHROOT$CHROOT_CRAWL_BASEDIR/$GAME_BINARY
# Absolute path to save game directory
SAVEDIR=$GAMEDIR/saves
DATADIR=$GAMEDIR/data
assert-not-evil "$SAVEDIR"
assert-not-evil "$DATADIR"
echo "Installing game"
install-game
register-game-version
else
echo "Could not figure out version tags. Installation cancelled."
echo "Aborting installation!"
echo
exit 1
fi

212
chroot/sbin/remove-trunks.sh Executable file
View File

@ -0,0 +1,212 @@
#!/bin/bash
#
# ===========================================================================
# Copyright (C) 2008, 2009, 2010, 2011 Marc H. Thoben
# Copyright (C) 2011 Darshan Shaligram
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# ===========================================================================
#
set -u
CHROOT="%%DGL_CHROOT%%"
BASE_DIR="%%CHROOT_CRAWL_BASEDIR%%"
GAME="%%GAME%%"
BINPATH="%%CHROOT_CRAWL_BINARY_PATH%%"
VERSIONS_DB="%%VERSIONS_DB%%"
USER_ID="%%DGL_UID%%"
DGL_USER="%%DGL_USER%%"
GAME_BASE="$GAME-"
GAME_GLOB="$GAME_BASE*"
VERBOSE=
PROMPTS_ENABLED=1
# Toss the leading slash:
BASE_DIR=${BASE_DIR#/}
BINPATH=${BINPATH#/}
FORCE=
while getopts vq opt; do
case $opt in
v) VERBOSE=1 ;;
q) PROMPTS_ENABLED= ;;
f) FORCE=1 ;;
esac
done
shift $((OPTIND - 1))
verbose() {
[[ -n "$VERBOSE" ]]
}
prompts-enabled() {
[[ -n "$PROMPTS_ENABLED" ]]
}
hash-version-detail() {
local hash="$1"
sqlite3 "$VERSIONS_DB" <<EOF
SELECT description || ' (' || major || '.' || minor || ')'
FROM versions
WHERE hash='$hash';
EOF
}
canonicalise-version() {
local version="$1"
sqlite3 "$VERSIONS_DB" <<EOF
SELECT hash FROM versions
WHERE hash LIKE '$version%' OR description='$version';
EOF
}
saves-in-dir() {
local folder="$1"
local -a globs
globs=(${folder}/saves/{,sprint/,zotdef/}*.{sav,chr,cs})
if (( $# == 2 )); then
local suffix="/$2"
globs=($folder/saves$suffix/*.{sav,chr,cs})
fi
/bin/ls -1 ${globs[@]} 2>/dev/null
}
count-saves-in-dir() {
saves-in-dir "$@" | wc -l
}
strip-save-uid-extension() {
sed 's/-'${USER_ID}'//g;s/\.\(sav\|chr\|cs\)//g;'
}
savegame-dirs() {
/bin/ls -1td $GAME_GLOB
}
list_hashes()
{
cd $CHROOT/$BASE_DIR
if verbose; then
echo "Date Version Amount Players"
echo "**************************************************************"
for folder in $(savegame-dirs); do
local hash=${folder/$GAME_BASE/}
local version_detail="$(hash-version-detail $hash)"
local save_count="$(count-saves-in-dir "$folder")"
/bin/ls -1tdl ${folder} 2>/dev/null | \
sed "s/$GAME_BASE//g;" | \
awk '{ printf "%3s %2s %s %17s %6s ",
$6, $7, $8,
"'"$version_detail"'",
"'"$save_count"'" }'
for char in $(saves-in-dir "$folder" | strip-save-uid-extension)
do
echo -n "${char#$folder/saves/} "
done
echo
done
else
echo "Date Version Players in Games"
echo "*******************************************************************"
for folder in $(savegame-dirs)
do
local hash=${folder/$GAME_BASE/}
local version_detail="$(hash-version-detail $hash)"
local save_count="$(count-saves-in-dir "$folder" '')"
local sprint_save_count="$(count-saves-in-dir "$folder" 'sprint')"
local zotdef_save_count="$(count-saves-in-dir "$folder" 'zotdef')"
/bin/ls -1tdl ${folder} 2>/dev/null | \
sed "s/$GAME_BASE//g;" | \
awk '{ printf "%3s %2s %s %17s %6s in trunk, %3s in sprint, %3s in zotdef", $6, $7, $8,
"'"$version_detail"'",
"'"$save_count"'",
"'"$sprint_save_count"'",
"'"$zotdef_save_count"'" }'
echo
done
fi
}
PARAMS="$(echo "$*" | sed 's/[$*\/();|+]//g')"
if test $# -eq 0
then
if prompts-enabled; then
echo "Usage: $(basename $0) [-q] [-v] [hash] [hash] ..."
echo
fi
list_hashes
echo
exit 0
fi
cd $CHROOT
for raw_version in ${PARAMS}
do
version="$(canonicalise-version $raw_version)"
if [[ -z "$version" ]]; then
echo -e "Revision $raw_version unknown\n";
exit 1
fi
GAME_VER="$GAME-$version"
GAME_SAVEDIR="$BASE_DIR/$GAME_VER"
if test -f $BINPATH/$GAME_VER -a -d $GAME_SAVEDIR; then
if [[ "$(count-saves-in-dir "$GAME_SAVEDIR")" > 0 && -z "$FORCE" ]]
then
echo "$GAME_SAVEDIR contains save games, use -f to delete anyway"
exit 1
fi
if prompts-enabled; then
while { ps -fC $GAME_VER | awk '{ print $1" "$2"\t "$5" "$7"\t "$8" "$9" "$10 }' | grep ^"$DGL_USER"; }
do
echo "There are still active crawl processes running..."
echo "-- Press RETURN to try again --"
read
done
echo "Removing ${version} from repository..."
echo "delete from versions where hash=\"${version}\";"| sqlite3 ${VERSIONS_DB}
rm $BINPATH/$GAME_VER
rm -r $BASE_DIR/$GAME_VER
else
if { ps -fC $GAME_VER | awk '{ print $1" "$2"\t "$5" "$7"\t "$8" "$9" "$10 }' | grep ^"$DGL_USER" >/dev/null; }
then
echo "Revision ${version} is being played..."
else
echo "Removing ${version} from repository..."
echo "delete from versions where hash=\"${version}\";"| sqlite3 ${VERSIONS_DB}
rm $BINPATH/$GAME_VER
rm -r $BASE_DIR/$GAME_VER
fi
fi
else
echo "Revision ${version} not found..."
fi
done
echo
exit 0

110
chroot/sbin/savegame-transfer.sh Executable file
View File

@ -0,0 +1,110 @@
#!/bin/bash
#
# ===========================================================================
# Copyright (C) 2008, 2009, 2010, 2011 Marc H. Thoben
# Copyright (C) 2011 Darshan Shaligram
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# ===========================================================================
#
set -u
USER_ID="%%DGL_UID%%"
CHROOT="%%DGL_CHROOT%%"
PREFIX="$CHROOT%%CHROOT_CRAWL_BASEDIR%%"
VERSIONS_DB="%%VERSIONS_DB%%"
BINARY_MAIN_NAME="%%GAME%%"
C_NORMAL="\033[0m"
C_YELLOW="\033[1;33m"
C_GREEN="\033[1;32m"
C_RED="\033[1;31m"
PARAMS="$(echo "$*" | sed 's/[$*\();.|+-]//g')"
if test ${#PARAMS} -eq 0
then
$(dirname $0)/remove-trunks.sh -v | grep -v "Usage:"
echo "Usage: $(basename $0) <charname> [charname] ..."
exit 1
fi
LATEST_GAME_HASH="$(echo "select hash from versions order by time desc limit 1;" | sqlite3 ${VERSIONS_DB})"
for char in ${PARAMS}
do
CHAR_NAME="${char}"
GAME_MODE=""
PS_MOD="rc"
SAVE_FOUND="$(/bin/ls -1rt ${PREFIX}/${BINARY_MAIN_NAME}-*/saves/${CHAR_NAME}-${USER_ID}.sav ${PREFIX}/${BINARY_MAIN_NAME}-*/saves/${CHAR_NAME}-${USER_ID}.chr ${PREFIX}/${BINARY_MAIN_NAME}-*/saves/${CHAR_NAME}{-${USER_ID},}.cs 2>/dev/null | head -n 1)"
if test ${#SAVE_FOUND} -ne 0
then
OUR_GAME_HASH="$(echo ${SAVE_FOUND} | sed "s|${PREFIX}/${BINARY_MAIN_NAME}-\(.*\)/saves/${CHAR_NAME}.*|\1|")"
OUR_GAME_SV="$(echo select major,minor from versions where hash=\"${OUR_GAME_HASH}\"\; | sqlite3 -separator \. ${VERSIONS_DB})"
echo -n "Char \"${CHAR_NAME}\" in ${OUR_GAME_HASH} (${OUR_GAME_SV}). "
if test "${OUR_GAME_HASH}" != "${LATEST_GAME_HASH}"
then
OUR_SGV_MAJOR="$(echo "select major from versions where hash=\"${OUR_GAME_HASH}\";" | sqlite3 ${VERSIONS_DB})"
POSSIBLE_GAME_HASH="$(echo "select hash from versions where major=${OUR_SGV_MAJOR} order by time desc limit 1;" | sqlite3 ${VERSIONS_DB})"
if test "${OUR_GAME_HASH}" != "${POSSIBLE_GAME_HASH}"
then
POSSIBLE_GAME_SV="$(echo select major,minor from versions where hash=\"${POSSIBLE_GAME_HASH}\"\; | sqlite3 -separator \. ${VERSIONS_DB})"
echo -n "Moving to ${POSSIBLE_GAME_HASH} (${POSSIBLE_GAME_SV}):"
if test "$(basename ${CHAR_NAME})" != "${CHAR_NAME}"
then
GAME_MODE="$(dirname ${CHAR_NAME})"
CHAR_NAME="$(basename ${CHAR_NAME})"
PS_MOD="${GAME_MODE}"
fi
if { ps -fC ${BINARY_MAIN_NAME}-${OUR_GAME_HASH} | awk '{ print $8, $9, $10, $11 }' | grep "\-name ${CHAR_NAME} \-${PS_MOD}" &>/dev/null; }
then
echo -e " ${C_YELLOW}in use!${C_NORMAL}"
continue
fi
if test -d ${PREFIX}/${BINARY_MAIN_NAME}-${POSSIBLE_GAME_HASH}/saves/${GAME_MODE}
then
mv ${PREFIX}/${BINARY_MAIN_NAME}-${OUR_GAME_HASH}/saves/${GAME_MODE}/${CHAR_NAME}* ${PREFIX}/${BINARY_MAIN_NAME}-${OUR_GAME_HASH}/saves/${GAME_MODE}/start-${CHAR_NAME}-ns.prf ${PREFIX}/${BINARY_MAIN_NAME}-${POSSIBLE_GAME_HASH}/saves/${GAME_MODE}/
if test $? -eq 0
then
echo -e " ${C_GREEN}successful.${C_NORMAL}"
else
echo -e " ${C_RED}failed1!${C_NORMAL}"
continue
fi
else
echo -e " ${C_RED}failed2!${C_NORMAL}"
continue
fi
else
echo -e "${C_YELLOW}No transfer possible.${C_NORMAL}"
fi
else
echo "No transfer necessary."
fi
else
echo "Character \"${CHAR_NAME}\" not found."
fi
done
exit 0

191
config.py Normal file
View File

@ -0,0 +1,191 @@
import logging
try:
from collections import OrderedDict
except ImportError:
from ordereddict import OrderedDict
dgl_mode = True
bind_nonsecure = True # Set to false to only use SSL
bind_address = "0.0.0.0"
bind_port = 8080
bind_pairs = (
("0.0.0.0", 8080),
)
logging_config = {
"filename": "%%CHROOT_WEBDIR%%/run/webtiles.log",
"level": logging.INFO,
"format": "%(asctime)s %(levelname)s: %(message)s"
}
password_db = "%%CHROOT_LOGIN_DB%%"
static_path = "%%CHROOT_WEBDIR%%/static"
template_path = "%%CHROOT_WEBDIR%%/templates/"
# Path for server-side unix sockets (to be used to communicate with crawl)
server_socket_path = None # Uses global temp dir
# Server name, so far only used in the ttyrec metadata
server_id = "ctvo"
# Disable caching of game data files
game_data_no_cache = False
# Watch socket dirs for games not started by the server
watch_socket_dirs = True
# Game configs
# %n in paths is replaced by the current username
games = OrderedDict([
("dcss-git", dict(
name = "DCSS trunk",
crawl_binary = "/bin/crawl-git-launcher.sh",
send_json_options = True,
rcfile_path = "%%CHROOT_RCFILESDIR%%/crawl-git/",
macro_path = "%%CHROOT_RCFILESDIR%%/crawl-git/",
morgue_path = "%%CHROOT_MORGUEDIR%%/%n/",
morgue_url = "https://crawl.tildeverse.org/crawl/morgue/%n/",
inprogress_path = "%%CHROOT_INPROGRESSDIR%%/crawl-git/",
ttyrec_path = "%%CHROOT_TTYRECDIR%%/%n/",
socket_path = "%%CHROOT_WEBDIR%%/sockets")),
("spr-git", dict(
name = "Sprint trunk",
crawl_binary = "/bin/crawl-git-launcher.sh",
send_json_options = True,
rcfile_path = "%%CHROOT_RCFILESDIR%%/crawl-git/",
macro_path = "%%CHROOT_RCFILESDIR%%/crawl-git/",
morgue_path = "%%CHROOT_MORGUEDIR%%/%n/",
morgue_url = "https://crawl.tildeverse.org/crawl/morgue/%n/",
inprogress_path = "%%CHROOT_INPROGRESSDIR%%/crawl-git-sprint/",
ttyrec_path = "%%CHROOT_TTYRECDIR%%/%n/",
socket_path = "%%CHROOT_WEBDIR%%/sockets",
options = ["-sprint"])),
("tut-git", dict(
name = "Tutorial trunk",
crawl_binary = "/bin/crawl-git-launcher.sh",
send_json_options = True,
rcfile_path = "%%CHROOT_RCFILESDIR%%/crawl-git/",
macro_path = "%%CHROOT_RCFILESDIR%%/crawl-git/",
morgue_path = "%%CHROOT_MORGUEDIR%%/%n/",
morgue_url = "https://crawl.tildeverse.org/crawl/morgue/%n/",
inprogress_path = "%%CHROOT_INPROGRESSDIR%%/crawl-git-tut/",
ttyrec_path = "%%CHROOT_TTYRECDIR%%/%n/",
socket_path = "%%CHROOT_WEBDIR%%/sockets",
options = ["-tutorial"])),
("dcss-0.22", dict(
name = "DCSS 0.22",
crawl_binary = "/bin/crawl-stable-launcher.sh",
send_json_options = True,
pre_options = [ "0.22" ],
rcfile_path = "%%CHROOT_RCFILESDIR%%/crawl-0.22/",
macro_path = "%%CHROOT_RCFILESDIR%%/crawl-0.22/",
morgue_path = "%%CHROOT_MORGUEDIR%%/%n/",
morgue_url = "https://crawl.tildeverse.org/crawl/morgue/%n/",
inprogress_path = "%%CHROOT_INPROGRESSDIR%%/crawl-0.22/",
ttyrec_path = "%%CHROOT_TTYRECDIR%%/%n/",
socket_path = "%%CHROOT_WEBDIR%%/sockets")),
("spr-0.22", dict(
name = "Sprint 0.22",
crawl_binary = "/bin/crawl-stable-launcher.sh",
send_json_options = True,
pre_options = [ "0.22" ],
rcfile_path = "%%CHROOT_RCFILESDIR%%/crawl-0.22/",
macro_path = "%%CHROOT_RCFILESDIR%%/crawl-0.22/",
morgue_path = "%%CHROOT_MORGUEDIR%%/%n/",
morgue_url = "https://crawl.tildeverse.org/crawl/morgue/%n/",
inprogress_path = "%%CHROOT_INPROGRESSDIR%%/crawl-22-sprint/",
ttyrec_path = "%%CHROOT_TTYRECDIR%%/%n/",
socket_path = "%%CHROOT_WEBDIR%%/sockets",
options = ["-sprint"])),
("tut-0.22", dict(
name = "Tutorial 0.22",
crawl_binary = "/bin/crawl-git-launcher.sh",
send_json_options = True,
pre_options = [ "0.22" ],
rcfile_path = "%%CHROOT_RCFILESDIR%%/crawl-0.22/",
macro_path = "%%CHROOT_RCFILESDIR%%/crawl-0.22/",
morgue_path = "%%CHROOT_MORGUEDIR%%/%n/",
morgue_url = "https://crawl.tildeverse.org/crawl/morgue/%n/",
inprogress_path = "%%CHROOT_INPROGRESSDIR%%/crawl-0.22-tut/",
ttyrec_path = "%%CHROOT_TTYRECDIR%%/%n/",
socket_path = "%%CHROOT_WEBDIR%%/sockets",
options = ["-tutorial"])),
])
dgl_status_file = "%%CHROOT_WEBDIR%%/run/status"
# Set to None not to read milestones
milestone_file = [
"%%CHROOT_CRAWL_BASEDIR%%/crawl-0.22/saves/milestones",
"%%CHROOT_CRAWL_BASEDIR%%/crawl-0.22/saves/milestones-tutorial",
"%%CHROOT_CRAWL_BASEDIR%%/crawl-0.22/saves/milestones-sprint",
"%%CHROOT_CRAWL_BASEDIR%%/crawl-git/saves/milestones",
"%%CHROOT_CRAWL_BASEDIR%%/crawl-git/saves/milestones-tutorial",
"%%CHROOT_CRAWL_BASEDIR%%/crawl-git/saves/milestones-sprint",
"%%CHROOT_CRAWL_GAMEDIR%%/saves/milestones",
"%%CHROOT_CRAWL_GAMEDIR%%/saves/milestones-tutorial",
"%%CHROOT_CRAWL_GAMEDIR%%/saves/milestones-sprint"
]
status_file_update_rate = 5
recording_term_size = (80, 24)
max_connections = 500
# Script to initialize a user, e.g. make sure the paths
# and the rc file exist. This is not done by the server
# at the moment.
init_player_program = "/bin/init-webtiles.sh"
#ssl_options = None # No SSL
ssl_options = {
"certfile": "/etc/ssl/crawl.tildeverse.org.pem",
"keyfile": "/etc/ssl/private/crawl.tildeverse.org.pem",
"ca_certs": "/etc/ssl/certs/ca-certificates.crt"
}
ssl_address = "0.0.0.0"
ssl_port = 8081
ssl_bind_pairs = (
("0.0.0.0", 8081),
)
connection_timeout = 600
max_idle_time = 5 * 60 * 60
# Seconds until stale HTTP connections are closed
# This needs a patch currently not in mainline tornado.
http_connection_timeout = 600
kill_timeout = 10 # Seconds until crawl is killed after HUP is sent
nick_regex = r"^[a-zA-Z0-9]{3,20}$"
max_passwd_length = 20
# crypt() algorithm, e.g. "1" for MD5 or "6" for SHA-512; see crypt(3).
# If false, use traditional DES (but then only the first eight characters
# are significant).
crypt_algorithm = "6"
# If crypt_algorithm is true, the length of the salt string to use. If
# crypt_algorithm is false, a two-character salt is used.
crypt_salt_length = 16
login_token_lifetime = 7 # Days
uid = 1001 # If this is not None, the server will setuid to that (numeric) id
gid = 1001 # after binding its sockets.
umask = None # e.g. 0077
chroot = "%%DGL_CHROOT%%"
pidfile = "%%CHROOT_WEBDIR%%/run/webtiles.pid"
daemon = True # If true, the server will detach from the session after startup
player_url = "http://crawl.akrasiac.org/scoring/players/%s.html"

View File

@ -0,0 +1,4 @@
#! /bin/bash
perl -lne 'print $1 if /#define\s+TAG_MAJOR_VERSION\s+(\d+)/' \
source/tag-version.h

View File

@ -0,0 +1,92 @@
#!/bin/bash
VERSION=${1:-0.17}
# Quoting for =~ changed from bash 3.0 to 3.2; using a variable for the
# regexp works with both.
VERS_RE='^[0-9]+.[0-9]+$'
if [[ ! $VERSION =~ $VERS_RE ]]; then
echo "Bad crawl version $VERSION"
exit 1
fi
set -e
lock-or-die crawl-update "someone is already updating the crawl build"
source $DGL_CONF_HOME/crawl-git.conf
GAME=crawl-$VERSION
export DESTDIR=$CRAWL_BASEDIR
BRANCH=stone_soup-$VERSION
if [[ $VERSION != [0-9]* ]]; then
BRANCH=$VERSION
fi
check-crawl-basedir-exists
enable-prompts $*
TODAY="$(dgl-today)"
# Second argument can be a revision (SHA) to build
REVISION="$2"
./update-public-repository.sh $BRANCH "$REVISION"
REVISION="$(git-do rev-parse HEAD | cut -c 1-7)"
REVISION_FULL="$(git-do describe --long HEAD)"
VER_STR="$(git-do describe HEAD)"
VER_STR_OLD="$(($CRAWL_BINARY_PATH/$GAME -version 2>/dev/null || true) | sed -ne 's/Crawl version //p')"
REVISION_OLD="${VER_STR_OLD##*-g}"
[[ "$REVISION" == "$REVISION_OLD" || "$VER_STR" = "$VER_STR_OLD" ]] && \
abort-saying "Nothing new to install at the moment: you asked for $REVISION_FULL and it's already installed"
prompt "start update build"
cd $CRAWL_REPOSITORY_DIR/crawl-ref
echo "Copying CREDITS to docs/crawl_credits.txt..."
cp CREDITS.txt docs/crawl_credits.txt
dgl-git-log() {
git-do log --pretty=tformat:"--------------------------------------------------------------------------------%n%h | %an | %ci%n%n%s%n%b" "$@" | grep -v "git-svn-id" | awk 1 RS= ORS="\n\n" | fold -s
}
echo "Creating changelog in docs/crawl_changelog.txt..."
dgl-git-log $BRANCH > docs/crawl_changelog.txt
if prompts-enabled; then
echo "Changes to $BRANCH from $REVISION_OLD .. $REVISION"
dgl-git-log ${REVISION_OLD:+$REVISION_OLD..}${REVISION} | less
fi
prompt "compile ${GAME} (${REVISION})"
# REMEMBER to adjust /var/lib/dgamelaunch/sbin/install-stable.sh as well if make parameters change!
##################################################################################################
say-do crawl-do nice make -C source \
GAME=${GAME} \
GAME_MAIN=${GAME} MCHMOD=0755 MCHMOD_SAVEDIR=755 \
INSTALL_UGRP=$CRAWL_UGRP \
WEBTILES=YesPlease USE_DGAMELAUNCH=YesPlease WIZARD=YesPlease \
STRIP=true DESTDIR=${DESTDIR} prefix= bin_prefix=/bin \
SAVEDIR=$CHROOT_CRAWL_BASEDIR/${GAME}/saves \
DATADIR=$CHROOT_CRAWL_BASEDIR/${GAME}/data \
WEBDIR=$CHROOT_CRAWL_BASEDIR/${GAME}/data/web \
USE_PCRE=y \
EXTERNAL_FLAGS_L="-g"
prompt "install ${GAME} (${REVISION})"
say-do sudo -H $DGL_CHROOT/sbin/install-stable.sh "$VERSION"
if [[ $VERSION = [0-9]* ]]; then
SUPER_VER="Stable"
else
SUPER_VER="Experimental"
fi
announce "$SUPER_VER ($VERSION) branch on $DGL_SERVER updated to: ${REVISION_FULL}"
echo "All done."
echo

View File

@ -0,0 +1,87 @@
#!/bin/bash
set -e
lock-or-die crawl-update "someone is already updating the crawl build"
source $DGL_CONF_HOME/crawl-git.conf
check-versions-db-exists
export DESTDIR=$CRAWL_BASEDIR
check-crawl-basedir-exists
enable-prompts $*
TODAY="$(dgl-today)"
# First argument can be a revision (SHA) to build
REVISION="$1"
./update-public-repository.sh $BRANCH "$REVISION"
REVISION="$(git-do rev-parse HEAD | cut -c 1-10)"
REVISION_FULL="$(git-do describe --long HEAD)"
REVISION_OLD="$(echo "select hash from versions order by time desc limit 1;" | sqlite3 ${VERSIONS_DB})"
[[ "$REVISION" == "$REVISION_OLD" ]] && \
abort-saying "Nothing new to install at the moment: you asked for $REVISION_FULL and it's already installed"
prompt "start update build"
cd $CRAWL_REPOSITORY_DIR/crawl-ref
echo "Copying CREDITS to docs/crawl_credits.txt..."
cp CREDITS.txt docs/crawl_credits.txt
dgl-git-log() {
git-do log --pretty=tformat:"--------------------------------------------------------------------------------%n%h | %an | %ci%n%n%s%n%b" "$@" | grep -v "git-svn-id" | awk 1 RS= ORS="\n\n" | fold -s
}
echo "Creating changelog in docs/crawl_changelog.txt..."
dgl-git-log $BRANCH > docs/crawl_changelog.txt
if prompts-enabled; then
echo "Changes to $BRANCH from $REVISION_OLD .. $REVISION"
dgl-git-log ${REVISION_OLD}..${REVISION} | less
fi
prompt "compile ${GAME}-${REVISION}"
# REMEMBER to adjust /var/lib/dgamelaunch/sbin/install-trunk.sh as well if make parameters change!
##################################################################################################
say-do crawl-do nice make -C source \
GAME=${GAME}-${REVISION} \
GAME_MAIN=${GAME} MCHMOD=0755 MCHMOD_SAVEDIR=755 \
INSTALL_UGRP=$CRAWL_UGRP \
WEBTILES=YesPlease USE_DGAMELAUNCH=YesPlease WIZARD=YesPlease \
STRIP=true DESTDIR=${DESTDIR} prefix= bin_prefix=/bin \
SAVEDIR=$CHROOT_CRAWL_BASEDIR/${GAME}-${REVISION}/saves \
DATADIR=$CHROOT_CRAWL_BASEDIR/${GAME}-${REVISION}/data \
WEBDIR=$CHROOT_CRAWL_BASEDIR/${GAME}-${REVISION}/data/web \
SHAREDDIR=$CHROOT_CRAWL_BASEDIR/${GAME}/saves \
USE_PCRE=y \
EXTERNAL_FLAGS_L="-g"
prompt "install ${GAME}-${REVISION}"
if [[ "$(uname)" != "Darwin" ]] && {
ps -fC ${GAME}-${REVISION} |
awk '{ print $1" "$2"\t "$5" "$7"\t "$8" "$9" "$10 }' |
grep ^"$DGL_USER";
}
then
abort-saying "There are already active instances of this version (${REVISION_FULL}) running"
fi
echo "Searching for version tags..."
export SGV_MAJOR=$($CRAWL_BUILD_DIR/crawl-tag-major-version.sh)
[[ -n "$SGV_MAJOR" ]] || abort-saying "Couldn't find save major version"
echo "Save major version: $SGV_MAJOR"
export SGV_MINOR="0"
say-do sudo -H $DGL_CHROOT/sbin/install-trunk.sh "$REVISION" \
"$REVISION_FULL" "$SGV_MAJOR" "$SGV_MINOR"
announce "Unstable branch on $DGL_SERVER updated to: ${REVISION_FULL} (${SGV_MAJOR})"
echo "All done."
echo

View File

@ -0,0 +1,40 @@
#!/bin/bash
set -e
source $DGL_CONF_HOME/sh-utils
source $DGL_CONF_HOME/crawl-git.conf
REPO_DIR=$PWD/$CRAWL_REPOSITORY_DIR
clone-crawl-ref() {
if [[ -d "$CRAWL_REPOSITORY_DIR" && -d "$CRAWL_REPOSITORY_DIR/.git" ]]; then
return 0
fi
CMDLINE="git clone $CRAWL_GIT_URL $CRAWL_REPOSITORY_DIR"
say "$CMDLINE"
$CMDLINE
}
update-crawl-ref() {
say "Updating git repository $REPO_DIR"
( cd $REPO_DIR && git checkout -f &&
git checkout $BRANCH &&
git pull )
if [[ -n "$REVISION" ]]; then
say "Checking out requested revision: $REVISION"
( cd $REPO_DIR && git checkout "$REVISION" )
fi
}
update-submodules() {
say "Updating git submodules in $REPO_DIR"
( cd $REPO_DIR && git submodule update --init )
}
BRANCH=$1
REVISION="$2"
[[ -n "$BRANCH" ]] || abort-saying "$0: Checkout branch not specified!"
clone-crawl-ref
update-crawl-ref
update-submodules

View File

@ -0,0 +1,13 @@
CREATE TABLE versions(hash TEXT(7) PRIMARY KEY,
description STRING,
time INTEGER,
major INTEGER,
minor INTEGER,
wizard INTEGER);
CREATE TABLE branches(name TEXT(50) NOT NULL PRIMARY KEY,
git TEXT(50) NOT NULL,
description STRING NOT NULL,
abbrev TEXT(1) NOT NULL,
sprintabbr TEXT(1), -- null means no sprint
ord INTEGER, -- null to disable?
wizard INTEGER NOT NULL); -- boolean?

64
crawl-git.conf Normal file
View File

@ -0,0 +1,64 @@
#! /bin/bash
[[ -z "$BRANCH" ]] && BRANCH="master"
CONFIG_READ="true"
export GAME="crawl-git"
CRAWL_BUILD_DIR=$DGL_CONF_HOME/crawl-build
CRAWL_REPOSITORY_DIR=crawl-git-repository
CRAWL_REPO=$DGL_CONF_HOME/crawl-build/$CRAWL_REPOSITORY_DIR
CRAWL_GIT_URL=https://github.com/crawl/crawl.git
export CHROOT_CRAWL_BINARY_PATH="/usr/games"
export CRAWL_BINARY_PATH="$DGL_CHROOT$CHROOT_CRAWL_BINARY_PATH"
export CHROOT_CRAWL_STABLE_GAMEDIR=/var/games
# Path in chroot where the build's data and savedir will be created:
export CHROOT_CRAWL_BASEDIR=/crawl-master
export CHROOT_CRAWL_GAMEDIR=$CHROOT_CRAWL_BASEDIR/$GAME
# Build config:
export CRAWL_UGRP=crawl:crawl
export CRAWL_BASEDIR=$DGL_CHROOT$CHROOT_CRAWL_BASEDIR
export CRAWL_GAMEDIR=$DGL_CHROOT$CHROOT_CRAWL_GAMEDIR
export CHROOT_VERSIONS_DB="/crawl-versions.db3"
export VERSIONS_DB="$DGL_CHROOT$CHROOT_VERSIONS_DB"
check-versions-db-exists() {
if [[ ! -f "$VERSIONS_DB" ]]; then
echo -e "Crawl version db $VERSIONS_DB does not exist"
echo -e "Please run 'dgl create-versions-db' as root to create it."
exit 1
fi
}
check-crawl-basedir-exists() {
if [[ ! -d "$CRAWL_GAMEDIR" ]]; then
echo -e "Chroot crawl game directory $CRAWL_GAMEDIR does not exist."
echo -e "Please run 'dgl create-crawl-gamedir' to create it."
exit 1
fi
}
crawl-repo-do() {
( cd $CRAWL_REPO && "$@" )
}
crawl-do() {
( cd $CRAWL_REPO/crawl-ref && "$@" )
}
git-do() {
crawl-repo-do git "$@"
}
latest-game-hash() {
query <<EOF
SELECT hash FROM versions ORDER BY time DESC LIMIT 1;
EOF
}

508
dgamelaunch.conf Normal file
View File

@ -0,0 +1,508 @@
# Global config variables:
# Max amount of registered users to allow.
maxusers = 64000
allow_new_nicks = yes
# Max length for newly registered nicks. Must be less than 20.
# By default, NetHack only stores the first 10 chars of a name into
# the record/logfile.
maxnicklen = 20
# Set the default watching-screen sorting mode. Can be one of
# "username", "game", "windowsize", "starttime" or "idletime".
# "username" is the default.
sortmode = "username"
# Maximum idle time in menus
menu_max_idle_time = 3600
# Path to a prepared chroot jail.
chroot_path = "%%DGL_CHROOT%%/"
# From inside the jail, dgamelaunch's working directory for rcfiles/ttyrec/etc
dglroot = "%%CHROOT_DGLDIR%%/"
# Server ID string
server_id = "CTVO - Dungeon Crawl Stone Soup - crawl.tildeverse.org"
# From inside the jail, location of a banner file, the topmost line will be
# shown in submenus that cannot be defined separately.
# Some string substitution is done for the file:
# $VERSION replaced with "dgamelaunch v" + dgl version number.
# $SERVERID replaced with the server_id string, as defined above.
banner = "%%CHROOT_DGLDIR%%/data/dgl-banner"
# The following two options are fairly insecure. They will force us to
# load the password/group database into memory while still having root
# privileges. Replace them with shed_uid/shed_gid entries as soon as
# possible if you decide to use them. dgamelaunch will inform you of
# the uids/gids corresponding to your choices when it loads.
#
# Note that shed_uid and shed_gid will always take precedence over
# shed_user and shed_group if they are specified.
# shed_user: username to shed privileges to
# shed_user = crawl
# shed_group: group name to shed privileges to
# shed_group = crawl
# Preferably, you may use the respective gids/uids.
# crawl/crawl
shed_uid = 1001
shed_gid = 1001
# The defaults are usually just fine for this. passwd refers to the file
# that stores the user database, and lockfile is only used internally by
# dgamelaunch.
passwd = "%%CHROOT_DGLDIR%%/data/dgl-login"
lockfile = "%%CHROOT_DGLDIR%%/data/dgl-lock"
watch_columns = [ ["", "", 0, "%s)"],
["User", "username", 3, "%-15s"],
["Game", "game", 19, "%-9s"],
["Where", "extrainfo", 33, "%-18s"],
["Term", "windowsize", 53, "%s"],
["Idle", "idletime", 62, "%-10s"],
["Viewers", "watchers", 73, "%4s"]
]
#
# define some commands that are run when something happens. format is
# commands [ <time> ] = <command> ...
#
# <time> can be one of:
# dglstart = when someone telnets in
# login = when user has logged in
# register = right after a new user is registered
# gamestart = just before a game is started
#
# <command> is:
# mkdir "foo" = create a directory "foo"
# chdir "foo" = change current work dir to "foo"
# cp "foo" "bar" = copy file "foo" to "bar", overwriting previous "bar"
# ifnxcp "foo" "bar" = copy file "foo" to "bar", if "bar" doesn't exist
# unlink "foo" = delete file "foo"
# setenv "foo" "bar" = set environment variable "foo" to "bar"
# exec "foo" "bar" = execute "foo" with "bar" as it's param
# chpasswd = do the change password prompting, if logged in
# chmail = do the change email prompting, if logged in
# watch_menu = go to the watching menu
# quit = quit dgl
# ask_login = do the login prompting, if not logged in
# ask_register = do register new user prompting, if not logged in and
# registration of new nicks is allowed.
# edit_options "foo" = edit options for game which has the short name "foo"
# (user must be logged in)
# play_game "foo" = start game which has the short name "foo"
# (user must be logged in)
# submenu "foo" = go to submenu "foo"
# return = return from submenu
#
# The commands will be done inside the chroot and with the uid and gid
# defined above.
# Parameters to the commands are subject to variable substitution:
# %r = dglroot, as defined above
# %n = user nick, if user is logged in
# %u = shed_uid, as defined above, but numeric
# %g = game name, if user has selected a game.
# %s = short game name, if user has selected a game.
#
# eg. commands[login] = mkdir "foo", unlink "bar", setenv "Z" "foo"
#
commands[register] = mkdir "%%CHROOT_TTYRECDIR%%/%n",
ifnxcp "%rdata/crawl-git.macro" "%rrcfiles/crawl-git/%n.macro",
ifnxcp "%rdata/crawl-git-settings/init.txt" "%rrcfiles/crawl-git/%n.rc",
ifnxcp "%rdata/crawl-git.macro" "%rrcfiles/crawl-0.22/%n.macro",
ifnxcp "%rdata/crawl-0.22-settings/init.txt" "%rrcfiles/crawl-0.22/%n.rc"
commands[login] = mkdir "%%CHROOT_TTYRECDIR%%/%n",
ifnxcp "%rdata/crawl-git.macro" "%rrcfiles/crawl-git/%n.macro",
ifnxcp "%rdata/crawl-git-settings/init.txt" "%rrcfiles/crawl-git/%n.rc",
ifnxcp "%rdata/crawl-git.macro" "%rrcfiles/crawl-0.22/%n.macro",
ifnxcp "%rdata/crawl-0.22-settings/init.txt" "%rrcfiles/crawl-0.22/%n.rc"
# commands[gamestart] =
# mkdir "%%CHROOT_TTYRECDIR%%/%n",
# mkdir "%%CHROOT_TTYRECDIR%%/%n/sprint",
# mkdir "%%CHROOT_TTYRECDIR%%/%n/zotdef",
# setenv "SIMPLEMAIL" "1",
# setenv "MAIL" "%%CHROOT_MAILSPOOL%%/%n"
menu["mainmenu_anon"] {
bannerfile = "%%CHROOT_DGLDIR%%/data/menus/main_anon.txt"
# cursor = (5,18)
commands["lL"] = ask_login
commands["rR"] = ask_register
commands["wW"] = watch_menu
commands["qQ"] = quit
}
menu["mainmenu_admin"] {
bannerfile = "%%CHROOT_DGLDIR%%/data/menus/main_admin.txt"
commands["cC"] = chpasswd
commands["eE"] = chmail
commands["wW"] = watch_menu
commands["tT"] = submenu "crawl-git"
commands["0"] = submenu "crawl-0.22"
commands["pP"] = play_game "dcss-0.22"
commands["sS"] = play_game "spr-0.22"
commands["qQ"] = quit
}
menu["mainmenu_user"] {
bannerfile = "%%CHROOT_DGLDIR%%/data/menus/main_user.txt"
commands["cC"] = chpasswd
commands["eE"] = chmail
commands["wW"] = watch_menu
commands["tT"] = submenu "crawl-git"
commands["0"] = submenu "crawl-0.22"
commands["pP"] = play_game "dcss-0.22"
commands["sS"] = play_game "spr-0.22"
commands["qQ"] = quit
}
menu["watchmenu_help"] {
bannerfile = "%%CHROOT_DGLDIR%%/data/menus/watchmenu_help.txt"
commands["qQ "] = return
}
menu["crawl-git"] {
bannerfile = "%%CHROOT_DGLDIR%%/data/menus/crawl_git.txt"
commands["o"] = exec "ee" "%rrcfiles/crawl-git/%n.rc"
commands["O"] = exec "virus" "%rrcfiles/crawl-git/%n.rc"
commands["m"] = exec "ee" "%rrcfiles/crawl-git/%n.macro"
commands["M"] = exec "virus" "%rrcfiles/crawl-git/%n.macro"
commands["v"] = exec "ee" "%%CHROOT_CRAWL_GAMEDIR%%/data/docs/crawl_changelog.txt"
commands["V"] = exec "virus" "%%CHROOT_CRAWL_GAMEDIR%%/data/docs/crawl_changelog.txt"
commands["pP"] = play_game "dcss-git"
commands["tT"] = play_game "tut-git"
commands["sS"] = play_game "spr-git"
commands["A"] = submenu "crawl-git-adv"
commands["wW"] = watch_menu
commands["qQ"] = return
}
menu["crawl-0.22"] {
bannerfile = "%%CHROOT_DGLDIR%%/data/menus/crawl-0.22.txt"
commands["o"] = exec "ee" "%rrcfiles/crawl-0.22/%n.rc"
commands["O"] = exec "virus" "%rrcfiles/crawl-0.22/%n.rc"
commands["m"] = exec "ee" "%rrcfiles/crawl-0.22/%n.macro"
commands["M"] = exec "virus" "%rrcfiles/crawl-0.22/%n.macro"
commands["v"] = exec "ee" "%%CHROOT_CRAWL_GAMEDIR%%/crawl-0.22/data/docs/crawl_changelog.txt"
commands["V"] = exec "virus" "%%CHROOT_CRAWL_GAMEDIR%%/crawl-0.22/data/docs/crawl_changelog.txt"
commands["pP"] = play_game "dcss-0.22"
commands["tT"] = play_game "tut-0.22"
commands["sS"] = play_game "spr-0.22"
commands["A"] = submenu "crawl-0.22-adv"
commands["wW"] = watch_menu
commands["qQ"] = return
}
menu["crawl-git-adv"] {
bannerfile = "%%CHROOT_DGLDIR%%/data/menus/crawl_git_adv.txt"
commands["B"] =
exec "/bin/savegame-backup.sh" "%n crawl-git %%CHROOT_CRAWL_BASEDIR%%",
return
commands["O"] =
cp "%rdata/crawl-git-settings/init.txt" "%rrcfiles/crawl-git/%n.rc",
return
commands["M"] =
cp "%rdata/crawl-git.macro" "%rrcfiles/crawl-git/%n.macro",
return
commands["qQ"] = return
}
menu["crawl-0.22-adv"] {
bannerfile = "%%CHROOT_DGLDIR%%/data/menus/crawl-0.22_adv.txt"
commands["B"] =
exec "/bin/savegame-backup.sh" "%n crawl-0.22 %%CHROOT_CRAWL_BASEDIR%%",
return
commands["O"] =
cp "%rdata/crawl-0.22-settings/init.txt" "%rrcfiles/crawl-0.22/%n.rc",
return
commands["M"] =
cp "%rdata/crawl-git.macro" "%rrcfiles/crawl-0.22/%n.macro",
return
commands["qQ"] = return
}
##############################################################################
## NON-CRAWL GAMES
##############################################################################
#DEFINE {
# game_path = "/bin/atc-launcher.sh"
# game_name = "atc"
# short_name = "atc"
# game_args = "/bin/atc-launcher.sh", "%n"
# inprogressdir = "%rinprogress/atc/"
# ttyrecdir = "%%CHROOT_TTYRECDIR%%-atc/"
# encoding = "UTF-8"
# spooldir = "%%CHROOT_MAILSPOOL%%/"
#}
#
#DEFINE {
# game_path = "/bin/boggle-launcher.sh"
# game_name = "boggle"
# short_name = "boggle"
# game_args = "/bin/boggle-launcher.sh", "%n"
# inprogressdir = "%rinprogress/boggle/"
# ttyrecdir = "%%CHROOT_TTYRECDIR%%-boggle/"
# encoding = "UTF-8"
# spooldir = "%%CHROOT_MAILSPOOL%%/"
#}
#
#DEFINE {
# game_path = "/usr/games/robotfindskitten"
# game_name = "robotfindskitten"
# short_name = "rfk"
# game_args = "/usr/games/robotfindskitten"
# inprogressdir = "%rinprogress/rfk/"
# ttyrecdir = "%%CHROOT_TTYRECDIR%%-rfk/"
# encoding = "UTF-8"
# spooldir = "%%CHROOT_MAILSPOOL%%/"
#}
##############################################################################
## GIT
##############################################################################
DEFINE {
game_path = "/bin/crawl-git-launcher.sh"
game_name = "Crawl (trunk)"
short_name = "dcss-git"
game_args = "/bin/crawl-git-launcher.sh",
"-name", "%n",
"-rc", "%rrcfiles/crawl-git/%n.rc",
"-macro", "%rrcfiles/crawl-git/%n.macro",
"-webtiles-socket", "%%CHROOT_CRAWL_BASEDIR%%/webserver/sockets/%n:dcss-git.sock",
"-morgue", "%rmorgue/%n/"
extra_info_file = "%rmorgue/%n/%n.dglwhere"
#
# From inside the jail, where dgamelaunch should put mail - should
# match up with the game's settings.
spooldir = "%%CHROOT_MAILSPOOL%%/"
max_idle_time = 3600
# make sure the inprogress dir actually exists. default is "inprogress/"
# each game you define here must have it's own.
inprogressdir = "%rinprogress/crawl-git/"
ttyrecdir = "%%CHROOT_TTYRECDIR%%/%n/"
commands =
ifnxcp "%rdata/crawl-git.macro" "%rrcfiles/crawl-git/%n.macro",
ifnxcp "%rdata/crawl-git-settings/init.txt" "%rrcfiles/crawl-git/%n.rc",
setenv "MAIL" "%%CHROOT_MAILSPOOL%%/%n",
setenv "SIMPLEMAIL" "1",
unlink "%%CHROOT_MAILSPOOL%%/%n",
mkdir "%rmorgue/%n/"
encoding = "UTF-8"
}
##############################################################################
DEFINE {
game_path = "/bin/crawl-git-launcher.sh"
game_name = "Sprint (trunk)"
short_name = "spr-git"
game_args = "/bin/crawl-git-launcher.sh",
"-name", "%n",
"-rc", "%rrcfiles/crawl-git/%n.rc",
"-macro", "%rrcfiles/crawl-git/%n.macro",
"-webtiles-socket", "%%CHROOT_CRAWL_BASEDIR%%/webserver/sockets/%n:spr-git.sock",
"-morgue", "%rmorgue/%n/",
"-sprint"
extra_info_file = "%rmorgue/%n/%n.dglwhere"
#
# From inside the jail, where dgamelaunch should put mail - should
# match up with the game's settings.
spooldir = "%%CHROOT_MAILSPOOL%%/"
max_idle_time = 3600
# make sure the inprogress dir actually exists. default is "inprogress/"
# each game you define here must have it's own.
inprogressdir = "%rinprogress/crawl-git-sprint/"
ttyrecdir = "%%CHROOT_TTYRECDIR%%/%n/"
commands =
ifnxcp "%rdata/crawl-git.macro" "%rrcfiles/crawl-git/%n.macro",
ifnxcp "%rdata/crawl-git-settings/init.txt" "%rrcfiles/crawl-git/%n.rc",
setenv "MAIL" "%%CHROOT_MAILSPOOL%%/%n",
setenv "SIMPLEMAIL" "1",
unlink "%%CHROOT_MAILSPOOL%%/%n",
mkdir "%rmorgue/%n/"
encoding = "UTF-8"
}
##############################################################################
DEFINE {
game_path = "/bin/crawl-git-launcher.sh"
game_name = "Tutorial (trunk)"
short_name = "tut-git"
game_args = "/bin/crawl-git-launcher.sh",
"-name", "%n",
"-rc", "%rrcfiles/crawl-git/%n.rc",
"-macro", "%rrcfiles/crawl-git/%n.macro",
"-webtiles-socket", "%%CHROOT_CRAWL_BASEDIR%%/webserver/sockets/%n:tut-git.sock",
"-morgue", "%rmorgue/%n/",
"-tutorial"
extra_info_file = "%rmorgue/%n/%n.dglwhere"
#
# From inside the jail, where dgamelaunch should put mail - should
# match up with the game's settings.
spooldir = "%%CHROOT_MAILSPOOL%%/"
max_idle_time = 3600
# make sure the inprogress dir actually exists. default is "inprogress/"
# each game you define here must have it's own.
inprogressdir = "%rinprogress/crawl-git-tut/"
ttyrecdir = "%%CHROOT_TTYRECDIR%%/%n/"
commands =
ifnxcp "%rdata/crawl-git.macro" "%rrcfiles/crawl-git/%n.macro",
ifnxcp "%rdata/crawl-git-settings/init.txt" "%rrcfiles/crawl-git/%n.rc",
setenv "MAIL" "%%CHROOT_MAILSPOOL%%/%n",
setenv "SIMPLEMAIL" "1",
unlink "%%CHROOT_MAILSPOOL%%/%n",
mkdir "%rmorgue/%n/"
encoding = "UTF-8"
}
##############################################################################
## 0.22
##############################################################################
DEFINE {
game_path = "/bin/crawl-stable-launcher.sh"
game_name = "Crawl (0.22)"
short_name = "dcss-0.22"
game_args = "/bin/crawl-stable-launcher.sh", "0.22",
"-name", "%n",
"-rc", "%rrcfiles/crawl-0.22/%n.rc",
"-macro", "%rrcfiles/crawl-0.22/%n.macro",
"-webtiles-socket", "%%CHROOT_CRAWL_BASEDIR%%/webserver/sockets/%n:dcss-0.22.sock",
"-morgue", "%rmorgue/%n/"
extra_info_file = "%rmorgue/%n/%n.dglwhere"
#
# From inside the jail, where dgamelaunch should put mail - should
# match up with the game's settings.
spooldir = "%%CHROOT_MAILSPOOL%%/"
max_idle_time = 3600
# make sure the inprogress dir actually exists. default is "inprogress/"
# each game you define here must have it's own.
inprogressdir = "%rinprogress/crawl-0.22/"
ttyrecdir = "%%CHROOT_TTYRECDIR%%/%n/"
commands =
ifnxcp "%rdata/crawl-git.macro" "%rrcfiles/crawl-0.22/%n.macro",
ifnxcp "%rdata/crawl-0.22-settings/init.txt" "%rrcfiles/crawl-0.22/%n.rc",
setenv "MAIL" "%%CHROOT_MAILSPOOL%%/%n",
setenv "SIMPLEMAIL" "1",
unlink "%%CHROOT_MAILSPOOL%%/%n",
mkdir "%rmorgue/%n/"
encoding = "UTF-8"
}
##############################################################################
DEFINE {
game_path = "/bin/crawl-stable-launcher.sh"
game_name = "Sprint (0.22)"
short_name = "spr-0.22"
game_args = "/bin/crawl-stable-launcher.sh", "0.22",
"-name", "%n",
"-rc", "%rrcfiles/crawl-0.22/%n.rc",
"-macro", "%rrcfiles/crawl-0.22/%n.macro",
"-webtiles-socket", "%%CHROOT_CRAWL_BASEDIR%%/webserver/sockets/%n:spr-0.22.sock",
"-morgue", "%rmorgue/%n/",
"-sprint"
extra_info_file = "%rmorgue/%n/%n.dglwhere"
#
# From inside the jail, where dgamelaunch should put mail - should
# match up with the game's settings.
spooldir = "%%CHROOT_MAILSPOOL%%/"
max_idle_time = 3600
# make sure the inprogress dir actually exists. default is "inprogress/"
# each game you define here must have it's own.
inprogressdir = "%rinprogress/crawl-0.22-sprint/"
ttyrecdir = "%%CHROOT_TTYRECDIR%%/%n/"
commands =
ifnxcp "%rdata/crawl-git.macro" "%rrcfiles/crawl-0.22/%n.macro",
ifnxcp "%rdata/crawl-0.22-settings/init.txt" "%rrcfiles/crawl-0.22/%n.rc",
setenv "MAIL" "%%CHROOT_MAILSPOOL%%/%n",
setenv "SIMPLEMAIL" "1",
unlink "%%CHROOT_MAILSPOOL%%/%n",
mkdir "%rmorgue/%n/"
encoding = "UTF-8"
}
##############################################################################
DEFINE {
game_path = "/bin/crawl-stable-launcher.sh"
game_name = "Tutorial (0.22)"
short_name = "tut-0.22"
game_args = "/bin/crawl-stable-launcher.sh", "0.22",
"-name", "%n",
"-rc", "%rrcfiles/crawl-0.22/%n.rc",
"-macro", "%rrcfiles/crawl-0.22/%n.macro",
"-webtiles-socket", "%%CHROOT_CRAWL_BASEDIR%%/webserver/sockets/%n:tut-0.22.sock",
"-morgue", "%rmorgue/%n/",
"-tutorial"
extra_info_file = "%rmorgue/%n/%n.dglwhere"
#
# From inside the jail, where dgamelaunch should put mail - should
# match up with the game's settings.
spooldir = "%%CHROOT_MAILSPOOL%%/"
max_idle_time = 3600
# make sure the inprogress dir actually exists. default is "inprogress/"
# each game you define here must have it's own.
inprogressdir = "%rinprogress/crawl-0.22-tut/"
ttyrecdir = "%%CHROOT_TTYRECDIR%%/%n/"
commands =
ifnxcp "%rdata/crawl-git.macro" "%rrcfiles/crawl-0.22/%n.macro",
ifnxcp "%rdata/crawl-0.22-settings/init.txt" "%rrcfiles/crawl-0.22/%n.rc",
setenv "MAIL" "%%CHROOT_MAILSPOOL%%/%n",
setenv "SIMPLEMAIL" "1",
unlink "%%CHROOT_MAILSPOOL%%/%n",
mkdir "%rmorgue/%n/"
encoding = "UTF-8"
}

39
dgl-manage.conf Normal file
View File

@ -0,0 +1,39 @@
#! /bin/bash
export ANNOUNCEMENTS_FILE="/home/crawl-dev/logs/announcements.log"
export DGL_CHROOT=/home/crawl/DGL
export CHROOT_DGLDIR=/dgldir
export CHROOT_TTYRECDIR=/dgldir/ttyrec
export CHROOT_MORGUEDIR=/dgldir/morgue
export CHROOT_RCFILESDIR=/dgldir/rcfiles
export CHROOT_INPROGRESSDIR=/dgldir/inprogress
export CHROOT_LOGIN_DB=$CHROOT_DGLDIR/dgamelaunch.db
export CHROOT_DGL_SETTINGS_DIR=$CHROOT_DGLDIR/data
export CHROOT_SAVE_DUMPDIR=$CHROOT_DGLDIR/dumps
export CHROOT_MAILSPOOL=/var/mail
export CHROOT_CRAWL_BASEDIR=/crawl-master
export CHROOT_WEBDIR=$CHROOT_CRAWL_BASEDIR/webserver
# User id that dgamelaunch uses when shedding root privileges.
export DGL_USER=crawl
export DGL_UID=1001
export CHROOT_COREDIR=/cores
# L27 OgRe; Shoals:5
export DGL_INFO_MAX_LENGTH=
export DGL_SERVER=crawl.tildeverse.org
export WEB_SAVEDUMP_URL="https://crawl.tildeverse.org/saves"
export LOGIN_DB=$DGL_CHROOT$CHROOT_LOGIN_DB
export SAVE_DUMPDIR=$DGL_CHROOT$CHROOT_SAVE_DUMPDIR
export DGLDIR=$DGL_CHROOT$CHROOT_DGLDIR
export TTYRECDIR=$DGL_CHROOT$CHROOT_TTYRECDIR
export MORGUEDIR=$DGL_CHROOT$CHROOT_MORGUEDIR
export RCFILESDIR=$DGL_CHROOT$CHROOT_RCFILESDIR
export INPROGRESSDIR=$DGL_CHROOT$CHROOT_INPROGRESSDIR
export WEBDIR=$DGL_CHROOT$CHROOT_WEBDIR
export DGL_SETTINGS_DIR=$DGL_CHROOT$CHROOT_DGL_SETTINGS_DIR

5
fsc.el Normal file
View File

@ -0,0 +1,5 @@
;; -*- mode: emacs-lisp -*-
;; fsc.el: Autogenerated on Sat Mar 26 13:26:28 2011
(scala-fsc :classes "bin" :classpath
'("lib/*.jar")
:source "source")

7
help/admin.txt Normal file
View File

@ -0,0 +1,7 @@
dgl admin: Manages dgamelaunch admin users.
Usage: dgl admin ls List admin users
dgl admin add <user> Make <user> an admin
dgl admin rm <user> Make <user> a regular (non-admin) user.

53
lib/DGLMan.pm Normal file
View File

@ -0,0 +1,53 @@
package DGLMan;
use strict;
use warnings;
use base 'Exporter';
our @EXPORT = qw/say_good say_bad say_emphasized say_coloured
coloured_text good_text bad_text neutral_text
emphasized_text/;
use Term::ANSIColor;
sub emphasized_text(@) {
coloured_text('bold', @_)
}
# Neutral text that should be coloured differently.
sub neutral_text(@) {
coloured_text('blue', @_)
}
sub good_text(@) {
coloured_text('green', @_)
}
sub bad_text(@) {
coloured_text('red', @_)
}
sub coloured_text($@) {
my $color = shift;
color($color) . join('', @_) . color('reset')
}
sub say_coloured($@) {
my $color = shift;
print(color($color), @_, color('reset'));
}
sub say_good(@) {
print(good_text(@_));
}
sub say_bad(@) {
print(bad_text(@_));
}
sub say_emphasized(@) {
print(coloured_text('bold', @_));
}
1

173
sh-utils Normal file
View File

@ -0,0 +1,173 @@
#! /bin/bash
source "$DGL_CONF_HOME/dgl-manage.conf"
DGL_CONF_LOCK_DIR="$DGL_CONF_HOME/locks"
declare -a DGL_LOCKS
DGL_LOCKS=()
PROMPTS_ENABLED=
GIVE_HELP=
help() {
if [[ -n "$GIVE_HELP" ]]; then
cat
echo
exit 0
fi
}
dgl-run() {
"$0" "$@"
}
say() {
echo ";;;; $@"
}
say-do() {
echo "[EXEC] $@"
"$@"
}
running-as-root() {
[[ "$UID" == "0" ]]
}
assert-running-as-root() {
if ! running-as-root; then
abort-saying "$SCRIPT_NAME needs to be run as root"
fi
}
not-running-as-root() {
[[ "$UID" != "0" ]]
}
each-do() {
local cmd="$1"
shift
for arg in "$@"; do
$cmd "$arg"
done
}
announce() {
echo
echo "---------------------------------------------------------------------"
echo "$@"
echo "$@" >>$ANNOUNCEMENTS_FILE
}
abort-saying() {
echo -e "$@, aborting."
exit 1
}
# Call with any argument to disable prompts
enable-prompts() {
local opt
while getopts p opt; do
PROMPTS_ENABLED=1
done
shift $((OPTIND - 1))
# Would be nice to be able to modify the caller's arguments...
}
prompts-enabled() {
[[ -n "$PROMPTS_ENABLED" && -t 0 ]]
}
prompt() {
if prompts-enabled; then
echo "-- Press RETURN to $@ --"
read
else
say "$@"
fi
}
unlock-dgl-locks() {
if (( "${#DGL_LOCKS[@]}" > 0 )); then
rm -f ${DGL_LOCKS[@]}
fi
}
unlock-on-error() {
unlock-dgl-locks
exit 1
}
trap-lock-hook-cleanup() {
if [[ -z "$DGL_TRAP_LOCK_CLEANUP_HOOKED" ]]; then
trap unlock-on-error INT TERM
trap unlock-dgl-locks EXIT
DGL_TRAP_LOCK_CLEANUP_HOOKED=1
fi
}
lock-or-die() {
local lock_name=$1
mkdir -p "$DGL_CONF_LOCK_DIR"
local lock_file="$DGL_CONF_LOCK_DIR/${lock_name}.lock"
shift || true
if ( set -o noclobber; echo "$$" > "$lock_file" ) 2>/dev/null; then
DGL_LOCKS=(${DGL_LOCKS[@]} "$lock_file")
trap-lock-hook-cleanup
else
echo "Could not lock $lock_file: $@"
exit 1
fi
}
dgl-today() {
date +%y%m%d-%H%M
}
cat-error() {
cat >&2
}
assert-chroot-exists() {
if [[ ! -d "$DGL_CHROOT" ]]; then
cat-error <<ERROR
DGL chroot $DGL_CHROOT doesn't exist.
Please create it, or edit $DGL_CONF_HOME/dgl-manage.conf to
point at the real chroot.
ERROR
exit 1
fi
}
assert-login-db-exists() {
if [[ ! -f "$LOGIN_DB" ]]; then
cat-error <<EOF
DGL login db $LOGIN_DB is missing; please check that the chroot
is correctly setup, and that $DGL_CONF_HOME/dgl-manage.conf points
at the correct chroot path.
EOF
exit 1
fi
}
login-query() {
sqlite3 "$LOGIN_DB"
}
dgl-user-exists() {
local user="$1"
local found="$(echo "SELECT username FROM dglusers WHERE username='$user';" |
login-query)"
[[ -n "$found" ]]
}
dgl-user-is-admin() {
local user="$1"
local found="$(echo "SELECT username FROM dglusers
WHERE username='$user' AND (flags & 1) = 1;" |
login-query)"
[[ -n "$found" ]]
}

95
utils/auth-save-downloader.pl Executable file
View File

@ -0,0 +1,95 @@
#! /usr/bin/perl
#
# Allows DGL admin users to download saves from CSZO's save dump directory.
#
use CGI qw/:standard/;
use MIME::Base64;
use DBI;
my $DB = "%%LOGIN_DB%%";
my $CONTENT_DIR = '%%SAVE_DUMPDIR%%/';
my $AUTH_REALM = 'CSZO developer account';
sub request_auth() {
print(header(-type => 'text/html',
-status => '401 Authorization Required',
-WWW_Authenticate => "Basic realm=\"$AUTH_REALM\""),
start_html('CSZO save dumps'),
p('Must authenticate to access saves'),
end_html);
return undef;
}
sub match_password($$) {
my ($plain, $crypt) = @_;
my $cc = crypt($plain, $crypt);
return crypt($plain, $crypt) eq $crypt;
}
sub valid_user($$) {
my ($user, $password) = @_;
my $db = DBI->connect("dbi:SQLite:dbname=$DB", '', '')
or die "Can't open auth db: $DB\n";
my $st = $db->prepare(<<QUERY);
SELECT username, password FROM dglusers
WHERE username=? AND (flags & 1) = 1;
QUERY
$st->execute($user);
my $row = $st->fetchrow_arrayref;
# Should have at least one row.
return defined($row) && match_password($password, $row->[1]);
}
sub valid_auth($) {
my $header = shift;
return unless $header =~ s/^Basic //;
my $decoded = decode_base64($header);
my ($user, $password) = $decoded =~ /(.*?):(.*)/;
valid_user($user, $password)
}
sub authenticate() {
my $auth_header = http('Authorization');
return request_auth() unless $auth_header && valid_auth($auth_header);
1
}
sub file_bytes($) {
my $file = shift;
open my $inf, '<', $file;
binmode $inf;
my $content = do { local $/; <$inf> };
close $inf;
$content
}
sub serve_file() {
my ($file) = param('file');
my $absfile = "$CONTENT_DIR/$file";
if ($file =~ /[.]{2}/ ||
$file !~ /^[a-zA-Z0-9._-]+$/ ||
$file !~ /\.(?:tar\.bz2|cs|core)$/ ||
!-r $absfile)
{
print(header(-status => '404 Not Found'),
start_html,
p("Could not find $absfile"),
end_html);
return;
}
print(header(-type => 'application/octet-stream'),
file_bytes($absfile));
}
sub main() {
return unless authenticate();
serve_file();
}
main();

165
utils/trigger-rebuild.pl Executable file
View File

@ -0,0 +1,165 @@
#! /usr/bin/perl
#
# Allows DGL admin users to trigger rebuilds of trunk or stable.
use CGI qw/:standard/;
use MIME::Base64;
use DBI;
my $DGL = "/home/crawl-dev/dgamelaunch-config/bin/dgl";
my $DB = "%%LOGIN_DB%%";
my $CONTENT_DIR = '%%SAVE_DUMPDIR%%/';
my $AUTH_REALM = 'CSZO developer account';
sub request_auth() {
print(header(-type => 'text/html',
-status => '401 Authorization Required',
-WWW_Authenticate => "Basic realm=\"$AUTH_REALM\""),
start_html('CSZO rebuild trigger'),
p('Must authenticate to trigger rebuilds.'),
end_html);
return undef;
}
sub match_password($$) {
my ($plain, $crypt) = @_;
my $cc = crypt($plain, $crypt);
return crypt($plain, $crypt) eq $crypt;
}
sub valid_user($$) {
my ($user, $password) = @_;
my $db = DBI->connect("dbi:SQLite:dbname=$DB", '', '')
or die "Can't open auth db: $DB\n";
my $st = $db->prepare(<<QUERY);
SELECT username, password FROM dglusers
WHERE username=? AND (flags & 1) = 1;
QUERY
$st->execute($user);
my $row = $st->fetchrow_arrayref;
# Should have at least one row.
return defined($row) && match_password($password, $row->[1]);
}
sub valid_auth($) {
my $header = shift;
return unless $header =~ s/^Basic //;
my $decoded = decode_base64($header);
my ($user, $password) = $decoded =~ /(.*?):(.*)/;
valid_user($user, $password)
}
sub authenticate() {
my $auth_header = http('Authorization');
return request_auth() unless $auth_header && valid_auth($auth_header);
1
}
sub file_bytes($) {
my $file = shift;
open my $inf, '<', $file;
binmode $inf;
my $content = do { local $/; <$inf> };
close $inf;
$content
}
sub serve_file() {
my ($file) = param('file');
my $absfile = "$CONTENT_DIR/$file";
if ($file =~ /[.]{2}/ ||
$file !~ /^[a-zA-Z0-9._-]+$/ ||
$file !~ /\.(?:tar\.bz2|cs)$/ ||
!-r $absfile)
{
print(header(-status => '404 Not Found'),
start_html,
p("Could not find $absfile"),
end_html);
return;
}
print(header(-type => 'application/octet-stream'),
file_bytes($absfile));
}
sub do_update($;$) {
my $branch = shift;
my $specific = $_[0] or $branch;
local $| = 1;
print(header(-type => 'text/html',
-WWW_Authenticate => "Basic realm=\"$AUTH_REALM\""),
start_html('CSZO rebuild trigger'),
p("Rebuilding $specific. . ."));
print "<pre>";
open my $olderr, ">&STDERR";
open STDERR, ">&STDOUT";
system(qw(sudo -u crawl-dev), $DGL, "update-$branch", @_);
print "</pre>";
if ($?) {
my $msg;
if ($? == -1) {
$msg = "could not execute: $?";
} elsif ($? & 0xff) {
$msg = "signal " . ($? & 0xff);
} else {
$msg = "returned " . ($? >> 8);
}
print p({-style => 'background-color: #ffcccc;'},
"Failed: $msg");
} else {
print p("Done!");
}
print end_html;
open STDERR, $olderr;
}
sub do_prompt(@) {
print(header(-type => 'text/html',
-WWW_Authenticate => "Basic realm=\"$AUTH_REALM\""),
start_html('CSZO rebuild trigger'),
start_form,
p('Select a version'),
popup_menu(-name => 'v', -values => [ @_ ]),
submit,
end_form,
end_html);
}
sub do_fail($) {
my $msg = shift;
print(header(-type => 'text/html',
-status => '403 Forbidden',
-WWW_Authenticate => "Basic realm=\"$AUTH_REALM\""),
start_html('CSZO rebuild trigger'),
start_form,
p({-style=>'background-color: #ffcccc;'}, $msg),
popup_menu(-name => 'v', -values => @_),
submit,
end_form,
end_html);
}
sub main() {
return unless authenticate();
my $ver = param('v');
if (not $ver) {
do_prompt 'trunk', '0.17', '0.16', '0.15', '0.14', '0.13', '0.12', '0.11', '0.10';
} elsif ($ver eq 'trunk') {
do_update 'trunk';
} elsif ($ver =~ /^0.1[01234567]$/) {
do_update 'stable', $ver;
} else {
do_fail "Unknown version " . escapeHTML($ver);
}
}
main();

71
utils/webtiles Executable file
View File

@ -0,0 +1,71 @@
#!/bin/sh
### BEGIN INIT INFO
# Provides: webtiles
# Required-Start: $local_fs $remote_fs $network $named
# Required-Stop: $local_fs $remote_fs $network $named
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# X-Interactive: true
# Short-Description: Start/stop Dungeon Crawl webtiles server
### END INIT INFO
. /lib/lsb/init-functions
# kill -TERM doesn't work
signal=ABRT
announce() {
echo "$@" >> %%ANNOUNCEMENTS_FILE%%
}
quietly() {
"$@" >/dev/null 2>&1
}
stop_webtiles() {
log_daemon_msg "Stopping webtiles server" "webtiles"
[ -z "$1" ] || ! quietly ps "$1" || kill -$signal "$1"
local result=$?
log_end_msg $result
return $result
}
start_webtiles() {
log_daemon_msg "Starting webtiles server" "webtiles"
ulimit -n 4096
PYTHONPATH=/home/crawl-dev/tornado/ python ./server.py
local result=$?
log_end_msg $result
return $result
}
cd %%CRAWL_BASEDIR%%/webserver
pid=$([ -e run/webtiles.pid ] && cat run/webtiles.pid)
case $1 in
start)
if [ -n "$pid" ] && quietly ps "$pid"; then
log_warning_msg "Webtiles was already running!"
else
start_webtiles && announce "Webtiles server started."
fi
;;
stop)
stop_webtiles "$pid" && announce "Webtiles server stopped."
;;
restart|reload)
if stop_webtiles "$pid" && sleep 3; then
if start_webtiles; then
announce "Webtiles server restarted.";
else
announce "Webtiles server failed to restart.";
fi
fi
;;
*)
log_success_msg "Usage: /etc/init.d/webtiles {start|stop|restart}"
exit 1
;;
esac