http://packetstormsecurity.org/UNIX/admin/xscreensaver-3.32.tar.gz
[xscreensaver] / driver / xscreensaver-getimage.c
1 /* xscreensaver, Copyright (c) 2001 by Jamie Zawinski <jwz@jwz.org>
2  *
3  * Permission to use, copy, modify, distribute, and sell this software and its
4  * documentation for any purpose is hereby granted without fee, provided that
5  * the above copyright notice appear in all copies and that both that
6  * copyright notice and this permission notice appear in supporting
7  * documentation.  No representations are made about the suitability of this
8  * software for any purpose.  It is provided "as is" without express or 
9  * implied warranty.
10  */
11
12 /* xscreensaver-getimage -- helper program that puts an image
13    (e.g., a snapshot of the desktop) onto the given window.
14  */
15
16 #include "utils.h"
17
18 #include <X11/Intrinsic.h>
19 #include <errno.h>
20
21 #include "yarandom.h"
22 #include "grabscreen.h"
23 #include "resources.h"
24 #include "colorbars.h"
25 #include "prefs.h"
26 #include "vroot.h"
27
28
29 static char *defaults[] = {
30 #include "../driver/XScreenSaver_ad.h"
31  0
32 };
33
34
35
36 char *progname = 0;
37 char *progclass = "XScreenSaver";
38 XrmDatabase db;
39 XtAppContext app;
40
41 extern void grabscreen_verbose (void);
42
43
44 #define GETIMAGE_VIDEO_PROGRAM "xscreensaver-getimage-video"
45 #define GETIMAGE_FILE_PROGRAM  "xscreensaver-getimage-file"
46
47
48 const char *
49 blurb (void)
50 {
51   return progname;
52 }
53
54
55 static void
56 exec_error (char **av)
57 {
58   char buf [512];
59   char *token;
60
61   sprintf (buf, "%s: could not execute \"%s\"", progname, av[0]);
62   perror (buf);
63
64   if (errno == ENOENT &&
65       (token = getenv("PATH")))
66     {
67 # ifndef PATH_MAX
68 #  ifdef MAXPATHLEN
69 #   define PATH_MAX MAXPATHLEN
70 #  else
71 #   define PATH_MAX 2048
72 #  endif
73 # endif
74       char path[PATH_MAX];
75       fprintf (stderr, "\n");
76       *path = 0;
77 # if defined(HAVE_GETCWD)
78       getcwd (path, sizeof(path));
79 # elif defined(HAVE_GETWD)
80       getwd (path);
81 # endif
82       if (*path)
83         fprintf (stderr, "    Current directory is: %s\n", path);
84       fprintf (stderr, "    PATH is:\n");
85       token = strtok (strdup(token), ":");
86       while (token)
87         {
88           fprintf (stderr, "        %s\n", token);
89           token = strtok(0, ":");
90         }
91       fprintf (stderr, "\n");
92     }
93
94   exit (1);
95 }
96
97
98 static void
99 get_image (Screen *screen, Window window, Bool verbose_p)
100 {
101   Display *dpy = DisplayOfScreen (screen);
102   Bool desk_p  = get_boolean_resource ("grabDesktopImages",  "Boolean");
103   Bool video_p = get_boolean_resource ("grabVideoFrames",    "Boolean");
104   Bool image_p = get_boolean_resource ("chooseRandomImages", "Boolean");
105   char *dir    = get_string_resource ("imageDirectory", "ImageDirectory");
106
107   enum { do_desk, do_video, do_image, do_bars } which = do_bars;
108   int count = 0;
109   if (desk_p) count++;
110   if (video_p) count++;
111   if (image_p) count++;
112
113   if (verbose_p)
114     {
115       fprintf (stderr, "%s: grabDesktopImages:  %s\n",
116                progname, desk_p ? "True" : "False");
117       fprintf (stderr, "%s: grabVideoFrames:    %s\n",
118                progname, video_p ? "True" : "False");
119       fprintf (stderr, "%s: chooseRandomImages: %s\n",
120                progname, image_p ? "True" : "False");
121       fprintf (stderr, "%s: imageDirectory:     %s\n",
122                progname, (dir ? dir : ""));
123     }
124
125   if (!dir || !*dir)
126     {
127       if (verbose_p && image_p)
128         fprintf (stderr,
129                  "%s: no imageDirectory: turning off chooseRandomImages.\n",
130                  progname);
131       image_p = False;
132     }
133
134 # ifndef _VROOT_H_
135 #  error Error!  This file definitely needs vroot.h!
136 # endif
137
138   /* If the window is not the root window (real or virtual!) then the hack
139      that called this program is running in "-window" mode instead of in
140      "-root" mode.
141
142      If the window is not the root window, then it's not possible to grab
143      video or images onto it (the contract with those programs is to draw on
144      the root.)  So turn off those options in that case, and turn on desktop
145      grabbing.  (Since we're running in a window on the desktop already, we
146      know it's not a security problem to expose desktop bits.)
147    */
148
149   if (window != VirtualRootWindowOfScreen (screen))
150     {
151       Bool changed_p = False;
152       if (!desk_p) desk_p  = True,  changed_p = True;
153       if (video_p) video_p = False, changed_p = True;
154       if (image_p) image_p = False, changed_p = True;
155       if (changed_p && verbose_p)
156         fprintf (stderr,
157                  "%s: not running on root window: grabbing desktop.\n",
158                  progname);
159     }
160
161   if (count == 0)
162     which = do_bars;
163   else
164     while (1)  /* loop until we get one that's permitted */
165       {
166         which = (random() % 3);
167         if (which == do_desk  && desk_p)  break;
168         if (which == do_video && video_p) break;
169         if (which == do_image && image_p) break;
170       }
171
172   if (which == do_desk)
173     {
174       if (verbose_p)
175         {
176           fprintf (stderr, "%s: grabbing desktop image\n", progname);
177           grabscreen_verbose();
178         }
179       grab_screen_image (screen, window);
180       XSync (dpy, False);
181     }
182   else if (which == do_bars)
183     {
184       XWindowAttributes xgwa;
185       XGetWindowAttributes (dpy, window, &xgwa);
186       if (verbose_p)
187         fprintf (stderr, "%s: drawing colorbars\n", progname);
188       draw_colorbars (dpy, window, 0, 0, xgwa.width, xgwa.height);
189       XSync (dpy, False);
190     }
191   else
192     {
193       char *av[10];
194       memset (av, 0, sizeof(av));
195       switch (which)
196         {
197         case do_video:
198           if (verbose_p)
199             fprintf (stderr, "%s: grabbing video\n", progname);
200           av[0] = GETIMAGE_VIDEO_PROGRAM;
201           break;
202         case do_image:
203           if (verbose_p)
204             fprintf (stderr, "%s: loading random image file\n", progname);
205           av[0] = GETIMAGE_FILE_PROGRAM;
206           av[1] = dir;
207           break;
208         default:
209           abort();
210           break;
211         }
212
213       if (verbose_p)
214         {
215           int i;
216           for (i = (sizeof(av)/sizeof(*av))-1; i > 1; i--)
217             av[i] = av[i-1];
218           av[1] = strdup ("--verbose");
219         }
220
221       if (verbose_p)
222         {
223           int i = 0;
224           fprintf (stderr, "%s: executing \"", progname);
225           while (av[i])
226             {
227               fprintf (stderr, "%s", av[i]);
228               if (av[++i]) fprintf (stderr, " ");
229             }
230           fprintf (stderr, "\"\n");
231         }
232
233 # ifdef HAVE_PUTENV
234       /* Store our "-display" argument into the $DISPLAY variable,
235          so that the subprocess gets the right display if the
236          prevailing $DISPLAY is different. */
237       {
238         const char *odpy = DisplayString (dpy);
239         char *ndpy = (char *) malloc(strlen(odpy) + 20);
240         strcpy (ndpy, "DISPLAY=");
241         strcat (ndpy, odpy);
242         if (putenv (ndpy))
243           abort ();
244       }
245 # endif /* HAVE_PUTENV */
246
247       close (ConnectionNumber (dpy));   /* close display fd */
248
249       execvp (av[0], av);               /* shouldn't return */
250       exec_error (av);
251     }
252 }
253
254
255 #if 0
256 static Bool
257 mapper (XrmDatabase *db, XrmBindingList bindings, XrmQuarkList quarks,
258         XrmRepresentation *type, XrmValue *value, XPointer closure)
259 {
260   int i;
261   for (i = 0; quarks[i]; i++)
262     {
263       if (bindings[i] == XrmBindTightly)
264         fprintf (stderr, (i == 0 ? "" : "."));
265       else if (bindings[i] == XrmBindLoosely)
266         fprintf (stderr, "*");
267       else
268         fprintf (stderr, " ??? ");
269       fprintf(stderr, "%s", XrmQuarkToString (quarks[i]));
270     }
271
272   fprintf (stderr, ": %s\n", (char *) value->addr);
273
274   return False;
275 }
276 #endif
277
278
279 int
280 main (int argc, char **argv)
281 {
282   saver_preferences P;
283   Widget toplevel;
284   Display *dpy;
285   Screen *screen;
286   Window window = (Window) 0;
287   Bool verbose_p = False;
288   char *s;
289   int i;
290
291   progname = argv[0];
292   s = strrchr (progname, '/');
293   if (s) progname = s+1;
294
295   /* We must read exactly the same resources as xscreensaver.
296      That means we must have both the same progclass *and* progname,
297      at least as far as the resource database is concerned.  So,
298      put "xscreensaver" in argv[0] while initializing Xt.
299    */
300   argv[0] = "xscreensaver";
301   toplevel = XtAppInitialize (&app, progclass, 0, 0, &argc, argv,
302                               defaults, 0, 0);
303   argv[0] = progname;
304   dpy = XtDisplay (toplevel);
305   screen = XtScreen (toplevel);
306   db = XtDatabase (dpy);
307
308   XtGetApplicationNameAndClass (dpy, &s, &progclass);
309
310   /* half-assed way of avoiding buffer-overrun attacks. */
311   if (strlen (progname) >= 100) progname[100] = 0;
312
313   for (i = 1; i < argc; i++)
314     {
315       if (argv[i][0] == '-' && argv[i][1] == '-') argv[i]++;
316       if (!strcmp (argv[i], "-v") ||
317           !strcmp (argv[i], "-verbose"))
318         verbose_p = True;
319       else if (window == 0)
320         {
321           unsigned long w;
322           char dummy;
323
324           if (!strcmp (argv[i], "root") ||
325               !strcmp (argv[i], "-root") ||
326               !strcmp (argv[i], "--root"))
327             window = RootWindowOfScreen (screen);
328
329           else if ((1 == sscanf (argv[i], " 0x%x %c", &w, &dummy) ||
330                     1 == sscanf (argv[i], " %d %c",   &w, &dummy)) &&
331                    w != 0)
332             window = (Window) w;
333           else
334             goto LOSE;
335         }
336       else
337         {
338          LOSE:
339           fprintf (stderr,
340             "usage: %s [ -display host:dpy.screen ] [ -v ] window-id\n",
341                    progname);
342           fprintf (stderr, "\n"
343         "\tThis program puts an image of the desktop on the given window.\n"
344         "\tIt is used by those xscreensaver demos that operate on images.\n"
345         "\n");
346           exit (1);
347         }
348     }
349
350   if (window == 0) goto LOSE;
351
352   /* Randomize -- only need to do this here because this program
353      doesn't use the `screenhack.h' or `lockmore.h' APIs. */
354 # undef ya_rand_init
355   ya_rand_init (0);
356
357   memset (&P, 0, sizeof(P));
358   P.db = db;
359   load_init_file (&P);
360
361   if (P.verbose_p)
362     verbose_p = True;
363
364 #if 0
365   /* Print out all the resources we read. */
366   {
367     XrmName name = { 0 };
368     XrmClass class = { 0 };
369     int count = 0;
370     XrmEnumerateDatabase (db, &name, &class, XrmEnumAllLevels, mapper,
371                           (XtPointer) &count);
372   }
373 #endif
374
375   get_image (screen, window, verbose_p);
376   exit (0);
377 }