http://ftp.aanet.ru/pub/Linux/X11/apps/xscreensaver-2.31.tar.gz
[xscreensaver] / driver / xscreensaver.c
index f3f43a772747a098742b86cb6cf9ec0659126aae..8942df98c5198ad6708bcf5bf577508147e87cfe 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1991-1998 Jamie Zawinski <jwz@netscape.com>
+/* xscreensaver, Copyright (c) 1991-1998 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
@@ -159,7 +159,8 @@ XrmDatabase db = 0;
 
 
 static Atom XA_ACTIVATE, XA_DEACTIVATE, XA_CYCLE, XA_NEXT, XA_PREV;
-static Atom XA_EXIT, XA_RESTART, XA_DEMO, XA_LOCK;
+static Atom XA_EXIT, XA_RESTART, XA_LOCK;
+Atom XA_DEMO, XA_PREFS;
 
 \f
 static XrmOptionDescRec options [] = {
@@ -173,14 +174,21 @@ static XrmOptionDescRec options [] = {
   { "-no-install",        ".installColormap",  XrmoptionNoArg, "off" },
   { "-verbose",                   ".verbose",          XrmoptionNoArg, "on" },
   { "-silent",            ".verbose",          XrmoptionNoArg, "off" },
+  { "-timestamp",         ".timestamp",        XrmoptionNoArg, "on" },
   { "-xidle-extension",           ".xidleExtension",   XrmoptionNoArg, "on" },
   { "-no-xidle-extension", ".xidleExtension",  XrmoptionNoArg, "off" },
   { "-mit-extension",     ".mitSaverExtension",XrmoptionNoArg, "on" },
   { "-no-mit-extension",   ".mitSaverExtension",XrmoptionNoArg, "off" },
   { "-sgi-extension",     ".sgiSaverExtension",XrmoptionNoArg, "on" },
   { "-no-sgi-extension",   ".sgiSaverExtension",XrmoptionNoArg, "off" },
+  { "-splash",            ".splash",           XrmoptionNoArg, "on" },
+  { "-no-splash",         ".splash",           XrmoptionNoArg, "off" },
+  { "-nosplash",          ".splash",           XrmoptionNoArg, "off" },
   { "-idelay",            ".initialDelay",     XrmoptionSepArg, 0 },
-  { "-nice",              ".nice",             XrmoptionSepArg, 0 }
+  { "-nice",              ".nice",             XrmoptionSepArg, 0 },
+
+  /* Actually this one is built in to Xt, but just to be sure... */
+  { "-synchronous",       ".synchronous",      XrmoptionNoArg, "on" }
 };
 
 static char *defaults[] = {
@@ -188,30 +196,30 @@ static char *defaults[] = {
  0
 };
 
+#ifdef _VROOT_H_
+ERROR!  You must not include vroot.h in this file.
+#endif
+
 static void
 do_help (saver_info *si)
 {
-  printf ("\
-xscreensaver %s, copyright (c) 1991-1998 by Jamie Zawinski <jwz@netscape.com>\n\
+  fflush (stdout);
+  fflush (stderr);
+  fprintf (stdout, "\
+xscreensaver %s, copyright (c) 1991-1998 by Jamie Zawinski <jwz@jwz.org>\n\
 The standard Xt command-line options are accepted; other options include:\n\
 \n\
-    -timeout <minutes>         When the screensaver should activate.\n\
-    -cycle <minutes>           How long to let each hack run.\n\
-    -lock-mode                 Require a password before deactivating.\n\
-    -no-lock-mode              Don't.\n\
-    -lock-timeout <minutes>    Grace period before locking; default 0.\n\
-    -visual <id-or-class>      Which X visual to run on.\n\
-    -install                   Install a private colormap.\n\
-    -no-install                Don't.\n\
-    -verbose                   Be loud.\n\
-    -silent                    Don't.\n\
-    -mit-extension             Use the R6 MIT_SCREEN_SAVER server extension.\n\
-    -no-mit-extension          Don't.\n\
-    -sgi-extension             Use the SGI SCREEN-SAVER server extension.\n\
-    -no-sgi-extension          Don't.\n\
-    -xidle-extension           Use the R5 XIdle server extension.\n\
-    -no-xidle-extension        Don't.\n\
-    -help                      This message.\n\
+    -timeout <minutes>       When the screensaver should activate.\n\
+    -cycle <minutes>         How long to let each hack run before switching.\n\
+    -lock-mode               Require a password before deactivating.\n\
+    -lock-timeout <minutes>  Grace period before locking; default 0.\n\
+    -visual <id-or-class>    Which X visual to run on.\n\
+    -install                 Install a private colormap.\n\
+    -verbose                 Be loud.\n\
+    -no-splash               Don't display a splash-screen at startup.\n\
+    -help                    This message.\n\
+\n\
+See the manual for other options and X resources.\n\
 \n\
 The `xscreensaver' program should be left running in the background.\n\
 Use the `xscreensaver-command' program to manipulate a running xscreensaver.\n\
@@ -219,21 +227,16 @@ Use the `xscreensaver-command' program to manipulate a running xscreensaver.\n\
 The `*programs' resource controls which graphics demos will be launched by\n\
 the screensaver.  See `man xscreensaver' or the web page for more details.\n\
 \n\
-For updates, check http://people.netscape.com/jwz/xscreensaver/\n\n",
+Just getting started?  Try this:\n\
+\n\
+        xscreensaver &\n\
+        xscreensaver-command -demo\n\
+\n\
+For updates, check http://www.jwz.org/xscreensaver/\n\
+\n",
          si->version);
-
-#ifdef NO_LOCKING
-  printf ("Support for locking was not enabled at compile-time.\n");
-#endif
-#ifdef NO_DEMO_MODE
-  printf ("Support for demo mode was not enabled at compile-time.\n");
-#endif
-#if !defined(HAVE_XIDLE_EXTENSION) && !defined(HAVE_MIT_SAVER_EXTENSION) && !defined(HAVE_SGI_SAVER_EXTENSION)
-  printf ("Support for the XIDLE, SCREEN_SAVER, and MIT-SCREEN-SAVER server\
- extensions\nwas not enabled at compile-time.\n");
-#endif /* !HAVE_XIDLE_EXTENSION && !HAVE_MIT_SAVER_EXTENSION && !HAVE_SGI_SAVER_EXTENSION */
-
   fflush (stdout);
+  fflush (stderr);
   exit (1);
 }
 
@@ -292,7 +295,7 @@ get_screenhacks (saver_info *si)
     {
       fprintf (stderr,
        "%s: the `monoPrograms' and `colorPrograms' resources are obsolete;\n\
-       see the manual for details.\n", progname);
+       see the manual for details.\n", blurb());
       free(d);
     }
 
@@ -376,13 +379,21 @@ get_screenhacks (saver_info *si)
 }
 
 
+static Bool blurb_timestamp_p = False;   /* kludge */
+
+
 static void
 get_resources (saver_info *si)
 {
   char *s;
   saver_preferences *p = &si->prefs;
 
+  p->xsync_p       = get_boolean_resource ("synchronous", "Synchronous");
+  if (p->xsync_p)
+    XSynchronize(si->dpy, True);
+
   p->verbose_p     = get_boolean_resource ("verbose", "Boolean");
+  p->timestamp_p    = get_boolean_resource ("timestamp", "Boolean");
   p->lock_p        = get_boolean_resource ("lock", "Boolean");
   p->fade_p        = get_boolean_resource ("fade", "Boolean");
   p->unfade_p      = get_boolean_resource ("unfade", "Boolean");
@@ -391,10 +402,11 @@ get_resources (saver_info *si)
   p->install_cmap_p = get_boolean_resource ("installColormap", "Boolean");
   p->nice_inferior  = get_integer_resource ("nice", "Nice");
 
-  p->initial_delay  = get_seconds_resource ("initialDelay", "Time");
-  p->timeout        = 1000 * get_minutes_resource ("timeout", "Time");
-  p->lock_timeout   = 1000 * get_minutes_resource ("lockTimeout", "Time");
-  p->cycle          = 1000 * get_minutes_resource ("cycle", "Time");
+  p->initial_delay   = get_seconds_resource ("initialDelay", "Time");
+  p->splash_duration = 1000 * get_seconds_resource ("splashDuration", "Time");
+  p->timeout         = 1000 * get_minutes_resource ("timeout", "Time");
+  p->lock_timeout    = 1000 * get_minutes_resource ("lockTimeout", "Time");
+  p->cycle           = 1000 * get_minutes_resource ("cycle", "Time");
 
 #ifndef NO_LOCKING
   p->passwd_timeout = 1000 * get_seconds_resource ("passwdTimeout", "Time");
@@ -405,6 +417,13 @@ get_resources (saver_info *si)
                                                       "Time");
   p->shell = get_string_resource ("bourneShell", "BourneShell");
 
+  p->help_url = get_string_resource("helpURL", "URL");
+  p->load_url_command = get_string_resource("loadURL", "LoadURL");
+
+  if ((s = get_string_resource ("splash", "Boolean")))
+    if (!get_boolean_resource("splash", "Boolean"))
+      p->splash_duration = 0;
+  if (s) free (s);
 
   /* don't set use_xidle_extension unless it is explicitly specified */
   if ((s = get_string_resource ("xidleExtension", "Boolean")))
@@ -464,29 +483,20 @@ get_resources (saver_info *si)
 #ifdef NO_LOCKING
   si->locking_disabled_p = True;
   si->nolock_reason = "not compiled with locking support";
-  if (p->lock_p)
-    {
-      p->lock_p = False;
-      fprintf (stderr, "%s: not compiled with support for locking.\n",
-              progname);
-    }
-#else  /* ! NO_LOCKING */
-  if (p->lock_p && si->locking_disabled_p)
-    {
-      fprintf (stderr, "%s: locking is disabled (%s).\n", progname,
-              si->nolock_reason);
-      p->lock_p = False;
-    }
-#endif /* ! NO_LOCKING */
+#endif /* NO_LOCKING */
 
   get_screenhacks (si);
 
   if (p->debug_p)
     {
       XSynchronize(si->dpy, True);
+      p->xsync_p = True;
       p->verbose_p = True;
+      p->timestamp_p = True;
       p->initial_delay = 0;
     }
+
+  blurb_timestamp_p = p->timestamp_p;
 }
 
 
@@ -510,6 +520,8 @@ main (int argc, char **argv)
   memset(&si, 0, sizeof(si));
   global_si_kludge = &si;      /* I hate C so much... */
   initialize (&si, argc, argv);
+  if (!si.demo_mode_p)
+    pop_splash_dialog (&si);
   main_loop (&si);             /* doesn't return */
   return 0;
 }
@@ -520,21 +532,71 @@ saver_ehandler (Display *dpy, XErrorEvent *error)
 {
   saver_info *si = global_si_kludge;   /* I hate C so much... */
 
-  fprintf (real_stderr, "\nX error in %s:\n", progname);
+  fprintf (real_stderr, "\n"
+          "#######################################"
+          "#######################################\n\n"
+          "%s: X Error!  PLEASE REPORT THIS BUG.\n\n"
+          "#######################################"
+          "#######################################\n\n",
+          blurb());
   if (XmuPrintDefaultErrorMessage (dpy, error, real_stderr))
-    saver_exit (si, -1);
+    {
+      fprintf (real_stderr, "\n");
+      if (si->prefs.xsync_p)
+       {
+         saver_exit (si, -1, "because of synchronous X Error");
+       }
+      else
+       {
+         fprintf(real_stderr,
+                 "%s: to dump a core file, re-run with `-sync'.\n\n",
+                 blurb());
+         saver_exit (si, -1, 0);
+       }
+    }
   else
     fprintf (real_stderr, " (nonfatal.)\n");
   return 0;
 }
 
+
+const char *
+blurb (void)
+{
+  if (!blurb_timestamp_p)
+    return progname;
+  else
+    {
+      static char buf[255];
+      char *ct = timestring();
+      int n = strlen(progname);
+      if (n > 100) n = 99;
+      strncpy(buf, progname, n);
+      buf[n++] = ':';
+      buf[n++] = ' ';
+      strncpy(buf+n, ct+11, 8);
+      strcpy(buf+n+9, ": ");
+      return buf;
+    }
+}
+
 static void
 initialize_connection (saver_info *si, int argc, char **argv)
 {
   int i;
-  Widget toplevel_shell = XtAppInitialize (&si->app, progclass,
-                                          options, XtNumber (options),
-                                          &argc, argv, defaults, 0, 0);
+  Widget toplevel_shell;
+  saver_preferences *p = &si->prefs;
+
+  /* The X resource database blows up if argv[0] has a "." in it. */
+  {
+    char *s = argv[0];
+    while ((s = strchr (s, '.')))
+      *s = '_';
+  }
+
+  toplevel_shell = XtAppInitialize (&si->app, progclass,
+                                   options, XtNumber (options),
+                                   &argc, argv, defaults, 0, 0);
 
   si->dpy = XtDisplay (toplevel_shell);
   si->db = XtDatabase (si->dpy);
@@ -544,7 +606,10 @@ initialize_connection (saver_info *si, int argc, char **argv)
 
   db = si->db; /* resources.c needs this */
 
-  if (argc == 2 && !strcmp (argv[1], "-help"))
+  if (argc == 2 &&
+      (!strcmp (argv[1], "-h") ||
+       !strcmp (argv[1], "-help") ||
+       !strcmp (argv[1], "--help")))
     do_help (si);
 
   else if (argc == 2 && !strcmp (argv[1], "-debug"))
@@ -554,7 +619,7 @@ initialize_connection (saver_info *si, int argc, char **argv)
     {
       const char *s = argv[1];
       fprintf (stderr, "%s: unknown option \"%s\".  Try \"-help\".\n",
-              progname, s);
+              blurb(), s);
 
       if (s[0] == '-' && s[1] == '-') s++;
       if (!strcmp (s, "-activate") ||
@@ -565,6 +630,8 @@ initialize_connection (saver_info *si, int argc, char **argv)
          !strcmp (s, "-exit") ||
          !strcmp (s, "-restart") ||
          !strcmp (s, "-demo") ||
+         !strcmp (s, "-prefs") ||
+         !strcmp (s, "-preferences") ||
          !strcmp (s, "-lock") ||
          !strcmp (s, "-version") ||
          !strcmp (s, "-time"))
@@ -574,7 +641,7 @@ initialize_connection (saver_info *si, int argc, char **argv)
     The `xscreensaver' program is a daemon that runs in the background.\n\
     You control a running xscreensaver process by sending it messages\n\
     with `xscreensaver-command'.  See the man pages for details,\n\
-    or check the web page: http://people.netscape.com/jwz/xscreensaver/\n\n",
+    or check the web page: http://www.jwz.org/xscreensaver/\n\n",
                   s);
 
          /* Since version 1.21 renamed the "-lock" option to "-lock-mode",
@@ -588,9 +655,28 @@ initialize_connection (saver_info *si, int argc, char **argv)
       exit (1);
     }
   get_resources (si);
-#ifndef NO_SETUID
-  hack_uid_warn (si);
-#endif /* NO_SETUID */
+
+  if (p->lock_p && si->locking_disabled_p)
+    {
+      p->lock_p = False;
+      fprintf (stderr, "%s: locking is disabled (%s).\n", blurb(),
+              si->nolock_reason);
+      if (strstr (si->nolock_reason, "passw"))
+       fprintf (stderr, "%s: does xscreensaver need to be setuid?  "
+                "consult the manual.\n", blurb());
+    }
+
+  /* Defer the printing of this message until after we have loaded the
+     resources and know whether `verbose' is on.
+   */
+  if (p->verbose_p && si->uid_message)
+    {
+      if (si->orig_uid && *si->orig_uid)
+       fprintf (stderr, "%s: initial effective uid/gid was %s.\n", blurb(),
+                si->orig_uid);
+      fprintf (stderr, "%s: %s\n", blurb(), si->uid_message);
+    }
+
   XA_VROOT = XInternAtom (si->dpy, "__SWM_VROOT", False);
   XA_SCREENSAVER = XInternAtom (si->dpy, "SCREENSAVER", False);
   XA_SCREENSAVER_VERSION = XInternAtom (si->dpy, "_SCREENSAVER_VERSION",False);
@@ -605,6 +691,7 @@ initialize_connection (saver_info *si, int argc, char **argv)
   XA_PREV = XInternAtom (si->dpy, "PREV", False);
   XA_EXIT = XInternAtom (si->dpy, "EXIT", False);
   XA_DEMO = XInternAtom (si->dpy, "DEMO", False);
+  XA_PREFS = XInternAtom (si->dpy, "PREFS", False);
   XA_LOCK = XInternAtom (si->dpy, "LOCK", False);
 
   si->nscreens = ScreenCount(si->dpy);
@@ -695,8 +782,8 @@ initialize (saver_info *si, int argc, char **argv)
   initialize_connection (si, argc, argv);
 
   if (p->verbose_p)
-    printf ("\
-%s %s, copyright (c) 1991-1998 by Jamie Zawinski <jwz@netscape.com>\n\
+    fprintf (stderr, "\
+%s %s, copyright (c) 1991-1998 by Jamie Zawinski <jwz@jwz.org>\n\
  pid = %d.\n", progname, si->version, (int) getpid ());
 
   
@@ -709,6 +796,20 @@ initialize (saver_info *si, int argc, char **argv)
   si->demo_mode_p = initial_demo_mode_p;
   srandom ((int) time ((time_t *) 0));
 
+  if (p->debug_p)
+    fprintf (stderr, "\n"
+            "%s: Warning: running in DEBUG MODE.  Be afraid.\n"
+            "\n"
+            "\tNote that in debug mode, the xscreensaver window will only\n"
+            "\tcover the left half of the screen.  (The idea is that you\n"
+            "\tcan still see debugging output in a shell, if you position\n"
+            "\tit on the right side of the screen.)\n"
+            "\n"
+            "\tDebug mode is NOT SECURE.  Do not run with -debug in\n"
+            "\tuntrusted environments.\n"
+            "\n",
+            progname);
+
   if (p->use_sgi_saver_extension)
     {
 #ifdef HAVE_SGI_SAVER_EXTENSION
@@ -716,27 +817,27 @@ initialize (saver_info *si, int argc, char **argv)
        {
          fprintf (stderr,
         "%s: display %s does not support the SGI SCREEN_SAVER extension.\n",
-                  progname, DisplayString (si->dpy));
+                  blurb(), DisplayString (si->dpy));
          p->use_sgi_saver_extension = False;
        }
       else if (p->use_mit_saver_extension)
        {
          fprintf (stderr, "%s: SGI SCREEN_SAVER extension used instead\
  of MIT-SCREEN-SAVER extension.\n",
-                  progname);
+                  blurb());
          p->use_mit_saver_extension = False;
        }
       else if (p->use_xidle_extension)
        {
          fprintf (stderr,
         "%s: SGI SCREEN_SAVER extension used instead of XIDLE extension.\n",
-                  progname);
+                  blurb());
          p->use_xidle_extension = False;
        }
 #else  /* !HAVE_MIT_SAVER_EXTENSION */
       fprintf (stderr,
        "%s: not compiled with support for the SGI SCREEN_SAVER extension.\n",
-              progname);
+              blurb());
       p->use_sgi_saver_extension = False;
 #endif /* !HAVE_SGI_SAVER_EXTENSION */
     }
@@ -748,20 +849,20 @@ initialize (saver_info *si, int argc, char **argv)
        {
          fprintf (stderr,
         "%s: display %s does not support the MIT-SCREEN-SAVER extension.\n",
-                  progname, DisplayString (si->dpy));
+                  blurb(), DisplayString (si->dpy));
          p->use_mit_saver_extension = False;
        }
       else if (p->use_xidle_extension)
        {
          fprintf (stderr,
         "%s: MIT-SCREEN-SAVER extension used instead of XIDLE extension.\n",
-                  progname);
+                  blurb());
          p->use_xidle_extension = False;
        }
 #else  /* !HAVE_MIT_SAVER_EXTENSION */
       fprintf (stderr,
        "%s: not compiled with support for the MIT-SCREEN-SAVER extension.\n",
-              progname);
+              blurb());
       p->use_mit_saver_extension = False;
 #endif /* !HAVE_MIT_SAVER_EXTENSION */
     }
@@ -774,12 +875,12 @@ initialize (saver_info *si, int argc, char **argv)
        {
          fprintf (stderr,
                   "%s: display %s does not support the XIdle extension.\n",
-                  progname, DisplayString (si->dpy));
+                  blurb(), DisplayString (si->dpy));
          p->use_xidle_extension = False;
        }
 #else  /* !HAVE_XIDLE_EXTENSION */
       fprintf (stderr, "%s: not compiled with support for XIdle.\n",
-              progname);
+              blurb());
       p->use_xidle_extension = False;
 #endif /* !HAVE_XIDLE_EXTENSION */
     }
@@ -793,13 +894,13 @@ initialize (saver_info *si, int argc, char **argv)
 
   if (p->verbose_p && p->use_mit_saver_extension)
     fprintf (stderr, "%s: using MIT-SCREEN-SAVER server extension.\n",
-            progname);
+            blurb());
   if (p->verbose_p && p->use_sgi_saver_extension)
     fprintf (stderr, "%s: using SGI SCREEN_SAVER server extension.\n",
-            progname);
+            blurb());
   if (p->verbose_p && p->use_xidle_extension)
     fprintf (stderr, "%s: using XIdle server extension.\n",
-            progname);
+            blurb());
 
   initialize_stderr (si);
   XSetErrorHandler (saver_ehandler);
@@ -816,18 +917,21 @@ initialize (saver_info *si, int argc, char **argv)
        {
          if (p->verbose_p)
            {
-             printf ("%s: waiting for %d second%s...", progname,
-                     (int) p->initial_delay,
-                     (p->initial_delay == 1 ? "" : "s"));
+             fprintf (stderr, "%s: waiting for %d second%s...", blurb(),
+                      (int) p->initial_delay,
+                      (p->initial_delay == 1 ? "" : "s"));
+             fflush (stderr);
              fflush (stdout);
            }
          sleep (p->initial_delay);
          if (p->verbose_p)
-           printf (" done.\n");
+           fprintf (stderr, " done.\n");
        }
       if (p->verbose_p)
        {
-         printf ("%s: selecting events on extant windows...", progname);
+         fprintf (stderr, "%s: selecting events on extant windows...",
+                  blurb());
+         fflush (stderr);
          fflush (stdout);
        }
 
@@ -839,7 +943,7 @@ initialize (saver_info *si, int argc, char **argv)
                                   RootWindowOfScreen (si->screens[i].screen));
 
       if (p->verbose_p)
-       printf (" done.\n");
+       fprintf (stderr, " done.\n");
     }
 }
 
@@ -859,8 +963,8 @@ main_loop (saver_info *si)
 #endif /* !NO_DEMO_MODE */
        {
          if (p->verbose_p)
-           printf ("%s: user is idle; waking up at %s.\n", progname,
-                   timestring());
+           fprintf (stderr, "%s: user is idle; waking up at %s.\n", blurb(),
+                    timestring());
          blank_screen (si);
          spawn_screenhack (si, True);
          if (p->cycle)
@@ -888,37 +992,18 @@ main_loop (saver_info *si)
              if (si->locking_disabled_p) abort ();
              si->dbox_up_p = True;
 
-             /* We used to ungrab the keyboard here, before calling unlock_p()
-                to pop up the dialog box.  This left the keyboard ungrabbed
-                for a small window, during an insecure state.  Bennett Todd
-                was seeing the bahavior that, when the load was high, he could
-                actually get characters through to a shell under the saver
-                window (he accidentally typed his password there...)
-
-                So the ungrab has been moved down into pop_passwd_dialog()
-                just after the server is grabbed, closing this window
-                entirely.
-              */
-             /* ungrab_keyboard_and_mouse (si); */
-
              {
                saver_screen_info *ssi = si->default_screen;
                suspend_screenhack (si, True);
                XUndefineCursor (si->dpy, ssi->screensaver_window);
                if (p->verbose_p)
-                 printf ("%s: prompting for password.\n", progname);
+                 fprintf (stderr, "%s: prompting for password.\n", blurb());
                val = unlock_p (si);
                if (p->verbose_p && val == False)
-                 printf ("%s: password incorrect!\n", progname);
+                 fprintf (stderr, "%s: password incorrect!\n", blurb());
                si->dbox_up_p = False;
                XDefineCursor (si->dpy, ssi->screensaver_window, ssi->cursor);
                suspend_screenhack (si, False);
-
-               /* I think this grab is now redundant, but it shouldn't hurt.
-                */
-               if (!si->demo_mode_p)
-                 grab_keyboard_and_mouse (si, ssi->screensaver_window,
-                                          ssi->cursor);
              }
 
              if (! val)
@@ -927,6 +1012,10 @@ main_loop (saver_info *si)
            }
 #endif /* !NO_LOCKING */
 
+         if (p->verbose_p)
+           fprintf (stderr, "%s: user is active at %s.\n",
+                    blurb(), timestring ());
+
          /* Let's kill it before unblanking, to get it to stop drawing as
             soon as possible... */
          kill_screenhack (si);
@@ -947,8 +1036,7 @@ main_loop (saver_info *si)
 #endif /* !NO_LOCKING */
 
          if (p->verbose_p)
-           printf ("%s: user is active; going to sleep at %s.\n", progname,
-                   timestring ());
+           fprintf (stderr, "%s: going to sleep.\n", blurb());
        }
     }
 }
@@ -965,14 +1053,14 @@ handle_clientmessage (saver_info *si, XEvent *event, Bool until_idle_p)
       char *str;
       str = XGetAtomName (si->dpy, event->xclient.message_type);
       fprintf (stderr, "%s: unrecognised ClientMessage type %s received\n",
-              progname, (str ? str : "(null)"));
+              blurb(), (str ? str : "(null)"));
       if (str) XFree (str);
       return False;
     }
   if (event->xclient.format != 32)
     {
       fprintf (stderr, "%s: ClientMessage of format %d received, not 32\n",
-              progname, event->xclient.format);
+              blurb(), event->xclient.format);
       return False;
     }
 
@@ -982,7 +1070,8 @@ handle_clientmessage (saver_info *si, XEvent *event, Bool until_idle_p)
       if (until_idle_p)
        {
          if (p->verbose_p)
-           printf ("%s: ACTIVATE ClientMessage received.\n", progname);
+           fprintf (stderr,
+                    "%s: ACTIVATE ClientMessage received.\n", blurb());
          if (p->use_mit_saver_extension || p->use_sgi_saver_extension)
            {
              XForceScreenSaver (si->dpy, ScreenSaverActive);
@@ -995,14 +1084,15 @@ handle_clientmessage (saver_info *si, XEvent *event, Bool until_idle_p)
        }
       fprintf (stderr,
               "%s: ClientMessage ACTIVATE received while already active.\n",
-              progname);
+              blurb());
     }
   else if (type == XA_DEACTIVATE)
     {
       if (! until_idle_p)
        {
          if (p->verbose_p)
-           printf ("%s: DEACTIVATE ClientMessage received.\n", progname);
+           fprintf (stderr, "%s: DEACTIVATE ClientMessage received.\n",
+                    blurb());
          if (p->use_mit_saver_extension || p->use_sgi_saver_extension)
            {
              XForceScreenSaver (si->dpy, ScreenSaverReset);
@@ -1015,14 +1105,14 @@ handle_clientmessage (saver_info *si, XEvent *event, Bool until_idle_p)
        }
       fprintf (stderr,
               "%s: ClientMessage DEACTIVATE received while inactive.\n",
-              progname);
+              blurb());
     }
   else if (type == XA_CYCLE)
     {
       if (! until_idle_p)
        {
          if (p->verbose_p)
-           printf ("%s: CYCLE ClientMessage received.\n", progname);
+           fprintf (stderr, "%s: CYCLE ClientMessage received.\n", blurb());
          if (si->cycle_id)
            XtRemoveTimeOut (si->cycle_id);
          si->cycle_id = 0;
@@ -1030,12 +1120,12 @@ handle_clientmessage (saver_info *si, XEvent *event, Bool until_idle_p)
          return False;
        }
       fprintf (stderr, "%s: ClientMessage CYCLE received while inactive.\n",
-              progname);
+              blurb());
     }
   else if (type == XA_NEXT || type == XA_PREV)
     {
       if (p->verbose_p)
-       printf ("%s: %s ClientMessage received.\n", progname,
+       fprintf (stderr, "%s: %s ClientMessage received.\n", blurb(),
                (type == XA_NEXT ? "NEXT" : "PREV"));
       si->next_mode_p = 1 + (type == XA_PREV);
 
@@ -1055,18 +1145,18 @@ handle_clientmessage (saver_info *si, XEvent *event, Bool until_idle_p)
       if (until_idle_p || !si->locked_p)
        {
          if (p->verbose_p)
-           printf ("%s: EXIT ClientMessage received.\n", progname);
+           fprintf (stderr, "%s: EXIT ClientMessage received.\n", blurb());
          if (! until_idle_p)
            {
              unblank_screen (si);
              kill_screenhack (si);
              XSync (si->dpy, False);
            }
-         saver_exit (si, 0);
+         saver_exit (si, 0, 0);
        }
       else
        fprintf (stderr, "%s: EXIT ClientMessage received while locked.\n",
-                progname);
+                blurb());
     }
   else if (type == XA_RESTART)
     {
@@ -1076,7 +1166,7 @@ handle_clientmessage (saver_info *si, XEvent *event, Bool until_idle_p)
       if (until_idle_p || !si->locked_p)
        {
          if (p->verbose_p)
-           printf ("%s: RESTART ClientMessage received.\n", progname);
+           fprintf (stderr, "%s: RESTART ClientMessage received.\n", blurb());
          if (! until_idle_p)
            {
              unblank_screen (si);
@@ -1094,45 +1184,62 @@ handle_clientmessage (saver_info *si, XEvent *event, Bool until_idle_p)
        }
       else
        fprintf(stderr, "%s: RESTART ClientMessage received while locked.\n",
-               progname);
+               blurb());
     }
   else if (type == XA_DEMO)
     {
 #ifdef NO_DEMO_MODE
       fprintf (stderr, "%s: not compiled with support for DEMO mode\n",
-              progname);
+              blurb());
 #else
       if (until_idle_p)
        {
          if (p->verbose_p)
-           printf ("%s: DEMO ClientMessage received.\n", progname);
+           fprintf (stderr, "%s: DEMO ClientMessage received.\n", blurb());
          si->demo_mode_p = True;
          return True;
        }
       fprintf (stderr,
-              "%s: DEMO ClientMessage received while active.\n", progname);
+              "%s: DEMO ClientMessage received while active.\n", blurb());
+#endif
+    }
+  else if (type == XA_PREFS)
+    {
+#ifdef NO_DEMO_MODE
+      fprintf (stderr, "%s: not compiled with support for DEMO mode\n",
+              blurb());
+#else
+      if (until_idle_p)
+       {
+         if (p->verbose_p)
+           fprintf (stderr, "%s: PREFS ClientMessage received.\n", blurb());
+         si->demo_mode_p = (Bool) 2;  /* kludge, so sue me. */
+         return True;
+       }
+      fprintf (stderr,
+              "%s: PREFS ClientMessage received while active.\n", blurb());
 #endif
     }
   else if (type == XA_LOCK)
     {
 #ifdef NO_LOCKING
       fprintf (stderr, "%s: not compiled with support for LOCK mode\n",
-              progname);
+              blurb());
 #else
       if (si->locking_disabled_p)
        fprintf (stderr,
               "%s: LOCK ClientMessage received, but locking is disabled.\n",
-                progname);
+                blurb());
       else if (si->locked_p)
        fprintf (stderr,
               "%s: LOCK ClientMessage received while already locked.\n",
-                progname);
+                blurb());
       else
        {
          si->locked_p = True;
          if (p->verbose_p) 
-           printf ("%s: LOCK ClientMessage received;%s locking.\n",
-                   progname, until_idle_p ? " activating and" : "");
+           fprintf (stderr, "%s: LOCK ClientMessage received;%s locking.\n",
+                   blurb(), until_idle_p ? " activating and" : "");
 
          if (si->lock_id)      /* we're doing it now, so lose the timeout */
            {
@@ -1162,11 +1269,11 @@ handle_clientmessage (saver_info *si, XEvent *event, Bool until_idle_p)
       if (str)
        fprintf (stderr,
                 "%s: unrecognised screensaver ClientMessage %s received\n",
-                progname, str);
+                blurb(), str);
       else
        fprintf (stderr,
                "%s: unrecognised screensaver ClientMessage 0x%x received\n",
-                progname, (unsigned int) event->xclient.data.l[0]);
+                blurb(), (unsigned int) event->xclient.data.l[0]);
       if (str) XFree (str);
     }
   return False;