http://packetstormsecurity.org/UNIX/admin/xscreensaver-4.01.tar.gz
[xscreensaver] / driver / xscreensaver-getimage.c
index c8e8228b6820af6711b371f9ab2a80637c378deb..46e3019eee924e3024348b265e53402e49870395 100644 (file)
 #include "utils.h"
 
 #include <X11/Intrinsic.h>
+#include <ctype.h>
 #include <errno.h>
 
+#ifdef HAVE_XMU
+# ifndef VMS
+#  include <X11/Xmu/Error.h>
+# else /* VMS */
+#  include <Xmu/Error.h>
+# endif
+#else
+# include "xmu.h"
+#endif
+
 #include "yarandom.h"
 #include "grabscreen.h"
 #include "resources.h"
 #include "colorbars.h"
+#include "visual.h"
 #include "prefs.h"
 #include "vroot.h"
 
@@ -94,6 +106,18 @@ exec_error (char **av)
   exit (1);
 }
 
+static int
+x_ehandler (Display *dpy, XErrorEvent *error)
+{
+  fprintf (stderr, "\nX error in %s:\n", progname);
+  if (XmuPrintDefaultErrorMessage (dpy, error, stderr))
+    exit (-1);
+  else
+    fprintf (stderr, " (nonfatal.)\n");
+  return 0;
+}
+
+
 
 static void
 get_image (Screen *screen, Window window, Bool verbose_p)
@@ -106,9 +130,10 @@ get_image (Screen *screen, Window window, Bool verbose_p)
 
   enum { do_desk, do_video, do_image, do_bars } which = do_bars;
   int count = 0;
-  if (desk_p) count++;
-  if (video_p) count++;
-  if (image_p) count++;
+
+  XWindowAttributes xgwa;
+  XGetWindowAttributes (dpy, window, &xgwa);
+  screen = xgwa.screen;
 
   if (verbose_p)
     {
@@ -146,7 +171,17 @@ get_image (Screen *screen, Window window, Bool verbose_p)
      know it's not a security problem to expose desktop bits.)
    */
 
-  if (window != VirtualRootWindowOfScreen (screen))
+  if ((desk_p || video_p || image_p) &&
+      !top_level_window_p (screen, window))
+    {
+      desk_p  = False;
+      video_p = False;
+      image_p = False;
+      if (verbose_p)
+        fprintf (stderr, "%s: not a top-level window: using colorbars.\n",
+                 progname);
+    }
+  else if (window != VirtualRootWindowOfScreen (screen))
     {
       Bool changed_p = False;
       if (!desk_p) desk_p  = True,  changed_p = True;
@@ -158,16 +193,25 @@ get_image (Screen *screen, Window window, Bool verbose_p)
                  progname);
     }
 
+  count = 0;
+  if (desk_p)  count++;
+  if (video_p) count++;
+  if (image_p) count++;
+
   if (count == 0)
     which = do_bars;
   else
-    while (1)  /* loop until we get one that's permitted */
-      {
-        which = (random() % 3);
-        if (which == do_desk  && desk_p)  break;
-        if (which == do_video && video_p) break;
-        if (which == do_image && image_p) break;
-      }
+    {
+      int i = 0;
+      while (1)  /* loop until we get one that's permitted */
+        {
+          which = (random() % 3);
+          if (which == do_desk  && desk_p)  break;
+          if (which == do_video && video_p) break;
+          if (which == do_image && image_p) break;
+          if (++i > 200) abort();
+        }
+    }
 
   if (which == do_desk)
     {
@@ -181,8 +225,6 @@ get_image (Screen *screen, Window window, Bool verbose_p)
     }
   else if (which == do_bars)
     {
-      XWindowAttributes xgwa;
-      XGetWindowAttributes (dpy, window, &xgwa);
       if (verbose_p)
         fprintf (stderr, "%s: drawing colorbars\n", progname);
       draw_colorbars (dpy, window, 0, 0, xgwa.width, xgwa.height);
@@ -237,8 +279,20 @@ get_image (Screen *screen, Window window, Bool verbose_p)
       {
         const char *odpy = DisplayString (dpy);
         char *ndpy = (char *) malloc(strlen(odpy) + 20);
+        char *s;
+        int screen_no = screen_number (screen);  /* might not be default now */
+
         strcpy (ndpy, "DISPLAY=");
-        strcat (ndpy, odpy);
+        s = ndpy + strlen(ndpy);
+        strcpy (s, odpy);
+
+        while (*s && *s != ':') s++;           /* skip to colon */
+        while (*s == ':') s++;                 /* skip over colons */
+        while (isdigit(*s)) s++;               /* skip over dpy number */
+        while (*s == '.') s++;                 /* skip over dot */
+        if (s[-1] != '.') *s++ = '.';          /* put on a dot */
+        sprintf(s, "%d", screen_no);           /* put on screen number */
+
         if (putenv (ndpy))
           abort ();
       }
@@ -306,6 +360,8 @@ main (int argc, char **argv)
   db = XtDatabase (dpy);
 
   XtGetApplicationNameAndClass (dpy, &s, &progclass);
+  XSetErrorHandler (x_ehandler);
+  XSync (dpy, False);
 
   /* half-assed way of avoiding buffer-overrun attacks. */
   if (strlen (progname) >= 100) progname[100] = 0;