#!/bin/sh

# This script was taken from the Debian xvfb package, version 4.3.0-7
# (testing branch), and modified for portability on non-Linux platforms.
# (mnoble@space.mit.edu 5/6/2004)
#
# xvfb-run - run the specified command in a virtual X server
#
# This script starts an instance of Xvfb, the "fake" X server, runs a
# command with that server available, and kills the X server when
# done.  The return value of the command becomes the return value of
# this script.
#
# If anyone is using this to build a Debian package, make sure the
# package Build-Depends on xvfb, xbase-clients, and xfonts-base.

set -e

PROGNAME=xvfb-run
SERVERNUM=99
HOSTNAME=
#AUTHFILE=$(tempfile -s .xfvb-run)
AUTHFILE=./Xauthority-${LOGNAME}
ERRORFILE=/dev/null
STARTWAIT=3
XVFBARGS="-screen 0 1024x768x24"
LISTENTCP="-nolisten tcp"
XAUTHPROTO=.

# display a usage message
usage () {
    cat << EOF
Usage: $PROGNAME [OPTION ...] COMMAND

run COMMAND (usually an X client) in a virtual X server environment

Options:
-a        try to get a free server number, starting at -n value (default: $SERVERNUM)
-e FILE   file used to store xauth errors and Xvfb output (default: $ERRORFILE)
-f FILE   file used to store auth cookie (default: ./.Xauthority)
-h        this usage message and exit
-n NUM    server number to use (default: $SERVERNUM)
-l        enable TCP port listening in the X server
-p PROTO  X authority protocol name to use (defaults to xauth's default)
-s ARGS   arguments (other than server number and -nolisten tcp) to pass 
          to the Xvfb server (default: "$XVFBARGS")
-u        prepend output of "uname -n" to DISPLAY value used by client
-w DELAY  delay in seconds to wait for Xvfb to start (default: $STARTWAIT)
EOF
    :;
}

# find free server number by looking at .X*-lock files in /tmp
find_free_servernum() {
    i=$SERVERNUM
    while [ -f /tmp/.X$i-lock ]; do
        let i=i+1
    done
    echo $i;
}

# parse command line
ARGS=`getopt ae:f:hn:lp:s:uw: "$@"`

if [ $? -ne 0 ]; then
    echo "$PROGNAME: error while getting options" >&2
    exit 1
fi

eval set -- "$ARGS"

while :; do
    case "$1" in
        -a) SERVERNUM=`find_free_servernum` ;;
        -e) ERRORFILE="$2"; shift ;;
        -f) AUTHFILE="$2"; shift ;;
        -h) SHOWHELP="yes" ;;
        -n) SERVERNUM="$2"; shift ;;
        -l) LISTENTCP="" ;;
        -p) XAUTHPROTO="$2"; shift ;;
        -s) XVFBARGS="$2"; shift ;;
        -w) STARTWAIT="$2"; shift ;;
        -u) HOSTNAME=`uname -n` ;;
        --) shift; break ;;
        *) echo "$PROGNAME: error while parsing option \"$1\"" >&2; USAGE=`usage`; echo "$USAGE" >&2; exit 1 ;;
    esac
    shift
done

if [ "$SHOWHELP" ]; then
    usage
    exit 0
fi

if [ -z "$*" ]; then
    echo "$PROGNAME: need a command to run" >&2
    exit 2
fi

# start Xvfb
\rm -f $AUTHFILE
MCOOKIE=`mcookie`
XAUTHORITY=$AUTHFILE xauth add :$SERVERNUM $XAUTHPROTO $MCOOKIE > $ERRORFILE 2>&1

XAUTHORITY=$AUTHFILE Xvfb -pn :$SERVERNUM $XVFBARGS $LISTENTCP > $ERRORFILE 2>&1 &
XVFBPID=$!
sleep $STARTWAIT

# start the command and save its exit status
set +e
DISPLAY=${HOSTNAME}:$SERVERNUM XAUTHORITY=$AUTHFILE $@ 2>&1
RETVAL=$?
set -e

# kill Xvfb now that the command has exited
kill $XVFBPID

# clean up
XAUTHORITY=$AUTHFILE xauth remove :$SERVERNUM > $ERRORFILE 2>&1
\rm $AUTHFILE

# return the executed command's exit status
exit $RETVAL
