#!/bin/sh # # monotone: This script starts and stops the monotone server # # chkconfig: - 90 10 # description: Monotone netsync protocol server # processname: monotone-server # pidfile: /var/run/monotone/monotone-server.pid # config: /etc/sysconfig/monotone # config: /etc/monotone/monotonerc # Do not load RH compatibility interface. WITHOUT_RC_COMPAT=1 # Source function library. . /etc/rc.d/init.d/functions # Source networking configuration. . /etc/sysconfig/network # Check that networking is up. [ ${NETWORKING} = "no" ] && exit 0 # Get configuration settings. [ -f /etc/sysconfig/monotone ] && . /etc/sysconfig/monotone # By default it's all good RETVAL=0 STARTED=1 MT=/usr/bin/mtn MTSERVER=/usr/sbin/monotone-server PIDFILE=/var/run/monotone/monotone-server.pid LOGFILE=${MONOTONE_LOGFILE:-/var/log/monotone.log} MONOTONE_DBDIR=`dirname $MONOTONE_DBFILE` MONOTONE_OLDDB=$MONOTONE_DBDIR/server.db LOCKFILE=/var/lock/subsys/monotone USER=${MONOTONE_USER:-monotone} GROUP=${MONOTONE_GROUP:-monotone} random_passphrase() { # As of 0.22, 32 chars is the maximum pass phrase length. dd if=/dev/urandom bs=32 count=1 2> /dev/null | md5sum | { read sum rest; echo $sum; } } umask 077 check_db_version() { db_version=`su -s /bin/bash - $USER \ -c "LC_ALL=C \ $MT $MONOTONE_RCOPTS $MONOTONE_DBOPTS \ db version"` || exit 2 set -- $db_version [ "$5" == "(usable)" ] return $? } start_monotone_daemon() { local ANNOUNCE BASENAME CMDNAME DISPNAME EXPECT FLAGS LOCKFILE MAKE_PIDFILE NICE PIDFILE LOGFILE STATUS SU WHICH # Process options. ANNOUNCE=1 CMDNAME= DISPNAME= EXPECT= LOCKFILE= MAKE_BACKGROUND= NICE=0 PIDFILE= LOGFILE= SU= while [ "$1" != "${1##-}" -o "$1" != "${1##+}" ]; do case "$1" in --) shift break ;; --announce) shift ANNOUNCE=1 ;; --no-announce) shift ANNOUNCE= ;; --displayname) shift DISPNAME="$1" shift ;; --expect-user) shift EXPECT="$1" shift ;; --lockfile) shift LOCKFILE="$1" shift ;; --background) shift MAKE_BACKGROUND='--background' ;; --name) shift CMDNAME="$1" shift ;; --pidfile) shift PIDFILE="$1" shift ;; --logfile) shift LOGFILE="$1" shift ;; --user|--set-user) shift SU="$1" [ -n "$EXPECT" ] || EXPECT="$SU" shift ;; [-+][0-9]*) NICE="$1" shift ;; *) echo "start_daemon: unrecognized option: $1" >&2 return 1 ;; esac done # We need the absolute pathname. if [ -z "$1" ]; then msg_usage "start_daemon [options]... {program}..." return 1 fi WHICH="$(absolute "$1")" || return 1 [ -n "$CMDNAME" ] && BASENAME="$(basename "$CMDNAME")" || BASENAME="$(basename "$1")" || return 1 shift if [ -n "$CMDNAME" -a -z "$PIDFILE" ]; then echo "start_daemon: --name is set but --pidfile is not set" >&2 return 1 fi [ -n "$DISPNAME" ] || DISPNAME="$BASENAME" # Use a safe umask #umask 077 # Don't do coredumps. ulimit -Sc 0 >/dev/null 2>&1 # Don't export these because they may be invalid under another UID and the # directories may be gone while the daemon is still running. export -n HOME TMP TMPDIR FLAGS="--start -N $NICE" [ -z "$CMDNAME" ] && FLAGS="$FLAGS --exec $WHICH" || FLAGS="$FLAGS --startas $WHICH --name $CMDNAME" [ -z "$PIDFILE" ] || FLAGS="$FLAGS --pidfile $PIDFILE" [ -z "$EXPECT" ] || FLAGS="$FLAGS --user $EXPECT" [ -z "$MAKE_BACKGROUND" ] || FLAGS="$FLAGS $MAKE_BACKGROUND" # Is it running at all? if ! start-stop-daemon $FLAGS --test > /dev/null; then msg_already_running "$DISPNAME" passed "$BASENAME startup" STATUS=$? echo return $STATUS fi [ -e "$PIDFILE" ] && rm -f "$PIDFILE" # Announce the action. [ -z "$ANNOUNCE" ] || msg_starting "$DISPNAME" # Actually start the daemon. [ -z "$LOGFILE" ] || LOG_ADD=" >>$LOGFILE 2>&1" [ -z "$SU" ] || START_CMD="start-stop-daemon $FLAGS -- \"$*$LOG_ADD\"" && START_CMD="start-stop-daemon $FLAGS --startas /bin/su -- -s /bin/sh -l \"$SU\" -c \"$WHICH $*$LOG_ADD\"" initlog $INITLOG_ARGS -n "$BASENAME" -c "$START_CMD" STATUS=$? if [ $STATUS = 0 ]; then [ -z "$LOCKFILE" ] || touch "$LOCKFILE" [ "$BOOTUP" != verbose ] || echo -n " $DISPNAME " success "$BASENAME startup" else failure "$BASENAME startup" fi echo return $STATUS } start() { if [ -e $MONOTONE_DBFILE ]; then check_db_version || $0 migrate elif [ -e $MONOTONE_OLDDB ]; then echo -n $"Pre-0.26 monotone database must be migrated by hand: " failure echo false else $0 init fi RETVAL=$? if [ $RETVAL = 0 ] && [ "x`ls $MONOTONE_KEYDIR`" = x ]; then $0 genkey RETVAL=$? fi if [ $RETVAL = 0 ]; then # Start daemon. msg_starting $"monotone server" { exec 3>> $LOGFILE && chown :$GROUP $LOGFILE && chmod g+w $LOGFILE && echo >&3 "Server restart at `date`" && start_monotone_daemon --no-announce --pidfile "$PIDFILE" --lockfile "$LOCKFILE" \ --user $USER --logfile $LOGFILE --background -- $MTSERVER \ $MONOTONE_RCOPTS $MONOTONE_DBOPTS $MONOTONE_PPOPTS \ serve --pid-file=$PIDFILE } RETVAL=$? fi return $RETVAL } stop() { # Stop daemons. msg_stopping $"monotone server" stop_daemon --no-announce --pidfile "$PIDFILE" --lockfile "$LOCKFILE" \ --expect-user $USER -HUP -- $MTSERVER RETVAL=$? [ $RETVAL = 0 ] && [ -e "$PIDFILE" ] && rm -f "$PIDFILE" return $RETVAL } init() { echo -n $"Initializing database" "${MONOTONE_DBFILE}: " { [ -d "$MONOTONE_DBDIR" ] || /usr/bin/install -o $USER -g $GROUP \ -m 0770 -d $MONOTONE_DBDIR; } && su -s /bin/bash - $USER -c "umask 007; \ $MT $MONOTONE_RCOPTS $MONOTONE_DBOPTS db init" >>$LOGFILE 2>&1 && success $"database initialization" || failure $"database initialization" RETVAL=$? echo return $RETVAL } genkey() { MONOTONE_KEYID=${2:-${MONOTONE_KEYID:-`/bin/hostname -f`}} MONOTONE_PPFILE=${MONOTONE_PPFILE:-$MONOTONE_DBDIR/passphrase.lua} echo -n $"Generating RSA key for server $MONOTONE_KEYID" tmp=/tmp/mtserver$$ if passphrase=`random_passphrase` && { echo $passphrase; echo $passphrase; } | (umask 027; $MT $MONOTONE_RCOPTS $MONOTONE_DBOPTS \ genkey $MONOTONE_KEYID >>$LOGFILE 2>&1) && /bin/chgrp $GROUP \ "$MONOTONE_KEYDIR/$MONOTONE_KEYID" && /bin/chmod 0640 "$MONOTONE_KEYDIR/$MONOTONE_KEYID" && cat > $tmp <>$LOGFILE 2>&1 && $MT $MONOTONE_RCOPTS $MONOTONE_DBOPTS $MONOTONE_PPOPTS db regenerate_caches >>$LOGFILE 2>&1 && /bin/chgrp -R $GROUP $MONOTONE_KEYDIR) RETVAL=$? echo -n $"Checking database format in" "${MONOTONE_DBFILE}: " [ $RETVAL = 0 ] && success $"database check" || failure $"database check" echo return $RETVAL } import() { started && stop echo -n $"Importing packets to monotone database: " su -s /bin/bash - $USER -c "umask 007; \ $MT $MONOTONE_RCOPTS $MONOTONE_DBOPTS read" >>$LOGFILE 2>&1 && success $"packet import" || failure $"packet import" RETVAL=$? echo started && start return $RETVAL } checkstatus() { status --pidfile "$PIDFILE" --expect-user $USER $MTSERVER return $? } checkstarted() { checkstatus >/dev/null 2>&1 STARTED=$? } started() { return $STARTED } listkeys() { started && stop echo $"Printing monotone database list of imported keys:" su -s /bin/bash - $USER -c "umask 007; \ $MT $MONOTONE_RCOPTS $MONOTONE_DBOPTS list keys" RETVAL=$? started && start return $RETVAL } # See how we were called. case "$1" in start) start ;; stop) stop ;; status) checkstatus RETVAL=$? ;; restart) stop start ;; condstop) if [ -f "$LOCKFILE" ]; then stop fi ;; condrestart) if [ -f "$LOCKFILE" ]; then stop start fi ;; init) init ;; genkey) genkey ;; migrate) migrate ;; # Use "monotone pubkey me@my.com | service monotone import" # to import the first keys to enable in /etc/monotone/write-permission. # Thereafter, those with write permission can add other keys via # netsync with "monotone push --key-to-push=IDENT" and then IDENT # can be used in the read-permission and write-permission files. import) checkstarted import ;; listkeys) checkstarted listkeys ;; *) echo "\ Usage: $0 {start|stop|restart|status|condrestart|init|import|genkey [IDENT]}" RETVAL=1 ;; esac exit $RETVAL