http://packetstormsecurity.org/UNIX/admin/xscreensaver-4.02.tar.gz
[xscreensaver] / hacks / bsod.c
index a3b0a9cc5b18a9237dd3dcd19c3f1a32698ea346..e516c813587fbb70ca10bae7711d34726614f72b 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1998 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1998-2001 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
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
  * this version written by jwz, 4-Jun-98.
  *
  *   TODO:
  * this version written by jwz, 4-Jun-98.
  *
  *   TODO:
- *      -  Should have a "macsbug" mode.
  *      -  Should simulate a Unix kernel panic and reboot.
  *      -  Making various boot noises would be fun, too.
  *      -  Should simulate a Unix kernel panic and reboot.
  *      -  Making various boot noises would be fun, too.
- *      -  Maybe scatter some random bits across the screen,
- *         to simulate corruption of video ram?
  *      -  Should randomize the various hex numbers printed.
  */
 
 #include "screenhack.h"
  *      -  Should randomize the various hex numbers printed.
  */
 
 #include "screenhack.h"
+#include "xpm-pixmap.h"
 #include <stdio.h>
 #include <X11/Xutil.h>
 
 #include <stdio.h>
 #include <X11/Xutil.h>
 
-#ifdef HAVE_XPM
-# include <X11/xpm.h>
-# include "images/amiga.xpm"
-#endif
 
 
+#include "images/amiga.xpm"
 #include "images/atari.xbm"
 #include "images/mac.xbm"
 #include "images/atari.xbm"
 #include "images/mac.xbm"
+#include "images/macbomb.xbm"
 
 
 
 
-static void
+static int
 draw_string (Display *dpy, Window window, GC gc, XGCValues *gcv,
             XFontStruct *font,
             int xoff, int yoff,
 draw_string (Display *dpy, Window window, GC gc, XGCValues *gcv,
             XFontStruct *font,
             int xoff, int yoff,
@@ -120,6 +116,8 @@ draw_string (Display *dpy, Window window, GC gc, XGCValues *gcv,
        }
       s++;
     }
        }
       s++;
     }
+
+  return width * char_width;
 }
 
 
 }
 
 
@@ -158,22 +156,36 @@ double_pixmap(Display *dpy, GC gc, Visual *visual, int depth, Pixmap pixmap,
 static Bool
 bsod_sleep(Display *dpy, int seconds)
 {
 static Bool
 bsod_sleep(Display *dpy, int seconds)
 {
-  XEvent event;
   int q = seconds * 4;
   int q = seconds * 4;
-  int mask = KeyPressMask|ButtonPressMask;
+  int quantum = 250000;
+
+  if (seconds == -1)
+    q = 1, quantum = 100000;
+
   do
     {
       XSync(dpy, False);
   do
     {
       XSync(dpy, False);
-      if (XCheckMaskEvent(dpy, mask, &event))
-       {
-         while (XCheckMaskEvent(dpy, mask, &event))
-           ;
-         return True;
-       }
+      while (XPending (dpy))
+        {
+          XEvent event;
+          XNextEvent (dpy, &event);
+          if (event.xany.type == ButtonPress)
+            return True;
+          if (event.xany.type == KeyPress)
+            {
+              KeySym keysym;
+              char c = 0;
+              XLookupString (&event.xkey, &c, 1, &keysym, 0);
+              if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
+                return True;
+            }
+          screenhack_handle_event (dpy, &event);
+        }
+
       if (q > 0)
        {
          q--;
       if (q > 0)
        {
          q--;
-         usleep(250000);
+         usleep(quantum);
        }
     }
   while (q > 0);
        }
     }
   while (q > 0);
@@ -182,8 +194,8 @@ bsod_sleep(Display *dpy, int seconds)
 }
 
 
 }
 
 
-static void
-windows (Display *dpy, Window window, int delay, Bool w95p)
+static Bool
+windows (Display *dpy, Window window, int delay, int which)
 {
   XGCValues gcv;
   XWindowAttributes xgwa;
 {
   XGCValues gcv;
   XWindowAttributes xgwa;
@@ -204,7 +216,7 @@ windows (Display *dpy, Window window, int delay, Bool w95p)
      "\n"
      "_Press any key to continue");
 
      "\n"
      "_Press any key to continue");
 
-  const char *wnt =
+  const char *wnt = /* from Jim Niemira <urmane@urmane.org> */
     ("*** STOP: 0x0000001E (0x80000003,0x80106fc0,0x8025ea21,0xfd6829e8)\n"
    "Unhandled Kernel exception c0000047 from fa8418b4 (8025ea21,fd6829e8)\n"
    "\n"
     ("*** STOP: 0x0000001E (0x80000003,0x80106fc0,0x8025ea21,0xfd6829e8)\n"
    "Unhandled Kernel exception c0000047 from fa8418b4 (8025ea21,fd6829e8)\n"
    "\n"
@@ -250,15 +262,34 @@ windows (Display *dpy, Window window, int delay, Bool w95p)
    "contact your system administrator or technical support group."
      );
 
    "contact your system administrator or technical support group."
      );
 
+  const char *w2ka =
+    ("*** STOP: 0x000000D1 (0xE1D38000,0x0000001C,0x00000000,0xF09D42DA)\n"
+     "DRIVER_IRQL_NOT_LESS_OR_EQUAL \n"
+     "\n"
+    "*** Address F09D42DA base at F09D4000, DateStamp 39f459ff - CRASHDD.SYS\n"
+     "\n"
+     "Beginning dump of physical memory\n");
+  const char *w2kb =
+    ("Physical memory dump complete. Contact your system administrator or\n"
+     "technical support group.\n");
+
+  if (which < 0 || which > 2) abort();
+
+  if (!get_boolean_resource((which == 0 ? "doWindows" :
+                             which == 1 ? "doNT" :
+                                          "doWin2K"),
+                            "DoWindows"))
+    return False;
+
   XGetWindowAttributes (dpy, window, &xgwa);
 
   fontname = get_string_resource ((xgwa.height > 600
   XGetWindowAttributes (dpy, window, &xgwa);
 
   fontname = get_string_resource ((xgwa.height > 600
-                                  ? (w95p
-                                     ? "windows95.font2"
-                                     : "windowsNT.font2")
-                                  : (w95p
-                                     ? "windows95.font"
-                                     : "windowsNT.font")),
+                                  ? (which == 0 ? "windows95.font2" :
+                                      which == 1 ? "windowsNT.font2" :
+                                                   "windows2K.font2")
+                                  : (which == 0 ? "windows95.font" :
+                                     which == 1 ? "windowsNT.font" :
+                                                   "windows2K.font")),
                                  "Windows.Font");
   if (!fontname || !*fontname) fontname = (char *)def_font;
   font = XLoadQueryFont (dpy, fontname);
                                  "Windows.Font");
   if (!fontname || !*fontname) fontname = (char *)def_font;
   font = XLoadQueryFont (dpy, fontname);
@@ -268,14 +299,14 @@ windows (Display *dpy, Window window, int delay, Bool w95p)
     free (fontname);
 
   gcv.font = font->fid;
     free (fontname);
 
   gcv.font = font->fid;
-  gcv.foreground = get_pixel_resource((w95p
-                                      ? "windows95.foreground"
-                                      : "windowsNT.foreground"),
+  gcv.foreground = get_pixel_resource((which == 0 ? "windows95.foreground" :
+                                      which == 1 ? "windowsNT.foreground" :
+                                                    "windows2K.foreground"),
                                      "Windows.Foreground",
                                      dpy, xgwa.colormap);
                                      "Windows.Foreground",
                                      dpy, xgwa.colormap);
-  gcv.background = get_pixel_resource((w95p
-                                      ? "windows95.background"
-                                      : "windowsNT.background"),
+  gcv.background = get_pixel_resource((which == 0 ? "windows95.background" :
+                                      which == 1 ? "windowsNT.background" :
+                                                    "windows2K.background"),
                                      "Windows.Background",
                                      dpy, xgwa.colormap);
   XSetWindowBackground(dpy, window, gcv.background);
                                      "Windows.Background",
                                      dpy, xgwa.colormap);
   XSetWindowBackground(dpy, window, gcv.background);
@@ -283,23 +314,35 @@ windows (Display *dpy, Window window, int delay, Bool w95p)
 
   gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
 
 
   gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
 
-  if (w95p)
+  if (which == 0)
     draw_string(dpy, window, gc, &gcv, font,
                0, 0, xgwa.width, xgwa.height, w95, 0);
     draw_string(dpy, window, gc, &gcv, font,
                0, 0, xgwa.width, xgwa.height, w95, 0);
-  else
+  else if (which == 1)
     draw_string(dpy, window, gc, &gcv, font, 0, 0, 10, 10, wnt, 750);
     draw_string(dpy, window, gc, &gcv, font, 0, 0, 10, 10, wnt, 750);
+  else
+    {
+      int line_height = font->ascent + font->descent + 1;
+      int x = 20;
+      int y = (xgwa.height / 4);
+
+      draw_string(dpy, window, gc, &gcv, font, x, y, 10, 10, w2ka, 750);
+      y += line_height * 6;
+      bsod_sleep(dpy, 4);
+      draw_string(dpy, window, gc, &gcv, font, x, y, 10, 10, w2kb, 750);
+    }
 
   XFreeGC(dpy, gc);
   XSync(dpy, False);
   bsod_sleep(dpy, delay);
   XClearWindow(dpy, window);
   XFreeFont(dpy, font);
 
   XFreeGC(dpy, gc);
   XSync(dpy, False);
   bsod_sleep(dpy, delay);
   XClearWindow(dpy, window);
   XFreeFont(dpy, font);
+  return True;
 }
 
 /* SCO OpenServer 5 panic, by Tom Kelly <tom@ancilla.toronto.on.ca>
  */
 }
 
 /* SCO OpenServer 5 panic, by Tom Kelly <tom@ancilla.toronto.on.ca>
  */
-static void
-openserver (Display *dpy, Window window, int delay)
+static Bool
+sco (Display *dpy, Window window, int delay)
 {
   XGCValues gcv;
   XWindowAttributes xgwa;
 {
   XGCValues gcv;
   XWindowAttributes xgwa;
@@ -307,10 +350,11 @@ openserver (Display *dpy, Window window, int delay)
   const char *def_font = "fixed";
   XFontStruct *font;
   GC gc;
   const char *def_font = "fixed";
   XFontStruct *font;
   GC gc;
+  int lines_1 = 0, lines_2 = 0, lines_3 = 0, lines_4 = 0;
+  const char *s;
 
 
-  const char *openserver_panic =
-    ("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
-     "Unexpected trap in kernel mode:\n"
+  const char *sco_panic_1 =
+    ("Unexpected trap in kernel mode:\n"
      "\n"
      "cr0 0x80010013     cr2  0x00000014     cr3 0x00000000  tlb  0x00000000\n"
      "ss  0x00071054    uesp  0x00012055     efl 0x00080888  ipl  0x00000005\n"
      "\n"
      "cr0 0x80010013     cr2  0x00000014     cr3 0x00000000  tlb  0x00000000\n"
      "ss  0x00071054    uesp  0x00012055     efl 0x00080888  ipl  0x00000005\n"
@@ -321,22 +365,35 @@ openserver (Display *dpy, Window window, int delay)
      "\n"
      "PANIC: k_trap - kernel mode trap type 0x0000000E\n"
      "Trying to dump 5023 pages to dumpdev hd (1/41), 63 pages per '.'\n"
      "\n"
      "PANIC: k_trap - kernel mode trap type 0x0000000E\n"
      "Trying to dump 5023 pages to dumpdev hd (1/41), 63 pages per '.'\n"
-     "...............................................................................\n"
-     "5023 pages dumped\n"
+    );
+  const char *sco_panic_2 =
+   ("...............................................................................\n"
+    );
+  const char *sco_panic_3 =
+    ("5023 pages dumped\n"
      "\n"
      "\n"
      "\n"
      "\n"
-     "**   Safe to Power Off   **\n"
+     );
+  const char *sco_panic_4 =
+    ("**   Safe to Power Off   **\n"
      "           - or -\n"
      "** Press Any Key to Reboot **\n"
     );
 
      "           - or -\n"
      "** Press Any Key to Reboot **\n"
     );
 
+  if (!get_boolean_resource("doSCO", "DoSCO"))
+    return False;
+
+  for (s = sco_panic_1; *s; s++) if (*s == '\n') lines_1++;
+  for (s = sco_panic_2; *s; s++) if (*s == '\n') lines_2++;
+  for (s = sco_panic_3; *s; s++) if (*s == '\n') lines_3++;
+  for (s = sco_panic_4; *s; s++) if (*s == '\n') lines_4++;
 
   XGetWindowAttributes (dpy, window, &xgwa);
 
   fontname = get_string_resource ((xgwa.height > 600
 
   XGetWindowAttributes (dpy, window, &xgwa);
 
   fontname = get_string_resource ((xgwa.height > 600
-                                  ? "openserver.font2"
-                                  : "openserver.font"),
-                                 "OpenServer.Font");
+                                  ? "sco.font2"
+                                  : "sco.font"),
+                                 "SCO.Font");
   if (!fontname || !*fontname) fontname = (char *)def_font;
   font = XLoadQueryFont (dpy, fontname);
   if (!font) font = XLoadQueryFont (dpy, def_font);
   if (!fontname || !*fontname) fontname = (char *)def_font;
   font = XLoadQueryFont (dpy, fontname);
   if (!font) font = XLoadQueryFont (dpy, def_font);
@@ -345,11 +402,11 @@ openserver (Display *dpy, Window window, int delay)
     free (fontname);
 
   gcv.font = font->fid;
     free (fontname);
 
   gcv.font = font->fid;
-  gcv.foreground = get_pixel_resource(("openserver.foreground"),
-                                     "OpenServer.Foreground",
+  gcv.foreground = get_pixel_resource(("sco.foreground"),
+                                     "SCO.Foreground",
                                      dpy, xgwa.colormap);
                                      dpy, xgwa.colormap);
-  gcv.background = get_pixel_resource(("openserver.background"),
-                                     "OpenServer.Background",
+  gcv.background = get_pixel_resource(("sco.background"),
+                                     "SCO.Background",
                                      dpy, xgwa.colormap);
   XSetWindowBackground(dpy, window, gcv.background);
   XClearWindow(dpy, window);
                                      dpy, xgwa.colormap);
   XSetWindowBackground(dpy, window, gcv.background);
   XClearWindow(dpy, window);
@@ -357,18 +414,53 @@ openserver (Display *dpy, Window window, int delay)
   gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
 
   draw_string(dpy, window, gc, &gcv, font,
   gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
 
   draw_string(dpy, window, gc, &gcv, font,
-               0, 0, xgwa.width, xgwa.height, openserver_panic, 0);
-  XFreeGC(dpy, gc);
+             10, xgwa.height - ((lines_1 + lines_2 + lines_3 + lines_4 + 1) *
+                                 (font->ascent + font->descent + 1)),
+             10, 10,
+             sco_panic_1, 0);
   XSync(dpy, False);
   XSync(dpy, False);
+  for (s = sco_panic_2; *s; s++)
+    {
+      char *ss = strdup(sco_panic_2);
+      ss[s - sco_panic_2] = 0;
+      draw_string(dpy, window, gc, &gcv, font,
+                  10, xgwa.height - ((lines_2 + lines_3 + lines_4 + 1) *
+                                     (font->ascent + font->descent + 1)),
+                  10, 10,
+                  ss, 0);
+      XSync(dpy, False);
+      free(ss);
+      if (bsod_sleep (dpy, -1))
+        goto DONE;
+    }
+
+  draw_string(dpy, window, gc, &gcv, font,
+             10, xgwa.height - ((lines_3 + lines_4 + 1) *
+                                 (font->ascent + font->descent + 1)),
+             10, 10,
+             sco_panic_3, 0);
+  XSync(dpy, False);
+  if (bsod_sleep(dpy, 1))
+    goto DONE;
+  draw_string(dpy, window, gc, &gcv, font,
+             10, xgwa.height - ((lines_4 + 1) *
+                                 (font->ascent + font->descent + 1)),
+             10, 10,
+             sco_panic_4, 0);
+  XSync(dpy, False);
+
   bsod_sleep(dpy, delay);
   bsod_sleep(dpy, delay);
+ DONE:
   XClearWindow(dpy, window);
   XClearWindow(dpy, window);
+  XFreeGC(dpy, gc);
   XFreeFont(dpy, font);
   XFreeFont(dpy, font);
+  return True;
 }
 
 
 /* Linux (sparc) panic, by Tom Kelly <tom@ancilla.toronto.on.ca>
  */
 }
 
 
 /* Linux (sparc) panic, by Tom Kelly <tom@ancilla.toronto.on.ca>
  */
-static void
+static Bool
 sparc_linux (Display *dpy, Window window, int delay)
 {
   XGCValues gcv;
 sparc_linux (Display *dpy, Window window, int delay)
 {
   XGCValues gcv;
@@ -377,6 +469,8 @@ sparc_linux (Display *dpy, Window window, int delay)
   const char *def_font = "fixed";
   XFontStruct *font;
   GC gc;
   const char *def_font = "fixed";
   XFontStruct *font;
   GC gc;
+  int lines = 1;
+  const char *s;
 
   const char *linux_panic =
     ("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
 
   const char *linux_panic =
     ("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
@@ -397,10 +491,13 @@ sparc_linux (Display *dpy, Window window, int delay)
        "l4: 0000ffff l5: f0131550 l6: f012c000 l7: f0130400\n"
        "i0: f1b13fb0 i1: 00000001 i2: 00000002 i3: 0007c000\n"
        "i4: f01457c0 i5: 00000004 i6: f1b13f70 i7: f0015360\n"
        "l4: 0000ffff l5: f0131550 l6: f012c000 l7: f0130400\n"
        "i0: f1b13fb0 i1: 00000001 i2: 00000002 i3: 0007c000\n"
        "i4: f01457c0 i5: 00000004 i6: f1b13f70 i7: f0015360\n"
-       "Instruction DUMP:"
-
+       "Instruction DUMP:\n"
     );
 
     );
 
+  if (!get_boolean_resource("doSparcLinux", "DoSparcLinux"))
+    return False;
+
+  for (s = linux_panic; *s; s++) if (*s == '\n') lines++;
 
   XGetWindowAttributes (dpy, window, &xgwa);
 
 
   XGetWindowAttributes (dpy, window, &xgwa);
 
@@ -428,15 +525,162 @@ sparc_linux (Display *dpy, Window window, int delay)
   gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
 
   draw_string(dpy, window, gc, &gcv, font,
   gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
 
   draw_string(dpy, window, gc, &gcv, font,
-               0, 0, xgwa.width, xgwa.height, linux_panic, 0);
+             10, xgwa.height - (lines * (font->ascent + font->descent + 1)),
+             10, 10,
+             linux_panic, 0);
   XFreeGC(dpy, gc);
   XSync(dpy, False);
   bsod_sleep(dpy, delay);
   XClearWindow(dpy, window);
   XFreeFont(dpy, font);
   XFreeGC(dpy, gc);
   XSync(dpy, False);
   bsod_sleep(dpy, delay);
   XClearWindow(dpy, window);
   XFreeFont(dpy, font);
+  return True;
 }
 
 }
 
-static void
+/* BSD Panic by greywolf@starwolf.com - modeled after the Linux panic above.
+   By Grey Wolf <greywolf@siteROCK.com>
+ */
+static Bool
+bsd (Display *dpy, Window window, int delay)
+{
+  XGCValues gcv;
+  XWindowAttributes xgwa;
+  char *fontname;
+  const char *def_font = "fixed";
+  XFontStruct *font;
+  GC gc;
+  int lines = 1;
+  int i, n, b;
+  const char *rbstr, *panicking;
+  char syncing[80], bbuf[5], *bp;
+
+  const char *panicstr[] =
+   {"panic: ifree: freeing free inode",
+    "panic: blkfree: freeing free block",
+    "panic: improbability coefficient below zero",
+    "panic: cgsixmmap",
+    "panic: crazy interrupts",
+    "panic: nmi",
+    "panic: attempted windows install",
+    "panic: don't",
+    "panic: free inode isn't",
+    "panic: cpu_fork: curproc",
+    "panic: malloc: out of space in kmem_map",
+    "panic: vogon starship detected",
+    "panic: teleport chamber: out of order",
+    "panic: Brain fried - core dumped"};
+     
+  if (!get_boolean_resource("doBSD", "DoBSD"))
+    return False;
+
+  for (i = 0; i < sizeof(syncing); i++)
+    syncing[i] = 0;
+
+  i = (random() & 0xffff) % (sizeof(panicstr) / sizeof(*panicstr));
+
+  panicking = panicstr[i];
+  strcpy(syncing, "Syncing disks: ");
+
+  b = (random() & 0xff) % 40;
+  for (n = 0; (n < 20) && (b > 0); n++)
+    {
+      if (i)
+        {
+          i = (random() & 0x7);
+          b -= (random() & 0xff) % 20;
+          if (b < 0)
+            b = 0;
+        }
+      sprintf (bbuf, "%d ", b);
+      strcat (syncing, bbuf);
+    }
+
+  if (b)
+    rbstr = "damn!";
+  else
+    rbstr = "sunk!";
+
+  lines = 5;
+
+  XGetWindowAttributes (dpy, window, &xgwa);
+
+  fontname = get_string_resource ((xgwa.height > 600
+                                  ? "bsd.font2"
+                                  : "bsd.font"),
+                                 "BSD.Font");
+  if (!fontname || !*fontname) fontname = (char *)def_font;
+  font = XLoadQueryFont (dpy, fontname);
+  if (!font) font = XLoadQueryFont (dpy, def_font);
+  if (!font) exit(-1);
+  if (fontname && fontname != def_font)
+    free (fontname);
+
+  gcv.font = font->fid;
+  gcv.foreground = get_pixel_resource(("bsd.foreground"),
+                                     "BSD.Foreground",
+                                     dpy, xgwa.colormap);
+  gcv.background = get_pixel_resource(("bsd.background"),
+                                     "BSD.Background",
+                                     dpy, xgwa.colormap);
+  XSetWindowBackground(dpy, window, gcv.background);
+  XClearWindow(dpy, window);
+
+  gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
+
+  draw_string(dpy, window, gc, &gcv, font,
+             10, xgwa.height - (lines * (font->ascent + font->descent + 1)),
+             10, 10,
+             panicking, 0);
+  XSync(dpy, False);
+  lines--;
+
+  for (bp = syncing; *bp;)
+    {
+      char *bsd_bufs, oc = 0;
+      for (;*bp && (*bp != ' '); bp++)
+        ;
+      if (*bp == ' ')
+        {
+          oc = *bp;
+          *bp = 0;
+        }
+      bsd_bufs = strdup(syncing);
+      draw_string(dpy, window, gc, &gcv, font,
+                  10,
+                  xgwa.height - (lines * (font->ascent + font->descent + 1)),
+                  10, 10,
+                  bsd_bufs, 0);
+      XSync(dpy, False);
+      free(bsd_bufs);
+      if (oc)
+       *bp = oc;
+      if (bsod_sleep(dpy, -1))
+        goto DONE;
+      bp++;
+    }
+
+  lines--;
+  
+  draw_string(dpy, window, gc, &gcv, font,
+             10, xgwa.height - (lines * (font->ascent + font->descent + 1)),
+             10, 10,
+             rbstr, 0);
+  lines--;
+  draw_string(dpy, window, gc, &gcv, font,
+             10, xgwa.height - (lines * (font->ascent + font->descent + 1)),
+             10, 10,
+             "Rebooting", 0);
+
+  XFreeGC(dpy, gc);
+  XSync(dpy, False);
+  bsod_sleep(dpy, delay);
+
+DONE:
+  XClearWindow(dpy, window);
+  XFreeFont(dpy, font);
+  return True;
+}
+
+static Bool
 amiga (Display *dpy, Window window, int delay)
 {
   XGCValues gcv;
 amiga (Display *dpy, Window window, int delay)
 {
   XGCValues gcv;
@@ -448,12 +692,17 @@ amiga (Display *dpy, Window window, int delay)
   int height;
   unsigned long fg, bg, bg2;
   Pixmap pixmap = 0;
   int height;
   unsigned long fg, bg, bg2;
   Pixmap pixmap = 0;
-  int pix_w, pix_h;
+  int pix_w = 0, pix_h = 0;
+  int string_width;
+  int margin;
 
   const char *string =
     ("_Software failure.  Press left mouse button to continue.\n"
      "_Guru Meditation #00000003.00C01570");
 
 
   const char *string =
     ("_Software failure.  Press left mouse button to continue.\n"
      "_Guru Meditation #00000003.00C01570");
 
+  if (!get_boolean_resource("doAmiga", "DoAmiga"))
+    return False;
+
   XGetWindowAttributes (dpy, window, &xgwa);
 
   fontname = get_string_resource ((xgwa.height > 600
   XGetWindowAttributes (dpy, window, &xgwa);
 
   fontname = get_string_resource ((xgwa.height > 600
@@ -484,37 +733,10 @@ amiga (Display *dpy, Window window, int delay)
 
   height = (font->ascent + font->descent) * 6;
 
 
   height = (font->ascent + font->descent) * 6;
 
-#ifdef HAVE_XPM
-  {
-    XpmAttributes xpmattrs;
-    int result;
-    xpmattrs.valuemask = 0;
-
-# ifdef XpmCloseness
-    xpmattrs.valuemask |= XpmCloseness;
-    xpmattrs.closeness = 40000;
-# endif
-# ifdef XpmVisual
-    xpmattrs.valuemask |= XpmVisual;
-    xpmattrs.visual = xgwa.visual;
-# endif
-# ifdef XpmDepth
-    xpmattrs.valuemask |= XpmDepth;
-    xpmattrs.depth = xgwa.depth;
-# endif
-# ifdef XpmColormap
-    xpmattrs.valuemask |= XpmColormap;
-    xpmattrs.colormap = xgwa.colormap;
-# endif
-
-    result = XpmCreatePixmapFromData(dpy, window, amiga_hand,
-                                    &pixmap, 0 /* mask */, &xpmattrs);
-    if (!pixmap || (result != XpmSuccess && result != XpmColorError))
-      pixmap = 0;
-    pix_w = xpmattrs.width;
-    pix_h = xpmattrs.height;
-  }
-#endif /* HAVE_XPM */
+#if defined(HAVE_GDK_PIXBUF) || defined (HAVE_XPM)
+  pixmap = xpm_data_to_pixmap (dpy, window, (char **) amiga_hand,
+                               &pix_w, &pix_h, 0);
+#endif /* HAVE_GDK_PIXBUF || HAVE_XPM */
 
   if (pixmap && xgwa.height > 600)     /* scale up the bitmap */
     {
 
   if (pixmap && xgwa.height > 600)     /* scale up the bitmap */
     {
@@ -539,18 +761,24 @@ amiga (Display *dpy, Window window, int delay)
     }
 
   XFillRectangle(dpy, window, gc2, 0, 0, xgwa.width, height);
     }
 
   XFillRectangle(dpy, window, gc2, 0, 0, xgwa.width, height);
-  draw_string(dpy, window, gc, &gcv, font, 0, 0, xgwa.width, height, string,0);
-
+  margin = font->ascent;
+  string_width = draw_string(dpy, window, gc, &gcv, font,
+                             margin, 0,
+                             xgwa.width - (margin * 2), height,
+                             string, 0);
   {
     GC gca = gc;
     while (delay > 0)
       {
   {
     GC gca = gc;
     while (delay > 0)
       {
-       XFillRectangle(dpy, window, gca, 0, 0, xgwa.width, font->ascent);
-       XFillRectangle(dpy, window, gca, 0, 0, font->ascent, height);
-       XFillRectangle(dpy, window, gca, xgwa.width-font->ascent, 0,
-                      font->ascent, height);
-       XFillRectangle(dpy, window, gca, 0, height-font->ascent, xgwa.width,
-                      font->ascent);
+        int x2;
+       XFillRectangle(dpy, window, gca, 0, 0, xgwa.width, margin);
+       XFillRectangle(dpy, window, gca, 0, 0, margin, height);
+        XFillRectangle(dpy, window, gca,
+                       0, height - margin, xgwa.width, margin);
+        x2 = margin + string_width;
+        if (x2 < xgwa.width - margin) x2 = xgwa.width - margin;
+        XFillRectangle(dpy, window, gca, x2, 0, margin, height);
+
        gca = (gca == gc ? gc2 : gc);
        XSync(dpy, False);
        if (bsod_sleep(dpy, 1))
        gca = (gca == gc ? gc2 : gc);
        XSync(dpy, False);
        if (bsod_sleep(dpy, 1))
@@ -564,6 +792,7 @@ amiga (Display *dpy, Window window, int delay)
   XSync(dpy, False);
   XClearWindow(dpy, window);
   XFreeFont(dpy, font);
   XSync(dpy, False);
   XClearWindow(dpy, window);
   XFreeFont(dpy, font);
+  return True;
 }
 
 
 }
 
 
@@ -577,7 +806,7 @@ amiga (Display *dpy, Window window, int delay)
        Perhaps somebody else can tell you more about it..  its just
        a quick hack :-}
  */
        Perhaps somebody else can tell you more about it..  its just
        a quick hack :-}
  */
-static void
+static Bool
 atari (Display *dpy, Window window, int delay)
 {
        
 atari (Display *dpy, Window window, int delay)
 {
        
@@ -589,9 +818,12 @@ atari (Display *dpy, Window window, int delay)
   Pixmap pixmap = 0;
   int pix_w = atari_width;
   int pix_h = atari_height;
   Pixmap pixmap = 0;
   int pix_w = atari_width;
   int pix_h = atari_height;
-  int offset = atari_width + 2;
+  int offset;
   int i, x, y;
 
   int i, x, y;
 
+  if (!get_boolean_resource("doAtari", "DoAtari"))
+    return False;
+
   XGetWindowAttributes (dpy, window, &xgwa);
 
   font = XLoadQueryFont (dpy, def_font);
   XGetWindowAttributes (dpy, window, &xgwa);
 
   font = XLoadQueryFont (dpy, def_font);
@@ -609,11 +841,15 @@ atari (Display *dpy, Window window, int delay)
   gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
 
   pixmap = XCreatePixmapFromBitmapData(dpy, window, (char *) atari_bits,
   gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
 
   pixmap = XCreatePixmapFromBitmapData(dpy, window, (char *) atari_bits,
-                                      atari_width, atari_height,
-                                      gcv.foreground,
-                                      gcv.background,
+                                      pix_w, pix_h,
+                                      gcv.foreground, gcv.background,
                                       xgwa.depth);
                                       xgwa.depth);
+  pixmap = double_pixmap(dpy, gc, xgwa.visual, xgwa.depth,
+                        pixmap, pix_w, pix_h);
+  pix_w *= 2;
+  pix_h *= 2;
 
 
+  offset = pix_w + 2;
   x = 5;
   y = (xgwa.height - (xgwa.height / 5));
   if (y < 0) y = 0;
   x = 5;
   y = (xgwa.height - (xgwa.height / 5));
   if (y < 0) y = 0;
@@ -624,21 +860,24 @@ atari (Display *dpy, Window window, int delay)
   }  
   
   for (i=7 ; i<10 ; i++) {
   }  
   
   for (i=7 ; i<10 ; i++) {
-    bsod_sleep(dpy, 1);
+    if (bsod_sleep(dpy, 1))
+      goto DONE;
     XCopyArea(dpy, pixmap, window, gc, 0, 0, pix_w, pix_h,
              (x + (i*offset)), y);
   }
 
     XCopyArea(dpy, pixmap, window, gc, 0, 0, pix_w, pix_h,
              (x + (i*offset)), y);
   }
 
+  bsod_sleep(dpy, delay);
+ DONE:
   XFreePixmap(dpy, pixmap);
   XFreeGC(dpy, gc);
   XSync(dpy, False);
   XFreePixmap(dpy, pixmap);
   XFreeGC(dpy, gc);
   XSync(dpy, False);
-  bsod_sleep(dpy, delay);
   XClearWindow(dpy, window);
   XFreeFont(dpy, font);
   XClearWindow(dpy, window);
   XFreeFont(dpy, font);
+  return True;
 }
 
 
 }
 
 
-static void
+static Bool
 mac (Display *dpy, Window window, int delay)
 {
   XGCValues gcv;
 mac (Display *dpy, Window window, int delay)
 {
   XGCValues gcv;
@@ -656,6 +895,9 @@ mac (Display *dpy, Window window, int delay)
   const char *string = ("0 0 0 0 0 0 0 F\n"
                        "0 0 0 0 0 0 0 3");
 
   const char *string = ("0 0 0 0 0 0 0 F\n"
                        "0 0 0 0 0 0 0 3");
 
+  if (!get_boolean_resource("doMac", "DoMac"))
+    return False;
+
   XGetWindowAttributes (dpy, window, &xgwa);
 
   fontname = get_string_resource ("mac.font", "Mac.Font");
   XGetWindowAttributes (dpy, window, &xgwa);
 
   fontname = get_string_resource ("mac.font", "Mac.Font");
@@ -682,9 +924,6 @@ mac (Display *dpy, Window window, int delay)
                                       gcv.background,
                                       xgwa.depth);
 
                                       gcv.background,
                                       xgwa.depth);
 
-  draw_string(dpy, window, gc, &gcv, font, 0, 0,
-             xgwa.width, xgwa.height + offset, string, 0);
-
   for(i = 0; i < 2; i++)
     {
       pixmap = double_pixmap(dpy, gc, xgwa.visual, xgwa.depth,
   for(i = 0; i < 2; i++)
     {
       pixmap = double_pixmap(dpy, gc, xgwa.visual, xgwa.depth,
@@ -702,14 +941,18 @@ mac (Display *dpy, Window window, int delay)
     XFreePixmap(dpy, pixmap);
   }
 
     XFreePixmap(dpy, pixmap);
   }
 
+  draw_string(dpy, window, gc, &gcv, font, 0, 0,
+             xgwa.width, xgwa.height + offset, string, 0);
+
   XFreeGC(dpy, gc);
   XSync(dpy, False);
   bsod_sleep(dpy, delay);
   XClearWindow(dpy, window);
   XFreeFont(dpy, font);
   XFreeGC(dpy, gc);
   XSync(dpy, False);
   bsod_sleep(dpy, delay);
   XClearWindow(dpy, window);
   XFreeFont(dpy, font);
+  return True;
 }
 
 }
 
-static void
+static Bool
 macsbug (Display *dpy, Window window, int delay)
 {
   XGCValues gcv;
 macsbug (Display *dpy, Window window, int delay)
 {
   XGCValues gcv;
@@ -820,6 +1063,9 @@ macsbug (Display *dpy, Window window, int delay)
   const char *s;
   int body_lines = 1;
 
   const char *s;
   int body_lines = 1;
 
+  if (!get_boolean_resource("doMacsBug", "DoMacsBug"))
+    return False;
+
   for (s = body; *s; s++) if (*s == '\n') body_lines++;
 
   XGetWindowAttributes (dpy, window, &xgwa);
   for (s = body; *s; s++) if (*s == '\n') body_lines++;
 
   XGetWindowAttributes (dpy, window, &xgwa);
@@ -921,85 +1167,557 @@ macsbug (Display *dpy, Window window, int delay)
   XFreeGC(dpy, gc2);
   XClearWindow(dpy, window);
   XFreeFont(dpy, font);
   XFreeGC(dpy, gc2);
   XClearWindow(dpy, window);
   XFreeFont(dpy, font);
+  return True;
+}
+
+static Bool
+mac1 (Display *dpy, Window window, int delay)
+{
+  XGCValues gcv;
+  XWindowAttributes xgwa;
+  GC gc;
+  Pixmap pixmap = 0;
+  int pix_w = macbomb_width;
+  int pix_h = macbomb_height;
+
+  if (!get_boolean_resource("doMac1", "DoMac1"))
+    return False;
+
+  XGetWindowAttributes (dpy, window, &xgwa);
+
+  gcv.foreground = get_pixel_resource("mac1.foreground", "Mac.Foreground",
+                                     dpy, xgwa.colormap);
+  gcv.background = get_pixel_resource("mac1.background", "Mac.Background",
+                                     dpy, xgwa.colormap);
+  XSetWindowBackground(dpy, window, gcv.background);
+  XClearWindow(dpy, window);
+
+  gc = XCreateGC(dpy, window, GCForeground|GCBackground, &gcv);
+
+  pixmap = XCreatePixmapFromBitmapData(dpy, window, (char *) macbomb_bits,
+                                      macbomb_width, macbomb_height,
+                                      gcv.foreground,
+                                      gcv.background,
+                                      xgwa.depth);
+
+  {
+    int x = (xgwa.width - pix_w) / 2;
+    int y = (xgwa.height - pix_h) / 2;
+    if (y < 0) y = 0;
+    XFillRectangle (dpy, window, gc, 0, 0, xgwa.width, xgwa.height);
+    XSync(dpy, False);
+    if (bsod_sleep(dpy, 1))
+      goto DONE;
+    XCopyArea(dpy, pixmap, window, gc, 0, 0, pix_w, pix_h, x, y);
+  }
+
+ DONE:
+  XFreeGC(dpy, gc);
+  XFreePixmap(dpy, pixmap);
+  XSync(dpy, False);
+  bsod_sleep(dpy, delay);
+  XClearWindow(dpy, window);
+  return True;
 }
 
 
 }
 
 
+
+
 \f
 \f
-char *progclass = "BSOD";
+/* blit damage
+ *
+ * by Martin Pool <mbp@samba.org>, Feb 2000.
+ *
+ * This is meant to look like the preferred failure mode of NCD
+ * Xterms.  The parameters for choosing what to copy where might not
+ * be quite right, but it looks about ugly enough.
+ */
+static Bool
+blitdamage (Display *dpy, Window window, int delay)
+{
+  XGCValues gcv;
+  XWindowAttributes xwa;
+  GC gc0;
+  int i;
+  int delta_x = 0, delta_y = 0;
+  int w, h;
+  int chunk_h, chunk_w;
+  int steps;
+  long gc_mask = 0;
+  int src_x, src_y;
+  int x, y;
+  
+  if (!get_boolean_resource("doBlitDamage", "DoBlitDamage"))
+    return False;
 
 
-char *defaults [] = {
-  "*delay:              30",
-
-  ".Windows.font:       -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
-  ".Windows.font2:      -*-courier-bold-r-*-*-*-180-*-*-m-*-*-*",
-  ".Windows.foreground:         White",
-  ".Windows.background:         Blue",
-
-  ".Amiga.font:                 -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
-  ".Amiga.font2:        -*-courier-bold-r-*-*-*-180-*-*-m-*-*-*",
-  ".Amiga.foreground:   Red",
-  ".Amiga.background:   Black",
-  ".Amiga.background2:  White",
-
-  ".Mac.font:           -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
-  ".Mac.foreground:     PaleTurquoise1",
-  ".Mac.background:     Black",
-
-  ".Atari.foreground:   Black",
-  ".Atari.background:   White",
-
-  ".MacsBug.font:       -*-courier-medium-r-*-*-*-100-*-*-m-*-*-*",
-  ".MacsBug.font2:      -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
-  ".MacsBug.font3:      -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
-  ".MacsBug.foreground:         Black",
-  ".MacsBug.background:         White",
-  ".MacsBug.borderColor: #AAAAAA",
+  XGetWindowAttributes(dpy, window, &xwa);
+
+  grab_screen_image(xwa.screen, window);
+
+  w = xwa.width;
+  h = xwa.height;
+
+  gc_mask = GCForeground;
   
   
-  ".OpenServer.font:    -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
-  ".OpenServer.font2:   -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
-  ".OpenServer.foreground: White",
-  ".OpenServer.background: Black",
+  gcv.plane_mask = random();
+  gc_mask |= GCPlaneMask;
   
   
-  ".SparcLinux.font:    -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
-  ".SparcLinux.font2:   -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
+  gc0 = XCreateGC(dpy, window, gc_mask, &gcv);
+
+  steps = 50;
+  chunk_w = w / (random() % 1 + 1);
+  chunk_h = h / (random() % 1 + 1);
+  if (random() & 0x1000) 
+    delta_y = random() % 600;
+  if (!delta_y || (random() & 0x2000))
+    delta_x = random() % 600;
+  src_x = 0; 
+  src_y = 0; 
+  x = 0;
+  y = 0;
+  
+  for (i = 0; i < steps; i++) {
+    if (x + chunk_w > w) 
+      x -= w;
+    else
+      x += delta_x;
+    
+    if (y + chunk_h > h)
+      y -= h;
+    else
+      y += delta_y;
+    
+    XCopyArea(dpy, window, window, gc0,
+             src_x, src_y, 
+             chunk_w, chunk_h,
+             x, y);
+
+    if (bsod_sleep(dpy, 0))
+      goto DONE;
+  }
+
+  bsod_sleep(dpy, delay);
+
+ DONE:
+  XFreeGC(dpy, gc0);
+
+  return True;
+}
+
+\f
+/*
+ * SPARC Solaris panic. Should look pretty authentic on Solaris boxes.
+ * Anton Solovyev <solovam@earthlink.net>
+ */ 
+
+static int solaris_max_scroll = 10;
+
+typedef struct
+{
+  Display *dpy;
+  Window window;
+  GC gc;
+  Pixmap subwindow;             /* The text subwindow */
+  XFontStruct *xfs;
+  int width;                    /* Window width in pixels */
+  int height;                   /* Window height in pixels */
+  int sub_width;                /* Text subwindow width in pixels */
+  int sub_height;               /* Text subwindow height in pixels */
+  int sub_x;                    /* upper left corner of the text subwindow */
+  int sub_y;                    /* upper left corner of the text subwindow */
+  int char_width;               /* Char width in pixels */
+  int line_height;              /* Line height in pixels */
+  int columns;                  /* Number of columns in the text screen */
+  int lines;                    /* Number of lines in the text screen */
+  int x;                        /* position of the cursor */
+  int y;                        /* position of the cursor */
+} solaris_console;
+
+
+static solaris_console *
+make_solaris_console (Display *dpy, Window window)
+{
+  const char *def_font = "fixed";
+  solaris_console* ts;
+
+  XWindowAttributes xgwa;
+  XGCValues gcv;
+  char* fontname;
+
+  ts = malloc(sizeof(solaris_console));
+
+  ts->window = window;
+  ts->dpy = dpy;
+
+  ts->x = 0;
+  ts->y = 0;
+
+  XGetWindowAttributes (dpy, window, &xgwa);
+  ts->width = xgwa.width;
+  ts->height = xgwa.height;
+  ts->sub_width = ts->width * 0.8;
+  ts->sub_height = ts->height * 0.8;
+
+  fontname = get_string_resource ("solaris.font", "Solaris.Font");
+  ts->xfs = XLoadQueryFont (dpy, fontname);
+  if (!ts->xfs)
+    {
+      fontname = get_string_resource("solaris.font2", "Solaris.Font");
+      ts->xfs = XLoadQueryFont(dpy, fontname);
+    }
+  if (!ts->xfs)
+    ts->xfs = XLoadQueryFont(dpy, def_font);
+  if (!ts->xfs)
+    {
+      fprintf (stderr, "Can't load font\n");
+      XFreeFont (dpy, ts->xfs);
+      free (ts);
+      exit (1);
+    }
+  gcv.font = ts->xfs->fid;
+  ts->char_width = (ts->xfs->per_char
+                    ? ts->xfs->per_char[ts->xfs->min_char_or_byte2 +
+                                       ts->xfs->default_char].width
+                    : ts->xfs->max_bounds.width);
+  ts->line_height = ts->xfs->ascent + ts->xfs->descent + 1;
+
+  ts->columns = ts->sub_width / ts->char_width;
+  ts->lines = ts->sub_height / ts->line_height;
+
+  ts->sub_x = (ts->width - ts->sub_width) / 2;
+  ts->sub_y = (ts->height - ts->sub_height) / 2;
+
+  ts->subwindow = XCreatePixmap (dpy, window, ts->sub_width,
+                                 ts->sub_height * (solaris_max_scroll + 1),
+                                 xgwa.depth);
+  grab_screen_image (xgwa.screen, window);
+  gcv.function = GXcopy;
+  gcv.background = XBlackPixel (dpy, XDefaultScreen(dpy));
+  gcv.foreground = XWhitePixel (dpy, XDefaultScreen(dpy));
+  ts->gc = XCreateGC (dpy, window,
+                      GCFunction | GCBackground | GCForeground | GCFont,
+                      &gcv);
+  XCopyArea (dpy, window, ts->subwindow, ts->gc,
+             ts->sub_x, ts->sub_y, ts->sub_width, ts->sub_height,
+             0, 0);
+  XFillRectangle (dpy, ts->subwindow, ts->gc, 0, ts->sub_height,
+                  ts->sub_width, ts->sub_height * solaris_max_scroll);
+
+  gcv.background = XWhitePixel (dpy, XDefaultScreen (dpy));
+  gcv.foreground = XBlackPixel (dpy, XDefaultScreen (dpy));
+  XChangeGC (dpy, ts->gc, GCBackground | GCForeground, &gcv);
+
+  return(ts);
+}
+
+static void
+free_solaris_console (solaris_console* ts)
+{
+  XFreePixmap (ts->dpy, ts->subwindow);
+  XFreeGC (ts->dpy, ts->gc);
+  XFreeFont (ts->dpy, ts->xfs);
+  free (ts);
+}
+
+static void
+solaris_draw (solaris_console* ts)
+{
+  XCopyArea (ts->dpy, ts->subwindow, ts->window, ts->gc, 0,
+             (ts->y + 1) * ts->line_height, ts->sub_width,
+             ts->sub_height, ts->sub_x, ts->sub_y);
+}
+
+static void
+solaris_putc (solaris_console* ts, const char aChar)
+{
+  if (ts->y >= solaris_max_scroll * ts->lines)
+    return;
+
+  if (!ts->y && !ts->x)
+    solaris_draw (ts);
+
+  switch (aChar)
+    {
+    case '\n':
+      ts->y++;
+      ts->x = 0;
+      solaris_draw (ts);
+      break;
+    case '\b':
+      if(ts->x > 0)
+        ts->x--;
+      break;
+    default:
+      XDrawImageString (ts->dpy, ts->subwindow, ts->gc,
+                        (ts->x * ts->char_width -
+                         ts->xfs->min_bounds.lbearing),
+                        (ts->sub_height + (ts->y + 1) *
+                         ts->line_height - ts->xfs->descent),
+                        &aChar, 1);
+      XCopyArea (ts->dpy, ts->subwindow, ts->window, ts->gc,
+                 ts->x * ts->char_width,
+                 ts->y * ts->line_height + ts->sub_height,
+                 ts->xfs->max_bounds.rbearing - ts->xfs->min_bounds.lbearing,
+                 ts->line_height, ts->sub_x + ts->x * ts->char_width,
+                 ts->sub_y + ts->sub_height - ts->line_height);
+      ts->x++;
+      if (ts->x >= ts->columns)
+        {
+          ts->x = 0;
+          solaris_putc(ts, '\n');
+        }
+      break;
+    }
+}
+
+static void
+solaris_puts (solaris_console* ts, const char* aString, int delay)
+{
+  const char *c;
+  for (c = aString; *c; ++c)
+    {
+      solaris_putc (ts, *c);
+      if (delay)
+        {
+          XSync(ts->dpy, 0);
+          usleep(delay);
+        }
+    }
+  XSync (ts->dpy, 0);
+}
+
+static Bool
+sparc_solaris (Display* dpy, Window window, int delay)
+{
+  const char *msg1 =
+    "BAD TRAP: cpu=0 type=0x31 rp=0x2a10043b5e0 addr=0xf3880 mmu_fsr=0x0\n"
+    "BAD TRAP occured in module \"unix\" due to an illegal access to a"
+    " user address.\n"
+    "adb: trap type = 0x31\n"
+    "addr=0xf3880\n"
+    "pid=307, pc=0x100306e4, sp=0x2a10043ae81, tstate=0x4480001602,"
+    " context=0x87f\n"
+    "g1-g7: 1045b000, 32f, 10079440, 180, 300000ebde8, 0, 30000953a20\n"
+    "Begin traceback... sp = 2a10043ae81\n"
+    "Called from 100bd060, fp=2a10043af31, args=f3700 300008cc988 f3880 0"
+    " 1 300000ebde0.\n"
+    "Called from 101fe1bc, fp=2a10043b011, args=3000045a240 104465a0"
+    " 300008e47d0 300008e48fa 300008ae350 300008ae410\n"
+    "Called from 1007c520, fp=2a10043b0c1, args=300008e4878 300003596e8 0"
+    " 3000045a320 0 3000045a220\n"
+    "Called from 1007c498, fp=2a10043b171, args=1045a000 300007847f0 20"
+    " 3000045a240 1 0\n"
+    "Called from 1007972c, fp=2a10043b221, args=1 300009517c0 30000951e58 1"
+    " 300007847f0 0\n"
+    "Called from 10031e10, fp=2a10043b2d1, args=3000095b0c8 0 300009396a8"
+    " 30000953a20 0 1\n"
+    "Called from 10000bdd8, fp=ffffffff7ffff1c1, args=0 57 100131480"
+    " 100131480 10012a6e0 0\n"
+    "End traceback...\n"
+    "panic[cpu0]/thread=30000953a20: trap\n"
+    "syncing file systems...";
+  const char *msg2 =
+    " 1 done\n"
+    "dumping to /dev/dsk/c0t0d0s3, offset 26935296\n";
+  const char *msg3 =
+    ": 2803 pages dumped, compression ratio 2.88, dump succeeded\n";
+  const char *msg4 =
+    "rebooting...\n"
+    "Resetting ...";
+
+  solaris_console* ts;
+  int i;
+  char buf[256];
+
+  if (!get_boolean_resource("doSolaris", "DoSolaris"))
+    return False;
+
+  ts = make_solaris_console (dpy, window);
+
+  solaris_puts (ts, msg1, 0);
+  if (bsod_sleep (dpy, 3))
+    goto DONE;
+
+  solaris_puts (ts, msg2, 0);
+  if (bsod_sleep (dpy, 2))
+    goto DONE;
+
+  for (i = 1; i <= 100; ++i)
+    {
+      sprintf(buf, "\b\b\b\b\b\b\b\b\b\b\b%3d%% done", i);
+      solaris_puts(ts, buf, 0);
+      if (bsod_sleep (dpy, -1))
+        goto DONE;
+    }
+
+  solaris_puts (ts, msg3, 0);
+  if (bsod_sleep (dpy, 2))
+    goto DONE;
+
+  solaris_puts (ts, msg4, 0);
+  if (bsod_sleep(dpy, 3))
+    goto DONE;
+
+  XFillRectangle (ts->dpy, ts->window, ts->gc, 0, 0,
+                  ts->width, ts->height);
+
+  bsod_sleep (dpy, 3);
+
+ DONE:
+  free_solaris_console (ts);
+
+  return True;
+}
+
+\f
+char *progclass = "BSOD";
+
+char *defaults [] = {
+  "*delay:                30",
+
+  "*doWindows:            True",
+  "*doNT:                 True",
+  "*doWin2K:              True",
+  "*doAmiga:              True",
+  "*doMac:                True",
+  "*doMacsBug:            True",
+  "*doMac1:               True",
+  "*doSCO:                True",
+  "*doAtari:              False",      /* boring */
+  "*doBSD:                False",      /* boring */
+  "*doSparcLinux:         False",      /* boring */
+  "*doBlitDamage:          True",
+  "*doSolaris:             True",
+
+  ".Windows.font:         -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
+  ".Windows.font2:        -*-courier-bold-r-*-*-*-180-*-*-m-*-*-*",
+  ".Windows.foreground:           White",
+  ".Windows.background:           Blue",
+
+  ".Amiga.font:                   -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
+  ".Amiga.font2:          -*-courier-bold-r-*-*-*-180-*-*-m-*-*-*",
+  ".Amiga.foreground:     Red",
+  ".Amiga.background:     Black",
+  ".Amiga.background2:    White",
+
+  ".Mac.font:             -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
+  ".Mac.foreground:       PaleTurquoise1",
+  ".Mac.background:       Black",
+
+  ".Atari.foreground:     Black",
+  ".Atari.background:     White",
+
+  ".MacsBug.font:         -*-courier-medium-r-*-*-*-100-*-*-m-*-*-*",
+  ".MacsBug.font2:        -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
+  ".MacsBug.font3:        -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
+  ".MacsBug.foreground:           Black",
+  ".MacsBug.background:           White",
+  ".MacsBug.borderColor:   #AAAAAA",
+
+  ".mac1.foreground:      Black",
+  ".mac1.background:      White",
+
+  ".SCO.font:             -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
+  ".SCO.font2:            -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
+  ".SCO.foreground:       White",
+  ".SCO.background:       Black",
+
+  ".SparcLinux.font:      -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
+  ".SparcLinux.font2:     -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
   ".SparcLinux.foreground: White",
   ".SparcLinux.background: Black",
   ".SparcLinux.foreground: White",
   ".SparcLinux.background: Black",
+
+  ".BSD.font:              vga",
+  ".BSD.font:              -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
+  ".BSD.font2:             -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
+/* ".BSD.font2:                    -sun-console-medium-r-*-*-22-*-*-*-m-*-*-*", */
+  ".BSD.foreground:        #c0c0c0",
+  ".BSD.background:        Black",
+
+  ".Solaris.font:           -sun-gallant-*-*-*-*-19-*-*-*-*-120-*-*",
+  ".Solaris.font2:          -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
+  "*dontClearRoot:          True",
   0
 };
 
 XrmOptionDescRec options [] = {
   { "-delay",          ".delay",               XrmoptionSepArg, 0 },
   0
 };
 
 XrmOptionDescRec options [] = {
   { "-delay",          ".delay",               XrmoptionSepArg, 0 },
+  { "-windows",                ".doWindows",           XrmoptionNoArg,  "True"  },
+  { "-no-windows",     ".doWindows",           XrmoptionNoArg,  "False" },
+  { "-nt",             ".doNT",                XrmoptionNoArg,  "True"  },
+  { "-no-nt",          ".doNT",                XrmoptionNoArg,  "False" },
+  { "-2k",             ".doWin2K",             XrmoptionNoArg,  "True"  },
+  { "-no-2k",          ".doWin2K",             XrmoptionNoArg,  "False" },
+  { "-amiga",          ".doAmiga",             XrmoptionNoArg,  "True"  },
+  { "-no-amiga",       ".doAmiga",             XrmoptionNoArg,  "False" },
+  { "-mac",            ".doMac",               XrmoptionNoArg,  "True"  },
+  { "-no-mac",         ".doMac",               XrmoptionNoArg,  "False" },
+  { "-atari",          ".doAtari",             XrmoptionNoArg,  "True"  },
+  { "-no-atari",       ".doAtari",             XrmoptionNoArg,  "False" },
+  { "-macsbug",                ".doMacsBug",           XrmoptionNoArg,  "True"  },
+  { "-no-macsbug",     ".doMacsBug",           XrmoptionNoArg,  "False" },
+  { "-sco",            ".doSCO",               XrmoptionNoArg,  "True"  },
+  { "-no-sco",         ".doSCO",               XrmoptionNoArg,  "False" },
+  { "-bsd",            ".doBSD",               XrmoptionNoArg,  "True"  },
+  { "-no-bsd",         ".doBSD",               XrmoptionNoArg,  "False" },
+  { "-sparclinux",     ".doSparcLinux",        XrmoptionNoArg,  "True"  },
+  { "-no-sparclinux",  ".doSparcLinux",        XrmoptionNoArg,  "False" },
+  { "-blitdamage",     ".doBlitDamage",        XrmoptionNoArg,  "True"  },
+  { "-no-blitdamage",  ".doBlitDamage",        XrmoptionNoArg,  "False" },
+  { "-solaris",                ".doSolaris",           XrmoptionNoArg,  "True"  },
+  { "-no-solaris",     ".doSolaris",           XrmoptionNoArg,  "False" },
   { 0, 0, 0, 0 }
 };
 
   { 0, 0, 0, 0 }
 };
 
+
 void
 screenhack (Display *dpy, Window window)
 {
 void
 screenhack (Display *dpy, Window window)
 {
+  int loop = 0;
   int i = -1;
   int j = -1;
   int delay = get_integer_resource ("delay", "Integer");
   if (delay < 3) delay = 3;
 
   if (!get_boolean_resource ("root", "Boolean"))
   int i = -1;
   int j = -1;
   int delay = get_integer_resource ("delay", "Integer");
   if (delay < 3) delay = 3;
 
   if (!get_boolean_resource ("root", "Boolean"))
-    XSelectInput(dpy, window, KeyPressMask|ButtonPressMask);
+    {
+      XWindowAttributes xgwa;
+      XGetWindowAttributes (dpy, window, &xgwa);
+      XSelectInput (dpy, window,
+                    xgwa.your_event_mask | KeyPressMask | ButtonPressMask);
+    }
 
   while (1)
     {
 
   while (1)
     {
-      while (i == j) i = random() % 8;
-      j = i;
-
+      Bool did;
+      do {  i = (random() & 0xFF) % 13; } while (i == j);
       switch (i)
        {
       switch (i)
        {
-       case 0: windows(dpy, window, delay, True); break;
-       case 1: windows(dpy, window, delay, False); break;
-       case 2: amiga(dpy, window, delay); break;
-       case 3: mac(dpy, window, delay); break;
-       case 4: macsbug(dpy, window, delay); break;
-       case 5: openserver(dpy, window, delay); break;
-       case 6: sparc_linux(dpy, window, delay); break;
-       case 7: atari(dpy, window, delay); break;
+       case 0: did = windows(dpy, window, delay, 0); break;
+       case 1: did = windows(dpy, window, delay, 1); break;
+       case 2: did = windows(dpy, window, delay, 2); break;
+       case 3: did = amiga(dpy, window, delay); break;
+       case 4: did = mac(dpy, window, delay); break;
+       case 5: did = macsbug(dpy, window, delay); break;
+       case 6: did = mac1(dpy, window, delay); break;
+       case 7: did = sco(dpy, window, delay); break;
+       case 8: did = sparc_linux(dpy, window, delay); break;
+       case 9: did = bsd(dpy, window, delay); break;
+       case 10: did = atari(dpy, window, delay); break;
+       case 11: did = blitdamage(dpy, window, delay); break;
+       case 12: did = sparc_solaris(dpy, window, delay); break;
        default: abort(); break;
        }
        default: abort(); break;
        }
-      XSync (dpy, True);
+      loop++;
+      if (loop > 100) j = -1;
+      if (loop > 200)
+        {
+          fprintf (stderr, "%s: no display modes enabled?\n", progname);
+          exit(-1);
+        }
+      if (!did) continue;
+      XSync (dpy, False);
+      j = i;
+      loop = 0;
     }
 }
     }
 }