-/* xscreensaver, Copyright (c) 1991-1998 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1991-1999 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
#include <X11/StringDefs.h>
#include <X11/Shell.h>
#include <X11/Xos.h>
+#include <netdb.h> /* for gethostbyname() */
#ifdef HAVE_XMU
# ifndef VMS
# include <X11/Xmu/Error.h>
#endif /* !HAVE_XMU */
#ifdef HAVE_XIDLE_EXTENSION
-#include <X11/extensions/xidle.h>
+# include <X11/extensions/xidle.h>
#endif /* HAVE_XIDLE_EXTENSION */
#include "xscreensaver.h"
{ "-no-mit-extension", ".mitSaverExtension",XrmoptionNoArg, "off" },
{ "-sgi-extension", ".sgiSaverExtension",XrmoptionNoArg, "on" },
{ "-no-sgi-extension", ".sgiSaverExtension",XrmoptionNoArg, "off" },
+ { "-proc-interrupts", ".procInterrupts", XrmoptionNoArg, "on" },
+ { "-no-proc-interrupts", ".procInterrupts", XrmoptionNoArg, "off" },
{ "-splash", ".splash", XrmoptionNoArg, "on" },
{ "-no-splash", ".splash", XrmoptionNoArg, "off" },
{ "-nosplash", ".splash", XrmoptionNoArg, "off" },
fflush (stdout);
fflush (stderr);
fprintf (stdout, "\
-xscreensaver %s, copyright (c) 1991-1998 by Jamie Zawinski <jwz@jwz.org>\n\
+xscreensaver %s, copyright (c) 1991-1999 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\
{
saver_info *si = global_si_kludge; /* I hate C so much... */
+ if (!real_stderr) real_stderr = stderr;
+
fprintf (real_stderr, "\n"
"#######################################"
"#######################################\n\n"
}
else
{
- fprintf(real_stderr,
- "%s: to dump a core file, re-run with `-sync'.\n"
- "%s: see http://www.jwz.org/xscreensaver/bugs.html\n"
- "\t\tfor bug reporting information.\n\n",
- blurb(), blurb());
+ fprintf (real_stderr,
+ "#######################################"
+ "#######################################\n\n");
+ fprintf (real_stderr,
+ " If at all possible, please re-run xscreensaver with the command line\n"
+ " arguments `-sync -verbose', and reproduce this bug. That will cause\n"
+ " xscreensaver to dump a `core' file to the current directory. Please\n"
+ " include the stack trace from that core file in your bug report.\n"
+ "\n"
+ " http://www.jwz.org/xscreensaver/bugs.html explains how to create the\n"
+ " most useful bug reports, and how to examine core files.\n"
+ "\n"
+ " The more information you can provide, the better. But please report\n"
+ " report this bug, regardless!\n"
+ "\n");
+ fprintf (real_stderr,
+ "#######################################"
+ "#######################################\n\n");
+
saver_exit (si, -1, 0);
}
}
return 0;
}
+
+/* This error handler is used only while the X connection is being set up;
+ after we've got a connection, we don't use this handler again. The only
+ reason for having this is so that we can present a more idiot-proof error
+ message than "cannot open display."
+ */
+static void
+startup_ehandler (String name, String type, String class,
+ String defalt, /* one can't even spel properly
+ in this joke of a language */
+ String *av, Cardinal *ac)
+{
+ char fmt[512];
+ String p[10];
+ saver_info *si = global_si_kludge; /* I hate C so much... */
+ XrmDatabase *db = XtAppGetErrorDatabase(si->app);
+ *fmt = 0;
+ XtAppGetErrorDatabaseText(si->app, name, type, class, defalt,
+ fmt, sizeof(fmt)-1, *db);
+
+ fprintf (stderr, "%s: ", blurb());
+
+ memset (p, 0, sizeof(p));
+ if (*ac > countof (p)) *ac = countof (p);
+ memcpy ((char *) p, (char *) av, (*ac) * sizeof(*av));
+ fprintf (stderr, fmt, /* Did I mention that I hate C? */
+ p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9]);
+ fprintf (stderr, "\n");
+
+ describe_uids (si, stderr);
+ fprintf (stderr, "\n"
+ "%s: Errors at startup are usually authorization problems.\n"
+ " Did you read the manual? Specifically, the parts\n"
+ " that talk about XAUTH, XDM, and root logins?\n"
+ "\n"
+ " http://www.jwz.org/xscreensaver/man.html\n"
+ "\n",
+ blurb());
+
+ fflush (stderr);
+ fflush (stdout);
+ exit (1);
+}
+
\f
/* The zillions of initializations.
*/
static void
privileged_initialization (saver_info *si, int *argc, char **argv)
{
+#ifndef NO_LOCKING
+ /* before hack_uid() for proper permissions */
+ lock_priv_init (*argc, argv, si->prefs.verbose_p);
+#endif /* NO_LOCKING */
+
+#ifndef NO_SETUID
+ hack_uid (si);
+#endif /* NO_SETUID */
+}
+
+
+/* Figure out what locking mechanisms are supported.
+ */
+static void
+lock_initialization (saver_info *si, int *argc, char **argv)
+{
#ifdef NO_LOCKING
si->locking_disabled_p = True;
si->nolock_reason = "not compiled with locking support";
#else /* !NO_LOCKING */
si->locking_disabled_p = False;
- /* before hack_uid() for proper permissions */
+
+ /* Finish initializing locking, now that we're out of privileged code. */
if (! lock_init (*argc, argv, si->prefs.verbose_p))
{
si->locking_disabled_p = True;
Widget toplevel_shell;
XSetErrorHandler (saver_ehandler);
+
+ XtAppSetErrorMsgHandler (si->app, startup_ehandler);
toplevel_shell = XtAppInitialize (&si->app, progclass,
options, XtNumber (options),
argc, argv, defaults, 0, 0);
+ XtAppSetErrorMsgHandler (si->app, 0);
si->dpy = XtDisplay (toplevel_shell);
si->prefs.db = XtDatabase (si->dpy);
if (p->verbose_p)
fprintf (stderr,
- "%s %s, copyright (c) 1991-1998 "
+ "%s %s, copyright (c) 1991-1999 "
"by Jamie Zawinski <jwz@jwz.org>.\n",
progname, si->version);
Bool server_has_xidle_extension_p = False;
Bool server_has_sgi_saver_extension_p = False;
Bool server_has_mit_saver_extension_p = False;
+ Bool system_has_proc_interrupts_p = False;
+ const char *piwhy = 0;
si->using_xidle_extension = p->use_xidle_extension;
si->using_sgi_saver_extension = p->use_sgi_saver_extension;
si->using_mit_saver_extension = p->use_mit_saver_extension;
+ si->using_proc_interrupts = p->use_proc_interrupts;
#ifdef HAVE_XIDLE_EXTENSION
server_has_xidle_extension_p = query_xidle_extension (si);
#ifdef HAVE_MIT_SAVER_EXTENSION
server_has_mit_saver_extension_p = query_mit_saver_extension (si);
#endif
+#ifdef HAVE_PROC_INTERRUPTS
+ system_has_proc_interrupts_p = query_proc_interrupts_available (si, &piwhy);
+#endif
if (!server_has_xidle_extension_p)
si->using_xidle_extension = False;
"%s: not using server's lame MIT-SCREEN-SAVER extension.\n",
blurb());
}
+
+ if (!system_has_proc_interrupts_p)
+ {
+ si->using_proc_interrupts = False;
+ if (p->verbose_p && piwhy)
+ fprintf (stderr, "%s: not using /proc/interrupts: %s.\n", blurb(),
+ piwhy);
+ }
+ else if (p->verbose_p)
+ {
+ if (si->using_proc_interrupts)
+ fprintf (stderr,
+ "%s: consulting /proc/interrupts for keyboard activity.\n",
+ blurb());
+ else
+ fprintf (stderr,
+ "%s: not consulting /proc/interrupts for keyboard activity.\n",
+ blurb());
+ }
}
for window creation events, so that new subwindows will be noticed.
*/
for (i = 0; i < si->nscreens; i++)
- start_notice_events_timer (si, RootWindowOfScreen (si->screens[i].screen));
+ start_notice_events_timer (si, RootWindowOfScreen (si->screens[i].screen),
+ False);
if (p->verbose_p)
fprintf (stderr, " done.\n");
maybe_reload_init_file (si);
- blank_screen (si);
+ if (! blank_screen (si))
+ {
+ /* We were unable to grab either the keyboard or mouse.
+ This means we did not (and must not) blank the screen.
+ If we were to blank the screen while some other program
+ is holding both the mouse and keyboard grabbed, then
+ we would never be able to un-blank it! We would never
+ see any events, and the display would be wedged.
+
+ So, just go around the loop again and wait for the
+ next bout of idleness.
+ */
+
+ fprintf (stderr,
+ "%s: unable to grab keyboard or mouse! Blanking aborted.\n",
+ blurb());
+ continue;
+ }
+
kill_screenhack (si);
spawn_screenhack (si, True);
exit (1);
load_init_file (p);
+ lock_initialization (si, &argc, argv);
if (p->xsync_p) XSynchronize (si->dpy, True);
blurb_timestamp_p = p->timestamp_p; /* kludge */
L++;
XChangeProperty (si->dpy, w, XA_SCREENSAVER_RESPONSE, XA_STRING, 8,
- PropModeReplace, proto, L);
+ PropModeReplace, (unsigned char *) proto, L);
XSync (si->dpy, False);
free (proto);
}
}
}
}
+
+Bool
+display_is_on_console_p (saver_info *si)
+{
+ Bool not_on_console = True;
+ char *dpystr = DisplayString (si->dpy);
+ char *tail = (char *) strchr (dpystr, ':');
+ if (! tail || strncmp (tail, ":0", 2))
+ not_on_console = True;
+ else
+ {
+ char dpyname[255], localname[255];
+ strncpy (dpyname, dpystr, tail-dpystr);
+ dpyname [tail-dpystr] = 0;
+ if (!*dpyname ||
+ !strcmp(dpyname, "unix") ||
+ !strcmp(dpyname, "localhost"))
+ not_on_console = False;
+ else if (gethostname (localname, sizeof (localname)))
+ not_on_console = True; /* can't find hostname? */
+ else
+ {
+ /* We have to call gethostbyname() on the result of gethostname()
+ because the two aren't guarenteed to be the same name for the
+ same host: on some losing systems, one is a FQDN and the other
+ is not. Here in the wide wonderful world of Unix it's rocket
+ science to obtain the local hostname in a portable fashion.
+
+ And don't forget, gethostbyname() reuses the structure it
+ returns, so we have to copy the fucker before calling it again.
+ Thank you master, may I have another.
+ */
+ struct hostent *h = gethostbyname (dpyname);
+ if (!h)
+ not_on_console = True;
+ else
+ {
+ char hn [255];
+ struct hostent *l;
+ strcpy (hn, h->h_name);
+ l = gethostbyname (localname);
+ not_on_console = (!l || !!(strcmp (l->h_name, hn)));
+ }
+ }
+ }
+ return !not_on_console;
+}