1956 lines
		
	
	
		
			45 KiB
		
	
	
	
		
			Bash
		
	
	
	
	
	
			
		
		
	
	
			1956 lines
		
	
	
		
			45 KiB
		
	
	
	
		
			Bash
		
	
	
	
	
	
#!/bin/sh
 | 
						|
# ----------------------------------------------------------------------
 | 
						|
#    Copyright (C) 2005-2011 Karl J. Runge <runge@karlrunge.com> 
 | 
						|
#    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 <http://www.gnu.org/licenses/>.
 | 
						|
# ----------------------------------------------------------------------
 | 
						|
# 
 | 
						|
# 
 | 
						|
# 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> <Xserver-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.
 | 
						|
 | 
						|
Config file:
 | 
						|
 | 
						|
	If the file $program.cfg exists it will be sourced as shell
 | 
						|
	commands.  Usually one will set some variables this way.
 | 
						|
	To disable sourcing, supply -nocfg or set XDUMMY_NOCFG=1.
 | 
						|
 | 
						|
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 <unistd.h>
 | 
						|
#include <stdlib.h>
 | 
						|
#include <sys/types.h>
 | 
						|
#include <stdio.h>
 | 
						|
 | 
						|
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.
 | 
						|
 | 
						|
	-nocfg		Do not try to source $program.cfg even if it
 | 
						|
			exists.  Same as setting XDUMMY_NOCFG=1.
 | 
						|
 | 
						|
	-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.
 | 
						|
 | 
						|
	You can set the env. var. XDUMMY_EXTRA_SERVER_ARGS to hold some
 | 
						|
	extra Xserver-args too. (Useful for cfg file.)
 | 
						|
 | 
						|
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
 | 
						|
	elif [ "X$arg" = "X-nocfg" ]; then
 | 
						|
		XDUMMY_NOCFG=1
 | 
						|
		export XDUMMY_NOCFG
 | 
						|
	fi
 | 
						|
done
 | 
						|
 | 
						|
if [ "X$XDUMMY_NOCFG" = "X" -a -f "$0.cfg" ]; then
 | 
						|
	. "$0.cfg"
 | 
						|
fi
 | 
						|
 | 
						|
# 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
 | 
						|
                ;;
 | 
						|
	"-nocfg") :
 | 
						|
                ;;
 | 
						|
	"-nodebug") debug=""
 | 
						|
                ;;
 | 
						|
	"-strace") strace=1
 | 
						|
                ;;
 | 
						|
	"-ltrace") strace=2
 | 
						|
                ;;
 | 
						|
	"-h")	 help; exit 0
 | 
						|
                ;;
 | 
						|
	"-help") help; exit 0
 | 
						|
                ;;
 | 
						|
	*)	args="$args $1"
 | 
						|
                ;;
 | 
						|
    esac
 | 
						|
    shift
 | 
						|
done
 | 
						|
 | 
						|
if [ "X$XDUMMY_EXTRA_SERVER_ARGS" != "X" ]; then
 | 
						|
	args="$args $XDUMMY_EXTRA_SERVER_ARGS"
 | 
						|
fi
 | 
						|
 | 
						|
# 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 <<END
 | 
						|
 | 
						|
Section "ServerLayout"
 | 
						|
    Identifier     "Layout0"
 | 
						|
    Screen      0  "Screen0"
 | 
						|
    InputDevice    "Keyboard0" "CoreKeyboard"
 | 
						|
    InputDevice    "Mouse0" "CorePointer"
 | 
						|
EndSection
 | 
						|
 | 
						|
Section "Files"
 | 
						|
EndSection
 | 
						|
 | 
						|
Section "Module"
 | 
						|
    Load           "dbe"
 | 
						|
    Load           "extmod"
 | 
						|
    Load           "freetype"
 | 
						|
    Load           "glx"
 | 
						|
EndSection
 | 
						|
 | 
						|
Section "InputDevice"
 | 
						|
    Identifier     "Mouse0"
 | 
						|
    Driver         "mouse"
 | 
						|
    Option         "Protocol" "auto"
 | 
						|
    Option         "Device" "/dev/psaux"
 | 
						|
    Option         "Emulate3Buttons" "no"
 | 
						|
    Option         "ZAxisMapping" "4 5"
 | 
						|
EndSection
 | 
						|
 | 
						|
Section "InputDevice"
 | 
						|
    Identifier     "Keyboard0"
 | 
						|
    Driver         "kbd"
 | 
						|
EndSection
 | 
						|
 | 
						|
Section "Monitor"
 | 
						|
    Identifier     "Monitor0"
 | 
						|
    VendorName     "Unknown"
 | 
						|
    ModelName      "Unknown"
 | 
						|
    HorizSync       30.0 - 130.0
 | 
						|
    VertRefresh     50.0 - 250.0
 | 
						|
    Option         "DPMS"
 | 
						|
EndSection
 | 
						|
 | 
						|
Section "Device"
 | 
						|
    Identifier     "Device0"
 | 
						|
    Driver         "foovideo"
 | 
						|
    VendorName     "foovideo Corporation"
 | 
						|
EndSection
 | 
						|
 | 
						|
Section "Screen"
 | 
						|
    Identifier     "Screen0"
 | 
						|
    Device         "Device0"
 | 
						|
    Monitor        "Monitor0"
 | 
						|
    DefaultDepth    24
 | 
						|
    SubSection     "Display"
 | 
						|
        Depth       24
 | 
						|
        Modes           "1280x1024"
 | 
						|
    EndSubSection
 | 
						|
EndSection
 | 
						|
 | 
						|
END
 | 
						|
	fi
 | 
						|
 | 
						|
	if [ -f "$config" ]; then
 | 
						|
		tweak_config $config
 | 
						|
	fi
 | 
						|
 | 
						|
	# now we need to get our tweaked config file onto the command line:
 | 
						|
	if [ "X$cmdline_config" = "X" ]; then
 | 
						|
		# append to cmdline (FUBAR will be substituted below.)
 | 
						|
		if [ "X$stype" = "Xxorg" ]; then
 | 
						|
			args="$args -config FUBAR"
 | 
						|
		else
 | 
						|
			args="$args -xf86config FUBAR"
 | 
						|
		fi
 | 
						|
	fi
 | 
						|
	if [ "X$config2" != "X" ]; then
 | 
						|
		# or modify $args:
 | 
						|
		c2=$config2
 | 
						|
		if [ "X$root" = "X" ]; then
 | 
						|
			# ordinary user cannot use absolute path.
 | 
						|
			c2=`basename $config2`
 | 
						|
		fi
 | 
						|
		args=`echo "$args" | sed \
 | 
						|
			-e "s,-config  *[^ ][^ ]*,-config $c2,g" \
 | 
						|
			-e "s,-xf86config  *[^ ][^ ]*,-xf86config $c2,g"`
 | 
						|
	fi
 | 
						|
fi
 | 
						|
 | 
						|
if [ $prconf ]; then
 | 
						|
	warn ""
 | 
						|
	warn "Printing out the Xorg/XFree86 server config file:"
 | 
						|
	warn ""
 | 
						|
	if [ "X$config2" = "X" ]; then
 | 
						|
		warn "NO CONFIG GENERATED."
 | 
						|
		exit 1
 | 
						|
	else
 | 
						|
		cat "$config2"
 | 
						|
	fi
 | 
						|
	exit 0
 | 
						|
fi
 | 
						|
 | 
						|
if [ $debug ]; then
 | 
						|
	XDUMMY_DEBUG=1
 | 
						|
	export XDUMMY_DEBUG
 | 
						|
fi
 | 
						|
if [ $root ]; then
 | 
						|
	XDUMMY_ROOT=1
 | 
						|
	export XDUMMY_ROOT
 | 
						|
fi
 | 
						|
 | 
						|
# Finally, run it:
 | 
						|
#
 | 
						|
if [ "X$debug" != "X" -o "X$runit" = "X" ]; then
 | 
						|
	if [ ! $runit ]; then
 | 
						|
		echo ""
 | 
						|
		echo "/usr/bin/env:"
 | 
						|
		env | egrep -v '^(LS_COLORS|TERMCAP)' | sort
 | 
						|
		echo ""
 | 
						|
		echo "XDUMMY*:"
 | 
						|
		env | grep '^XDUMMY' | sort
 | 
						|
		echo ""
 | 
						|
	fi
 | 
						|
	warn ""
 | 
						|
	warn "The command to run is:"
 | 
						|
	warn ""
 | 
						|
	so=$SO
 | 
						|
	pwd=`pwd`
 | 
						|
	if echo "$so" | grep '^\./' > /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 <stdio.h>
 | 
						|
#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 <unistd.h>
 | 
						|
#include <stdlib.h>
 | 
						|
#include <string.h>
 | 
						|
 | 
						|
#include <linux/vt.h>
 | 
						|
#include <linux/kd.h>
 | 
						|
 | 
						|
#define __USE_GNU
 | 
						|
#include <dlfcn.h>
 | 
						|
 | 
						|
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
 | 
						|
}
 |