tests/xvfb-run
changeset 75 6575679d2e8e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/tests/xvfb-run	Fri Jun 08 14:48:00 2018 +0100
     1.3 @@ -0,0 +1,190 @@
     1.4 +#!/bin/sh
     1.5 +
     1.6 +# This script starts an instance of Xvfb, the "fake" X server, runs a command
     1.7 +# with that server available, and kills the X server when done.  The return
     1.8 +# value of the command becomes the return value of this script.
     1.9 +#
    1.10 +# If anyone is using this to build a Debian package, make sure the package
    1.11 +# Build-Depends on xvfb and xauth.
    1.12 +
    1.13 +set -e
    1.14 +
    1.15 +PROGNAME=xvfb-run
    1.16 +SERVERNUM=99
    1.17 +AUTHFILE=
    1.18 +ERRORFILE=/dev/null
    1.19 +XVFBARGS="-screen 0 640x480x8"
    1.20 +LISTENTCP="-nolisten tcp"
    1.21 +XAUTHPROTO=.
    1.22 +
    1.23 +# Query the terminal to establish a default number of columns to use for
    1.24 +# displaying messages to the user.  This is used only as a fallback in the event
    1.25 +# the COLUMNS variable is not set.  ($COLUMNS can react to SIGWINCH while the
    1.26 +# script is running, and this cannot, only being calculated once.)
    1.27 +DEFCOLUMNS=$(stty size 2>/dev/null | awk '{print $2}') || true
    1.28 +if ! expr "$DEFCOLUMNS" : "[[:digit:]]\+$" >/dev/null 2>&1; then
    1.29 +    DEFCOLUMNS=80
    1.30 +fi
    1.31 +
    1.32 +# Display a message, wrapping lines at the terminal width.
    1.33 +message () {
    1.34 +    echo "$PROGNAME: $*" | fmt -t -w ${COLUMNS:-$DEFCOLUMNS}
    1.35 +}
    1.36 +
    1.37 +# Display an error message.
    1.38 +error () {
    1.39 +    message "error: $*" >&2
    1.40 +}
    1.41 +
    1.42 +# Display a usage message.
    1.43 +usage () {
    1.44 +    if [ -n "$*" ]; then
    1.45 +        message "usage error: $*"
    1.46 +    fi
    1.47 +    cat <<EOF
    1.48 +Usage: $PROGNAME [OPTION ...] COMMAND
    1.49 +Run COMMAND (usually an X client) in a virtual X server environment.
    1.50 +Options:
    1.51 +-a        --auto-servernum          try to get a free server number, starting at
    1.52 +                                    --server-num
    1.53 +-e FILE   --error-file=FILE         file used to store xauth errors and Xvfb
    1.54 +                                    output (default: $ERRORFILE)
    1.55 +-f FILE   --auth-file=FILE          file used to store auth cookie
    1.56 +                                    (default: ./.Xauthority)
    1.57 +-h        --help                    display this usage message and exit
    1.58 +-n NUM    --server-num=NUM          server number to use (default: $SERVERNUM)
    1.59 +-l        --listen-tcp              enable TCP port listening in the X server
    1.60 +-p PROTO  --xauth-protocol=PROTO    X authority protocol name to use
    1.61 +                                    (default: xauth command's default)
    1.62 +-s ARGS   --server-args=ARGS        arguments (other than server number and
    1.63 +                                    "-nolisten tcp") to pass to the Xvfb server
    1.64 +                                    (default: "$XVFBARGS")
    1.65 +EOF
    1.66 +}
    1.67 +
    1.68 +# Find a free server number by looking at .X*-lock files in /tmp.
    1.69 +find_free_servernum() {
    1.70 +    # Sadly, the "local" keyword is not POSIX.  Leave the next line commented in
    1.71 +    # the hope Debian Policy eventually changes to allow it in /bin/sh scripts
    1.72 +    # anyway.
    1.73 +    #local i
    1.74 +
    1.75 +    i=$SERVERNUM
    1.76 +    while [ -f /tmp/.X$i-lock ]; do
    1.77 +        i=$(($i + 1))
    1.78 +    done
    1.79 +    echo $i
    1.80 +}
    1.81 +
    1.82 +# Clean up files
    1.83 +clean_up() {
    1.84 +    if [ -e "$AUTHFILE" ]; then
    1.85 +        XAUTHORITY=$AUTHFILE xauth remove ":$SERVERNUM" >>"$ERRORFILE" 2>&1
    1.86 +    fi
    1.87 +    if [ -n "$XVFB_RUN_TMPDIR" ]; then
    1.88 +        if ! rm -r "$XVFB_RUN_TMPDIR"; then
    1.89 +            error "problem while cleaning up temporary directory"
    1.90 +            exit 5
    1.91 +        fi
    1.92 +    fi
    1.93 +    if [ -n "$XVFBPID" ]; then
    1.94 +        kill "$XVFBPID" >>"$ERRORFILE" 2>&1
    1.95 +    fi
    1.96 +}
    1.97 +
    1.98 +# Parse the command line.
    1.99 +ARGS=$(getopt --options +ae:f:hn:lp:s:w: \
   1.100 +       --long auto-servernum,error-file:,auth-file:,help,server-num:,listen-tcp,xauth-protocol:,server-args:,wait: \
   1.101 +       --name "$PROGNAME" -- "$@")
   1.102 +GETOPT_STATUS=$?
   1.103 +
   1.104 +if [ $GETOPT_STATUS -ne 0 ]; then
   1.105 +    error "internal error; getopt exited with status $GETOPT_STATUS"
   1.106 +    exit 6
   1.107 +fi
   1.108 +
   1.109 +eval set -- "$ARGS"
   1.110 +
   1.111 +while :; do
   1.112 +    case "$1" in
   1.113 +        -a|--auto-servernum) SERVERNUM=$(find_free_servernum); AUTONUM="yes" ;;
   1.114 +        -e|--error-file) ERRORFILE="$2"; shift ;;
   1.115 +        -f|--auth-file) AUTHFILE="$2"; shift ;;
   1.116 +        -h|--help) SHOWHELP="yes" ;;
   1.117 +        -n|--server-num) SERVERNUM="$2"; shift ;;
   1.118 +        -l|--listen-tcp) LISTENTCP="" ;;
   1.119 +        -p|--xauth-protocol) XAUTHPROTO="$2"; shift ;;
   1.120 +        -s|--server-args) XVFBARGS="$2"; shift ;;
   1.121 +        -w|--wait) shift ;;
   1.122 +        --) shift; break ;;
   1.123 +        *) error "internal error; getopt permitted \"$1\" unexpectedly"
   1.124 +           exit 6
   1.125 +           ;;
   1.126 +    esac
   1.127 +    shift
   1.128 +done
   1.129 +
   1.130 +if [ "$SHOWHELP" ]; then
   1.131 +    usage
   1.132 +    exit 0
   1.133 +fi
   1.134 +
   1.135 +if [ -z "$*" ]; then
   1.136 +    usage "need a command to run" >&2
   1.137 +    exit 2
   1.138 +fi
   1.139 +
   1.140 +if ! which xauth >/dev/null; then
   1.141 +    error "xauth command not found"
   1.142 +    exit 3
   1.143 +fi
   1.144 +
   1.145 +# tidy up after ourselves
   1.146 +trap clean_up EXIT
   1.147 +
   1.148 +# If the user did not specify an X authorization file to use, set up a temporary
   1.149 +# directory to house one.
   1.150 +if [ -z "$AUTHFILE" ]; then
   1.151 +    XVFB_RUN_TMPDIR="$(mktemp -d -t $PROGNAME.XXXXXX)"
   1.152 +    # Create empty file to avoid xauth warning
   1.153 +    AUTHFILE=$(tempfile -n "$XVFB_RUN_TMPDIR/Xauthority")
   1.154 +fi
   1.155 +
   1.156 +# Start Xvfb.
   1.157 +MCOOKIE=$(mcookie)
   1.158 +tries=10
   1.159 +while [ $tries -gt 0 ]; do
   1.160 +    tries=$(( $tries - 1 ))
   1.161 +    XAUTHORITY=$AUTHFILE xauth source - << EOF >>"$ERRORFILE" 2>&1
   1.162 +add :$SERVERNUM $XAUTHPROTO $MCOOKIE
   1.163 +EOF
   1.164 +    # handle SIGUSR1 so Xvfb knows to send a signal when it's ready to accept
   1.165 +    # connections
   1.166 +    trap : USR1
   1.167 +    (trap '' USR1; exec Xvfb ":$SERVERNUM" $XVFBARGS $LISTENTCP -auth $AUTHFILE >>"$ERRORFILE" 2>&1) &
   1.168 +    XVFBPID=$!
   1.169 +
   1.170 +    wait || :
   1.171 +    if kill -0 $XVFBPID 2>/dev/null; then
   1.172 +        break
   1.173 +    elif [ -n "$AUTONUM" ]; then
   1.174 +        # The display is in use so try another one (if '-a' was specified).
   1.175 +        SERVERNUM=$((SERVERNUM + 1))
   1.176 +        SERVERNUM=$(find_free_servernum)
   1.177 +        continue
   1.178 +    fi
   1.179 +    error "Xvfb failed to start" >&2
   1.180 +    XVFBPID=
   1.181 +    exit 1
   1.182 +done
   1.183 +
   1.184 +# Start the command and save its exit status.
   1.185 +set +e
   1.186 +DISPLAY=:$SERVERNUM XAUTHORITY=$AUTHFILE "$@" 2>&1
   1.187 +RETVAL=$?
   1.188 +set -e
   1.189 +
   1.190 +# Return the executed command's exit status.
   1.191 +exit $RETVAL
   1.192 +
   1.193 +# vim:set ai et sts=4 sw=4 tw=80: