xref: /OK3568_Linux_fs/external/xserver/debian/local/xvfb-run (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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.
6#
7# If anyone is using this to build a Debian package, make sure the package
8# Build-Depends on xvfb and xauth.
9
10set -e
11
12PROGNAME=xvfb-run
13SERVERNUM=99
14AUTHFILE=
15ERRORFILE=/dev/null
16XVFBARGS="-screen 0 1280x1024x24"
17LISTENTCP="-nolisten tcp"
18XAUTHPROTO=.
19
20# Query the terminal to establish a default number of columns to use for
21# displaying messages to the user.  This is used only as a fallback in the event
22# the COLUMNS variable is not set.  ($COLUMNS can react to SIGWINCH while the
23# script is running, and this cannot, only being calculated once.)
24DEFCOLUMNS=$(stty size 2>/dev/null | awk '{print $2}') || true
25case "$DEFCOLUMNS" in
26    *[!0-9]*|'') DEFCOLUMNS=80 ;;
27esac
28
29# Display a message, wrapping lines at the terminal width.
30message () {
31    echo "$PROGNAME: $*" | fmt -t -w ${COLUMNS:-$DEFCOLUMNS}
32}
33
34# Display an error message.
35error () {
36    message "error: $*" >&2
37}
38
39# Display a usage message.
40usage () {
41    if [ -n "$*" ]; then
42        message "usage error: $*"
43    fi
44    cat <<EOF
45Usage: $PROGNAME [OPTION ...] COMMAND
46Run COMMAND (usually an X client) in a virtual X server environment.
47Options:
48-a        --auto-servernum          try to get a free server number, starting at
49                                    --server-num
50-e FILE   --error-file=FILE         file used to store xauth errors and Xvfb
51                                    output (default: $ERRORFILE)
52-f FILE   --auth-file=FILE          file used to store auth cookie
53                                    (default: ./.Xauthority)
54-h        --help                    display this usage message and exit
55-n NUM    --server-num=NUM          server number to use (default: $SERVERNUM)
56-l        --listen-tcp              enable TCP port listening in the X server
57-p PROTO  --xauth-protocol=PROTO    X authority protocol name to use
58                                    (default: xauth command's default)
59-s ARGS   --server-args=ARGS        arguments (other than server number and
60                                    "-nolisten tcp") to pass to the Xvfb server
61                                    (default: "$XVFBARGS")
62EOF
63}
64
65# Find a free server number by looking at .X*-lock files in /tmp.
66find_free_servernum() {
67    # Sadly, the "local" keyword is not POSIX.  Leave the next line commented in
68    # the hope Debian Policy eventually changes to allow it in /bin/sh scripts
69    # anyway.
70    #local i
71
72    i=$SERVERNUM
73    while [ -f /tmp/.X$i-lock ]; do
74        i=$(($i + 1))
75    done
76    echo $i
77}
78
79# Clean up files
80clean_up() {
81    if [ -e "$AUTHFILE" ]; then
82        XAUTHORITY=$AUTHFILE xauth remove ":$SERVERNUM" >>"$ERRORFILE" 2>&1
83    fi
84    if [ -n "$XVFB_RUN_TMPDIR" ]; then
85        if ! rm -r "$XVFB_RUN_TMPDIR"; then
86            error "problem while cleaning up temporary directory"
87            exit 5
88        fi
89    fi
90    if [ -n "$XVFBPID" ]; then
91        kill "$XVFBPID" >>"$ERRORFILE" 2>&1
92    fi
93}
94
95# Parse the command line.
96ARGS=$(getopt --options +ae:f:hn:lp:s:w: \
97       --long auto-servernum,error-file:,auth-file:,help,server-num:,listen-tcp,xauth-protocol:,server-args:,wait: \
98       --name "$PROGNAME" -- "$@")
99GETOPT_STATUS=$?
100
101if [ $GETOPT_STATUS -ne 0 ]; then
102    error "internal error; getopt exited with status $GETOPT_STATUS"
103    exit 6
104fi
105
106eval set -- "$ARGS"
107
108while :; do
109    case "$1" in
110        -a|--auto-servernum) SERVERNUM=$(find_free_servernum); AUTONUM="yes" ;;
111        -e|--error-file) ERRORFILE="$2"; shift ;;
112        -f|--auth-file) AUTHFILE="$2"; shift ;;
113        -h|--help) SHOWHELP="yes" ;;
114        -n|--server-num) SERVERNUM="$2"; shift ;;
115        -l|--listen-tcp) LISTENTCP="" ;;
116        -p|--xauth-protocol) XAUTHPROTO="$2"; shift ;;
117        -s|--server-args) XVFBARGS="$2"; shift ;;
118        -w|--wait) shift ;;
119        --) shift; break ;;
120        *) error "internal error; getopt permitted \"$1\" unexpectedly"
121           exit 6
122           ;;
123    esac
124    shift
125done
126
127if [ "$SHOWHELP" ]; then
128    usage
129    exit 0
130fi
131
132if [ -z "$*" ]; then
133    usage "need a command to run" >&2
134    exit 2
135fi
136
137if ! command -v xauth >/dev/null; then
138    error "xauth command not found"
139    exit 3
140fi
141
142# tidy up after ourselves
143trap clean_up EXIT
144
145# If the user did not specify an X authorization file to use, set up a temporary
146# directory to house one.
147if [ -z "$AUTHFILE" ]; then
148    XVFB_RUN_TMPDIR="$(mktemp -d -t $PROGNAME.XXXXXX)"
149    AUTHFILE="$XVFB_RUN_TMPDIR/Xauthority"
150    # Create empty file to avoid xauth warning
151    touch "$AUTHFILE"
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 "$@"
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:
192