2 # ----------------------------------------------------------------------
3 # Copyright (C) 2005-2011 Karl J. Runge <runge@karlrunge.com>
6 # This file is part of Xdummy.
8 # Xdummy is free software; you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation; either version 2 of the License, or (at
11 # your option) any later version.
13 # Xdummy is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
18 # You should have received a copy of the GNU General Public License
19 # along with Xdummy; if not, write to the Free Software
20 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA
21 # or see <http://www.gnu.org/licenses/>.
22 # ----------------------------------------------------------------------
25 # Xdummy: an LD_PRELOAD hack to run a stock Xorg(1) or XFree86(1) server
26 # with the "dummy" video driver to make it avoid Linux VT switching, etc.
28 # Run "Xdummy -help" for more info.
45 PATH
=$PATH:/bin
:/usr
/bin
48 program
=`basename "$0"`
54 A hack to run a stock Xorg(1) or XFree86(1) X server with the "dummy"
55 (RAM-only framebuffer) video driver such that it AVOIDS the Linux VT
56 switching, opening device files in /dev, keyboard and mouse conflicts,
57 and other problems associated with the normal use of "dummy".
59 In other words, it tries to make Xorg/XFree86 with the "dummy"
60 device driver act more like Xvfb(1).
62 The primary motivation for the Xdummy script is to provide a virtual X
63 server for x11vnc but with more features than Xvfb (or Xvnc); however
64 it could be used for other reasons (e.g. better automated testing
65 than with Xvfb.) One nice thing is the dummy server supports RANDR
66 dynamic resizing while Xvfb does not.
68 So, for example, x11vnc+Xdummy terminal services are a little better
71 To achieve this, while running the real Xserver $program intercepts
72 system and library calls via the LD_PRELOAD method and modifies
73 the behavior to make it work correctly (e.g. avoid the VT stuff.)
74 LD_PRELOAD tricks are usually "clever hacks" and so might not work
75 in all situations or break when something changes.
77 WARNING: Take care in using Xdummy, although it never has it is
78 possible that it could damage hardware. One can use the -prconf
79 option to have it print out the xorg.conf config that it would use
80 and then inspect it carefully before actually using it.
82 This program no longer needs to be run as root as of 12/2009.
83 However, if there are problems for certain situations (usually older
84 servers) it may perform better if run as root (use the -root option.)
85 When running as root remember the previous paragraph and that Xdummy
86 comes without any warranty.
88 gcc/cc and other build tools are required for this script to be able
89 to compile the LD_PRELOAD shared object. Be sure they are installed
90 on the system. See -install and -uninstall described below.
92 Your Linux distribution may not install the dummy driver by default,
95 /usr/lib/xorg/modules/drivers/dummy_drv.so
97 some have it in a package named xserver-xorg-video-dummy you that
102 $program <${program}-args> <Xserver-args>
104 (actually, the arguments can be supplied in any order.)
114 $program -tmpdir ~/mytmp :1 -nolisten tcp
118 startx -e bash -- $program :2 -depth 16
120 (if startx needs to be run as root, you can su(1) to a normal
121 user in the bash shell and then launch ~/.xinitrc or ~/.xsession,
122 gnome-session, startkde, startxfce4, etc.)
126 xdm -config /usr/local/dummy/xdm-config -nodaemon
128 where the xdm-config file has line:
130 DisplayManager.servers: /usr/local/dummy/Xservers
132 and /usr/local/dummy/Xservers has lines:
134 :1 local /usr/local/dummy/Xdummy :1 -debug
135 :2 local /usr/local/dummy/Xdummy :2 -debug
145 If the file $program.cfg exists it will be sourced as shell
146 commands. Usually one will set some variables this way.
147 To disable sourcing, supply -nocfg or set XDUMMY_NOCFG=1.
149 Root permission and x11vnc:
151 Update: as of 12/2009 this program no longer must be run as root.
152 So try it as non-root before running it as root and/or the
155 In some circumstances X server program may need to be run as root.
156 If so, one could run x11vnc as root with -unixpw (it switches
157 to the user that logs in) and that may be OK, some other ideas:
159 - add this to sudo via visudo:
161 ALL ALL = NOPASSWD: /usr/local/bin/Xdummy
163 - use this little suid wrapper:
167 cc -o ./xdummy xdummy.c
168 sudo cp ./xdummy /usr/local/bin/xdummy
169 sudo chown root:root /usr/local/bin/xdummy
170 sudo chmod u+s /usr/local/bin/xdummy
175 #include <sys/types.h>
178 int main (int argc, char *argv[]) {
179 extern char **environ;
181 sprintf(str, "XDUMMY_UID=%d", (int) getuid());
185 execv("/usr/local/bin/Xdummy", argv);
195 -install Compile the LD_PRELOAD shared object and install it
196 next to the $program script file as:
200 When that file exists it is used as the LD_PRELOAD
201 shared object without recompiling. Otherwise,
202 each time $program is run the LD_PRELOAD shared
203 object is compiled as a file in /tmp (or -tmpdir)
205 If you set the environment variable
206 INTERPOSE_GETUID=1 when building, then when
207 $program is run as an ordinary user, the shared
208 object will interpose getuid() calls and pretend
209 to be root. Otherwise it doesn't pretend to
212 You can also set the CFLAGS environment variable
213 to anything else you want on the compile cmdline.
215 -uninstall Remove the file:
219 The LD_PRELOAD shared object will then be compiled
220 each time this program is run.
222 The X server is not started under -install, -uninstall, or -prconf.
225 :N The DISPLAY (e.g. :15) is often the first
226 argument. It is passed to the real X server and
227 also used by the Xdummy script as an identifier.
229 -geom geom1[,geom2...] Take the geometry (e.g. 1024x768) or list
230 of geometries and insert them into the Screen
231 section of the tweaked X server config file.
232 Use this to have a different geometry than the
233 one(s) in the system config file.
235 The option -geometry can be used instead of -geom;
236 x11vnc calls Xdummy and Xvfb this way.
238 -nomodelines When you specify -geom/-geometry, $program will
239 create Modelines for each geometry and put them
240 in the Monitor section. If you do not want this
241 then supply -nomodelines.
243 -depth n Use pixel color depth n (e.g. 8, 16, or 24). This
244 makes sure the X config file has a Screen.Display
245 subsection of this depth. Note this option is
246 ALSO passed to the X server.
248 -DEPTH n Same as -depth, except not passed to X server.
250 -tmpdir dir Specify a temporary directory, owned by you and
251 only writable by you. This is used in place of
252 /tmp/Xdummy.\$USER/.. to place the $program.so
253 shared object, tweaked config files, etc.
255 -nonroot Run in non-root mode (working 12/2009, now default)
257 -root Run as root (may still be needed in some
258 environments.) Same as XDUMMY_RUN_AS_ROOT=1.
260 -nosudo Do not try to use sudo(1) when re-running as root,
263 -xserver path Specify the path to the Xserver to use. Default
264 is to try "Xorg" first and then "XFree86". If
265 those are not in \$PATH, it tries these locations:
268 /usr/X11R6/bin/XFree86
270 -n Do not run the command to start the X server,
271 just show the command that $program would run.
272 The LD_PRELOAD shared object will be built,
273 if needed. Also note any XDUMMY* environment
274 variables that need to be set.
276 -prconf Print, to stdout, the tweaked Xorg/XFree86
277 config file (-config and -xf86config server
278 options, respectively.) The Xserver is not
281 -notweak Do not tweak (modify) the Xorg/XFree86 config file
282 (system or server command line) at all. The -geom
283 and similar config file modifications are ignored.
285 It is up to you to make sure it is a working
286 config file (e.g. "dummy" driver, etc.)
287 Perhaps you want to use a file based on the
290 -nocfg Do not try to source $program.cfg even if it
291 exists. Same as setting XDUMMY_NOCFG=1.
293 -debug Extra debugging output.
295 -strace strace(1) the Xserver process (for troubleshooting.)
296 -ltrace ltrace(1) instead of strace (can be slow.)
298 -h, -help Print out this help.
303 Most of the Xorg and XFree86 options will work and are simply
304 passed along if you supply them. Important ones that may be
307 :N X Display number for server to use.
309 vtNN Linux virtual terminal (VT) to use (a VT is currently
310 still used, just not switched to and from.)
312 -config file Driver "dummy" tweaked config file, a
313 -xf86config file number of settings are tweaked besides Driver.
315 If -config/-xf86config is not given, the system one
316 (e.g. /etc/X11/xorg.conf) is used. If the system one cannot be
317 found, a built-in one is used. Any settings in the config file
318 that are not consistent with "dummy" mode will be overwritten
319 (unless -notweak is specified.)
321 Use -config xdummy-builtin to force usage of the builtin config.
323 If "file" is only a basename (e.g. "xorg.dummy.conf") with no /'s,
324 then no tweaking of it is done: the X server will look for that
325 basename via its normal search algorithm. If the found file does
326 not refer to the "dummy" driver, etc, then the X server will fail.
328 You can set the env. var. XDUMMY_EXTRA_SERVER_ARGS to hold some
329 extra Xserver-args too. (Useful for cfg file.)
333 The Xorg/XFree86 "dummy" driver is currently undocumented. It works
334 well in this mode, but it is evidently not intended for end-users.
335 So it could be removed or broken at any time.
337 If the display Xserver-arg (e.g. :1) is not given, or ":" is given
338 that indicates $program should try to find a free one (based on
341 If the display virtual terminal, VT, (e.g. vt9) is not given that
342 indicates $program should try to find a free one (or guess a high one.)
344 This program is not completely secure WRT files in /tmp (but it tries
345 to a good degree.) Better is to use the -tmpdir option to supply a
346 directory only writable by you. Even better is to get rid of users
347 on the local machine you do not trust :-)
349 Set XDUMMY_SET_XV=1 to turn on debugging output for this script.
358 if [ "X$XDUMMY_SET_XV" != "X" ]; then
362 if [ "X$XDUMMY_UID" = "X" ]; then
366 if [ "X$XDUMMY_UID" = "X0" ]; then
367 if [ "X$SUDO_UID" != "X" ]; then
373 # check if root=1 first:
375 if [ "X$XDUMMY_RUN_AS_ROOT" = "X1" ]; then
380 if [ "X$arg" = "X-nonroot" ]; then
382 elif [ "X$arg" = "X-root" ]; then
384 elif [ "X$arg" = "X-nocfg" ]; then
390 if [ "X$XDUMMY_NOCFG" = "X" -a -f "$0.cfg" ]; then
394 # See if it really needs to be run as root:
396 if [ "X$XDUMMY_SU_EXEC" = "X" -a "X$root" = "X1" -a "X`id -u`" != "X0" ]; then
397 # this is to prevent infinite loop in case su/sudo doesn't work:
399 export XDUMMY_SU_EXEC
406 if [ "X$arg" = "X-nonroot" ]; then
408 elif [ "X$arg" = "X-nosudo" ]; then
410 elif [ "X$arg" = "X-help" ]; then
412 elif [ "X$arg" = "X-h" ]; then
414 elif [ "X$arg" = "X-install" ]; then
416 elif [ "X$arg" = "X-uninstall" ]; then
418 elif [ "X$arg" = "X-n" ]; then
420 elif [ "X$arg" = "X-prconf" ]; then
425 # we need to restart it with su/sudo:
426 if type sudo
> /dev
/null
2>&1; then
431 if [ "X$nosudo" = "X" ]; then
432 warn
"$program: supply the sudo password to restart as root:"
433 if [ "X$XDUMMY_UID" != "X" ]; then
434 exec sudo
$0 -uid $XDUMMY_UID "$@"
439 warn
"$program: supply the root password to restart as root:"
440 if [ "X$XDUMMY_UID" != "X" ]; then
441 exec su
-c "$0 -uid $XDUMMY_UID $*"
451 # This will hold the X display, e.g. :20
457 # Process Xdummy args:
459 while [ "X$1" != "X" ]
461 if [ "X$1" = "X-config" -o "X$1" = "X-xf86config" ]; then
467 "-install") install=1; runit
=""
469 "-uninstall") uninstall
=1; runit
=""
477 "-prconf") prconf
=1; runit
=""
479 "-notweak") notweak
=1
489 "-xserver") xserver
="$2"; shift
491 "-uid") XDUMMY_UID
="$2"; shift
494 "-geom") geom
="$2"; shift
496 "-geometry") geom
="$2"; shift
498 "-nomodelines") nomodelines
=1
500 "-depth") depth
="$2"; args
="$args -depth $2";
503 "-DEPTH") depth
="$2"; shift
505 "-tmpdir") XDUMMY_TMPDIR
="$2"; shift
519 "-help") help; exit 0
527 if [ "X$XDUMMY_EXTRA_SERVER_ARGS" != "X" ]; then
528 args
="$args $XDUMMY_EXTRA_SERVER_ARGS"
531 # Try to get a username for use in our tmp directory, etc.
534 if [ X
`id -u` = "X0" ]; then
535 user
=root
# this will also be used below for id=0
536 elif [ "X$USER" != "X" ]; then
538 elif [ "X$LOGNAME" != "X" ]; then
544 if [ "X$user" = "X" ]; then
545 user
=`whoami 2>/dev/null`
547 if [ "X$user" = "X" ]; then
548 user
=`basename "$HOME"`
550 if [ "X$user" = "X" -o "X$user" = "X." ]; then
554 if [ "X$debug" = "X1" -a "X$runit" != "X" ]; then
557 env |
egrep -v '^(LS_COLORS|TERMCAP)' |
sort
561 # Function to compile the LD_PRELOAD shared object:
564 # extract code embedded in this script into a tmp C file:
565 n1
=`grep -n '^#code_begin' $0 | head -1 | awk -F: '{print $1}'`
566 n2
=`grep -n '^#code_end' $0 | head -1 | awk -F: '{print $1}'`
570 tmp
=$tdir/Xdummy.
$RANDOM$$.c
572 if [ -e $tmp -o -h $tmp ]; then
573 warn
"$tmp still exists."
577 tail -n +$n1 $0 |
head -n $dn > $tmp
579 # compile it to Xdummy.so:
580 if [ -f "$SO" ]; then
586 if [ ! -f "$SO" ]; then
587 SO
=$tdir/Xdummy.
$user.so
588 warn
"warning switching LD_PRELOAD shared object to: $SO"
591 if [ -f "$SO" ]; then
598 if [ "X$INTERPOSE_GETUID" = "X1" ]; then
599 CFLAGS
="$CFLAGS -DINTERPOSE_GETUID"
601 echo "$program:" cc
-shared -fPIC $CFLAGS -o $SO $tmp
602 cc
-shared -fPIC $CFLAGS -o $SO $tmp
605 if [ $rc != 0 ]; then
606 warn
"$program: cannot build $SO"
609 if [ "X$debug" != "X" -o "X$install" != "X" ]; then
610 warn
"$program: created $SO"
615 # Set tdir to tmp dir for make_so():
616 if [ "X$XDUMMY_TMPDIR" != "X" ]; then
623 # Handle -install/-uninstall case:
625 if [ "X$install" != "X" -o "X$uninstall" != "X" ]; then
626 if [ -e "$SO" -o -h "$SO" ]; then
627 warn
"$program: removing $SO"
629 if [ -f "$SO" ]; then
634 if [ -e "$SO" -o -h "$SO" ]; then
635 warn
"warning: $SO still exists."
638 if [ $install ]; then
640 if [ ! -f "$SO" ]; then
647 # We need a tmp directory for the .so, tweaked config file, and for
648 # redirecting filenames we cannot create (under -nonroot)
651 if [ "X$XDUMMY_TMPDIR" = "X" ]; then
652 XDUMMY_TMPDIR
="/tmp/Xdummy.$user"
654 # try to tack on a unique subdir (display number or pid)
655 # to allow multiple instances
657 if [ "X$disp" != "X" ]; then
662 tack
=`echo "$t0" | sed -e 's/^.*://'`
663 if echo "$tack" |
grep '^[0-9][0-9]*$' > /dev
/null
; then
668 if [ "X$tack" != "X" ]; then
669 XDUMMY_TMPDIR
="$XDUMMY_TMPDIR/$tack"
674 if echo "$tmp" |
grep '^/tmp' > /dev
/null
; then
675 if [ "X$tmp" != "X/tmp" -a "X$tmp" != "X/tmp/" ]; then
676 # clean this subdir of /tmp out, otherwise leave it...
677 rm -rf $XDUMMY_TMPDIR
678 if [ -e $XDUMMY_TMPDIR ]; then
679 warn
"$XDUMMY_TMPDIR still exists"
685 mkdir
-p $XDUMMY_TMPDIR
686 chmod 700 $XDUMMY_TMPDIR
687 if [ "X$tack" != "X" ]; then
688 chmod 700 `dirname "$XDUMMY_TMPDIR"` 2>/dev
/null
691 # See if we can write something there:
693 tfile
="$XDUMMY_TMPDIR/test.file"
695 if [ ! -f "$tfile" ]; then
696 XDUMMY_TMPDIR
="/tmp/Xdummy.$$.$USER"
697 warn
"warning: setting tmpdir to $XDUMMY_TMPDIR ..."
698 rm -rf $XDUMMY_TMPDIR ||
exit 1
699 mkdir
-p $XDUMMY_TMPDIR ||
exit 1
705 # Compile the LD_PRELOAD shared object if needed (needs XDUMMY_TMPDIR)
707 if [ ! -f "$SO" ]; then
708 SO
="$XDUMMY_TMPDIR/Xdummy.so"
712 # Decide which X server to use:
714 if [ "X$xserver" = "X" ]; then
715 if type Xorg
>/dev
/null
2>&1; then
717 elif type XFree86
>/dev
/null
2>&1; then
719 elif -x /usr
/bin
/Xorg
; then
720 xserver
="/usr/bin/Xorg"
721 elif -x /usr
/X11R
6/bin
/Xorg
; then
722 xserver
="/usr/X11R6/bin/Xorg"
723 elif -x /usr
/X11R
6/bin
/XFree86
; then
724 xserver
="/usr/X11R6/bin/XFree86"
726 if [ "X$xserver" = "X" ]; then
727 # just let it fail below.
728 xserver
="/usr/bin/Xorg"
729 warn
"$program: cannot locate a stock Xserver... assuming $xserver"
733 # See if the binary is suid or not readable under -nonroot mode:
735 if [ "X$BASH_VERSION" != "X" ]; then
736 xserver_path
=`type -p $xserver 2>/dev/null`
738 xserver_path
=`type $xserver 2>/dev/null | awk '{print $NF}'`
740 if [ -e "$xserver_path" -a "X$root" = "X" -a "X$runit" != "X" ]; then
741 if [ ! -r $xserver_path -o -u $xserver_path -o -g $xserver_path ]; then
742 # XXX not quite correct with rm -rf $XDUMMY_TMPDIR ...
743 # we keep on a filesystem we know root can write to.
744 base
=`basename "$xserver_path"`
745 new
="/tmp/$base.$user.bin"
747 snew
=`ls -l $new | awk '{print $5}' | grep '^[0-9][0-9]*$'`
748 sold
=`ls -l $xserver_path | awk '{print $5}' | grep '^[0-9][0-9]*$'`
749 if [ "X$snew" != "X" -a "X$sold" != "X" -a "X$sold" != "X$snew" ]; then
750 warn
"removing different sized copy:"
751 ls -l $new $xserver_path
755 if [ ! -e $new -o ! -s $new ]; then
758 chmod 700 $new ||
exit 1
759 if [ ! -r $xserver_path ]; then
761 warn
"NEED TO COPY UNREADABLE $xserver_path to $new as root:"
763 ls -l $xserver_path 1>&2
765 warn
"This only needs to be done once:"
766 warn
" cat $xserver_path > $new"
769 if type sudo
> /dev
/null
2>&1; then
774 if [ "X$nos" = "X1" ]; then
775 warn
"Please supply root passwd to 'su -c'"
776 su
-c "cat $xserver_path > $new"
778 warn
"Please supply the sudo passwd if asked:"
779 sudo
/bin
/sh
-c "cat $xserver_path > $new"
783 warn
"COPYING SETUID $xserver_path to $new"
785 ls -l $xserver_path 1>&2
787 cat $xserver_path > $new
798 warn
"Please restart Xdummy now."
801 if [ ! -O $new ]; then
802 warn
"file \"$new\" not owned by us!"
812 if [ "X$disp" != "X" ]; then
814 elif [ "X$1" != "X" ]; then
815 if echo "$1" |
grep '^:[0-9]' > /dev
/null
; then
818 elif [ "X$1" = "X:" ]; then
819 # ":" means for us to find one.
823 if [ "X$disp" = "X" -o "X$disp" = "X:" ]; then
824 # try to find an open display port:
826 ports
=`netstat -ant | grep LISTEN | awk '{print $4}' | sed -e 's/^.*://'`
830 port
=`printf "60%02d" $n`
831 if echo "$ports" |
grep "^${port}\$" > /dev
/null
; then
835 warn
"$program: auto-selected DISPLAY $disp"
842 # Work out which vt to use, try to find/guess an open one if necessary.
847 if echo "$arg" |
grep '^vt' > /dev
/null
; then
852 if [ "X$vt" = "X" ]; then
853 if [ "X$user" = "Xroot" ]; then
854 # root can user fuser(1) to see if it is in use:
855 if type fuser
>/dev
/null
2>&1; then
856 # try /dev/tty17 thru /dev/tty32
861 if fuser
$dev >/dev
/null
2>&1; then
865 warn
"$program: auto-selected VT $vt => $dev"
872 if [ "X$vt" = "X" ]; then
873 # take a wild guess...
875 warn
"$program: selected fallback VT $vt"
881 # Decide flavor of Xserver:
883 stype
=`basename "$xserver"`
884 if echo "$stype" |
grep -i xfree86
> /dev
/null
; then
892 config2
="$XDUMMY_TMPDIR/xdummy_modified_xconfig.conf"
893 if [ "X$disp" != "X" ]; then
894 d
=`echo "$disp" | sed -e 's,/,,g' -e 's/:/_/g'`
898 # perl script to tweak the config file... add/delete options, etc.
900 env XDUMMY_GEOM
=$geom \
901 XDUMMY_DEPTH
=$depth \
902 XDUMMY_NOMODELINES
=$nomodelines \
903 perl
> $config2 < $in -e '
905 $geom = $ENV{XDUMMY_GEOM};
906 $depth = $ENV{XDUMMY_DEPTH};
907 $nomodelines = $ENV{XDUMMY_NOMODELINES};
909 $videoram = "240000";
910 $HorizSync = "30.0 - 130.0";
911 $VertRefresh = "50.0 - 250.0";
914 foreach $g (split(/,/, $geom)) {
916 if (!$nomodelines && $g =~ /(\d+)x(\d+)/) {
919 $mode_str .= " Modeline \"$g\" ";
920 my $dot = sprintf("%.2f", $w * $h * 70 * 1.e-6);
922 $mode_str .= " " . $w;
923 $mode_str .= " " . int(1.02 * $w);
924 $mode_str .= " " . int(1.10 * $w);
925 $mode_str .= " " . int(1.20 * $w);
926 $mode_str .= " " . $h;
927 $mode_str .= " " . int($h + 1);
928 $mode_str .= " " . int($h + 3);
929 $mode_str .= " " . int($h + 20);
937 if ($ENV{XDUMMY_NOTWEAK}) {
943 # pass comments straight thru
947 if (/^\s*Section\s+(\S+)/i) {
956 if (/^\s*EndSection/i) {
958 if ($sect eq "serverflags") {
959 if (!$got_DontVTSwitch) {
960 print " ##Xdummy:##\n";
961 print " Option \"DontVTSwitch\" \"true\"\n";
963 if (!$got_AllowMouseOpenFail) {
964 print " ##Xdummy:##\n";
965 print " Option \"AllowMouseOpenFail\" \"true\"\n";
967 if (!$got_PciForceNone) {
968 print " ##Xdummy:##\n";
969 print " Option \"PciForceNone\" \"true\"\n";
971 } elsif ($sect eq "device") {
973 print " ##Xdummy:##\n";
974 print " Driver \"dummy\"\n";
976 if (!$got_VideoRam) {
977 print " ##Xdummy:##\n";
978 print " VideoRam $videoram\n";
980 } elsif ($sect eq "screen") {
981 if ($depth ne "" && !got_DefaultDepth) {
982 print " ##Xdummy:##\n";
983 print " DefaultDepth $depth\n";
985 if ($got_Monitor eq "") {
986 print " ##Xdummy:##\n";
987 print " Monitor \"Monitor0\"\n";
989 } elsif ($sect eq "monitor") {
990 if (!got_HorizSync) {
991 print " ##Xdummy:##\n";
992 print " HorizSync $HorizSync\n";
994 if (!got_VertRefresh) {
995 print " ##Xdummy:##\n";
996 print " VertRefresh $VertRefresh\n";
999 print " ##Xdummy:##\n";
1008 if (/^\s*SubSection\s+(\S+)/i) {
1011 $subsect =~ s/\W//g;
1012 $subsect =~ y/A-Z/a-z/;
1013 $subsects{$subsect} = 1;
1014 if ($sect eq "screen" && $subsect eq "display") {
1020 if (/^\s*EndSubSection/i) {
1022 if ($sect eq "screen") {
1023 if ($subsect eq "display") {
1024 if ($depth ne "" && !$set_Depth) {
1025 print " ##Xdummy:##\n";
1026 print " Depth\t$depth\n";
1028 if ($geom ne "" && ! $got_Modes) {
1029 print " ##Xdummy:##\n";
1030 print " Modes\t$geom\n";
1041 if ($sect eq "serverflags") {
1042 if ($l =~ /^\s*Option.*DontVTSwitch/i) {
1043 $_ =~ s/false/true/ig;
1044 $got_DontVTSwitch = 1;
1046 if ($l =~ /^\s*Option.*AllowMouseOpenFail/i) {
1047 $_ =~ s/false/true/ig;
1048 $got_AllowMouseOpenFail = 1;
1050 if ($l =~ /^\s*Option.*PciForceNone/i) {
1051 $_ =~ s/false/true/ig;
1052 $got_PciForceNone= 1;
1055 if ($sect eq "module") {
1056 if ($l =~ /^\s*Load.*\b(dri|fbdevhw)\b/i) {
1057 $_ = "##Xdummy## $_";
1060 if ($sect eq "monitor") {
1061 if ($l =~ /^\s*HorizSync/i) {
1064 if ($l =~ /^\s*VertRefresh/i) {
1065 $got_VertRefresh = 1;
1068 if ($sect eq "device") {
1069 if ($l =~ /^(\s*Driver)\b/i) {
1070 $_ = "$1 \"dummy\"\n";
1073 if ($l =~ /^\s*VideoRam/i) {
1077 if ($sect eq "inputdevice") {
1078 if ($l =~ /^\s*Option.*\bDevice\b/i) {
1079 print " ##Xdummy:##\n";
1080 $_ = " Option \"Device\" \"/dev/dilbert$n\"\n";
1083 if ($sect eq "screen") {
1084 if ($l =~ /^\s*DefaultDepth\s+(\d+)/i) {
1086 print " ##Xdummy:##\n";
1087 $_ = " DefaultDepth\t$depth\n";
1089 $got_DefaultDepth = 1;
1091 if ($l =~ /^\s*Monitor\s+(\S+)/i) {
1093 $got_Monitor =~ s/"//g;
1095 if ($subsect eq "display") {
1097 if ($l =~ /^(\s*Modes)\b/i) {
1098 print " ##Xdummy:##\n";
1103 if ($l =~ /^\s*Depth\s+(\d+)/i) {
1105 if (!$set_Depth && $depth ne "") {
1108 print " ##Xdummy:##\n";
1109 $_ = " Depth\t$depth\n";
1117 if ($ENV{XDUMMY_NOTWEAK}) {
1120 # create any crucial sections that are missing:
1121 if (! exists($sects{serverflags})) {
1122 print "\n##Xdummy:##\n";
1123 print "Section \"ServerFlags\"\n";
1124 print " Option \"DontVTSwitch\" \"true\"\n";
1125 print " Option \"AllowMouseOpenFail\" \"true\"\n";
1126 print " Option \"PciForceNone\" \"true\"\n";
1127 print "EndSection\n";
1129 if (! exists($sects{device})) {
1130 print "\n##Xdummy:##\n";
1131 print "Section \"Device\"\n";
1132 print " Identifier \"Videocard0\"\n";
1133 print " Driver \"dummy\"\n";
1134 print " VideoRam $videoram\n";
1135 print "EndSection\n";
1137 if (! exists($sects{monitor})) {
1138 print "\n##Xdummy:##\n";
1139 print "Section \"Monitor\"\n";
1140 print " Identifier \"Monitor0\"\n";
1141 print " HorizSync $HorizSync\n";
1142 print " VertRefresh $VertRefresh\n";
1143 print "EndSection\n";
1145 if (! exists($sects{screen})) {
1146 print "\n##Xdummy:##\n";
1147 print "Section \"Screen\"\n";
1148 print " Identifier \"Screen0\"\n";
1149 print " Device \"Videocard0\"\n";
1150 if ($got_Monitor ne "") {
1151 print " Monitor \"$got_Monitor\"\n";
1153 print " Monitor \"Monitor0\"\n";
1156 print " DefaultDepth $depth\n";
1158 print " DefaultDepth 24\n";
1160 print " SubSection \"Display\"\n";
1161 print " Viewport 0 0\n";
1162 print " Depth 24\n";
1165 } elsif ($geom ne "") {
1166 print " Modes $geom\n";
1168 print " Modes \"1280x1024\" \"1024x768\" \"800x600\"\n";
1170 print " EndSubSection\n";
1171 print "EndSection\n";
1176 # Work out config file and tweak it.
1178 if [ "X$cmdline_config" = "X" ]; then
1180 elif [ "X$cmdline_config" = "Xxdummy-builtin" ]; then
1182 elif echo "$cmdline_config" |
grep '/' > /dev
/null
; then
1185 # ignore basename only case (let server handle it)
1190 config
=$cmdline_config
1192 if [ "X$notweak" = "X1" -a "X$root" = "X" -a -f "$cmdline_config" ]; then
1193 # if not root we need to copy (but not tweak) the specified config.
1195 export XDUMMY_NOTWEAK
1199 if [ ! $notweak ]; then
1200 # tweaked config will be put in $config2:
1202 if [ "X$config" = "X" ]; then
1203 # use the default one:
1204 if [ "X$stype" = "Xxorg" ]; then
1205 config
=/etc
/X11
/xorg.conf
1207 if [ -f "/etc/X11/XF86Config-4" ]; then
1208 config
="/etc/X11/XF86Config-4"
1210 config
="/etc/X11/XF86Config"
1213 if [ ! -f "$config" ]; then
1214 for c
in /etc
/X11
/xorg.conf
/etc
/X11
/XF86Config-4
/etc
/X11
/XF86Config
1224 if [ "X$config" = "Xxdummy-builtin" ]; then
1228 if [ ! -f "$config" ]; then
1229 config
="$XDUMMY_TMPDIR/xorg.conf"
1230 warn
"$program: using minimal built-in xorg.conf settings."
1233 Section "ServerLayout"
1234 Identifier "Layout0"
1236 InputDevice "Keyboard0" "CoreKeyboard"
1237 InputDevice "Mouse0" "CorePointer"
1250 Section "InputDevice"
1253 Option "Protocol" "auto"
1254 Option "Device" "/dev/psaux"
1255 Option "Emulate3Buttons" "no"
1256 Option "ZAxisMapping" "4 5"
1259 Section "InputDevice"
1260 Identifier "Keyboard0"
1265 Identifier "Monitor0"
1266 VendorName "Unknown"
1268 HorizSync 30.0 - 130.0
1269 VertRefresh 50.0 - 250.0
1274 Identifier "Device0"
1276 VendorName "foovideo Corporation"
1280 Identifier "Screen0"
1284 SubSection "Display"
1293 if [ -f "$config" ]; then
1294 tweak_config
$config
1297 # now we need to get our tweaked config file onto the command line:
1298 if [ "X$cmdline_config" = "X" ]; then
1299 # append to cmdline (FUBAR will be substituted below.)
1300 if [ "X$stype" = "Xxorg" ]; then
1301 args
="$args -config FUBAR"
1303 args
="$args -xf86config FUBAR"
1306 if [ "X$config2" != "X" ]; then
1309 if [ "X$root" = "X" ]; then
1310 # ordinary user cannot use absolute path.
1311 c2
=`basename $config2`
1313 args
=`echo "$args" | sed \
1314 -e "s,-config *[^ ][^ ]*,-config $c2,g" \
1315 -e "s,-xf86config *[^ ][^ ]*,-xf86config $c2,g"`
1319 if [ $prconf ]; then
1321 warn
"Printing out the Xorg/XFree86 server config file:"
1323 if [ "X$config2" = "X" ]; then
1324 warn
"NO CONFIG GENERATED."
1343 if [ "X$debug" != "X" -o "X$runit" = "X" ]; then
1344 if [ ! $runit ]; then
1346 echo "/usr/bin/env:"
1347 env |
egrep -v '^(LS_COLORS|TERMCAP)' |
sort
1350 env |
grep '^XDUMMY' |
sort
1354 warn
"The command to run is:"
1358 if echo "$so" |
grep '^\./' > /dev
/null
; then
1359 so
=`echo "$so" | sed -e "s,^\.,$pwd,"`
1361 if echo "$so" |
grep '/' > /dev
/null
; then
1366 warn
"env LD_PRELOAD=$so $xserver $disp $args $vt"
1368 if [ ! $runit ]; then
1373 if [ $strace ]; then
1374 if [ "X$strace" = "X2" ]; then
1375 ltrace
-f env LD_PRELOAD
=$SO $xserver $disp $args $vt
1377 strace
-f env LD_PRELOAD
=$SO $xserver $disp $args $vt
1380 exec env LD_PRELOAD
=$SO $xserver $disp $args $vt
1385 #########################################################################
1390 #define O_ACCMODE 0003
1394 #define O_CREAT 0100 /* not fcntl */
1395 #define O_EXCL 0200 /* not fcntl */
1396 #define O_NOCTTY 0400 /* not fcntl */
1397 #define O_TRUNC 01000 /* not fcntl */
1398 #define O_APPEND 02000
1399 #define O_NONBLOCK 04000
1400 #define O_NDELAY O_NONBLOCK
1401 #define O_SYNC 010000
1402 #define O_FSYNC O_SYNC
1403 #define O_ASYNC 020000
1409 #include <linux/vt.h>
1410 #include <linux/kd.h>
1415 static char tmpdir
[4096];
1416 static char str1
[4096];
1417 static char str2
[4096];
1419 static char devs
[256][1024];
1420 static int debug
= -1;
1421 static int root
= -1;
1422 static int changed_uid
= 0;
1423 static int saw_fonts
= 0;
1424 static int saw_lib_modules
= 0;
1426 static time_t start
= 0;
1428 void check_debug
(void
) {
1430 if (getenv
("XDUMMY_DEBUG") != NULL
) {
1435 /* prevent other processes using the preload
: */
1436 putenv
("LD_PRELOAD=");
1439 void check_root
(void
) {
1441 /* script tells us
if we are root
*/
1442 if (getenv
("XDUMMY_ROOT") != NULL
) {
1450 void check_uid
(void
) {
1453 if (debug
) fprintf
(stderr
, "START: %u\n", (unsigned int
) start
);
1455 } else if (changed_uid
== 0) {
1456 if (saw_fonts ||
time(NULL
) > start
+ 20) {
1457 if (getenv
("XDUMMY_UID")) {
1458 int uid
= atoi
(getenv
("XDUMMY_UID"));
1459 if (debug
) fprintf
(stderr
, "SETREUID: %d saw_fonts=%d\n", uid
, saw_fonts
);
1461 /* this will simply fail
in -nonroot mode
: */
1470 #define CHECKIT if (debug < 0) check_debug(); \
1471 if (root
< 0) check_root
(); \
1474 static void set_tmpdir
(void
) {
1476 static int didset
= 0;
1480 s
= getenv
("XDUMMY_TMPDIR");
1486 strcat
(tmpdir
, "/");
1490 static char
*tmpdir_path
(const char
*path
) {
1501 strcpy
(str1
, tmpdir
);
1506 int open
(const char
*pathname
, int flags
, unsigned short mode
) {
1508 char
*store_dev
= NULL
;
1509 static int
(*real_open
)(const char
*, int
, unsigned short
) = NULL
;
1513 real_open
= (int
(*)(const char
*, int
, unsigned short
))
1514 dlsym
(RTLD_NEXT
, "open");
1517 if (strstr
(pathname
, "lib/modules/")) {
1518 /* not currently used.
*/
1519 saw_lib_modules
= 1;
1523 if (strstr
(pathname
, "/dev/") == pathname
) {
1524 store_dev
= strdup
(pathname
);
1526 if (strstr
(pathname
, "/dev/tty") == pathname
&& strcmp
(pathname
, "/dev/tty")) {
1527 pathname
= tmpdir_path
(pathname
);
1528 if (debug
) fprintf
(stderr
, "OPEN: %s -> %s (as FIFO)\n", store_dev
, pathname
);
1529 /* we
make it a FIFO so ioctl on it does not fail
*/
1531 mkfifo(pathname
, 0666);
1533 /* we used to handle
more /dev files ...
*/
1534 fd
= real_open
(pathname
, O_WRONLY|O_CREAT
, 0777);
1539 fd
= real_open
(pathname
, flags
, mode
);
1541 if (debug
) fprintf
(stderr
, "OPEN: %s %d %d fd=%d\n", pathname
, flags
, mode
, fd
);
1546 strcpy
(devs
[fd
], store_dev
);
1555 int open64
(const char
*pathname
, int flags
, unsigned short mode
) {
1559 if (debug
) fprintf
(stderr
, "OPEN64: %s %d %d\n", pathname
, flags
, mode
);
1561 fd
= open
(pathname
, flags
, mode
);
1565 int rename
(const char
*oldpath
, const char
*newpath
) {
1566 static int
(*real_rename
)(const char
*, const char
*) = NULL
;
1569 if (! real_rename
) {
1570 real_rename
= (int
(*)(const char
*, const char
*))
1571 dlsym
(RTLD_NEXT
, "rename");
1574 if (debug
) fprintf
(stderr
, "RENAME: %s %s\n", oldpath
, newpath
);
1577 return(real_rename
(oldpath
, newpath
));
1580 if (strstr
(oldpath
, "/var/log") == oldpath
) {
1581 if (debug
) fprintf
(stderr
, "RENAME: returning 0\n");
1584 return(real_rename
(oldpath
, newpath
));
1587 FILE
*fopen
(const char
*pathname
, const char
*mode
) {
1588 static FILE
* (*real_fopen
)(const char
*, const char
*) = NULL
;
1592 if (strstr
(pathname
, "/fonts/")) {
1593 if (strstr
(pathname
, "fonts.dir")) {
1595 } else if (strstr
(pathname
, "fonts.alias")) {
1603 real_fopen
= (FILE
* (*)(const char
*, const char
*))
1604 dlsym
(RTLD_NEXT
, "fopen");
1607 if (debug
) fprintf
(stderr
, "FOPEN: %s %s\n", pathname
, mode
);
1609 if (strstr
(pathname
, "xdummy_modified_xconfig.conf")) {
1610 /* make our config appear to be
in /etc
/X11
, etc.
*/
1611 char
*q
= strrchr
(pathname
, '/');
1612 if (q
!= NULL
&& getenv
("XDUMMY_TMPDIR") != NULL
) {
1613 strcpy
(str1
, getenv
("XDUMMY_TMPDIR"));
1615 if (debug
) fprintf
(stderr
, "FOPEN: %s -> %s\n", pathname
, str1
);
1621 return(real_fopen
(pathname
, mode
));
1624 str
= (char
*) pathname
;
1625 if (strstr
(pathname
, "/var/log") == pathname
) {
1626 str
= tmpdir_path
(pathname
);
1627 if (debug
) fprintf
(stderr
, "FOPEN: %s -> %s\n", pathname
, str
);
1629 return(real_fopen
(str
, mode
));
1633 #define RETURN0 if (debug) \
1634 {fprintf
(stderr
, "IOCTL: covered %d 0x%x\n", fd
, req
);} return 0;
1635 #define RETURN1 if (debug) \
1636 {fprintf
(stderr
, "IOCTL: covered %d 0x%x\n", fd
, req
);} return -1;
1638 int ioctl
(int fd
, int req
, void
*ptr
) {
1639 static int closed_xf86Info_consoleFd
= 0;
1640 static int
(*real_ioctl
)(int
, int
, void
*) = NULL
;
1644 real_ioctl
= (int
(*)(int
, int
, void
*))
1645 dlsym
(RTLD_NEXT
, "open");
1647 if (debug
) fprintf
(stderr
, "IOCTL: %d 0x%x %p\n", fd
, req
, ptr
);
1649 /* based on xorg-x11-6.8
.1-dualhead.
patch */
1650 if (req
== VT_GETMODE
) {
1651 /* close
(xf86Info.consoleFd
) */
1652 if (0 && ! closed_xf86Info_consoleFd
) {
1653 /* I think better not to close it...
*/
1655 closed_xf86Info_consoleFd
= 1;
1658 } else if (req
== VT_SETMODE
) {
1660 } else if (req
== VT_GETSTATE
) {
1662 } else if (req
== KDSETMODE
) {
1664 } else if (req
== KDSETLED
) {
1666 } else if (req
== KDGKBMODE
) {
1668 } else if (req
== KDSKBMODE
) {
1670 } else if (req
== VT_ACTIVATE
) {
1672 } else if (req
== VT_WAITACTIVE
) {
1674 } else if (req
== VT_RELDISP
) {
1675 if (ptr
== (void
*) 1) {
1677 } else if (ptr
== (void
*) VT_ACKACQ
) {
1682 return(real_ioctl
(fd
, req
, ptr
));
1685 typedef void
(*sighandler_t
)(int
);
1687 #define SIG_DFL ((sighandler_t)0)
1689 sighandler_t signal
(int signum
, sighandler_t handler
) {
1690 static sighandler_t
(*real_signal
)(int
, sighandler_t
) = NULL
;
1693 if (! real_signal
) {
1694 real_signal
= (sighandler_t
(*)(int
, sighandler_t
))
1695 dlsym
(RTLD_NEXT
, "signal");
1698 if (debug
) fprintf
(stderr
, "SIGNAL: %d %p\n", signum
, handler
);
1700 if (signum
== SIGUSR1
) {
1701 if (debug
) fprintf
(stderr
, "SIGNAL: skip SIGUSR1\n");
1705 return(real_signal
(signum
, handler
));
1709 static int
(*real_close
)(int
) = NULL
;
1713 real_close
= (int
(*)(int
)) dlsym
(RTLD_NEXT
, "close");
1716 if (debug
) fprintf
(stderr
, "CLOSE: %d\n", fd
);
1722 return(real_close
(fd
));
1729 int stat
(const char
*path
, struct stat
*buf
) {
1730 static int
(*real_stat
)(const char
*, struct stat
*) = NULL
;
1734 real_stat
= (int
(*)(const char
*, struct stat
*))
1735 dlsym
(RTLD_NEXT
, "stat");
1738 if (debug
) fprintf
(stderr
, "STAT: %s\n", path
);
1740 return(real_stat
(path
, buf
));
1743 int stat64
(const char
*path
, struct stat
*buf
) {
1744 static int
(*real_stat64
)(const char
*, struct stat
*) = NULL
;
1747 if (! real_stat64
) {
1748 real_stat64
= (int
(*)(const char
*, struct stat
*))
1749 dlsym
(RTLD_NEXT
, "stat64");
1752 if (debug
) fprintf
(stderr
, "STAT64: %s\n", path
);
1754 return(real_stat64
(path
, buf
));
1757 int chown
(const char
*path
, uid_t owner
, gid_t group
) {
1758 static int
(*real_chown
)(const char
*, uid_t
, gid_t
) = NULL
;
1762 real_chown
= (int
(*)(const char
*, uid_t
, gid_t
))
1763 dlsym
(RTLD_NEXT
, "chown");
1767 return(real_chown
(path
, owner
, group
));
1770 if (debug
) fprintf
(stderr
, "CHOWN: %s %d %d\n", path
, owner
, group
);
1772 if (strstr
(path
, "/dev") == path
) {
1773 if (debug
) fprintf
(stderr
, "CHOWN: return 0\n");
1777 return(real_chown
(path
, owner
, group
));
1780 extern int
*__errno_location
(void
);
1785 int ioperm
(unsigned long from
, unsigned long num
, int turn_on
) {
1786 static int
(*real_ioperm
)(unsigned long
, unsigned long
, int
) = NULL
;
1789 if (! real_ioperm
) {
1790 real_ioperm
= (int
(*)(unsigned long
, unsigned long
, int
))
1791 dlsym
(RTLD_NEXT
, "ioperm");
1793 if (debug
) fprintf
(stderr
, "IOPERM: %d %d %d\n", (int
) from
, (int
) num
, turn_on
);
1795 return(real_ioperm
(from
, num
, turn_on
));
1797 if (from
== 0 && num
== 1024 && turn_on
== 1) {
1798 /* we want xf86EnableIO to fail
*/
1799 if (debug
) fprintf
(stderr
, "IOPERM: setting ENODEV.\n");
1800 *__errno_location
() = ENODEV
;
1806 int iopl
(int level
) {
1807 static int
(*real_iopl
)(int
) = NULL
;
1811 real_iopl
= (int
(*)(int
)) dlsym
(RTLD_NEXT
, "iopl");
1813 if (debug
) fprintf
(stderr
, "IOPL: %d\n", level
);
1815 return(real_iopl
(level
));
1820 #ifdef INTERPOSE_GETUID
1823 * we got things to work w
/o pretending to be root.
1824 * so we no longer interpose getuid
(), etc.
1827 uid_t getuid
(void
) {
1828 static uid_t
(*real_getuid
)(void
) = NULL
;
1830 if (! real_getuid
) {
1831 real_getuid
= (uid_t
(*)(void
)) dlsym
(RTLD_NEXT
, "getuid");
1834 return(real_getuid
());
1836 if (debug
) fprintf
(stderr
, "GETUID: 0\n");
1839 uid_t geteuid
(void
) {
1840 static uid_t
(*real_geteuid
)(void
) = NULL
;
1842 if (! real_geteuid
) {
1843 real_geteuid
= (uid_t
(*)(void
)) dlsym
(RTLD_NEXT
, "geteuid");
1846 return(real_geteuid
());
1848 if (debug
) fprintf
(stderr
, "GETEUID: 0\n");
1851 uid_t geteuid_kludge1
(void
) {
1852 static uid_t
(*real_geteuid
)(void
) = NULL
;
1854 if (! real_geteuid
) {
1855 real_geteuid
= (uid_t
(*)(void
)) dlsym
(RTLD_NEXT
, "geteuid");
1857 if (debug
) fprintf
(stderr
, "GETEUID: 0 saw_libmodules=%d\n", saw_lib_modules
);
1858 if (root
&& !saw_lib_modules
) {
1859 return(real_geteuid
());
1861 saw_lib_modules
= 0;
1866 uid_t getuid32
(void
) {
1867 static uid_t
(*real_getuid32
)(void
) = NULL
;
1869 if (! real_getuid32
) {
1870 real_getuid32
= (uid_t
(*)(void
)) dlsym
(RTLD_NEXT
, "getuid32");
1873 return(real_getuid32
());
1875 if (debug
) fprintf
(stderr
, "GETUID32: 0\n");
1878 uid_t geteuid32
(void
) {
1879 static uid_t
(*real_geteuid32
)(void
) = NULL
;
1881 if (! real_geteuid32
) {
1882 real_geteuid32
= (uid_t
(*)(void
)) dlsym
(RTLD_NEXT
, "geteuid32");
1885 return(real_geteuid32
());
1887 if (debug
) fprintf
(stderr
, "GETEUID32: 0\n");
1891 gid_t getgid
(void
) {
1892 static gid_t
(*real_getgid
)(void
) = NULL
;
1894 if (! real_getgid
) {
1895 real_getgid
= (gid_t
(*)(void
)) dlsym
(RTLD_NEXT
, "getgid");
1898 return(real_getgid
());
1900 if (debug
) fprintf
(stderr
, "GETGID: 0\n");
1903 gid_t getegid
(void
) {
1904 static gid_t
(*real_getegid
)(void
) = NULL
;
1906 if (! real_getegid
) {
1907 real_getegid
= (gid_t
(*)(void
)) dlsym
(RTLD_NEXT
, "getegid");
1910 return(real_getegid
());
1912 if (debug
) fprintf
(stderr
, "GETEGID: 0\n");
1915 gid_t getgid32
(void
) {
1916 static gid_t
(*real_getgid32
)(void
) = NULL
;
1918 if (! real_getgid32
) {
1919 real_getgid32
= (gid_t
(*)(void
)) dlsym
(RTLD_NEXT
, "getgid32");
1922 return(real_getgid32
());
1924 if (debug
) fprintf
(stderr
, "GETGID32: 0\n");
1927 gid_t getegid32
(void
) {
1928 static gid_t
(*real_getegid32
)(void
) = NULL
;
1930 if (! real_getegid32
) {
1931 real_getegid32
= (gid_t
(*)(void
)) dlsym
(RTLD_NEXT
, "getegid32");
1934 return(real_getegid32
());
1936 if (debug
) fprintf
(stderr
, "GETEGID32: 0\n");
1942 /* maybe we need to interpose on strcmp someday... here is the template
*/
1943 int strcmp
(const char
*s1
, const char
*s2
) {
1944 static int
(*real_strcmp
)(const char
*, const char
*) = NULL
;
1946 if (! real_strcmp
) {
1947 real_strcmp
= (int
(*)(const char
*, const char
*)) dlsym
(RTLD_NEXT
, "strcmp");
1949 if (debug
) fprintf
(stderr
, "STRCMP: '%s' '%s'\n", s1
, s2
);
1950 return(real_strcmp
(s1
, s2
));