Package: xvfb Version: 1.9.4.901-1 It seems that there are differences between the Xvfb command for Linux (Debian/RedHat), AIX and Solaris.
I have patched the script so that it works on AIX and Solaris, in addition to Linux. I have tested the script on AIX 6.1 and Solaris Sparc 10. The following changes were made: It checks if the script is running in a Korn(-like) or Bash(-like) shell. If it isn't, exit code 7 is returned. The reason is that on Solaris, /bin/sh is linked to the standard Bourne shell. On AIX, there is no Xvfb command. The standard X command is used instead. The default arguments used by the xvfb-run script when running Xvfb are different between Linux, AIX and Solaris. The script uses the correct arguments based on the operating system being used. It checks if the GNU version of getopt is installed. If it isn't, then, the standard version of getopt is used and long options are disabled. It checks if the tempfile command is installed. If it is, it used, otherwise, mktemp is used as it was in previous versions of the script. I also ported a fix from RedHat's version of Xvfb-run in terms of using the mktemp script. Details of the fix are here: https://bugzilla.redhat.com/show_bug.cgi?id=508739 and here: https://bugzilla.redhat.com/show_bug.cgi?id=632879. If the mcookie utility is not installed, it is simulated based on code found at the following URL: http://git.debian.org/?p=pkg-xorg/app/xinit.git;a=blob_plain;f=configure .ac;hb=HEAD. By default, I am using the /dev/urandom device. If security is an issue, it can be changed to use the /dev/random device instead. Here is the original version of the file: Xvfb-run.orig ============ #!/bin/sh # $Id: xvfb-run 2027 2004-11-16 14:54:16Z branden $ # 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 AUTHFILE= ERRORFILE=/dev/null STARTWAIT=3 XVFBARGS="-screen 0 640x480x8" LISTENTCP="-nolisten tcp" XAUTHPROTO=. # Query the terminal to establish a default number of columns to use for # displaying messages to the user. This is used only as a fallback in the event # the COLUMNS variable is not set. ($COLUMNS can react to SIGWINCH while the # script is running, and this cannot, only being calculated once.) DEFCOLUMNS=$(stty size 2>/dev/null | awk '{print $2}') || true if ! expr "$DEFCOLUMNS" : "[[:digit:]]\+$" >/dev/null 2>&1; then DEFCOLUMNS=80 fi # Display a message, wrapping lines at the terminal width. message () { echo "$PROGNAME: $*" | fmt -t -w ${COLUMNS:-$DEFCOLUMNS} } # Display an error message. error () { message "error: $*" >&2 } # Display a usage message. usage () { if [ -n "$*" ]; then message "usage error: $*" fi cat <<EOF Usage: $PROGNAME [OPTION ...] COMMAND Run COMMAND (usually an X client) in a virtual X server environment. Options: -a --auto-servernum try to get a free server number, starting at --server-num -e FILE --error-file=FILE file used to store xauth errors and Xvfb output (default: $ERRORFILE) -f FILE --auth-file=FILE file used to store auth cookie (default: ./.Xauthority) -h --help display this usage message and exit -n NUM --server-num=NUM server number to use (default: $SERVERNUM) -l --listen-tcp enable TCP port listening in the X server -p PROTO --xauth-protocol=PROTO X authority protocol name to use (default: xauth command's default) -s ARGS --server-args=ARGS arguments (other than server number and "-nolisten tcp") to pass to the Xvfb server (default: "$XVFBARGS") -w DELAY --wait=DELAY delay in seconds to wait for Xvfb to start before running COMMAND (default: $STARTWAIT) EOF } # Find a free server number by looking at .X*-lock files in /tmp. find_free_servernum() { # Sadly, the "local" keyword is not POSIX. Leave the next line commented in # the hope Debian Policy eventually changes to allow it in /bin/sh scripts # anyway. #local i i=$SERVERNUM while [ -f /tmp/.X$i-lock ]; do i=$(($i + 1)) done echo $i } # Clean up files clean_up() { if [ -e "$AUTHFILE" ]; then XAUTHORITY=$AUTHFILE xauth remove ":$SERVERNUM" >>"$ERRORFILE" 2>&1 fi if [ -n "$XVFB_RUN_TMPDIR" ]; then if ! rm -r "$XVFB_RUN_TMPDIR"; then error "problem while cleaning up temporary directory" exit 5 fi fi } # Parse the command line. ARGS=$(getopt --options +ae:f:hn:lp:s:w: \ --long auto-servernum,error-file:,auth-file:,help,server-num:,listen-tcp,xauth- protocol:,server-args:,wait: \ --name "$PROGNAME" -- "$@") GETOPT_STATUS=$? if [ $GETOPT_STATUS -ne 0 ]; then error "internal error; getopt exited with status $GETOPT_STATUS" exit 6 fi eval set -- "$ARGS" while :; do case "$1" in -a|--auto-servernum) SERVERNUM=$(find_free_servernum); AUTONUM="yes" ;; -e|--error-file) ERRORFILE="$2"; shift ;; -f|--auth-file) AUTHFILE="$2"; shift ;; -h|--help) SHOWHELP="yes" ;; -n|--server-num) SERVERNUM="$2"; shift ;; -l|--listen-tcp) LISTENTCP="" ;; -p|--xauth-protocol) XAUTHPROTO="$2"; shift ;; -s|--server-args) XVFBARGS="$2"; shift ;; -w|--wait) STARTWAIT="$2"; shift ;; --) shift; break ;; *) error "internal error; getopt permitted \"$1\" unexpectedly" exit 6 ;; esac shift done if [ "$SHOWHELP" ]; then usage exit 0 fi if [ -z "$*" ]; then usage "need a command to run" >&2 exit 2 fi if ! which xauth >/dev/null; then error "xauth command not found" exit 3 fi # tidy up after ourselves trap clean_up EXIT # If the user did not specify an X authorization file to use, set up a temporary # directory to house one. if [ -z "$AUTHFILE" ]; then XVFB_RUN_TMPDIR="$(mktemp -d -t $PROGNAME.XXXXXX)" # Create empty file to avoid xauth warning AUTHFILE=$(tempfile -n "$XVFB_RUN_TMPDIR/Xauthority") fi # Start Xvfb. MCOOKIE=$(mcookie) tries=10 while [ $tries -gt 0 ]; do tries=$(( $tries - 1 )) XAUTHORITY=$AUTHFILE xauth source - << EOF >>"$ERRORFILE" 2>&1 add :$SERVERNUM $XAUTHPROTO $MCOOKIE EOF XAUTHORITY=$AUTHFILE Xvfb ":$SERVERNUM" $XVFBARGS $LISTENTCP >>"$ERRORFILE" 2>&1 & XVFBPID=$! sleep "$STARTWAIT" if kill -0 $XVFBPID 2>/dev/null; then break elif [ -n "$AUTONUM" ]; then # The display is in use so try another one (if '-a' was specified). SERVERNUM=$((SERVERNUM + 1)) SERVERNUM=$(find_free_servernum) continue fi error "Xvfb failed to start" >&2 exit 1 done # Start the command and save its exit status. set +e DISPLAY=:$SERVERNUM XAUTHORITY=$AUTHFILE "$@" 2>&1 RETVAL=$? set -e # Kill Xvfb now that the command has exited. kill $XVFBPID # Return the executed command's exit status. exit $RETVAL # vim:set ai et sts=4 sw=4 tw=80: Here is the modified version of the file: Xvfb-run ======== #!/bin/sh # $Id: xvfb-run 2027 2004-11-16 14:54:16Z branden $ # 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. # If /bin/sh is not a Korn(-like) or BASH shell, adjust the first line in # the script to point to a Korn(-like) or BASH shell. # On some platforms, you will need to install mktemp # in order to get the script to work. # # mktemp can be downloaded from http://www.mktemp.org. # There is also version of mktemp that is part of GNU CoreUtils. PROGNAME=xvfb-run # # Make sure we are running in a Korn(-like) shell. # set +e HOME_DIR=`cd ~ 2>/dev/null` if test $? -ne 0 then echo "$PROGNAME: This script must be run using a Korn or Bash shell." exit 7 fi set -e SERVERNUM=99 XVFB=Xvfb XVFBOPTIONS= AUTHFILE= ERRORFILE=/dev/null STARTWAIT=3 XVFBARGS="-screen 0 640x480x8" LISTENTCP="-nolisten tcp" XAUTHPROTO=. OS_TYPE=$(uname -s) # On AIX/SunOS, adjust arguments that work differently or are not supported. case $OS_TYPE in AIX) XVFB="/usr/bin/X11/X" XVFBOPTIONS="-vfb -force -x abx -x dbe -x GLX" XVFBARGS="-I \"${XVFBARGS}\"" LISTENTCP= ;; SunOS) XVFBARGS="screen 0 640x480x8" LISTENTCP= ;; esac # Query the terminal to establish a default number of columns to use for # displaying messages to the user. This is used only as a fallback in the event # the COLUMNS variable is not set. ($COLUMNS can react to SIGWINCH while the # script is running, and this cannot, only being calculated once.) DEFCOLUMNS=$(stty size 2>/dev/null | awk '{print $2}') || true if ! expr "$DEFCOLUMNS" : "[[:digit:]]\+$" >/dev/null 2>&1; then DEFCOLUMNS=80 fi # Display a message, wrapping lines at the terminal width. message () { echo "$PROGNAME: $*" | fmt -t -w ${COLUMNS:-$DEFCOLUMNS} } # Display an error message. error () { message "error: $*" >&2 } # Display a usage message. usage () { if [ -n "$*" ]; then message "usage error: $*" fi cat <<EOF Usage: $PROGNAME [OPTION ...] COMMAND Run COMMAND (usually an X client) in a virtual X server environment. Options: -a --auto-servernum try to get a free server number, starting at --server-num -e FILE --error-file=FILE file used to store xauth errors and Xvfb output (default: $ERRORFILE) -f FILE --auth-file=FILE file used to store auth cookie (default: ./.Xauthority) -h --help display this usage message and exit -n NUM --server-num=NUM server number to use (default: $SERVERNUM) -l --listen-tcp enable TCP port listening in the X server -p PROTO --xauth-protocol=PROTO X authority protocol name to use (default: xauth command's default) -s ARGS --server-args=ARGS arguments (other than server number and "-nolisten tcp") to pass to the Xvfb server (default: "$XVFBARGS") -w DELAY --wait=DELAY delay in seconds to wait for Xvfb to start before running COMMAND (default: $STARTWAIT) Note: Long options (e.g. --help) may not be available. EOF } # Find a free server number by looking at .X*-lock files in /tmp. find_free_servernum() { # Sadly, the "local" keyword is not POSIX. Leave the next line commented in # the hope Debian Policy eventually changes to allow it in /bin/sh scripts # anyway. #local i i=$SERVERNUM while [ -f /tmp/.X$i-lock ]; do i=$(($i + 1)) done echo $i } # Clean up files clean_up() { if [ -e "$AUTHFILE" ]; then XAUTHORITY=$AUTHFILE xauth remove ":$SERVERNUM" >>"$ERRORFILE" 2>&1 fi if [ -n "$XVFB_RUN_TMPDIR" ]; then if ! rm -r "$XVFB_RUN_TMPDIR"; then error "problem while cleaning up temporary directory" exit 5 fi fi } # Parse the command line. # Check if we are using the GNU version of GETOPT. If we # are, then use GNU specific syntax. Otherwise, use # standard getopt syntax. set +e GNU_GETOPT_INSTALLED=$(getopt --help 2>/dev/null) set -e if [ "$GNU_GETOPT_INSTALLED" != "-- " ]; then GNU_GETOPT_INSTALLED=yes else GNU_GETOPT_INSTALLED=no fi if [ "$GNU_GETOPT_INSTALLED" = "yes" ]; then ARGS=$(getopt --options +ae:f:hn:lp:s:w: \ --long auto-servernum,error-file:,auth-file:,help,server-num:,listen-tcp,xauth- protocol:,server-args:,wait: \ --name "$PROGNAME" -- "$@") GETOPT_STATUS=$? else ARGS=$(getopt ae:f:hn:lp:s:w: "$@") GETOPT_STATUS=$? fi if [ $GETOPT_STATUS -ne 0 ]; then error "internal error; getopt exited with status $GETOPT_STATUS" exit 6 fi eval set -- "$ARGS" while :; do case "$1" in -a|--auto-servernum) SERVERNUM=$(find_free_servernum); AUTONUM="yes" ;; -e|--error-file) ERRORFILE="$2"; shift ;; -f|--auth-file) AUTHFILE="$2"; shift ;; -h|--help) SHOWHELP="yes" ;; -n|--server-num) SERVERNUM="$2"; shift ;; -l|--listen-tcp) LISTENTCP="" ;; -p|--xauth-protocol) XAUTHPROTO="$2"; shift ;; -s|--server-args) XVFBARGS="$2"; shift ;; -w|--wait) STARTWAIT="$2"; shift ;; --) shift; break ;; *) error "internal error; getopt permitted \"$1\" unexpectedly" exit 6 ;; esac shift done if [ "$SHOWHELP" ]; then usage exit 0 fi if [ -z "$*" ]; then usage "need a command to run" >&2 exit 2 fi if ! which xauth >/dev/null; then error "xauth command not found" exit 3 fi # tidy up after ourselves trap clean_up EXIT # If the user did not specify an X authorization file to use, set up a temporary # directory to house one. if [ -z "$AUTHFILE" ]; then XVFB_RUN_TMPDIR="$(mktemp -d -t $PROGNAME.XXXXXX)" set +e TEMPFILE_INSTALLED=$(tempfile --help 2>/dev/null) if [ $? -eq 0 ]; then TEMPFILE_INSTALLED=yes else TEMPFILE_INSTALLED=no fi set -e # Create empty file to avoid xauth warning if [ "$TEMPFILE_INSTALLED" = "yes" ]; then AUTHFILE=$(tempfile -n "$XVFB_RUN_TMPDIR/Xauthority") else AUTHFILE=$(mktemp -p "$XVFB_RUN_TMPDIR" Xauthority.XXXXXX) fi fi # Get the cookie to use. set +e MCOOKIE=$(mcookie 2>/dev/null) # If the mcookie utility is not installed, simulate it. if [ $? -ne 0 ]; then # # Set the random device to /dev/random if you need very secure # random numbers. Otherwise, /dev/urandom will be fine. # RANDOM_DEVICE=/dev/urandom MCOOKIE=$(od -X -A n -N 16 $RANDOM_DEVICE | tr -d '\011\040') fi set -e # Start Xvfb. tries=10 while [ $tries -gt 0 ]; do tries=$(( $tries - 1 )) XAUTHORITY=$AUTHFILE xauth source - << EOF >>"$ERRORFILE" 2>&1 add :$SERVERNUM $XAUTHPROTO $MCOOKIE EOF XAUTHORITY=$AUTHFILE $XVFB $XVFBOPTIONS ":$SERVERNUM" \ $XVFBARGS $LISTENTCP >>"$ERRORFILE" 2>&1 & XVFBPID=$! sleep "$STARTWAIT" if kill -0 $XVFBPID 2>/dev/null; then break elif [ -n "$AUTONUM" ]; then # The display is in use so try another one (if '-a' was specified). SERVERNUM=$((SERVERNUM + 1)) SERVERNUM=$(find_free_servernum) continue fi error "Xvfb failed to start" >&2 exit 1 done # Start the command and save its exit status. set +e DISPLAY=:$SERVERNUM XAUTHORITY=$AUTHFILE "$@" 2>&1 RETVAL=$? set -e # Kill Xvfb now that the command has exited. kill $XVFBPID # Return the executed command's exit status. exit $RETVAL # vim:set ai et sts=4 sw=4 tw=80: Here is a context difference of the changes I made: *** xvfb-run.orig Mon Jan 31 15:09:04 2011 --- xvfb-run Tue Feb 08 14:49:22 2011 *************** *** 9,18 **** # 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 AUTHFILE= ERRORFILE=/dev/null STARTWAIT=3 --- 9,44 ---- # If anyone is using this to build a Debian package, make sure the package # Build-Depends on xvfb, xbase-clients, and xfonts-base. ! # If /bin/sh is not a Korn(-like) or BASH shell, adjust the first line in ! # the script to point to a Korn(-like) or BASH shell. ! ! # On some platforms, you will need to install mktemp ! # in order to get the script to work. ! # ! # mktemp can be downloaded from http://www.mktemp.org. ! # There is also version of mktemp that is part of GNU CoreUtils. PROGNAME=xvfb-run + + # + # Make sure we are running in a Korn(-like) shell. + # + + set +e + + HOME_DIR=`cd ~ 2>/dev/null` + + if test $? -ne 0 + then + echo "$PROGNAME: This script must be run using a Korn or Bash shell." + exit 7 + fi + + set -e + SERVERNUM=99 + XVFB=Xvfb + XVFBOPTIONS= AUTHFILE= ERRORFILE=/dev/null STARTWAIT=3 *************** *** 20,25 **** --- 46,65 ---- LISTENTCP="-nolisten tcp" XAUTHPROTO=. + OS_TYPE=$(uname -s) + + # On AIX/SunOS, adjust arguments that work differently or are not supported. + case $OS_TYPE in + AIX) XVFB="/usr/bin/X11/X" + XVFBOPTIONS="-vfb -force -x abx -x dbe -x GLX" + XVFBARGS="-I \"${XVFBARGS}\"" + LISTENTCP= + ;; + SunOS) XVFBARGS="screen 0 640x480x8" + LISTENTCP= + ;; + esac + # Query the terminal to establish a default number of columns to use for # displaying messages to the user. This is used only as a fallback in the event # the COLUMNS variable is not set. ($COLUMNS can react to SIGWINCH while the *************** *** 64,69 **** --- 104,111 ---- (default: "$XVFBARGS") -w DELAY --wait=DELAY delay in seconds to wait for Xvfb to start before running COMMAND (default: $STARTWAIT) + + Note: Long options (e.g. --help) may not be available. EOF } *************** *** 95,104 **** } # Parse the command line. ! ARGS=$(getopt --options +ae:f:hn:lp:s:w: \ ! --long auto-servernum,error-file:,auth-file:,help,server-num:,listen-tcp,xauth- protocol:,server-args:,wait: \ ! --name "$PROGNAME" -- "$@") ! GETOPT_STATUS=$? if [ $GETOPT_STATUS -ne 0 ]; then error "internal error; getopt exited with status $GETOPT_STATUS" --- 137,166 ---- } # Parse the command line. ! ! # Check if we are using the GNU version of GETOPT. If we ! # are, then use GNU specific syntax. Otherwise, use ! # standard getopt syntax. ! ! set +e ! GNU_GETOPT_INSTALLED=$(getopt --help 2>/dev/null) ! set -e ! ! if [ "$GNU_GETOPT_INSTALLED" != "-- " ]; then ! GNU_GETOPT_INSTALLED=yes ! else ! GNU_GETOPT_INSTALLED=no ! fi ! ! if [ "$GNU_GETOPT_INSTALLED" = "yes" ]; then ! ARGS=$(getopt --options +ae:f:hn:lp:s:w: \ ! --long auto-servernum,error-file:,auth-file:,help,server-num:,listen-tcp,xauth- protocol:,server-args:,wait: \ ! --name "$PROGNAME" -- "$@") ! GETOPT_STATUS=$? ! else ! ARGS=$(getopt ae:f:hn:lp:s:w: "$@") ! GETOPT_STATUS=$? ! fi if [ $GETOPT_STATUS -ne 0 ]; then error "internal error; getopt exited with status $GETOPT_STATUS" *************** *** 148,166 **** # directory to house one. if [ -z "$AUTHFILE" ]; then XVFB_RUN_TMPDIR="$(mktemp -d -t $PROGNAME.XXXXXX)" # Create empty file to avoid xauth warning ! AUTHFILE=$(tempfile -n "$XVFB_RUN_TMPDIR/Xauthority") fi # Start Xvfb. - MCOOKIE=$(mcookie) tries=10 while [ $tries -gt 0 ]; do tries=$(( $tries - 1 )) XAUTHORITY=$AUTHFILE xauth source - << EOF >>"$ERRORFILE" 2>&1 add :$SERVERNUM $XAUTHPROTO $MCOOKIE EOF ! XAUTHORITY=$AUTHFILE Xvfb ":$SERVERNUM" $XVFBARGS $LISTENTCP >>"$ERRORFILE" 2>&1 & XVFBPID=$! sleep "$STARTWAIT" --- 210,262 ---- # directory to house one. if [ -z "$AUTHFILE" ]; then XVFB_RUN_TMPDIR="$(mktemp -d -t $PROGNAME.XXXXXX)" + + set +e + TEMPFILE_INSTALLED=$(tempfile --help 2>/dev/null) + + if [ $? -eq 0 ]; then + TEMPFILE_INSTALLED=yes + else + TEMPFILE_INSTALLED=no + fi + set -e + # Create empty file to avoid xauth warning ! ! if [ "$TEMPFILE_INSTALLED" = "yes" ]; then ! AUTHFILE=$(tempfile -n "$XVFB_RUN_TMPDIR/Xauthority") ! else ! AUTHFILE=$(mktemp -p "$XVFB_RUN_TMPDIR" Xauthority.XXXXXX) ! fi fi + # Get the cookie to use. + set +e + MCOOKIE=$(mcookie 2>/dev/null) + + # If the mcookie utility is not installed, simulate it. + + if [ $? -ne 0 ]; then + # + # Set the random device to /dev/random if you need very secure + # random numbers. Otherwise, /dev/urandom will be fine. + # + + RANDOM_DEVICE=/dev/urandom + + MCOOKIE=$(od -X -A n -N 16 $RANDOM_DEVICE | tr -d '\011\040') + fi + set -e + # Start Xvfb. tries=10 while [ $tries -gt 0 ]; do tries=$(( $tries - 1 )) XAUTHORITY=$AUTHFILE xauth source - << EOF >>"$ERRORFILE" 2>&1 add :$SERVERNUM $XAUTHPROTO $MCOOKIE EOF ! XAUTHORITY=$AUTHFILE $XVFB $XVFBOPTIONS ":$SERVERNUM" \ ! $XVFBARGS $LISTENTCP >>"$ERRORFILE" 2>&1 & XVFBPID=$! sleep "$STARTWAIT" I know that the Xvfb utility also runs on HP-UX (and possibly other) systems. If you know of a way to get a shell account on an HP-UX system, let me know and I would be willing to try and get it running on HP-UX. If you have any questions, need more details, do not hesitate to ask. Thanks, Joel -- To UNSUBSCRIBE, email to debian-bugs-dist-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org