http://www.jwz.org/xscreensaver/xscreensaver-5.13.tar.gz
[xscreensaver] / utils / grabclient.c
index 3589ad9821d6af4d6f983faf4e99799646861f79..45053e9a6720664cae885c462eace6f445f00dc4 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1992-2008 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1992-2011 Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -31,6 +31,8 @@
 # include <X11/Intrinsic.h>   /* for XtInputId, etc */
 #endif /* !HAVE_COCOA */
 
+#include <sys/stat.h>
+
 #ifdef HAVE_UNISTD_H
 # include <unistd.h>
 #endif
@@ -247,6 +249,11 @@ hack_subproc_environment (Display *dpy)
   if (putenv (ndpy))
     abort ();
 #endif /* HAVE_PUTENV */
+
+  /* don't free (ndpy) -- some implementations of putenv (BSD 4.4,
+     glibc 2.0) copy the argument, but some (libc4,5, glibc 2.1.2, MacOS)
+     do not.  So we must leak it (and/or the previous setting). Yay.
+   */
 }
 
 
@@ -538,6 +545,7 @@ struct pipe_closure {
   Screen *screen;
   Window xwindow;
   Drawable drawable;
+  char *directory;
   void (*callback) (Screen *, Window, Drawable,
                     const char *name, XRectangle *geom,
                     void *closure);
@@ -552,6 +560,8 @@ pipe_cb (XtPointer closure, int *source, XtInputId *id)
    */
   struct pipe_closure *clo2 = (struct pipe_closure *) closure;
   char buf[10240];
+  const char *dir = clo2->directory;
+  char *absfile = 0;
   fgets (buf, sizeof(buf)-1, clo2->pipe);
   pclose (clo2->pipe);
   clo2->pipe = 0;
@@ -566,8 +576,17 @@ pipe_cb (XtPointer closure, int *source, XtInputId *id)
   Display *dpy = DisplayOfScreen (clo2->screen);
   XRectangle geom;
 
+  if (*buf && *buf != '/')             /* pathname is relative to dir. */
+    {
+      absfile = malloc (strlen(dir) + strlen(buf) + 10);
+      strcpy (absfile, dir);
+      if (dir[strlen(dir)-1] != '/')
+        strcat (absfile, "/");
+      strcat (absfile, buf);
+    }
+
   if (! osx_load_image_file (clo2->screen, clo2->xwindow, clo2->drawable,
-                             buf, &geom)) {
+                             (absfile ? absfile : buf), &geom)) {
     /* unable to load image - draw colorbars 
      */
     XWindowAttributes xgwa;
@@ -575,6 +594,21 @@ pipe_cb (XtPointer closure, int *source, XtInputId *id)
     Window r;
     int x, y;
     unsigned int w, h, bbw, d;
+    struct stat st;
+
+    /* Log something to syslog so we can tell the difference between
+       corrupted images and broken symlinks. */
+    if (!*buf)
+      fprintf (stderr, "%s: no image filename found\n", progname);
+    else if (! stat (buf, &st))
+      fprintf (stderr, "%s: %s: unparsable\n", progname, buf);
+    else
+      {
+        char buf2[2048];
+        sprintf (buf2, "%.255s: %.1024s", progname, buf);
+        perror (buf2);
+      }
+
     XGetGeometry (dpy, clo2->drawable, &r, &x, &y, &w, &h, &bbw, &d);
     draw_colorbars (clo2->screen, xgwa.visual, clo2->drawable, xgwa.colormap,
                     0, 0, w, h);
@@ -583,9 +617,11 @@ pipe_cb (XtPointer closure, int *source, XtInputId *id)
     geom.height = h;
   }
 
+  if (absfile) free (absfile);
   clo2->callback (clo2->screen, clo2->xwindow, clo2->drawable, buf, &geom,
                   clo2->closure);
   clo2->callback = 0;
+  free (clo2->directory);
   free (clo2);
 }
 
@@ -623,6 +659,7 @@ osx_load_image_file_async (Screen *screen, Window xwindow, Drawable drawable,
 
   Display *dpy = DisplayOfScreen (screen);
   struct pipe_closure *clo2 = (struct pipe_closure *) calloc (1, sizeof(*clo2));
+  clo2->directory = strdup (dir);
   clo2->pipe = open_image_name_pipe (dir);
   clo2->id = XtAppAddInput (XtDisplayToApplicationContext (dpy), 
                             fileno (clo2->pipe),
@@ -708,11 +745,9 @@ load_random_image_1 (Screen *screen, Window window, Drawable drawable,
     done = True;
   }
 
-  if (! done) {
+  if (! done)
     draw_colorbars (screen, xgwa.visual, drawable, xgwa.colormap,
                     0, 0, xgwa.width, xgwa.height);
-    done = True;
-  }
 
   if (callback) {
     /* If we got here, we loaded synchronously even though they wanted async.