From 2ddbc71e2bad4c287c28d4e8e4048db8fb801eb7 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Wed, 1 Oct 2014 19:26:52 -0400 Subject: [PATCH] Testcases: Use Xephyr instead of XDummy Replace the XDummy script with Xephyr. This is done because of some changes in the Xorg server that make XDummy difficult to use. Rename library internal variables and function names to replace "xdummy" with "xserver" to show this change (except for renaming the package and lib file for better git history). Rename the switch `--keep-xdummy-output` to `--keep-xserver-output`. This switch should now be rarely used because Xephyr requires less set up. Replace "xdummy" with "xephyr" in comments and utility help information. Update docs to show the new dependency. fixes #1367 --- docs/testsuite | 20 +- testcases/.gitignore | 1 - testcases/Xdummy | 1930 ----------------------------- testcases/complete-run.pl | 26 +- testcases/lib/StartXDummy.pm | 41 +- testcases/t/112-floating-resize.t | 2 +- 6 files changed, 43 insertions(+), 1977 deletions(-) delete mode 100755 testcases/Xdummy diff --git a/docs/testsuite b/docs/testsuite index 6c3a36d9..61a72219 100644 --- a/docs/testsuite +++ b/docs/testsuite @@ -74,6 +74,9 @@ client, simply called +cpan+. It comes with every Perl installation and can be used to install the testsuite. Many users prefer to use the more modern +cpanminus+ instead, though (because it asks no questions and just works): +The tests additionally require +Xephyr(1)+ to run a nested X server. Install ++xserver-xephyr+ on Debian or +xorg-xserver-xephyr+ on Arch Linux. + .Installing testsuite dependencies using cpanminus (preferred) -------------------------------------------------------------------------------- $ cd ~/i3/testcases @@ -102,7 +105,7 @@ more testcases. Also, it takes care of starting up a separate instance of i3 with an appropriate configuration file and creates a folder for each run containing the appropriate i3 logfile for each testcase. The latest folder can always be found under the symlink +latest/+. Unless told differently, it will -run the tests on a separate X server instance (using the Xdummy script). +run the tests on a separate X server instance (using Xephyr). .Example invocation of complete-run.pl+ --------------------------------------- @@ -146,12 +149,11 @@ $ less latest/i3-log-for-04-floating.t If your attempt to run the tests with a bare call to ./complete-run.pl fails, try this: --------------------------------------------------- -$ ./complete-run.pl --parallel=1 --keep-xdummy-output +$ ./complete-run.pl --parallel=1 --keep-xserver-output --------------------------------------------------- -One common cause of failures is not having the X dummy server module -installed. Under Debian and Ubuntu this is the package -+xserver-xorg-video-dummy+. +This will show the output of Xephyr, which is the X server implementation we +use for testing. ==== IPC interface @@ -175,10 +177,9 @@ manager. === Filesystem structure In the git root of i3, the testcases live in the folder +testcases+. This -folder contains the +complete-run.pl+ and +Xdummy+ scripts and a base -configuration file which will be used for the tests. The different testcases -(their file extension is .t, not .pl) themselves can be found in the -conventionally named subfolder +t+: +folder contains the +complete-run.pl+ and a base configuration file which will +be used for the tests. The different testcases (their file extension is .t, not +.pl) themselves can be found in the conventionally named subfolder +t+: .Filesystem structure -------------------------------------------- @@ -197,7 +198,6 @@ conventionally named subfolder +t+: │   │   ├── omitted for brevity │   │   ├── ... │   │   └── 74-regress-focus-toggle.t -│   └── Xdummy -------------------------------------------- == Anatomy of a testcase diff --git a/testcases/.gitignore b/testcases/.gitignore index 294f0dae..c11c5563 100644 --- a/testcases/.gitignore +++ b/testcases/.gitignore @@ -8,4 +8,3 @@ inc META.yml i3-cfg-for-* - -Xdummy.so diff --git a/testcases/Xdummy b/testcases/Xdummy deleted file mode 100755 index 638a7b3b..00000000 --- a/testcases/Xdummy +++ /dev/null @@ -1,1930 +0,0 @@ -#!/bin/sh -# ---------------------------------------------------------------------- -# Copyright (C) 2005-2010 Karl J. Runge -# All rights reserved. -# -# This file is part of Xdummy. -# -# Xdummy is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or (at -# your option) any later version. -# -# Xdummy is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Xdummy; if not, write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA -# or see . -# ---------------------------------------------------------------------- -# -# -# Xdummy: an LD_PRELOAD hack to run a stock Xorg(1) or XFree86(1) server -# with the "dummy" video driver to make it avoid Linux VT switching, etc. -# -# Run "Xdummy -help" for more info. -# -install="" -uninstall="" -runit=1 -prconf="" -notweak="" -root="" -nosudo="" -xserver="" -geom="" -nomodelines="" -depth="" -debug="" -strace="" -cmdline_config="" - -PATH=$PATH:/bin:/usr/bin -export PATH - -program=`basename "$0"` - -help () { - ${PAGER:-more} << END -$program: - - A hack to run a stock Xorg(1) or XFree86(1) X server with the "dummy" - (RAM-only framebuffer) video driver such that it AVOIDS the Linux VT - switching, opening device files in /dev, keyboard and mouse conflicts, - and other problems associated with the normal use of "dummy". - - In other words, it tries to make Xorg/XFree86 with the "dummy" - device driver act more like Xvfb(1). - - The primary motivation for the Xdummy script is to provide a virtual X - server for x11vnc but with more features than Xvfb (or Xvnc); however - it could be used for other reasons (e.g. better automated testing - than with Xvfb.) One nice thing is the dummy server supports RANDR - dynamic resizing while Xvfb does not. - - So, for example, x11vnc+Xdummy terminal services are a little better - than x11vnc+Xvfb. - - To achieve this, while running the real Xserver $program intercepts - system and library calls via the LD_PRELOAD method and modifies - the behavior to make it work correctly (e.g. avoid the VT stuff.) - LD_PRELOAD tricks are usually "clever hacks" and so might not work - in all situations or break when something changes. - - WARNING: Take care in using Xdummy, although it never has it is - possible that it could damage hardware. One can use the -prconf - option to have it print out the xorg.conf config that it would use - and then inspect it carefully before actually using it. - - This program no longer needs to be run as root as of 12/2009. - However, if there are problems for certain situations (usually older - servers) it may perform better if run as root (use the -root option.) - When running as root remember the previous paragraph and that Xdummy - comes without any warranty. - - gcc/cc and other build tools are required for this script to be able - to compile the LD_PRELOAD shared object. Be sure they are installed - on the system. See -install and -uninstall described below. - - Your Linux distribution may not install the dummy driver by default, - e.g: - - /usr/lib/xorg/modules/drivers/dummy_drv.so - - some have it in a package named xserver-xorg-video-dummy you that - need to install. - -Usage: - - $program <${program}-args> - - (actually, the arguments can be supplied in any order.) - -Examples: - - $program -install - - $program :1 - - $program -debug :1 - - $program -tmpdir ~/mytmp :1 -nolisten tcp - -startx example: - - startx -e bash -- $program :2 -depth 16 - - (if startx needs to be run as root, you can su(1) to a normal - user in the bash shell and then launch ~/.xinitrc or ~/.xsession, - gnome-session, startkde, startxfce4, etc.) - -xdm example: - - xdm -config /usr/local/dummy/xdm-config -nodaemon - - where the xdm-config file has line: - - DisplayManager.servers: /usr/local/dummy/Xservers - - and /usr/local/dummy/Xservers has lines: - - :1 local /usr/local/dummy/Xdummy :1 -debug - :2 local /usr/local/dummy/Xdummy :2 -debug - - (-debug is optional) - -gdm/kdm example: - - TBD. - -Root permission and x11vnc: - - Update: as of 12/2009 this program no longer must be run as root. - So try it as non-root before running it as root and/or the - following schemes. - - In some circumstances X server program may need to be run as root. - If so, one could run x11vnc as root with -unixpw (it switches - to the user that logs in) and that may be OK, some other ideas: - - - add this to sudo via visudo: - - ALL ALL = NOPASSWD: /usr/local/bin/Xdummy - - - use this little suid wrapper: -/* - * xdummy.c - * - cc -o ./xdummy xdummy.c - sudo cp ./xdummy /usr/local/bin/xdummy - sudo chown root:root /usr/local/bin/xdummy - sudo chmod u+s /usr/local/bin/xdummy - * - */ -#include -#include -#include -#include - -int main (int argc, char *argv[]) { - extern char **environ; - char str[100]; - sprintf(str, "XDUMMY_UID=%d", (int) getuid()); - putenv(str); - setuid(0); - setgid(0); - execv("/usr/local/bin/Xdummy", argv); - exit(1); - return 1; -} - - -Options: - - ${program}-args: - - -install Compile the LD_PRELOAD shared object and install it - next to the $program script file as: - - $0.so - - When that file exists it is used as the LD_PRELOAD - shared object without recompiling. Otherwise, - each time $program is run the LD_PRELOAD shared - object is compiled as a file in /tmp (or -tmpdir) - - If you set the environment variable - INTERPOSE_GETUID=1 when building, then when - $program is run as an ordinary user, the shared - object will interpose getuid() calls and pretend - to be root. Otherwise it doesn't pretend to - be root. - - You can also set the CFLAGS environment variable - to anything else you want on the compile cmdline. - - -uninstall Remove the file: - - $0.so - - The LD_PRELOAD shared object will then be compiled - each time this program is run. - - The X server is not started under -install, -uninstall, or -prconf. - - - :N The DISPLAY (e.g. :15) is often the first - argument. It is passed to the real X server and - also used by the Xdummy script as an identifier. - - -geom geom1[,geom2...] Take the geometry (e.g. 1024x768) or list - of geometries and insert them into the Screen - section of the tweaked X server config file. - Use this to have a different geometry than the - one(s) in the system config file. - - The option -geometry can be used instead of -geom; - x11vnc calls Xdummy and Xvfb this way. - - -nomodelines When you specify -geom/-geometry, $program will - create Modelines for each geometry and put them - in the Monitor section. If you do not want this - then supply -nomodelines. - - -depth n Use pixel color depth n (e.g. 8, 16, or 24). This - makes sure the X config file has a Screen.Display - subsection of this depth. Note this option is - ALSO passed to the X server. - - -DEPTH n Same as -depth, except not passed to X server. - - -tmpdir dir Specify a temporary directory, owned by you and - only writable by you. This is used in place of - /tmp/Xdummy.\$USER/.. to place the $program.so - shared object, tweaked config files, etc. - - -nonroot Run in non-root mode (working 12/2009, now default) - - -root Run as root (may still be needed in some - environments.) Same as XDUMMY_RUN_AS_ROOT=1. - - -nosudo Do not try to use sudo(1) when re-running as root, - use su(1) instead. - - -xserver path Specify the path to the Xserver to use. Default - is to try "Xorg" first and then "XFree86". If - those are not in \$PATH, it tries these locations: - /usr/bin/Xorg - /usr/X11R6/bin/Xorg - /usr/X11R6/bin/XFree86 - - -n Do not run the command to start the X server, - just show the command that $program would run. - The LD_PRELOAD shared object will be built, - if needed. Also note any XDUMMY* environment - variables that need to be set. - - -prconf Print, to stdout, the tweaked Xorg/XFree86 - config file (-config and -xf86config server - options, respectively.) The Xserver is not - started. - - -notweak Do not tweak (modify) the Xorg/XFree86 config file - (system or server command line) at all. The -geom - and similar config file modifications are ignored. - - It is up to you to make sure it is a working - config file (e.g. "dummy" driver, etc.) - Perhaps you want to use a file based on the - -prconf output. - - -debug Extra debugging output. - - -strace strace(1) the Xserver process (for troubleshooting.) - -ltrace ltrace(1) instead of strace (can be slow.) - - -h, -help Print out this help. - - - Xserver-args: - - Most of the Xorg and XFree86 options will work and are simply - passed along if you supply them. Important ones that may be - supplied if missing: - - :N X Display number for server to use. - - vtNN Linux virtual terminal (VT) to use (a VT is currently - still used, just not switched to and from.) - - -config file Driver "dummy" tweaked config file, a - -xf86config file number of settings are tweaked besides Driver. - - If -config/-xf86config is not given, the system one - (e.g. /etc/X11/xorg.conf) is used. If the system one cannot be - found, a built-in one is used. Any settings in the config file - that are not consistent with "dummy" mode will be overwritten - (unless -notweak is specified.) - - Use -config xdummy-builtin to force usage of the builtin config. - - If "file" is only a basename (e.g. "xorg.dummy.conf") with no /'s, - then no tweaking of it is done: the X server will look for that - basename via its normal search algorithm. If the found file does - not refer to the "dummy" driver, etc, then the X server will fail. - -Notes: - - The Xorg/XFree86 "dummy" driver is currently undocumented. It works - well in this mode, but it is evidently not intended for end-users. - So it could be removed or broken at any time. - - If the display Xserver-arg (e.g. :1) is not given, or ":" is given - that indicates $program should try to find a free one (based on - tcp ports.) - - If the display virtual terminal, VT, (e.g. vt9) is not given that - indicates $program should try to find a free one (or guess a high one.) - - This program is not completely secure WRT files in /tmp (but it tries - to a good degree.) Better is to use the -tmpdir option to supply a - directory only writable by you. Even better is to get rid of users - on the local machine you do not trust :-) - - Set XDUMMY_SET_XV=1 to turn on debugging output for this script. - -END -} - -warn() { - echo "$*" 1>&2 -} - -if [ "X$XDUMMY_SET_XV" != "X" ]; then - set -xv -fi - -if [ "X$XDUMMY_UID" = "X" ]; then - XDUMMY_UID=`id -u` - export XDUMMY_UID -fi -if [ "X$XDUMMY_UID" = "X0" ]; then - if [ "X$SUDO_UID" != "X" ]; then - XDUMMY_UID=$SUDO_UID - export XDUMMY_UID - fi -fi - -# check if root=1 first: -# -if [ "X$XDUMMY_RUN_AS_ROOT" = "X1" ]; then - root=1 -fi -for arg in $* -do - if [ "X$arg" = "X-nonroot" ]; then - root="" - elif [ "X$arg" = "X-root" ]; then - root=1 - fi -done - -# See if it really needs to be run as root: -# -if [ "X$XDUMMY_SU_EXEC" = "X" -a "X$root" = "X1" -a "X`id -u`" != "X0" ]; then - # this is to prevent infinite loop in case su/sudo doesn't work: - XDUMMY_SU_EXEC=1 - export XDUMMY_SU_EXEC - - dosu=1 - nosudo="" - - for arg in $* - do - if [ "X$arg" = "X-nonroot" ]; then - dosu="" - elif [ "X$arg" = "X-nosudo" ]; then - nosudo="1" - elif [ "X$arg" = "X-help" ]; then - dosu="" - elif [ "X$arg" = "X-h" ]; then - dosu="" - elif [ "X$arg" = "X-install" ]; then - dosu="" - elif [ "X$arg" = "X-uninstall" ]; then - dosu="" - elif [ "X$arg" = "X-n" ]; then - dosu="" - elif [ "X$arg" = "X-prconf" ]; then - dosu="" - fi - done - if [ $dosu ]; then - # we need to restart it with su/sudo: - if type sudo > /dev/null 2>&1; then - : - else - nosudo=1 - fi - if [ "X$nosudo" = "X" ]; then - warn "$program: supply the sudo password to restart as root:" - if [ "X$XDUMMY_UID" != "X" ]; then - exec sudo $0 -uid $XDUMMY_UID "$@" - else - exec sudo $0 "$@" - fi - else - warn "$program: supply the root password to restart as root:" - if [ "X$XDUMMY_UID" != "X" ]; then - exec su -c "$0 -uid $XDUMMY_UID $*" - else - exec su -c "$0 $*" - fi - fi - # DONE: - exit - fi -fi - -# This will hold the X display, e.g. :20 -# -disp="" -args="" -cmdline_config="" - -# Process Xdummy args: -# -while [ "X$1" != "X" ] -do - if [ "X$1" = "X-config" -o "X$1" = "X-xf86config" ]; then - cmdline_config="$2" - fi - case $1 in - ":"*) disp=$1 - ;; - "-install") install=1; runit="" - ;; - "-uninstall") uninstall=1; runit="" - ;; - "-n") runit="" - ;; - "-no") runit="" - ;; - "-norun") runit="" - ;; - "-prconf") prconf=1; runit="" - ;; - "-notweak") notweak=1 - ;; - "-noconf") notweak=1 - ;; - "-nonroot") root="" - ;; - "-root") root=1 - ;; - "-nosudo") nosudo=1 - ;; - "-xserver") xserver="$2"; shift - ;; - "-uid") XDUMMY_UID="$2"; shift - export XDUMMY_UID - ;; - "-geom") geom="$2"; shift - ;; - "-geometry") geom="$2"; shift - ;; - "-nomodelines") nomodelines=1 - ;; - "-depth") depth="$2"; args="$args -depth $2"; - shift - ;; - "-DEPTH") depth="$2"; shift - ;; - "-tmpdir") XDUMMY_TMPDIR="$2"; shift - ;; - "-debug") debug=1 - ;; - "-nodebug") debug="" - ;; - "-strace") strace=1 - ;; - "-ltrace") strace=2 - ;; - "-h") help; exit 0 - ;; - "-help") help; exit 0 - ;; - *) args="$args $1" - ;; - esac - shift -done - -# Try to get a username for use in our tmp directory, etc. -# -user="" -if [ X`id -u` = "X0" ]; then - user=root # this will also be used below for id=0 -elif [ "X$USER" != "X" ]; then - user=$USER -elif [ "X$LOGNAME" != "X" ]; then - user=$LOGNAME -fi - -# Keep trying... -# -if [ "X$user" = "X" ]; then - user=`whoami 2>/dev/null` -fi -if [ "X$user" = "X" ]; then - user=`basename "$HOME"` -fi -if [ "X$user" = "X" -o "X$user" = "X." ]; then - user="u$$" -fi - -if [ "X$debug" = "X1" -a "X$runit" != "X" ]; then - echo "" - echo "/usr/bin/env:" - env | egrep -v '^(LS_COLORS|TERMCAP)' | sort - echo "" -fi - -# Function to compile the LD_PRELOAD shared object: -# -make_so() { - # extract code embedded in this script into a tmp C file: - n1=`grep -n '^#code_begin' $0 | head -1 | awk -F: '{print $1}'` - n2=`grep -n '^#code_end' $0 | head -1 | awk -F: '{print $1}'` - n1=`expr $n1 + 1` - dn=`expr $n2 - $n1` - - tmp=$tdir/Xdummy.$RANDOM$$.c - rm -f $tmp - if [ -e $tmp -o -h $tmp ]; then - warn "$tmp still exists." - exit 1 - fi - touch $tmp || exit 1 - tail -n +$n1 $0 | head -n $dn > $tmp - - # compile it to Xdummy.so: - if [ -f "$SO" ]; then - mv $SO $SO.$$ - rm -f $SO.$$ - fi - rm -f $SO - touch $SO - if [ ! -f "$SO" ]; then - SO=$tdir/Xdummy.$user.so - warn "warning switching LD_PRELOAD shared object to: $SO" - fi - - if [ -f "$SO" ]; then - mv $SO $SO.$$ - rm -f $SO.$$ - fi - rm -f $SO - - # we assume gcc: - if [ "X$INTERPOSE_GETUID" = "X1" ]; then - CFLAGS="$CFLAGS -DINTERPOSE_GETUID" - fi - echo "$program:" cc -shared -fPIC $CFLAGS -o $SO $tmp - cc -shared -fPIC $CFLAGS -o $SO $tmp - rc=$? - rm -f $tmp - if [ $rc != 0 ]; then - warn "$program: cannot build $SO" - exit 1 - fi - if [ "X$debug" != "X" -o "X$install" != "X" ]; then - warn "$program: created $SO" - ls -l "$SO" - fi -} - -# Set tdir to tmp dir for make_so(): -if [ "X$XDUMMY_TMPDIR" != "X" ]; then - tdir=$XDUMMY_TMPDIR - mkdir -p $tdir -else - tdir="/tmp" -fi - -# Handle -install/-uninstall case: -SO=$0.so -if [ "X$install" != "X" -o "X$uninstall" != "X" ]; then - if [ -e "$SO" -o -h "$SO" ]; then - warn "$program: removing $SO" - fi - if [ -f "$SO" ]; then - mv $SO $SO.$$ - rm -f $SO.$$ - fi - rm -f $SO - if [ -e "$SO" -o -h "$SO" ]; then - warn "warning: $SO still exists." - exit 1 - fi - if [ $install ]; then - make_so - if [ ! -f "$SO" ]; then - exit 1 - fi - fi - exit 0 -fi - -# We need a tmp directory for the .so, tweaked config file, and for -# redirecting filenames we cannot create (under -nonroot) -# -tack="" -if [ "X$XDUMMY_TMPDIR" = "X" ]; then - XDUMMY_TMPDIR="/tmp/Xdummy.$user" - - # try to tack on a unique subdir (display number or pid) - # to allow multiple instances - # - if [ "X$disp" != "X" ]; then - t0=$disp - else - t0=$1 - fi - tack=`echo "$t0" | sed -e 's/^.*://'` - if echo "$tack" | grep '^[0-9][0-9]*$' > /dev/null; then - : - else - tack=$$ - fi - if [ "X$tack" != "X" ]; then - XDUMMY_TMPDIR="$XDUMMY_TMPDIR/$tack" - fi -fi - -tmp=$XDUMMY_TMPDIR -if echo "$tmp" | grep '^/tmp' > /dev/null; then - if [ "X$tmp" != "X/tmp" -a "X$tmp" != "X/tmp/" ]; then - # clean this subdir of /tmp out, otherwise leave it... - rm -rf $XDUMMY_TMPDIR - if [ -e $XDUMMY_TMPDIR ]; then - warn "$XDUMMY_TMPDIR still exists" - exit 1 - fi - fi -fi - -mkdir -p $XDUMMY_TMPDIR -chmod 700 $XDUMMY_TMPDIR -if [ "X$tack" != "X" ]; then - chmod 700 `dirname "$XDUMMY_TMPDIR"` 2>/dev/null -fi - -# See if we can write something there: -# -tfile="$XDUMMY_TMPDIR/test.file" -touch $tfile -if [ ! -f "$tfile" ]; then - XDUMMY_TMPDIR="/tmp/Xdummy.$$.$USER" - warn "warning: setting tmpdir to $XDUMMY_TMPDIR ..." - rm -rf $XDUMMY_TMPDIR || exit 1 - mkdir -p $XDUMMY_TMPDIR || exit 1 -fi -rm -f $tfile - -export XDUMMY_TMPDIR - -# Compile the LD_PRELOAD shared object if needed (needs XDUMMY_TMPDIR) -# -if [ ! -f "$SO" ]; then - SO="$XDUMMY_TMPDIR/Xdummy.so" - make_so -fi - -# Decide which X server to use: -# -if [ "X$xserver" = "X" ]; then - if type Xorg >/dev/null 2>&1; then - xserver="Xorg" - elif type XFree86 >/dev/null 2>&1; then - xserver="XFree86" - elif -x /usr/bin/Xorg; then - xserver="/usr/bin/Xorg" - elif -x /usr/X11R6/bin/Xorg; then - xserver="/usr/X11R6/bin/Xorg" - elif -x /usr/X11R6/bin/XFree86; then - xserver="/usr/X11R6/bin/XFree86" - fi - if [ "X$xserver" = "X" ]; then - # just let it fail below. - xserver="/usr/bin/Xorg" - warn "$program: cannot locate a stock Xserver... assuming $xserver" - fi -fi - -# See if the binary is suid or not readable under -nonroot mode: -# -if [ "X$BASH_VERSION" != "X" ]; then - xserver_path=`type -p $xserver 2>/dev/null` -else - xserver_path=`type $xserver 2>/dev/null | awk '{print $NF}'` -fi -if [ -e "$xserver_path" -a "X$root" = "X" -a "X$runit" != "X" ]; then - if [ ! -r $xserver_path -o -u $xserver_path -o -g $xserver_path ]; then - # XXX not quite correct with rm -rf $XDUMMY_TMPDIR ... - # we keep on a filesystem we know root can write to. - base=`basename "$xserver_path"` - new="/tmp/$base.$user.bin" - if [ -e $new ]; then - snew=`ls -l $new | awk '{print $5}' | grep '^[0-9][0-9]*$'` - sold=`ls -l $xserver_path | awk '{print $5}' | grep '^[0-9][0-9]*$'` - if [ "X$snew" != "X" -a "X$sold" != "X" -a "X$sold" != "X$snew" ]; then - warn "removing different sized copy:" - ls -l $new $xserver_path - rm -f $new - fi - fi - if [ ! -e $new -o ! -s $new ]; then - rm -f $new - touch $new || exit 1 - chmod 700 $new || exit 1 - if [ ! -r $xserver_path ]; then - warn "" - warn "NEED TO COPY UNREADABLE $xserver_path to $new as root:" - warn "" - ls -l $xserver_path 1>&2 - warn "" - warn "This only needs to be done once:" - warn " cat $xserver_path > $new" - warn "" - nos=$nosudo - if type sudo > /dev/null 2>&1; then - : - else - nos=1 - fi - if [ "X$nos" = "X1" ]; then - warn "Please supply root passwd to 'su -c'" - su -c "cat $xserver_path > $new" - else - warn "Please supply the sudo passwd if asked:" - sudo /bin/sh -c "cat $xserver_path > $new" - fi - else - warn "" - warn "COPYING SETUID $xserver_path to $new" - warn "" - ls -l $xserver_path 1>&2 - warn "" - cat $xserver_path > $new - fi - ls -l $new - if [ -s $new ]; then - : - else - rm -f $new - ls -l $new - exit 1 - fi - warn "" - warn "Please restart Xdummy now." - exit 0 - fi - if [ ! -O $new ]; then - warn "file \"$new\" not owned by us!" - ls -l $new - exit 1 - fi - xserver=$new - fi -fi - -# Work out display: -# -if [ "X$disp" != "X" ]; then - : -elif [ "X$1" != "X" ]; then - if echo "$1" | grep '^:[0-9]' > /dev/null; then - disp=$1 - shift - elif [ "X$1" = "X:" ]; then - # ":" means for us to find one. - shift - fi -fi -if [ "X$disp" = "X" -o "X$disp" = "X:" ]; then - # try to find an open display port: - # (tcp outdated...) - ports=`netstat -ant | grep LISTEN | awk '{print $4}' | sed -e 's/^.*://'` - n=0 - while [ $n -le 20 ] - do - port=`printf "60%02d" $n` - if echo "$ports" | grep "^${port}\$" > /dev/null; then - : - else - disp=":$n" - warn "$program: auto-selected DISPLAY $disp" - break - fi - n=`expr $n + 1` - done -fi - -# Work out which vt to use, try to find/guess an open one if necessary. -# -vt="" -for arg in $* -do - if echo "$arg" | grep '^vt' > /dev/null; then - vt=$arg - break - fi -done -if [ "X$vt" = "X" ]; then - if [ "X$user" = "Xroot" ]; then - # root can user fuser(1) to see if it is in use: - if type fuser >/dev/null 2>&1; then - # try /dev/tty17 thru /dev/tty32 - n=17 - while [ $n -le 32 ] - do - dev="/dev/tty$n" - if fuser $dev >/dev/null 2>&1; then - : - else - vt="vt$n" - warn "$program: auto-selected VT $vt => $dev" - break - fi - n=`expr $n + 1` - done - fi - fi - if [ "X$vt" = "X" ]; then - # take a wild guess... - vt=vt16 - warn "$program: selected fallback VT $vt" - fi -else - vt="" -fi - -# Decide flavor of Xserver: -# -stype=`basename "$xserver"` -if echo "$stype" | grep -i xfree86 > /dev/null; then - stype=xfree86 -else - stype=xorg -fi - -tweak_config() { - in="$1" - config2="$XDUMMY_TMPDIR/xdummy_modified_xconfig.conf" - if [ "X$disp" != "X" ]; then - d=`echo "$disp" | sed -e 's,/,,g' -e 's/:/_/g'` - config2="$config2$d" - fi - - # perl script to tweak the config file... add/delete options, etc. - # - env XDUMMY_GEOM=$geom \ - XDUMMY_DEPTH=$depth \ - XDUMMY_NOMODELINES=$nomodelines \ - perl > $config2 < $in -e ' - $n = 0; - $geom = $ENV{XDUMMY_GEOM}; - $depth = $ENV{XDUMMY_DEPTH}; - $nomodelines = $ENV{XDUMMY_NOMODELINES}; - $mode_str = ""; - $videoram = "24000"; - $HorizSync = "30.0 - 130.0"; - $VertRefresh = "50.0 - 250.0"; - if ($geom ne "") { - my $tmp = ""; - foreach $g (split(/,/, $geom)) { - $tmp .= "\"$g\" "; - if (!$nomodelines && $g =~ /(\d+)x(\d+)/) { - my $w = $1; - my $h = $2; - $mode_str .= " Modeline \"$g\" "; - my $dot = sprintf("%.2f", $w * $h * 70 * 1.e-6); - $mode_str .= $dot; - $mode_str .= " " . $w; - $mode_str .= " " . int(1.02 * $w); - $mode_str .= " " . int(1.10 * $w); - $mode_str .= " " . int(1.20 * $w); - $mode_str .= " " . $h; - $mode_str .= " " . int($h + 1); - $mode_str .= " " . int($h + 3); - $mode_str .= " " . int($h + 20); - $mode_str .= "\n"; - } - } - $tmp =~ s/\s*$//; - $geom = $tmp; - } - while (<>) { - if ($ENV{XDUMMY_NOTWEAK}) { - print $_; - next; - } - $n++; - if (/^\s*#/) { - # pass comments straight thru - print; - next; - } - if (/^\s*Section\s+(\S+)/i) { - # start of Section - $sect = $1; - $sect =~ s/\W//g; - $sect =~ y/A-Z/a-z/; - $sects{$sect} = 1; - print; - next; - } - if (/^\s*EndSection/i) { - # end of Section - if ($sect eq "serverflags") { - if (!$got_DontVTSwitch) { - print " ##Xdummy:##\n"; - print " Option \"DontVTSwitch\" \"true\"\n"; - } - if (!$got_AllowMouseOpenFail) { - print " ##Xdummy:##\n"; - print " Option \"AllowMouseOpenFail\" \"true\"\n"; - } - if (!$got_PciForceNone) { - print " ##Xdummy:##\n"; - print " Option \"PciForceNone\" \"true\"\n"; - } - } elsif ($sect eq "device") { - if (!$got_Driver) { - print " ##Xdummy:##\n"; - print " Driver \"dummy\"\n"; - } - if (!$got_VideoRam) { - print " ##Xdummy:##\n"; - print " VideoRam $videoram\n"; - } - } elsif ($sect eq "screen") { - if ($depth ne "" && !got_DefaultDepth) { - print " ##Xdummy:##\n"; - print " DefaultDepth $depth\n"; - } - if ($got_Monitor eq "") { - print " ##Xdummy:##\n"; - print " Monitor \"Monitor0\"\n"; - } - } elsif ($sect eq "monitor") { - if (!got_HorizSync) { - print " ##Xdummy:##\n"; - print " HorizSync $HorizSync\n"; - } - if (!got_VertRefresh) { - print " ##Xdummy:##\n"; - print " VertRefresh $VertRefresh\n"; - } - if (!$nomodelines) { - print " ##Xdummy:##\n"; - print $mode_str; - } - } - $sect = ""; - print; - next; - } - - if (/^\s*SubSection\s+(\S+)/i) { - # start of Section - $subsect = $1; - $subsect =~ s/\W//g; - $subsect =~ y/A-Z/a-z/; - $subsects{$subsect} = 1; - if ($sect eq "screen" && $subsect eq "display") { - $got_Modes = 0; - } - print; - next; - } - if (/^\s*EndSubSection/i) { - # end of SubSection - if ($sect eq "screen") { - if ($subsect eq "display") { - if ($depth ne "" && !$set_Depth) { - print " ##Xdummy:##\n"; - print " Depth\t$depth\n"; - } - if ($geom ne "" && ! $got_Modes) { - print " ##Xdummy:##\n"; - print " Modes\t$geom\n"; - } - } - } - $subsect = ""; - print; - next; - } - - $l = $_; - $l =~ s/#.*$//; - if ($sect eq "serverflags") { - if ($l =~ /^\s*Option.*DontVTSwitch/i) { - $_ =~ s/false/true/ig; - $got_DontVTSwitch = 1; - } - if ($l =~ /^\s*Option.*AllowMouseOpenFail/i) { - $_ =~ s/false/true/ig; - $got_AllowMouseOpenFail = 1; - } - if ($l =~ /^\s*Option.*PciForceNone/i) { - $_ =~ s/false/true/ig; - $got_PciForceNone= 1; - } - } - if ($sect eq "module") { - if ($l =~ /^\s*Load.*\b(dri|fbdevhw)\b/i) { - $_ = "##Xdummy## $_"; - } - } - if ($sect eq "monitor") { - if ($l =~ /^\s*HorizSync/i) { - $got_HorizSync = 1; - } - if ($l =~ /^\s*VertRefresh/i) { - $got_VertRefresh = 1; - } - } - if ($sect eq "device") { - if ($l =~ /^(\s*Driver)\b/i) { - $_ = "$1 \"dummy\"\n"; - $got_Driver = 1; - } - if ($l =~ /^\s*VideoRam/i) { - $got_VideoRam= 1; - } - } - if ($sect eq "inputdevice") { - if ($l =~ /^\s*Option.*\bDevice\b/i) { - print " ##Xdummy:##\n"; - $_ = " Option \"Device\" \"/dev/dilbert$n\"\n"; - } - } - if ($sect eq "screen") { - if ($l =~ /^\s*DefaultDepth\s+(\d+)/i) { - if ($depth ne "") { - print " ##Xdummy:##\n"; - $_ = " DefaultDepth\t$depth\n"; - } - $got_DefaultDepth = 1; - } - if ($l =~ /^\s*Monitor\s+(\S+)/i) { - $got_Monitor = $1; - $got_Monitor =~ s/"//g; - } - if ($subsect eq "display") { - if ($geom ne "") { - if ($l =~ /^(\s*Modes)\b/i) { - print " ##Xdummy:##\n"; - $_ = "$1 $geom\n"; - $got_Modes = 1; - } - } - if ($l =~ /^\s*Depth\s+(\d+)/i) { - my $d = $1; - if (!$set_Depth && $depth ne "") { - $set_Depth = 1; - if ($depth != $d) { - print " ##Xdummy:##\n"; - $_ = " Depth\t$depth\n"; - } - } - } - } - } - print; - } - if ($ENV{XDUMMY_NOTWEAK}) { - exit; - } - # create any crucial sections that are missing: - if (! exists($sects{serverflags})) { - print "\n##Xdummy:##\n"; - print "Section \"ServerFlags\"\n"; - print " Option \"DontVTSwitch\" \"true\"\n"; - print " Option \"AllowMouseOpenFail\" \"true\"\n"; - print " Option \"PciForceNone\" \"true\"\n"; - print "EndSection\n"; - } - if (! exists($sects{device})) { - print "\n##Xdummy:##\n"; - print "Section \"Device\"\n"; - print " Identifier \"Videocard0\"\n"; - print " Driver \"dummy\"\n"; - print " VideoRam $videoram\n"; - print "EndSection\n"; - } - if (! exists($sects{monitor})) { - print "\n##Xdummy:##\n"; - print "Section \"Monitor\"\n"; - print " Identifier \"Monitor0\"\n"; - print " HorizSync $HorizSync\n"; - print " VertRefresh $VertRefresh\n"; - print "EndSection\n"; - } - if (! exists($sects{screen})) { - print "\n##Xdummy:##\n"; - print "Section \"Screen\"\n"; - print " Identifier \"Screen0\"\n"; - print " Device \"Videocard0\"\n"; - if ($got_Monitor ne "") { - print " Monitor \"$got_Monitor\"\n"; - } else { - print " Monitor \"Monitor0\"\n"; - } - if ($depth ne "") { - print " DefaultDepth $depth\n"; - } else { - print " DefaultDepth 24\n"; - } - print " SubSection \"Display\"\n"; - print " Viewport 0 0\n"; - print " Depth 24\n"; - if ($got_Modes) { - ; - } elsif ($geom ne "") { - print " Modes $geom\n"; - } else { - print " Modes \"1280x1024\" \"1024x768\" \"800x600\"\n"; - } - print " EndSubSection\n"; - print "EndSection\n"; - } -'; -} - -# Work out config file and tweak it. -# -if [ "X$cmdline_config" = "X" ]; then - : -elif [ "X$cmdline_config" = "Xxdummy-builtin" ]; then - : -elif echo "$cmdline_config" | grep '/' > /dev/null; then - : -else - # ignore basename only case (let server handle it) - cmdline_config="" - notweak=1 -fi - -config=$cmdline_config - -if [ "X$notweak" = "X1" -a "X$root" = "X" -a -f "$cmdline_config" ]; then - # if not root we need to copy (but not tweak) the specified config. - XDUMMY_NOTWEAK=1 - export XDUMMY_NOTWEAK - notweak="" -fi - -if [ ! $notweak ]; then - # tweaked config will be put in $config2: - config2="" - if [ "X$config" = "X" ]; then - # use the default one: - if [ "X$stype" = "Xxorg" ]; then - config=/etc/X11/xorg.conf - else - if [ -f "/etc/X11/XF86Config-4" ]; then - config="/etc/X11/XF86Config-4" - else - config="/etc/X11/XF86Config" - fi - fi - if [ ! -f "$config" ]; then - for c in /etc/X11/xorg.conf /etc/X11/XF86Config-4 /etc/X11/XF86Config - do - if [ -f $c ]; then - config=$c - break - fi - done - fi - fi - - if [ "X$config" = "Xxdummy-builtin" ]; then - config="" - fi - - if [ ! -f "$config" ]; then - config="$XDUMMY_TMPDIR/xorg.conf" - warn "$program: using minimal built-in xorg.conf settings." - cat > $config < /dev/null; then - so=`echo "$so" | sed -e "s,^\.,$pwd,"` - fi - if echo "$so" | grep '/' > /dev/null; then - : - else - so="$pwd/$so" - fi - warn "env LD_PRELOAD=$so $xserver $disp $args $vt" - warn "" - if [ ! $runit ]; then - exit 0 - fi -fi - -if [ $strace ]; then - if [ "X$strace" = "X2" ]; then - ltrace -f env LD_PRELOAD=$SO $xserver $disp $args $vt - else - strace -f env LD_PRELOAD=$SO $xserver $disp $args $vt - fi -else - exec env LD_PRELOAD=$SO $xserver $disp $args $vt -fi - -exit $? - -######################################################################### - -code() { -#code_begin -#include -#define O_ACCMODE 0003 -#define O_RDONLY 00 -#define O_WRONLY 01 -#define O_RDWR 02 -#define O_CREAT 0100 /* not fcntl */ -#define O_EXCL 0200 /* not fcntl */ -#define O_NOCTTY 0400 /* not fcntl */ -#define O_TRUNC 01000 /* not fcntl */ -#define O_APPEND 02000 -#define O_NONBLOCK 04000 -#define O_NDELAY O_NONBLOCK -#define O_SYNC 010000 -#define O_FSYNC O_SYNC -#define O_ASYNC 020000 - -#include -#include -#include - -#include -#include - -#define __USE_GNU -#include - -static char tmpdir[4096]; -static char str1[4096]; -static char str2[4096]; - -static char devs[256][1024]; -static int debug = -1; -static int root = -1; -static int changed_uid = 0; -static int saw_fonts = 0; -static int saw_lib_modules = 0; - -static time_t start = 0; - -void check_debug(void) { - if (debug < 0) { - if (getenv("XDUMMY_DEBUG") != NULL) { - debug = 1; - } else { - debug = 0; - } - /* prevent other processes using the preload: */ - putenv("LD_PRELOAD="); - } -} -void check_root(void) { - if (root < 0) { - /* script tells us if we are root */ - if (getenv("XDUMMY_ROOT") != NULL) { - root = 1; - } else { - root = 0; - } - } -} - -void check_uid(void) { - if (start == 0) { - start = time(NULL); - if (debug) fprintf(stderr, "START: %u\n", (unsigned int) start); - return; - } else if (changed_uid == 0) { - if (saw_fonts || time(NULL) > start + 20) { - if (getenv("XDUMMY_UID")) { - int uid = atoi(getenv("XDUMMY_UID")); - if (debug) fprintf(stderr, "SETREUID: %d saw_fonts=%d\n", uid, saw_fonts); - if (uid >= 0) { - /* this will simply fail in -nonroot mode: */ - setreuid(uid, -1); - } - } - changed_uid = 1; - } - } -} - -#define CHECKIT if (debug < 0) check_debug(); \ - if (root < 0) check_root(); \ - check_uid(); - -static void set_tmpdir(void) { - char *s; - static int didset = 0; - if (didset) { - return; - } - s = getenv("XDUMMY_TMPDIR"); - if (! s) { - s = "/tmp"; - } - tmpdir[0] = '\0'; - strcat(tmpdir, s); - strcat(tmpdir, "/"); - didset = 1; -} - -static char *tmpdir_path(const char *path) { - char *str; - set_tmpdir(); - strcpy(str2, path); - str = str2; - while (*str) { - if (*str == '/') { - *str = '_'; - } - str++; - } - strcpy(str1, tmpdir); - strcat(str1, str2); - return str1; -} - -int open(const char *pathname, int flags, unsigned short mode) { - int fd; - char *store_dev = NULL; - static int (*real_open)(const char *, int , unsigned short) = NULL; - - CHECKIT - if (! real_open) { - real_open = (int (*)(const char *, int , unsigned short)) - dlsym(RTLD_NEXT, "open"); - } - - if (strstr(pathname, "lib/modules/")) { - /* not currently used. */ - saw_lib_modules = 1; - } - - if (!root) { - if (strstr(pathname, "/dev/") == pathname) { - store_dev = strdup(pathname); - } - if (strstr(pathname, "/dev/tty") == pathname && strcmp(pathname, "/dev/tty")) { - pathname = tmpdir_path(pathname); - if (debug) fprintf(stderr, "OPEN: %s -> %s (as FIFO)\n", store_dev, pathname); - /* we make it a FIFO so ioctl on it does not fail */ - unlink(pathname); - mkfifo(pathname, 0666); - } else if (0) { - /* we used to handle more /dev files ... */ - fd = real_open(pathname, O_WRONLY|O_CREAT, 0777); - close(fd); - } - } - - fd = real_open(pathname, flags, mode); - - if (debug) fprintf(stderr, "OPEN: %s %d %d fd=%d\n", pathname, flags, mode, fd); - - if (! root) { - if (store_dev) { - if (fd < 256) { - strcpy(devs[fd], store_dev); - } - free(store_dev); - } - } - - return(fd); -} - -int open64(const char *pathname, int flags, unsigned short mode) { - int fd; - - CHECKIT - if (debug) fprintf(stderr, "OPEN64: %s %d %d\n", pathname, flags, mode); - - fd = open(pathname, flags, mode); - return(fd); -} - -int rename(const char *oldpath, const char *newpath) { - static int (*real_rename)(const char *, const char *) = NULL; - - CHECKIT - if (! real_rename) { - real_rename = (int (*)(const char *, const char *)) - dlsym(RTLD_NEXT, "rename"); - } - - if (debug) fprintf(stderr, "RENAME: %s %s\n", oldpath, newpath); - - if (root) { - return(real_rename(oldpath, newpath)); - } - - if (strstr(oldpath, "/var/log") == oldpath) { - if (debug) fprintf(stderr, "RENAME: returning 0\n"); - return 0; - } - return(real_rename(oldpath, newpath)); -} - -FILE *fopen(const char *pathname, const char *mode) { - static FILE* (*real_fopen)(const char *, const char *) = NULL; - char *str; - - if (! saw_fonts) { - if (strstr(pathname, "/fonts/")) { - if (strstr(pathname, "fonts.dir")) { - saw_fonts = 1; - } else if (strstr(pathname, "fonts.alias")) { - saw_fonts = 1; - } - } - } - - CHECKIT - if (! real_fopen) { - real_fopen = (FILE* (*)(const char *, const char *)) - dlsym(RTLD_NEXT, "fopen"); - } - - if (debug) fprintf(stderr, "FOPEN: %s %s\n", pathname, mode); - - if (strstr(pathname, "xdummy_modified_xconfig.conf")) { - /* make our config appear to be in /etc/X11, etc. */ - char *q = strrchr(pathname, '/'); - if (q != NULL && getenv("XDUMMY_TMPDIR") != NULL) { - strcpy(str1, getenv("XDUMMY_TMPDIR")); - strcat(str1, q); - if (debug) fprintf(stderr, "FOPEN: %s -> %s\n", pathname, str1); - pathname = str1; - } - } - - if (root) { - return(real_fopen(pathname, mode)); - } - - str = (char *) pathname; - if (strstr(pathname, "/var/log") == pathname) { - str = tmpdir_path(pathname); - if (debug) fprintf(stderr, "FOPEN: %s -> %s\n", pathname, str); - } - return(real_fopen(str, mode)); -} - - -#define RETURN0 if (debug) \ - {fprintf(stderr, "IOCTL: covered %d 0x%x\n", fd, req);} return 0; -#define RETURN1 if (debug) \ - {fprintf(stderr, "IOCTL: covered %d 0x%x\n", fd, req);} return -1; - -int ioctl(int fd, int req, void *ptr) { - static int closed_xf86Info_consoleFd = 0; - static int (*real_ioctl)(int, int , void *) = NULL; - - CHECKIT - if (! real_ioctl) { - real_ioctl = (int (*)(int, int , void *)) - dlsym(RTLD_NEXT, "open"); - } - if (debug) fprintf(stderr, "IOCTL: %d 0x%x %p\n", fd, req, ptr); - - /* based on xorg-x11-6.8.1-dualhead.patch */ - if (req == VT_GETMODE) { - /* close(xf86Info.consoleFd) */ - if (0 && ! closed_xf86Info_consoleFd) { - /* I think better not to close it... */ - close(fd); - closed_xf86Info_consoleFd = 1; - } - RETURN0 - } else if (req == VT_SETMODE) { - RETURN0 - } else if (req == VT_GETSTATE) { - RETURN0 - } else if (req == KDSETMODE) { - RETURN0 - } else if (req == KDSETLED) { - RETURN0 - } else if (req == KDGKBMODE) { - RETURN0 - } else if (req == KDSKBMODE) { - RETURN0 - } else if (req == VT_ACTIVATE) { - RETURN0 - } else if (req == VT_WAITACTIVE) { - RETURN0 - } else if (req == VT_RELDISP) { - if (ptr == (void *) 1) { - RETURN1 - } else if (ptr == (void *) VT_ACKACQ) { - RETURN0 - } - } - - return(real_ioctl(fd, req, ptr)); -} - -typedef void (*sighandler_t)(int); -#define SIGUSR1 10 -#define SIG_DFL ((sighandler_t)0) - -sighandler_t signal(int signum, sighandler_t handler) { - static sighandler_t (*real_signal)(int, sighandler_t) = NULL; - - CHECKIT - if (! real_signal) { - real_signal = (sighandler_t (*)(int, sighandler_t)) - dlsym(RTLD_NEXT, "signal"); - } - - if (debug) fprintf(stderr, "SIGNAL: %d %p\n", signum, handler); - - if (signum == SIGUSR1) { - if (debug) fprintf(stderr, "SIGNAL: skip SIGUSR1\n"); - return SIG_DFL; - } - - return(real_signal(signum, handler)); -} - -int close(int fd) { - static int (*real_close)(int) = NULL; - - CHECKIT - if (! real_close) { - real_close = (int (*)(int)) dlsym(RTLD_NEXT, "close"); - } - - if (debug) fprintf(stderr, "CLOSE: %d\n", fd); - if (!root) { - if (fd < 256) { - devs[fd][0] = '\0'; - } - } - return(real_close(fd)); -} - -struct stat { - int foo; -}; - -int stat(const char *path, struct stat *buf) { - static int (*real_stat)(const char *, struct stat *) = NULL; - - CHECKIT - if (! real_stat) { - real_stat = (int (*)(const char *, struct stat *)) - dlsym(RTLD_NEXT, "stat"); - } - - if (debug) fprintf(stderr, "STAT: %s\n", path); - - return(real_stat(path, buf)); -} - -int stat64(const char *path, struct stat *buf) { - static int (*real_stat64)(const char *, struct stat *) = NULL; - - CHECKIT - if (! real_stat64) { - real_stat64 = (int (*)(const char *, struct stat *)) - dlsym(RTLD_NEXT, "stat64"); - } - - if (debug) fprintf(stderr, "STAT64: %s\n", path); - - return(real_stat64(path, buf)); -} - -int chown(const char *path, uid_t owner, gid_t group) { - static int (*real_chown)(const char *, uid_t, gid_t) = NULL; - - CHECKIT - if (! real_chown) { - real_chown = (int (*)(const char *, uid_t, gid_t)) - dlsym(RTLD_NEXT, "chown"); - } - - if (root) { - return(real_chown(path, owner, group)); - } - - if (debug) fprintf(stderr, "CHOWN: %s %d %d\n", path, owner, group); - - if (strstr(path, "/dev") == path) { - if (debug) fprintf(stderr, "CHOWN: return 0\n"); - return 0; - } - - return(real_chown(path, owner, group)); -} - -extern int *__errno_location (void); -#ifndef ENODEV -#define ENODEV 19 -#endif - -int ioperm(unsigned long from, unsigned long num, int turn_on) { - static int (*real_ioperm)(unsigned long, unsigned long, int) = NULL; - - CHECKIT - if (! real_ioperm) { - real_ioperm = (int (*)(unsigned long, unsigned long, int)) - dlsym(RTLD_NEXT, "ioperm"); - } - if (debug) fprintf(stderr, "IOPERM: %d %d %d\n", (int) from, (int) num, turn_on); - if (root) { - return(real_ioperm(from, num, turn_on)); - } - if (from == 0 && num == 1024 && turn_on == 1) { - /* we want xf86EnableIO to fail */ - if (debug) fprintf(stderr, "IOPERM: setting ENODEV.\n"); - *__errno_location() = ENODEV; - return -1; - } - return 0; -} - -int iopl(int level) { - static int (*real_iopl)(int) = NULL; - - CHECKIT - if (! real_iopl) { - real_iopl = (int (*)(int)) dlsym(RTLD_NEXT, "iopl"); - } - if (debug) fprintf(stderr, "IOPL: %d\n", level); - if (root) { - return(real_iopl(level)); - } - return 0; -} - -#ifdef INTERPOSE_GETUID - -/* - * we got things to work w/o pretending to be root. - * so we no longer interpose getuid(), etc. - */ - -uid_t getuid(void) { - static uid_t (*real_getuid)(void) = NULL; - CHECKIT - if (! real_getuid) { - real_getuid = (uid_t (*)(void)) dlsym(RTLD_NEXT, "getuid"); - } - if (root) { - return(real_getuid()); - } - if (debug) fprintf(stderr, "GETUID: 0\n"); - return 0; -} -uid_t geteuid(void) { - static uid_t (*real_geteuid)(void) = NULL; - CHECKIT - if (! real_geteuid) { - real_geteuid = (uid_t (*)(void)) dlsym(RTLD_NEXT, "geteuid"); - } - if (root) { - return(real_geteuid()); - } - if (debug) fprintf(stderr, "GETEUID: 0\n"); - return 0; -} -uid_t geteuid_kludge1(void) { - static uid_t (*real_geteuid)(void) = NULL; - CHECKIT - if (! real_geteuid) { - real_geteuid = (uid_t (*)(void)) dlsym(RTLD_NEXT, "geteuid"); - } - if (debug) fprintf(stderr, "GETEUID: 0 saw_libmodules=%d\n", saw_lib_modules); - if (root && !saw_lib_modules) { - return(real_geteuid()); - } else { - saw_lib_modules = 0; - return 0; - } -} - -uid_t getuid32(void) { - static uid_t (*real_getuid32)(void) = NULL; - CHECKIT - if (! real_getuid32) { - real_getuid32 = (uid_t (*)(void)) dlsym(RTLD_NEXT, "getuid32"); - } - if (root) { - return(real_getuid32()); - } - if (debug) fprintf(stderr, "GETUID32: 0\n"); - return 0; -} -uid_t geteuid32(void) { - static uid_t (*real_geteuid32)(void) = NULL; - CHECKIT - if (! real_geteuid32) { - real_geteuid32 = (uid_t (*)(void)) dlsym(RTLD_NEXT, "geteuid32"); - } - if (root) { - return(real_geteuid32()); - } - if (debug) fprintf(stderr, "GETEUID32: 0\n"); - return 0; -} - -gid_t getgid(void) { - static gid_t (*real_getgid)(void) = NULL; - CHECKIT - if (! real_getgid) { - real_getgid = (gid_t (*)(void)) dlsym(RTLD_NEXT, "getgid"); - } - if (root) { - return(real_getgid()); - } - if (debug) fprintf(stderr, "GETGID: 0\n"); - return 0; -} -gid_t getegid(void) { - static gid_t (*real_getegid)(void) = NULL; - CHECKIT - if (! real_getegid) { - real_getegid = (gid_t (*)(void)) dlsym(RTLD_NEXT, "getegid"); - } - if (root) { - return(real_getegid()); - } - if (debug) fprintf(stderr, "GETEGID: 0\n"); - return 0; -} -gid_t getgid32(void) { - static gid_t (*real_getgid32)(void) = NULL; - CHECKIT - if (! real_getgid32) { - real_getgid32 = (gid_t (*)(void)) dlsym(RTLD_NEXT, "getgid32"); - } - if (root) { - return(real_getgid32()); - } - if (debug) fprintf(stderr, "GETGID32: 0\n"); - return 0; -} -gid_t getegid32(void) { - static gid_t (*real_getegid32)(void) = NULL; - CHECKIT - if (! real_getegid32) { - real_getegid32 = (gid_t (*)(void)) dlsym(RTLD_NEXT, "getegid32"); - } - if (root) { - return(real_getegid32()); - } - if (debug) fprintf(stderr, "GETEGID32: 0\n"); - return 0; -} -#endif - -#if 0 -/* maybe we need to interpose on strcmp someday... here is the template */ -int strcmp(const char *s1, const char *s2) { - static int (*real_strcmp)(const char *, const char *) = NULL; - CHECKIT - if (! real_strcmp) { - real_strcmp = (int (*)(const char *, const char *)) dlsym(RTLD_NEXT, "strcmp"); - } - if (debug) fprintf(stderr, "STRCMP: '%s' '%s'\n", s1, s2); - return(real_strcmp(s1, s2)); -} -#endif - -#code_end -} diff --git a/testcases/complete-run.pl b/testcases/complete-run.pl index 7ca89016..9592c767 100755 --- a/testcases/complete-run.pl +++ b/testcases/complete-run.pl @@ -43,7 +43,7 @@ sub Log { say $log "@_" } my %timings; my $help = 0; -# Number of tests to run in parallel. Important to know how many Xdummy +# Number of tests to run in parallel. Important to know how many Xephyr # instances we need to start (unless @displays are given). Defaults to # num_cores * 2. my $parallel = undef; @@ -55,11 +55,11 @@ my %options = ( coverage => 0, restart => 0, ); -my $keep_xdummy_output = 0; +my $keep_xserver_output = 0; my $result = GetOptions( "coverage-testing" => \$options{coverage}, - "keep-xdummy-output" => \$keep_xdummy_output, + "keep-xserver-output" => \$keep_xserver_output, "valgrind" => \$options{valgrind}, "strace" => \$options{strace}, "xtrace" => \$options{xtrace}, @@ -86,6 +86,9 @@ foreach my $binary (@binaries) { die "$binary is not an executable" unless -x $binary; } +qx(Xephyr -help 2>&1); +die "Xephyr was not found in your path. Please install Xephyr (xserver-xephyr on Debian)." if $?; + @displays = split(/,/, join(',', @displays)); @displays = map { s/ //g; $_ } @displays; @@ -97,9 +100,9 @@ my @testfiles = @ARGV; my $numtests = scalar @testfiles; -# No displays specified, let’s start some Xdummy instances. +# No displays specified, let’s start some Xephyr instances. if (@displays == 0) { - @displays = start_xdummy($parallel, $numtests, $keep_xdummy_output); + @displays = start_xserver($parallel, $numtests, $keep_xserver_output); } # 1: create an output directory for this test-run @@ -115,8 +118,7 @@ symlink("$outdir", "latest") or die "Could not symlink latest to $outdir"; # connect to all displays for two reasons: # 1: check if the display actually works # 2: keep the connection open so that i3 is not the only client. this prevents -# the X server from exiting (Xdummy will restart it, but not quick enough -# sometimes) +# the X server from exiting my @single_worker; for my $display (@displays) { my $screen; @@ -346,7 +348,7 @@ complete-run.pl [files...] =head1 EXAMPLE -To run the whole testsuite on a reasonable number of Xdummy instances (your +To run the whole testsuite on a reasonable number of Xephyr instances (your running X11 will not be touched), run: ./complete-run.pl @@ -365,11 +367,11 @@ will parallelize the tests: # Run tests on the second X server ./complete-run.pl -d :1 - # Run four tests in parallel on some Xdummy servers + # Run four tests in parallel on some Xephyr servers ./complete-run.pl -d :1,:2,:3,:4 Note that it is not necessary to specify this anymore. If omitted, -complete-run.pl will start (num_cores * 2) Xdummy instances. +complete-run.pl will start (num_cores * 2) Xephyr instances. =item B<--valgrind> @@ -392,8 +394,8 @@ Exits i3 cleanly (instead of kill -9) to make coverage testing work properly. =item B<--parallel> -Number of Xdummy instances to start (if you don’t want to start num_cores * 2 +Number of Xephyr instances to start (if you don’t want to start num_cores * 2 instances for some reason). - # Run all tests on a single Xdummy instance + # Run all tests on a single Xephyr instance ./complete-run.pl -p 1 diff --git a/testcases/lib/StartXDummy.pm b/testcases/lib/StartXDummy.pm index 592feb85..444f630a 100644 --- a/testcases/lib/StartXDummy.pm +++ b/testcases/lib/StartXDummy.pm @@ -7,7 +7,7 @@ use Exporter 'import'; use Time::HiRes qw(sleep); use v5.10; -our @EXPORT = qw(start_xdummy); +our @EXPORT = qw(start_xserver); my @pids; my $x_socketpath = '/tmp/.X11-unix/X'; @@ -19,15 +19,15 @@ sub slurp { <$fh>; } -# forks an Xdummy or Xdmx process +# forks an X server process sub fork_xserver { - my $keep_xdummy_output = shift; + my $keep_xserver_output = shift; my $displaynum = shift; my $pid = fork(); die "Could not fork: $!" unless defined($pid); if ($pid == 0) { - # Child, close stdout/stderr, then start Xdummy. - if (!$keep_xdummy_output) { + # Child, close stdout/stderr, then start Xephyr + if (!$keep_xserver_output) { close STDOUT; close STDERR; } @@ -60,16 +60,17 @@ sub wait_for_x { } } -=head2 start_xdummy($parallel) +=head2 start_xserver($parallel) -Starts C<$parallel> (or number of cores * 2 if undef) Xdummy processes (see -the file ./Xdummy) and returns two arrayrefs: a list of X11 display numbers to -the Xdummy processes and a list of PIDs of the processes. +Starts C<$parallel> (or number of cores * 2 if undef) Xephyr processes (see +http://www.freedesktop.org/wiki/Software/Xephyr/) and returns two arrayrefs: a +list of X11 display numbers to the Xephyr processes and a list of PIDs of the +processes. =cut -sub start_xdummy { - my ($parallel, $numtests, $keep_xdummy_output) = @_; +sub start_xserver { + my ($parallel, $numtests, $keep_xserver_output) = @_; my @displays = (); my @childpids = (); @@ -78,11 +79,8 @@ sub start_xdummy { my $child = waitpid -1, POSIX::WNOHANG; @pids = grep { $_ != $child } @pids; return unless @pids == 0; - print STDERR "All Xdummy processes died.\n"; - print STDERR "Use ./complete-run.pl --parallel 1 --keep-xdummy-output\n"; - print STDERR ""; - print STDERR "A frequent cause for this is missing the DUMMY Xorg module,\n"; - print STDERR "package xserver-xorg-video-dummy on Debian.\n"; + print STDERR "All X server processes died.\n"; + print STDERR "Use ./complete-run.pl --parallel 1 --keep-xserver-output\n"; exit 1; }; @@ -104,16 +102,13 @@ sub start_xdummy { my ($displaynum) = map { /(\d+)$/ } reverse sort glob($x_socketpath . '*'); $displaynum++; - say "Starting $parallel Xdummy instances, starting at :$displaynum..."; + say "Starting $parallel Xephyr instances, starting at :$displaynum..."; my @sockets_waiting; for (1 .. $parallel) { - # We use -config /dev/null to prevent Xdummy from using the system - # Xorg configuration. The tests should be independant from the - # actual system X configuration. - my $socket = fork_xserver($keep_xdummy_output, $displaynum, - './Xdummy', ":$displaynum", '-config', '/dev/null', - '-configdir', '/dev/null', '-nolisten', 'tcp'); + my $socket = fork_xserver($keep_xserver_output, $displaynum, + 'Xephyr', ":$displaynum", '-screen', '1280x800', + '-nolisten', 'tcp'); push(@displays, ":$displaynum"); push(@sockets_waiting, $socket); $displaynum++; diff --git a/testcases/t/112-floating-resize.t b/testcases/t/112-floating-resize.t index ec690b5e..a7390051 100644 --- a/testcases/t/112-floating-resize.t +++ b/testcases/t/112-floating-resize.t @@ -69,7 +69,7 @@ cmd 'border 1pixel'; test_resize; ################################################################################ -# Check if we can position a floating window out of bounds. The XDummy screen +# Check if we can position a floating window out of bounds. The Xephyr screen # is 1280x1024, so x=2864, y=893 is out of bounds. ################################################################################