Imported Debian patch 2:1.15.1-0ubuntu2.6
[deb_xorg-server.git] / debian / local / xvfb-run
CommitLineData
7217e0ca
ML
1#!/bin/sh
2
3# This script starts an instance of Xvfb, the "fake" X server, runs a command
4# with that server available, and kills the X server when done. The return
5# value of the command becomes the return value of this script, except in cases
6# where this script encounters an error.
7#
8# If anyone is using this to build a Debian package, make sure the package
9# Build-Depends on xvfb and xauth.
10
11set -e
12
13PROGNAME=xvfb-run
14SERVERNUM=99
15AUTHFILE=
16ERRORFILE=/dev/null
17XVFBARGS="-screen 0 640x480x8"
18LISTENTCP="-nolisten tcp"
19XAUTHPROTO=.
20
21# Query the terminal to establish a default number of columns to use for
22# displaying messages to the user. This is used only as a fallback in the event
23# the COLUMNS variable is not set. ($COLUMNS can react to SIGWINCH while the
24# script is running, and this cannot, only being calculated once.)
25DEFCOLUMNS=$(stty size 2>/dev/null | awk '{print $2}') || true
26if ! expr "$DEFCOLUMNS" : "[[:digit:]]\+$" >/dev/null 2>&1; then
27 DEFCOLUMNS=80
28fi
29
30# Display a message, wrapping lines at the terminal width.
31message () {
32 echo "$PROGNAME: $*" | fmt -t -w ${COLUMNS:-$DEFCOLUMNS}
33}
34
35# Display an error message.
36error () {
37 message "error: $*" >&2
38}
39
40# Display a usage message.
41usage () {
42 if [ -n "$*" ]; then
43 message "usage error: $*"
44 fi
45 cat <<EOF
46Usage: $PROGNAME [OPTION ...] COMMAND
47Run COMMAND (usually an X client) in a virtual X server environment.
48Options:
49-a --auto-servernum try to get a free server number, starting at
50 --server-num
51-e FILE --error-file=FILE file used to store xauth errors and Xvfb
52 output (default: $ERRORFILE)
53-f FILE --auth-file=FILE file used to store auth cookie
54 (default: ./.Xauthority)
55-h --help display this usage message and exit
56-n NUM --server-num=NUM server number to use (default: $SERVERNUM)
57-l --listen-tcp enable TCP port listening in the X server
58-p PROTO --xauth-protocol=PROTO X authority protocol name to use
59 (default: xauth command's default)
60-s ARGS --server-args=ARGS arguments (other than server number and
61 "-nolisten tcp") to pass to the Xvfb server
62 (default: "$XVFBARGS")
63EOF
64}
65
66# Find a free server number by looking at .X*-lock files in /tmp.
67find_free_servernum() {
68 # Sadly, the "local" keyword is not POSIX. Leave the next line commented in
69 # the hope Debian Policy eventually changes to allow it in /bin/sh scripts
70 # anyway.
71 #local i
72
73 i=$SERVERNUM
74 while [ -f /tmp/.X$i-lock ]; do
75 i=$(($i + 1))
76 done
77 echo $i
78}
79
80# Clean up files
81clean_up() {
82 if [ -e "$AUTHFILE" ]; then
83 XAUTHORITY=$AUTHFILE xauth remove ":$SERVERNUM" >>"$ERRORFILE" 2>&1
84 fi
85 if [ -n "$XVFB_RUN_TMPDIR" ]; then
86 if ! rm -r "$XVFB_RUN_TMPDIR"; then
87 error "problem while cleaning up temporary directory"
88 exit 5
89 fi
90 fi
91 if [ -n "$XVFBPID" ]; then
92 kill "$XVFBPID" >>"$ERRORFILE" 2>&1
93 fi
94}
95
96# Parse the command line.
97ARGS=$(getopt --options +ae:f:hn:lp:s:w: \
98 --long auto-servernum,error-file:,auth-file:,help,server-num:,listen-tcp,xauth-protocol:,server-args:,wait: \
99 --name "$PROGNAME" -- "$@")
100GETOPT_STATUS=$?
101
102if [ $GETOPT_STATUS -ne 0 ]; then
103 error "internal error; getopt exited with status $GETOPT_STATUS"
104 exit 6
105fi
106
107eval set -- "$ARGS"
108
109while :; do
110 case "$1" in
111 -a|--auto-servernum) SERVERNUM=$(find_free_servernum); AUTONUM="yes" ;;
112 -e|--error-file) ERRORFILE="$2"; shift ;;
113 -f|--auth-file) AUTHFILE="$2"; shift ;;
114 -h|--help) SHOWHELP="yes" ;;
115 -n|--server-num) SERVERNUM="$2"; shift ;;
116 -l|--listen-tcp) LISTENTCP="" ;;
117 -p|--xauth-protocol) XAUTHPROTO="$2"; shift ;;
118 -s|--server-args) XVFBARGS="$2"; shift ;;
119 -w|--wait) shift ;;
120 --) shift; break ;;
121 *) error "internal error; getopt permitted \"$1\" unexpectedly"
122 exit 6
123 ;;
124 esac
125 shift
126done
127
128if [ "$SHOWHELP" ]; then
129 usage
130 exit 0
131fi
132
133if [ -z "$*" ]; then
134 usage "need a command to run" >&2
135 exit 2
136fi
137
138if ! which xauth >/dev/null; then
139 error "xauth command not found"
140 exit 3
141fi
142
143# tidy up after ourselves
144trap clean_up EXIT
145
146# If the user did not specify an X authorization file to use, set up a temporary
147# directory to house one.
148if [ -z "$AUTHFILE" ]; then
149 XVFB_RUN_TMPDIR="$(mktemp -d -t $PROGNAME.XXXXXX)"
150 # Create empty file to avoid xauth warning
151 AUTHFILE=$(tempfile -n "$XVFB_RUN_TMPDIR/Xauthority")
152fi
153
154# Start Xvfb.
155MCOOKIE=$(mcookie)
156tries=10
157while [ $tries -gt 0 ]; do
158 tries=$(( $tries - 1 ))
159 XAUTHORITY=$AUTHFILE xauth source - << EOF >>"$ERRORFILE" 2>&1
160add :$SERVERNUM $XAUTHPROTO $MCOOKIE
161EOF
162 # handle SIGUSR1 so Xvfb knows to send a signal when it's ready to accept
163 # connections
164 trap : USR1
165 (trap '' USR1; exec Xvfb ":$SERVERNUM" $XVFBARGS $LISTENTCP -auth $AUTHFILE >>"$ERRORFILE" 2>&1) &
166 XVFBPID=$!
167
168 wait || :
169 if kill -0 $XVFBPID 2>/dev/null; then
170 break
171 elif [ -n "$AUTONUM" ]; then
172 # The display is in use so try another one (if '-a' was specified).
173 SERVERNUM=$((SERVERNUM + 1))
174 SERVERNUM=$(find_free_servernum)
175 continue
176 fi
177 error "Xvfb failed to start" >&2
178 XVFBPID=
179 exit 1
180done
181
182# Start the command and save its exit status.
183set +e
184DISPLAY=:$SERVERNUM XAUTHORITY=$AUTHFILE "$@" 2>&1
185RETVAL=$?
186set -e
187
188# Return the executed command's exit status.
189exit $RETVAL
190
191# vim:set ai et sts=4 sw=4 tw=80: