Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 /* xscreensaver-command, Copyright (c) 1991-1998
  2  *  by Jamie Zawinski <jwz@jwz.org>
  3  *
  4  * Permission to use, copy, modify, distribute, and sell this software and its
  5  * documentation for any purpose is hereby granted without fee, provided that
  6  * the above copyright notice appear in all copies and that both that
  7  * copyright notice and this permission notice appear in supporting
  8  * documentation.  No representations are made about the suitability of this
  9  * software for any purpose.  It is provided "as is" without express or 
 10  * implied warranty.
 11  */
 12 
 13 #ifdef HAVE_CONFIG_H
 14 # include "config.h"
 15 #endif
 16 
 17 #include <stdio.h>
 18 #include <stdlib.h>
 19 #include <sys/time.h>
 20 #include <sys/types.h>
 21 
 22 #ifdef HAVE_SYS_SELECT_H
 23 # include <sys/select.h>
 24 #endif /* HAVE_SYS_SELECT_H */
 25 
 26 #ifdef HAVE_UNISTD_H
 27 # include <unistd.h>
 28 #endif
 29 
 30 #include <X11/Xproto.h>         /* for CARD32 */
 31 #include <X11/Xlib.h>
 32 #include <X11/Xatom.h>
 33 #include <X11/Xutil.h>          /* for XGetClassHint() */
 34 #include <X11/Xos.h>
 35 
 36 /* for xawtv */
 37 #include <X11/Intrinsic.h>
 38 extern XtAppContext      app_context;
 39 
 40 #include "remote.h"
 41 
 42 #ifdef _VROOT_H_
 43 ERROR! you must not include vroot.h in this file
 44 #endif
 45 
 46 static char *progname = "fixme";
 47 static Atom XA_SCREENSAVER, XA_SCREENSAVER_VERSION, XA_SCREENSAVER_RESPONSE;
 48 static Atom XA_SCREENSAVER_ID, XA_SCREENSAVER_STATUS, XA_EXIT;
 49 static Atom XA_VROOT, XA_SELECT, XA_DEMO, XA_BLANK, XA_LOCK;
 50 
 51 
 52 static XErrorHandler old_handler = 0;
 53 static Bool got_badwindow = False;
 54 static int
 55 BadWindow_ehandler (Display *dpy, XErrorEvent *error)
 56 {
 57   if (error->error_code == BadWindow)
 58     {
 59       got_badwindow = True;
 60       return 0;
 61     }
 62   else
 63     {
 64       fprintf (stderr, "%s: ", progname);
 65       if (!old_handler) abort();
 66       return (*old_handler) (dpy, error);
 67     }
 68 }
 69 
 70 
 71 
 72 static Window
 73 find_screensaver_window (Display *dpy, char **version)
 74 {
 75   unsigned int i;
 76   Window root = RootWindowOfScreen (DefaultScreenOfDisplay (dpy));
 77   Window root2, parent, *kids;
 78   unsigned int nkids;
 79 
 80   if (version) *version = 0;
 81 
 82   if (! XQueryTree (dpy, root, &root2, &parent, &kids, &nkids))
 83     abort ();
 84   if (root != root2)
 85     abort ();
 86   if (parent)
 87     abort ();
 88   if (! (kids && nkids))
 89     return 0;
 90   for (i = 0; i < nkids; i++)
 91     {
 92       Atom type;
 93       int format;
 94       unsigned long nitems, bytesafter;
 95       char *v;
 96       int status;
 97 
 98       /* We're walking the list of root-level windows and trying to find
 99          the one that has a particular property on it.  We need to trap
100          BadWindows errors while doing this, because it's possible that
101          some random window might get deleted in the meantime.  (That
102          window won't have been the one we're looking for.)
103        */
104       XSync (dpy, False);
105       if (old_handler) abort();
106       got_badwindow = False;
107       old_handler = XSetErrorHandler (BadWindow_ehandler);
108       status = XGetWindowProperty (dpy, kids[i],
109                                    XA_SCREENSAVER_VERSION,
110                                    0, 200, False, XA_STRING,
111                                    &type, &format, &nitems, &bytesafter,
112                                    (unsigned char **) &v);
113       XSync (dpy, False);
114       XSetErrorHandler (old_handler);
115       old_handler = 0;
116 
117       if (got_badwindow)
118         {
119           status = BadWindow;
120           got_badwindow = False;
121         }
122 
123       if (status == Success && type != None)
124         {
125           if (version)
126             *version = v;
127           return kids[i];
128         }
129     }
130   return 0;
131 }
132 
133 
134 static int
135 send_xscreensaver_command (Display *dpy, Atom command, long arg,
136                            Window *window_ret, char **error_ret)
137 {
138   char *v = 0;
139   Window window = find_screensaver_window (dpy, &v);
140   XWindowAttributes xgwa;
141   char err[2048];
142 
143   if (window_ret)
144     *window_ret = window;
145 
146   if (!window)
147     {
148       sprintf (err, "no screensaver is running on display %s",
149                DisplayString (dpy));
150 
151       if (error_ret)
152         {
153           *error_ret = strdup (err);
154           return -1;
155         }
156 
157       if (command == XA_EXIT)
158         /* Don't print an error if xscreensaver is already dead. */
159         return 1;
160 
161       fprintf (stderr, "%s: %s\n", progname, err);
162       return -1;
163     }
164 
165   /* Select for property change events, so that we can read the response. */
166   XGetWindowAttributes (dpy, window, &xgwa);
167   XSelectInput (dpy, window, xgwa.your_event_mask | PropertyChangeMask);
168 
169   if (command == XA_SCREENSAVER_STATUS ||
170       command == XA_SCREENSAVER_VERSION)
171     {
172       XClassHint hint;
173       memset (&hint, 0, sizeof(hint));
174       if (!v || !*v)
175         {
176           sprintf (err, "version property not set on window 0x%x?",
177                    (unsigned int) window);
178           if (error_ret)
179             *error_ret = strdup (err);
180           else
181             fprintf (stderr, "%s: %s\n", progname, err);
182           return -1;
183         }
184 
185       XGetClassHint(dpy, window, &hint);
186       if (!hint.res_class)
187         {
188           sprintf (err, "class hints not set on window 0x%x?",
189                    (unsigned int) window);
190           if (error_ret)
191             *error_ret = strdup (err);
192           else
193             fprintf (stderr, "%s: %s\n", progname, err);
194           return -1;
195         }
196 
197       fprintf (stdout, "%s %s", hint.res_class, v);
198 
199       if (command != XA_SCREENSAVER_STATUS)
200         {
201           fprintf (stdout, "\n");
202         }
203       else
204         {
205           Atom type;
206           int format;
207           unsigned long nitems, bytesafter;
208           CARD32 *data = 0;
209 
210           if (XGetWindowProperty (dpy,
211                                   RootWindow (dpy, 0),
212                                   XA_SCREENSAVER_STATUS,
213                                   0, 999, False, XA_INTEGER,
214                                   &type, &format, &nitems, &bytesafter,
215                                   (unsigned char **) &data)
216               == Success
217               && type
218               && data)
219             {
220               Atom blanked;
221               time_t tt;
222               char *s;
223 
224               if (type != XA_INTEGER || nitems < 3)
225                 {
226                 STATUS_LOSE:
227                   if (data) free (data);
228                   fprintf (stdout, "\n");
229                   fflush (stdout);
230                   fprintf (stderr, "bad status format on root window.\n");
231                   return -1;
232                 }
233                   
234               blanked = (Atom) data[0];
235               tt = (time_t) data[1];
236 
237               if (tt <= (time_t) 666000000L) /* early 1991 */
238                 goto STATUS_LOSE;
239 
240               if (blanked == XA_BLANK)
241                 fputs (": screen blanked since ", stdout);
242               else if (blanked == XA_LOCK)
243                 fputs (": screen locked since ", stdout);
244               else if (blanked == 0)
245                 /* suggestions for a better way to phrase this are welcome. */
246                 fputs (": screen non-blanked since ", stdout);
247               else
248                 /* `blanked' has an unknown value - fail. */
249                 goto STATUS_LOSE;
250 
251               s = ctime(&tt);
252               if (s[strlen(s)-1] == '\n')
253                 s[strlen(s)-1] = 0;
254               fputs (s, stdout);
255 
256               {
257                 int nhacks = nitems - 2;
258                 Bool any = False;
259                 int i;
260                 for (i = 0; i < nhacks; i++)
261                   if (data[i + 2] > 0)
262                     {
263                       any = True;
264                       break;
265                     }
266 
267                 if (any && nhacks == 1)
268                   fprintf (stdout, " (hack #%ld)\n", data[2]);
269                 else if (any)
270                   {
271                     fprintf (stdout, " (hacks: ");
272                     for (i = 0; i < nhacks; i++)
273                       {
274                         fprintf (stdout, "#%ld", data[2 + i]);
275                         if (i != nhacks-1)
276                           fputs (", ", stdout);
277                       }
278                     fputs (")\n", stdout);
279                   }
280                 else
281                   fputs ("\n", stdout);
282               }
283 
284               if (data) free (data);
285             }
286           else
287             {
288               if (data) free (data);
289               fprintf (stdout, "\n");
290               fflush (stdout);
291               fprintf (stderr, "no saver status on root window.\n");
292               return -1;
293             }
294         }
295 
296       /* No need to read a response for these commands. */
297       return 1;
298     }
299   else
300     {
301       XEvent event;
302       long arg1 = arg;
303       long arg2 = 0;
304 
305       if (arg < 0)
306         abort();
307       else if (arg == 0 && command == XA_SELECT)
308         abort();
309       else if (arg != 0 && command == XA_DEMO)
310         {
311           arg1 = 300;   /* version number of the XA_DEMO protocol, */
312           arg2 = arg;   /* since it didn't use to take an argument. */
313         }
314 
315       event.xany.type = ClientMessage;
316       event.xclient.display = dpy;
317       event.xclient.window = window;
318       event.xclient.message_type = XA_SCREENSAVER;
319       event.xclient.format = 32;
320       memset (&event.xclient.data, 0, sizeof(event.xclient.data));
321       event.xclient.data.l[0] = (long) command;
322       event.xclient.data.l[1] = arg1;
323       event.xclient.data.l[2] = arg2;
324       if (! XSendEvent (dpy, window, False, 0L, &event))
325         {
326           sprintf (err, "XSendEvent(dpy, 0x%x ...) failed.\n",
327                    (unsigned int) window);
328           if (error_ret)
329             *error_ret = strdup (err);
330           else
331             fprintf (stderr, "%s: %s\n", progname, err);
332           return -1;
333         }
334     }
335   XSync (dpy, 0);
336   return 0;
337 }
338 
339 
340 static int
341 xscreensaver_command_response (Display *dpy, Window window,
342                                Bool verbose_p, Bool exiting_p,
343                                char **error_ret)
344 {
345   int fd = ConnectionNumber (dpy);
346   int timeout = 10;
347   int status;
348   fd_set fds;
349   struct timeval tv;
350   char err[2048];
351 
352   while (1)
353     {
354       FD_ZERO(&fds);
355       FD_SET(fd, &fds);
356       memset(&tv, 0, sizeof(tv));
357       tv.tv_sec = timeout;
358       status = select (fd+1, &fds, 0, &fds, &tv);
359 
360       if (status < 0)
361         {
362           char buf[1024];
363           if (error_ret)
364             {
365               sprintf (buf, "error waiting for reply");
366               *error_ret = strdup (buf);
367             }
368           else
369             {
370               sprintf (buf, "%s: error waiting for reply", progname);
371               perror (buf);
372             }
373           return status;
374         }
375       else if (status == 0)
376         {
377           sprintf (err, "no response to command.");
378           if (error_ret)
379             *error_ret = strdup (err);
380           else
381             fprintf (stderr, "%s: %s\n", progname, err);
382           return -1;
383         }
384       else
385         {
386           XEvent event;
387           XtAppNextEvent(app_context,&event);
388           if (event.xany.type == PropertyNotify &&
389               event.xproperty.state == PropertyNewValue &&
390               event.xproperty.atom == XA_SCREENSAVER_RESPONSE)
391             {
392               Status st2;
393               Atom type;
394               int format;
395               unsigned long nitems, bytesafter;
396               char *msg = 0;
397 
398               XSync (dpy, False);
399               if (old_handler) abort();
400               old_handler = XSetErrorHandler (BadWindow_ehandler);
401               st2 = XGetWindowProperty (dpy, window,
402                                         XA_SCREENSAVER_RESPONSE,
403                                         0, 1024, True,
404                                         AnyPropertyType,
405                                         &type, &format, &nitems, &bytesafter,
406                                         (unsigned char **) &msg);
407               XSync (dpy, False);
408               XSetErrorHandler (old_handler);
409               old_handler = 0;
410 
411               if (got_badwindow)
412                 {
413                   if (exiting_p)
414                     return 0;
415 
416                   sprintf (err, "xscreensaver window unexpectedly deleted.");
417 
418                   if (error_ret)
419                     *error_ret = strdup (err);
420                   else
421                     fprintf (stderr, "%s: %s\n", progname, err);
422 
423                   return -1;
424                 }
425 
426               if (st2 == Success && type != None)
427                 {
428                   if (type != XA_STRING || format != 8)
429                     {
430                       sprintf (err, "unrecognized response property.");
431 
432                       if (error_ret)
433                         *error_ret = strdup (err);
434                       else
435                         fprintf (stderr, "%s: %s\n", progname, err);
436 
437                       if (msg) XFree (msg);
438                       return -1;
439                     }
440                   else if (!msg || (msg[0] != '+' && msg[0] != '-'))
441                     {
442                       sprintf (err, "unrecognized response message.");
443 
444                       if (error_ret)
445                         *error_ret = strdup (err);
446                       else  
447                         fprintf (stderr, "%s: %s\n", progname, err);
448 
449                       if (msg) XFree (msg);
450                       return -1;
451                     }
452                   else
453                     {
454                       int ret = (msg[0] == '+' ? 0 : -1);
455                       sprintf (err, "%s: %s\n", progname, msg+1);
456 
457                       if (error_ret)
458                         *error_ret = strdup (err);
459                       else if (verbose_p || ret != 0)
460                         fprintf ((ret < 0 ? stderr : stdout), "%s\n", err);
461 
462                       XFree (msg);
463                       return ret;
464                     }
465                 }
466             } else {
467                 XtDispatchEvent(&event);
468             }
469         }
470     }
471 }
472 
473 
474 int
475 xscreensaver_command (Display *dpy, Atom command, long arg, Bool verbose_p,
476                       char **error_ret)
477 {
478   Window w = 0;
479   int status = send_xscreensaver_command (dpy, command, arg, &w, error_ret);
480   if (status == 0)
481     status = xscreensaver_command_response (dpy, w, verbose_p,
482                                             (command == XA_EXIT),
483                                             error_ret);
484 
485   fflush (stdout);
486   fflush (stderr);
487   return (status < 0 ? status : 0);
488 }
489 
490 
491 void
492 server_xscreensaver_version (Display *dpy,
493                              char **version_ret,
494                              char **user_ret,
495                              char **host_ret)
496 {
497   Window window = find_screensaver_window (dpy, 0);
498 
499   Atom type;
500   int format;
501   unsigned long nitems, bytesafter;
502 
503   if (version_ret)
504     *version_ret = 0;
505   if (user_ret)
506     *user_ret = 0;
507   if (host_ret)
508     *host_ret = 0;
509 
510   if (!window)
511     return;
512 
513   if (version_ret)
514     {
515       char *v = 0;
516       XGetWindowProperty (dpy, window, XA_SCREENSAVER_VERSION, 0, 1,
517                           False, XA_STRING, &type, &format, &nitems,
518                           &bytesafter, (unsigned char **) &v);
519       if (v)
520         {
521           *version_ret = strdup (v);
522           XFree (v);
523         }
524     }
525 
526   if (user_ret || host_ret)
527     {
528       char *id = 0;
529       const char *user = 0;
530       const char *host = 0;
531 
532       XGetWindowProperty (dpy, window, XA_SCREENSAVER_ID, 0, 512,
533                           False, XA_STRING, &type, &format, &nitems,
534                           &bytesafter, (unsigned char **) &id);
535       if (id && *id)
536         {
537           const char *old_tag = " on host ";
538           const char *s = strstr (id, old_tag);
539           if (s)
540             {
541               /* found ID of the form "1234 on host xyz". */
542               user = 0;
543               host = s + strlen (old_tag);
544             }
545           else
546             {
547               char *o = 0, *p = 0, *c = 0;
548               o = strchr (id, '(');
549               if (o) p = strchr (o, '@');
550               if (p) c = strchr (p, ')');
551               if (c)
552                 {
553                   /* found ID of the form "1234 (user@host)". */
554                   user = o+1;
555                   host = p+1;
556                   *p = 0;
557                   *c = 0;
558                 }
559             }
560 
561         }
562 
563       if (user && *user && *user != '?')
564         *user_ret = strdup (user);
565       else
566         *user_ret = 0;
567 
568       if (host && *host && *host != '?')
569         *host_ret = strdup (host);
570       else
571         *host_ret = 0;
572 
573       if (id)
574         XFree (id);
575     }
576 }
577 
578 void xscreensaver_init(Display *dpy)
579 {
580     XA_VROOT = XInternAtom (dpy, "__SWM_VROOT", False);
581     XA_SCREENSAVER = XInternAtom (dpy, "SCREENSAVER", False);
582     XA_SCREENSAVER_ID = XInternAtom (dpy, "_SCREENSAVER_ID", False);
583     XA_SCREENSAVER_VERSION = XInternAtom (dpy, "_SCREENSAVER_VERSION",False);
584     XA_SCREENSAVER_STATUS = XInternAtom (dpy, "_SCREENSAVER_STATUS", False);
585     XA_SCREENSAVER_RESPONSE = XInternAtom (dpy, "_SCREENSAVER_RESPONSE", False);
586     XA_SELECT = XInternAtom (dpy, "SELECT", False);
587     XA_EXIT = XInternAtom (dpy, "EXIT", False);
588     XA_DEMO = XInternAtom (dpy, "DEMO", False);
589     XA_LOCK = XInternAtom (dpy, "LOCK", False);
590     XA_BLANK = XInternAtom (dpy, "BLANK", False);
591 }
592 
  This page was automatically generated by the LXR engine.