http://packetstormsecurity.org/UNIX/admin/xscreensaver-4.14.tar.gz
[xscreensaver] / hacks / bsod.c
1 /* xscreensaver, Copyright (c) 1998-2003 Jamie Zawinski <jwz@jwz.org>
2  *
3  * Permission to use, copy, modify, distribute, and sell this software and its
4  * documentation for any purpose is hereby granted without fee, provided that
5  * the above copyright notice appear in all copies and that both that
6  * copyright notice and this permission notice appear in supporting
7  * documentation.  No representations are made about the suitability of this
8  * software for any purpose.  It is provided "as is" without express or 
9  * implied warranty.
10  *
11  * Blue Screen of Death: the finest in personal computer emulation.
12  * Concept cribbed from Stephen Martin <smartin@mks.com>;
13  * this version written by jwz, 4-Jun-98.
14  */
15
16 #include <math.h>
17 #include "screenhack.h"
18 #include "xpm-pixmap.h"
19 #include "apple2.h"
20 #include <stdio.h>
21 #include <ctype.h>
22 #include <time.h>
23 #include <sys/time.h>
24 #include <X11/Xutil.h>
25
26 #ifdef HAVE_XSHM_EXTENSION
27 #include "xshm.h"
28 #endif
29
30 #ifdef HAVE_UNAME
31 # include <sys/utsname.h>
32 #endif /* HAVE_UNAME */
33
34 #include "images/amiga.xpm"
35 #include "images/atari.xbm"
36 #include "images/mac.xbm"
37 #include "images/macbomb.xbm"
38 #include "images/hmac.xpm"
39
40 #undef countof
41 #define countof(x) (sizeof((x))/sizeof((*x)))
42
43 static int
44 draw_string (Display *dpy, Window window, GC gc, XGCValues *gcv,
45              XFontStruct *font,
46              int xoff, int yoff,
47              int win_width, int win_height,
48              const char *string, int delay)
49 {
50   int x, y;
51   int width = 0, height = 0, cw = 0;
52   int char_width, line_height;
53
54   const char *s = string;
55   const char *se = string;
56
57   /* This pretty much assumes fixed-width fonts */
58   char_width = (font->per_char
59                 ? font->per_char['n'-font->min_char_or_byte2].width
60                 : font->min_bounds.width);
61   line_height = font->ascent + font->descent + 1;
62
63   while (1)
64     {
65       if (*s == '\n' || !*s)
66         {
67           height++;
68           if (cw > width) width = cw;
69           cw = 0;
70           if (!*s) break;
71         }
72       else
73         cw++;
74       s++;
75     }
76
77   x = (win_width - (width * char_width)) / 2;
78   y = (win_height - (height * line_height)) / 2;
79
80   if (x < 0) x = 2;
81   if (y < 0) y = 2;
82
83   x += xoff;
84   y += yoff;
85
86   se = s = string;
87   while (1)
88     {
89       if (*s == '\n' || !*s)
90         {
91           int off = 0;
92           Bool flip = False;
93
94           if (*se == '@' || *se == '_')
95             {
96               if (*se == '@') flip = True;
97               se++;
98               off = (char_width * (width - (s - se))) / 2;
99             }
100
101           if (flip)
102             {
103               XSetForeground(dpy, gc, gcv->background);
104               XSetBackground(dpy, gc, gcv->foreground);
105             }
106
107           if (s != se)
108             XDrawImageString(dpy, window, gc, x+off, y+font->ascent, se, s-se);
109
110           if (flip)
111             {
112               XSetForeground(dpy, gc, gcv->foreground);
113               XSetBackground(dpy, gc, gcv->background);
114             }
115
116           se = s;
117           y += line_height;
118           if (!*s) break;
119           se = s+1;
120
121           if (delay)
122             {
123               XSync(dpy, False);
124               usleep(delay);
125             }
126         }
127       s++;
128     }
129
130   return width * char_width;
131 }
132
133
134 static Pixmap
135 double_pixmap(Display *dpy, GC gc, Visual *visual, int depth, Pixmap pixmap,
136              int pix_w, int pix_h)
137 {
138   int x, y;
139   Pixmap p2 = XCreatePixmap(dpy, pixmap, pix_w*2, pix_h*2, depth);
140   XImage *i1 = XGetImage(dpy, pixmap, 0, 0, pix_w, pix_h, ~0L, ZPixmap);
141   XImage *i2 = XCreateImage(dpy, visual, depth, ZPixmap, 0, 0,
142                             pix_w*2, pix_h*2, 8, 0);
143   i2->data = (char *) calloc(i2->height, i2->bytes_per_line);
144   for (y = 0; y < pix_h; y++)
145     for (x = 0; x < pix_w; x++)
146       {
147         unsigned long p = XGetPixel(i1, x, y);
148         XPutPixel(i2, x*2,   y*2,   p);
149         XPutPixel(i2, x*2+1, y*2,   p);
150         XPutPixel(i2, x*2,   y*2+1, p);
151         XPutPixel(i2, x*2+1, y*2+1, p);
152       }
153   free(i1->data); i1->data = 0;
154   XDestroyImage(i1);
155   XPutImage(dpy, p2, gc, i2, 0, 0, 0, 0, i2->width, i2->height);
156   free(i2->data); i2->data = 0;
157   XDestroyImage(i2);
158   XFreePixmap(dpy, pixmap);
159   return p2;
160 }
161
162
163 /* Sleep for N seconds and return False.  But if a key or mouse event is
164    seen, discard all pending key or mouse events, and return True.
165  */
166 static Bool
167 bsod_sleep(Display *dpy, int seconds)
168 {
169   int q = seconds * 4;
170   int quantum = 250000;
171
172   if (seconds == -1)
173     q = 1, quantum = 100000;
174
175   do
176     {
177       XSync(dpy, False);
178       while (XPending (dpy))
179         {
180           XEvent event;
181           XNextEvent (dpy, &event);
182           if (event.xany.type == ButtonPress)
183             return True;
184           if (event.xany.type == KeyPress)
185             {
186               KeySym keysym;
187               char c = 0;
188               XLookupString (&event.xkey, &c, 1, &keysym, 0);
189               if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
190                 return True;
191             }
192           screenhack_handle_event (dpy, &event);
193         }
194
195       if (q > 0)
196         {
197           q--;
198           usleep(quantum);
199         }
200     }
201   while (q > 0);
202
203   return False; 
204 }
205
206
207 static void
208 windows (Display *dpy, Window window, int delay, int which)
209 {
210   XGCValues gcv;
211   XWindowAttributes xgwa;
212   char *fontname;
213   const char *def_font = "fixed";
214   XFontStruct *font;
215   GC gc;
216
217   const char *w95 =
218     ("@Windows\n"
219      "A fatal exception 0E has occured at F0AD:42494C4C\n"
220      "the current application will be terminated.\n"
221      "\n"
222      "* Press any key to terminate the current application.\n"
223      "* Press CTRL+ALT+DELETE again to restart your computer.\n"
224      "  You will lose any unsaved information in all applications.\n"
225      "\n"
226      "\n"
227      "_Press any key to continue");
228
229 # ifdef __GNUC__
230   __extension__   /* don't warn about "string length is greater than the
231                      length ISO C89 compilers are required to support"
232                      in the following string constant... */
233 # endif
234
235   const char *wnt = /* from Jim Niemira <urmane@urmane.org> */
236     ("*** STOP: 0x0000001E (0x80000003,0x80106fc0,0x8025ea21,0xfd6829e8)\n"
237    "Unhandled Kernel exception c0000047 from fa8418b4 (8025ea21,fd6829e8)\n"
238    "\n"
239    "Dll Base Date Stamp - Name             Dll Base Date Stamp - Name\n"
240    "80100000 2be154c9 - ntoskrnl.exe       80400000 2bc153b0 - hal.dll\n"
241    "80258000 2bd49628 - ncrc710.sys        8025c000 2bd49688 - SCSIPORT.SYS \n"
242    "80267000 2bd49683 - scsidisk.sys       802a6000 2bd496b9 - Fastfat.sys\n"
243    "fa800000 2bd49666 - Floppy.SYS         fa810000 2bd496db - Hpfs_Rec.SYS\n"
244    "fa820000 2bd49676 - Null.SYS           fa830000 2bd4965a - Beep.SYS\n"
245    "fa840000 2bdaab00 - i8042prt.SYS       fa850000 2bd5a020 - SERMOUSE.SYS\n"
246    "fa860000 2bd4966f - kbdclass.SYS       fa870000 2bd49671 - MOUCLASS.SYS\n"
247    "fa880000 2bd9c0be - Videoprt.SYS       fa890000 2bd49638 - NCC1701E.SYS\n"
248    "fa8a0000 2bd4a4ce - Vga.SYS            fa8b0000 2bd496d0 - Msfs.SYS\n"
249    "fa8c0000 2bd496c3 - Npfs.SYS           fa8e0000 2bd496c9 - Ntfs.SYS\n"
250    "fa940000 2bd496df - NDIS.SYS           fa930000 2bd49707 - wdlan.sys\n"
251    "fa970000 2bd49712 - TDI.SYS            fa950000 2bd5a7fb - nbf.sys\n"
252    "fa980000 2bd72406 - streams.sys        fa9b0000 2bd4975f - ubnb.sys\n"
253    "fa9c0000 2bd5bfd7 - usbser.sys         fa9d0000 2bd4971d - netbios.sys\n"
254    "fa9e0000 2bd49678 - Parallel.sys       fa9f0000 2bd4969f - serial.SYS\n"
255    "faa00000 2bd49739 - mup.sys            faa40000 2bd4971f - SMBTRSUP.SYS\n"
256    "faa10000 2bd6f2a2 - srv.sys            faa50000 2bd4971a - afd.sys\n"
257    "faa60000 2bd6fd80 - rdr.sys            faaa0000 2bd49735 - bowser.sys\n"
258    "\n"
259    "Address dword dump Dll Base                                      - Name\n"
260    "801afc20 80106fc0 80106fc0 00000000 00000000 80149905 : "
261      "fa840000 - i8042prt.SYS\n"
262    "801afc24 80149905 80149905 ff8e6b8c 80129c2c ff8e6b94 : "
263      "8025c000 - SCSIPORT.SYS\n"
264    "801afc2c 80129c2c 80129c2c ff8e6b94 00000000 ff8e6b94 : "
265      "80100000 - ntoskrnl.exe\n"
266    "801afc34 801240f2 80124f02 ff8e6df4 ff8e6f60 ff8e6c58 : "
267      "80100000 - ntoskrnl.exe\n"
268    "801afc54 80124f16 80124f16 ff8e6f60 ff8e6c3c 8015ac7e : "
269      "80100000 - ntoskrnl.exe\n"
270    "801afc64 8015ac7e 8015ac7e ff8e6df4 ff8e6f60 ff8e6c58 : "
271      "80100000 - ntoskrnl.exe\n"
272    "801afc70 80129bda 80129bda 00000000 80088000 80106fc0 : "
273      "80100000 - ntoskrnl.exe\n"
274    "\n"
275    "Kernel Debugger Using: COM2 (Port 0x2f8, Baud Rate 19200)\n"
276    "Restart and set the recovery options in the system control panel\n"
277    "or the /CRASHDEBUG system start option. If this message reappears,\n"
278    "contact your system administrator or technical support group."
279      );
280
281   const char *w2ka =
282     ("*** STOP: 0x000000D1 (0xE1D38000,0x0000001C,0x00000000,0xF09D42DA)\n"
283      "DRIVER_IRQL_NOT_LESS_OR_EQUAL \n"
284      "\n"
285     "*** Address F09D42DA base at F09D4000, DateStamp 39f459ff - CRASHDD.SYS\n"
286      "\n"
287      "Beginning dump of physical memory\n");
288   const char *w2kb =
289     ("Physical memory dump complete. Contact your system administrator or\n"
290      "technical support group.\n");
291
292   const char *wmea =
293     ("    Windows protection error.  You need to restart your computer.");
294   const char *wmeb =
295     ("    System halted.");
296
297 # ifdef __GNUC__
298   __extension__   /* don't warn about "string length is greater than the
299                      length ISO C89 compilers are required to support"
300                      in the following string constant... */
301 # endif
302
303   const char *wxpa = /* From Wm. Rhodes <xscreensaver@27.org> */
304     ("A problem has been detected and windows has been shut down to prevent "
305       "damage\n"
306       "to your computer.\n"
307       "\n"
308       "If this is the first time you've seen this Stop error screen,\n"
309       "restart your computer. If this screen appears again, follow\n"
310       "these steps:\n"
311       "\n"
312       "Check to be sure you have adequate disk space. If a driver is\n"
313       "identified in the Stop message, disable the driver or check\n"
314       "with the manufacturer for driver updates. Try changing video\n"
315       "adapters.\n"
316       "\n"
317       "Check with you hardware vendor for any BIOS updates. Disable\n"
318       "BIOS memory options such as caching or shadowing. If you need\n"
319       "to use Safe Mode to remove or disable compinents, restart your\n"
320       "computer, press F8 to select Advanced Startup Options, and then\n"
321       "select Safe Mode.\n"
322       "\n"
323       "Technical information:\n"
324       "\n"
325       "*** STOP: 0x0000007E (0xC0000005,0xF88FF190,0x0xF8975BA0,0xF89758A0)\n"
326       "\n"
327       "\n"
328       "***  EPUSBDSK.sys - Address F88FF190 base at FF88FE000, datestamp "
329       "3b9f3248\n"
330       "\n"
331       "Beginning dump of physical memory\n");
332   const char *wxpb =
333     ("Physical memory dump complete.\n"
334      "Contact your system administrator or technical support group for "
335      "further\n"
336      "assitance.\n"
337      );
338
339   if (which < 0 || which > 2) abort();
340
341   /* kludge to lump Win2K, WinME, and WinXP together; seems silly to add
342      another preference/command line option just for these little ones. */
343   if (which == 2 && (random() % 2))
344     which = 3 + (random() % 2);
345
346   XGetWindowAttributes (dpy, window, &xgwa);
347
348   fontname = get_string_resource ((xgwa.height > 600
349                                    ? (which == 0 ? "windows95.font2" :
350                                       which == 1 ? "windowsNT.font2" :
351                                       which == 2 ? "windows2K.font2" :
352                                                    "windowsME.font2")
353                                    : (which == 0 ? "windows95.font" :
354                                       which == 1 ? "windowsNT.font" :
355                                       which == 2 ? "windows2K.font" :
356                                                    "windowsME.font")),
357                                   "Windows.Font");
358   if (!fontname || !*fontname) fontname = (char *)def_font;
359   font = XLoadQueryFont (dpy, fontname);
360   if (!font) font = XLoadQueryFont (dpy, def_font);
361   if (!font) exit(-1);
362   if (fontname && fontname != def_font)
363     free (fontname);
364
365   gcv.font = font->fid;
366   gcv.foreground = get_pixel_resource((which == 0 ? "windows95.foreground" :
367                                        which == 1 ? "windowsNT.foreground" :
368                                        which == 2 ? "windows2K.foreground" :
369                                                     "windowsME.foreground"),
370                                       "Windows.Foreground",
371                                       dpy, xgwa.colormap);
372   gcv.background = get_pixel_resource((which == 0 ? "windows95.background" :
373                                        which == 1 ? "windowsNT.background" :
374                                        which == 2 ? "windows2K.background" :
375                                                     "windowsME.background"),
376                                       "Windows.Background",
377                                       dpy, xgwa.colormap);
378   XSetWindowBackground(dpy, window, gcv.background);
379   XClearWindow(dpy, window);
380
381   gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
382
383   if (which == 0)
384     draw_string(dpy, window, gc, &gcv, font,
385                 0, 0, xgwa.width, xgwa.height, w95, 0);
386   else if (which == 1)
387     draw_string(dpy, window, gc, &gcv, font, 0, 0, 10, 10, wnt, 750);
388   else if (which == 2)
389     {
390       int line_height = font->ascent + font->descent + 1;
391       int x = 20;
392       int y = (xgwa.height / 4);
393
394       draw_string(dpy, window, gc, &gcv, font, x, y, 10, 10, w2ka, 750);
395       y += line_height * 6;
396       bsod_sleep(dpy, 4);
397       draw_string(dpy, window, gc, &gcv, font, x, y, 10, 10, w2kb, 750);
398     }
399   else if (which == 3)
400     {
401       int line_height = font->ascent + font->descent + 1;
402       int x = 4;
403       int y = 4;
404       draw_string(dpy, window, gc, &gcv, font, x, y, 10, 10, wxpa, 750);
405       y += line_height * 26;
406       bsod_sleep(dpy, 4);
407       draw_string(dpy, window, gc, &gcv, font, x, y, 10, 10, wxpb, 750);
408     }
409   else if (which == 4)
410     {
411       int line_height = font->ascent + font->descent;
412       int x = 0;
413       int y = (xgwa.height - line_height * 3) / 2;
414       draw_string (dpy, window, gc, &gcv, font, x, y, 10, 10, wmea, 0);
415       y += line_height * 2;
416       x = draw_string (dpy, window, gc, &gcv, font, x, y, 10, 10, wmeb, 0);
417       y += line_height;
418       while (delay > 0)
419         {
420           XDrawImageString (dpy, window, gc, x, y, "_", 1);
421           XSync(dpy, False);
422           usleep(120000L);
423           XDrawImageString (dpy, window, gc, x, y, " ", 1);
424           XSync(dpy, False);
425           usleep(120000L);
426           if (bsod_sleep(dpy, 0))
427             delay = 0;
428           else
429             delay--;
430         }
431     }
432   else
433     abort();
434
435   XFreeGC(dpy, gc);
436   XSync(dpy, False);
437   bsod_sleep(dpy, delay);
438   XClearWindow(dpy, window);
439   XFreeFont(dpy, font);
440 }
441
442 static void
443 windows_31 (Display *dpy, Window window, int delay)
444 {
445   windows (dpy, window, delay, 0);
446 }
447
448 static void
449 windows_nt (Display *dpy, Window window, int delay)
450 {
451   windows (dpy, window, delay, 1);
452 }
453
454 static void
455 windows_2k (Display *dpy, Window window, int delay)
456 {
457   windows (dpy, window, delay, 2);
458 }
459
460
461 /* SCO OpenServer 5 panic, by Tom Kelly <tom@ancilla.toronto.on.ca>
462  */
463 static void
464 sco (Display *dpy, Window window, int delay)
465 {
466   XGCValues gcv;
467   XWindowAttributes xgwa;
468   char *fontname;
469   const char *def_font = "fixed";
470   XFontStruct *font;
471   GC gc;
472   int lines_1 = 0, lines_2 = 0, lines_3 = 0, lines_4 = 0;
473   const char *s;
474
475 # ifdef __GNUC__
476   __extension__   /* don't warn about "string length is greater than the
477                      length ISO C89 compilers are required to support"
478                      in the following string constant... */
479 # endif
480
481   const char *sco_panic_1 =
482     ("Unexpected trap in kernel mode:\n"
483      "\n"
484      "cr0 0x80010013     cr2  0x00000014     cr3 0x00000000  tlb  0x00000000\n"
485      "ss  0x00071054    uesp  0x00012055     efl 0x00080888  ipl  0x00000005\n"
486      "cs  0x00092585     eip  0x00544a4b     err 0x004d4a47  trap 0x0000000E\n"
487      "eax 0x0045474b     ecx  0x0042544b     edx 0x57687920  ebx  0x61726520\n"
488      "esp 0x796f7520     ebp  0x72656164     esi 0x696e6720  edi  0x74686973\n"
489      "ds  0x3f000000     es   0x43494c48     fs  0x43525343  gs   0x4f4d4b53\n"
490      "\n"
491      "PANIC: k_trap - kernel mode trap type 0x0000000E\n"
492      "Trying to dump 5023 pages to dumpdev hd (1/41), 63 pages per '.'\n"
493     );
494   const char *sco_panic_2 =
495    ("................................................................."
496     "..............\n"
497     );
498   const char *sco_panic_3 =
499     ("5023 pages dumped\n"
500      "\n"
501      "\n"
502      );
503   const char *sco_panic_4 =
504     ("**   Safe to Power Off   **\n"
505      "           - or -\n"
506      "** Press Any Key to Reboot **\n"
507     );
508
509   for (s = sco_panic_1; *s; s++) if (*s == '\n') lines_1++;
510   for (s = sco_panic_2; *s; s++) if (*s == '\n') lines_2++;
511   for (s = sco_panic_3; *s; s++) if (*s == '\n') lines_3++;
512   for (s = sco_panic_4; *s; s++) if (*s == '\n') lines_4++;
513
514   XGetWindowAttributes (dpy, window, &xgwa);
515
516   fontname = get_string_resource ((xgwa.height > 600
517                                    ? "sco.font2"
518                                    : "sco.font"),
519                                   "SCO.Font");
520   if (!fontname || !*fontname) fontname = (char *)def_font;
521   font = XLoadQueryFont (dpy, fontname);
522   if (!font) font = XLoadQueryFont (dpy, def_font);
523   if (!font) exit(-1);
524   if (fontname && fontname != def_font)
525     free (fontname);
526
527   gcv.font = font->fid;
528   gcv.foreground = get_pixel_resource(("sco.foreground"),
529                                       "SCO.Foreground",
530                                       dpy, xgwa.colormap);
531   gcv.background = get_pixel_resource(("sco.background"),
532                                       "SCO.Background",
533                                       dpy, xgwa.colormap);
534   XSetWindowBackground(dpy, window, gcv.background);
535   XClearWindow(dpy, window);
536
537   gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
538
539   draw_string(dpy, window, gc, &gcv, font,
540               10, xgwa.height - ((lines_1 + lines_2 + lines_3 + lines_4 + 1) *
541                                  (font->ascent + font->descent + 1)),
542               10, 10,
543               sco_panic_1, 0);
544   XSync(dpy, False);
545   for (s = sco_panic_2; *s; s++)
546     {
547       char *ss = strdup(sco_panic_2);
548       ss[s - sco_panic_2] = 0;
549       draw_string(dpy, window, gc, &gcv, font,
550                   10, xgwa.height - ((lines_2 + lines_3 + lines_4 + 1) *
551                                      (font->ascent + font->descent + 1)),
552                   10, 10,
553                   ss, 0);
554       XSync(dpy, False);
555       free(ss);
556       if (bsod_sleep (dpy, -1))
557         goto DONE;
558     }
559
560   draw_string(dpy, window, gc, &gcv, font,
561               10, xgwa.height - ((lines_3 + lines_4 + 1) *
562                                  (font->ascent + font->descent + 1)),
563               10, 10,
564               sco_panic_3, 0);
565   XSync(dpy, False);
566   if (bsod_sleep(dpy, 1))
567     goto DONE;
568   draw_string(dpy, window, gc, &gcv, font,
569               10, xgwa.height - ((lines_4 + 1) *
570                                  (font->ascent + font->descent + 1)),
571               10, 10,
572               sco_panic_4, 0);
573   XSync(dpy, False);
574
575   bsod_sleep(dpy, delay);
576  DONE:
577   XClearWindow(dpy, window);
578   XFreeGC(dpy, gc);
579   XFreeFont(dpy, font);
580 }
581
582
583 /* Linux (sparc) panic, by Tom Kelly <tom@ancilla.toronto.on.ca>
584  */
585 static void
586 sparc_linux (Display *dpy, Window window, int delay)
587 {
588   XGCValues gcv;
589   XWindowAttributes xgwa;
590   char *fontname;
591   const char *def_font = "fixed";
592   XFontStruct *font;
593   GC gc;
594   int lines = 1;
595   const char *s;
596
597 # ifdef __GNUC__
598   __extension__   /* don't warn about "string length is greater than the
599                      length ISO C89 compilers are required to support"
600                      in the following string constant... */
601 # endif
602
603   const char *linux_panic =
604     ("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
605         "Unable to handle kernel paging request at virtual address f0d4a000\n"
606         "tsk->mm->context = 00000014\n"
607         "tsk->mm->pgd = f26b0000\n"
608         "              \\|/ ____ \\|/\n"
609         "              \"@'/ ,. \\`@\"\n"
610         "              /_| \\__/ |_\\\n"
611         "                 \\__U_/\n"
612         "gawk(22827): Oops\n"
613         "PSR: 044010c1 PC: f001c2cc NPC: f001c2d0 Y: 00000000\n"
614         "g0: 00001000 g1: fffffff7 g2: 04401086 g3: 0001eaa0\n"
615         "g4: 000207dc g5: f0130400 g6: f0d4a018 g7: 00000001\n"
616         "o0: 00000000 o1: f0d4a298 o2: 00000040 o3: f1380718\n"
617         "o4: f1380718 o5: 00000200 sp: f1b13f08 ret_pc: f001c2a0\n"
618         "l0: efffd880 l1: 00000001 l2: f0d4a230 l3: 00000014\n"
619         "l4: 0000ffff l5: f0131550 l6: f012c000 l7: f0130400\n"
620         "i0: f1b13fb0 i1: 00000001 i2: 00000002 i3: 0007c000\n"
621         "i4: f01457c0 i5: 00000004 i6: f1b13f70 i7: f0015360\n"
622         "Instruction DUMP:\n"
623     );
624
625   for (s = linux_panic; *s; s++) if (*s == '\n') lines++;
626
627   XGetWindowAttributes (dpy, window, &xgwa);
628
629   fontname = get_string_resource ((xgwa.height > 600
630                                    ? "sparclinux.font2"
631                                    : "sparclinux.font"),
632                                   "SparcLinux.Font");
633   if (!fontname || !*fontname) fontname = (char *)def_font;
634   font = XLoadQueryFont (dpy, fontname);
635   if (!font) font = XLoadQueryFont (dpy, def_font);
636   if (!font) exit(-1);
637   if (fontname && fontname != def_font)
638     free (fontname);
639
640   gcv.font = font->fid;
641   gcv.foreground = get_pixel_resource(("sparclinux.foreground"),
642                                       "SparcLinux.Foreground",
643                                       dpy, xgwa.colormap);
644   gcv.background = get_pixel_resource(("sparclinux.background"),
645                                       "SparcLinux.Background",
646                                       dpy, xgwa.colormap);
647   XSetWindowBackground(dpy, window, gcv.background);
648   XClearWindow(dpy, window);
649
650   gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
651
652   draw_string(dpy, window, gc, &gcv, font,
653               10, xgwa.height - (lines * (font->ascent + font->descent + 1)),
654               10, 10,
655               linux_panic, 0);
656   XFreeGC(dpy, gc);
657   XSync(dpy, False);
658   bsod_sleep(dpy, delay);
659   XClearWindow(dpy, window);
660   XFreeFont(dpy, font);
661 }
662
663 /* BSD Panic by greywolf@starwolf.com - modeled after the Linux panic above.
664    By Grey Wolf <greywolf@siteROCK.com>
665  */
666 static void
667 bsd (Display *dpy, Window window, int delay)
668 {
669   XGCValues gcv;
670   XWindowAttributes xgwa;
671   char *fontname;
672   const char *def_font = "fixed";
673   XFontStruct *font;
674   GC gc;
675   int lines = 1;
676   int i, n, b;
677   const char *rbstr, *panicking;
678   char syncing[80], bbuf[5], *bp;
679
680   const char *panicstr[] =
681    {"panic: ifree: freeing free inode",
682     "panic: blkfree: freeing free block",
683     "panic: improbability coefficient below zero",
684     "panic: cgsixmmap",
685     "panic: crazy interrupts",
686     "panic: nmi",
687     "panic: attempted windows install",
688     "panic: don't",
689     "panic: free inode isn't",
690     "panic: cpu_fork: curproc",
691     "panic: malloc: out of space in kmem_map",
692     "panic: vogon starship detected",
693     "panic: teleport chamber: out of order",
694     "panic: Brain fried - core dumped"};
695      
696   for (i = 0; i < sizeof(syncing); i++)
697     syncing[i] = 0;
698
699   i = (random() & 0xffff) % (sizeof(panicstr) / sizeof(*panicstr));
700
701   panicking = panicstr[i];
702   strcpy(syncing, "Syncing disks: ");
703
704   b = (random() & 0xff) % 40;
705   for (n = 0; (n < 20) && (b > 0); n++)
706     {
707       if (i)
708         {
709           i = (random() & 0x7);
710           b -= (random() & 0xff) % 20;
711           if (b < 0)
712             b = 0;
713         }
714       sprintf (bbuf, "%d ", b);
715       strcat (syncing, bbuf);
716     }
717
718   if (b)
719     rbstr = "damn!";
720   else
721     rbstr = "sunk!";
722
723   lines = 5;
724
725   XGetWindowAttributes (dpy, window, &xgwa);
726
727   fontname = get_string_resource ((xgwa.height > 600
728                                    ? "bsd.font2"
729                                    : "bsd.font"),
730                                   "BSD.Font");
731   if (!fontname || !*fontname) fontname = (char *)def_font;
732   font = XLoadQueryFont (dpy, fontname);
733   if (!font) font = XLoadQueryFont (dpy, def_font);
734   if (!font) exit(-1);
735   if (fontname && fontname != def_font)
736     free (fontname);
737
738   gcv.font = font->fid;
739   gcv.foreground = get_pixel_resource(("bsd.foreground"),
740                                       "BSD.Foreground",
741                                       dpy, xgwa.colormap);
742   gcv.background = get_pixel_resource(("bsd.background"),
743                                       "BSD.Background",
744                                       dpy, xgwa.colormap);
745   XSetWindowBackground(dpy, window, gcv.background);
746   XClearWindow(dpy, window);
747
748   gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
749
750   draw_string(dpy, window, gc, &gcv, font,
751               10, xgwa.height - (lines * (font->ascent + font->descent + 1)),
752               10, 10,
753               panicking, 0);
754   XSync(dpy, False);
755   lines--;
756
757   for (bp = syncing; *bp;)
758     {
759       char *bsd_bufs, oc = 0;
760       for (;*bp && (*bp != ' '); bp++)
761         ;
762       if (*bp == ' ')
763         {
764           oc = *bp;
765           *bp = 0;
766         }
767       bsd_bufs = strdup(syncing);
768       draw_string(dpy, window, gc, &gcv, font,
769                   10,
770                   xgwa.height - (lines * (font->ascent + font->descent + 1)),
771                   10, 10,
772                   bsd_bufs, 0);
773       XSync(dpy, False);
774       free(bsd_bufs);
775       if (oc)
776         *bp = oc;
777       if (bsod_sleep(dpy, -1))
778         goto DONE;
779       bp++;
780     }
781
782   lines--;
783   
784   draw_string(dpy, window, gc, &gcv, font,
785               10, xgwa.height - (lines * (font->ascent + font->descent + 1)),
786               10, 10,
787               rbstr, 0);
788   lines--;
789   draw_string(dpy, window, gc, &gcv, font,
790               10, xgwa.height - (lines * (font->ascent + font->descent + 1)),
791               10, 10,
792               "Rebooting", 0);
793
794   XFreeGC(dpy, gc);
795   XSync(dpy, False);
796   bsod_sleep(dpy, delay);
797
798 DONE:
799   XClearWindow(dpy, window);
800   XFreeFont(dpy, font);
801 }
802
803 static void
804 amiga (Display *dpy, Window window, int delay)
805 {
806   XGCValues gcv;
807   XWindowAttributes xgwa;
808   char *fontname;
809   const char *def_font = "fixed";
810   XFontStruct *font;
811   GC gc, gc2;
812   int height;
813   unsigned long fg, bg, bg2;
814   Pixmap pixmap = 0;
815   int pix_w = 0, pix_h = 0;
816   int string_width;
817   int margin;
818
819   const char *string =
820     ("_Software failure.  Press left mouse button to continue.\n"
821      "_Guru Meditation #00000003.00C01570");
822
823   XGetWindowAttributes (dpy, window, &xgwa);
824
825   fontname = get_string_resource ((xgwa.height > 600
826                                    ? "amiga.font2" : "amiga.font"),
827                                   "Amiga.Font");
828   if (!fontname || !*fontname) fontname = (char *)def_font;
829   font = XLoadQueryFont (dpy, fontname);
830   if (!font) font = XLoadQueryFont (dpy, def_font);
831   if (!font) exit(-1);
832   if (fontname && fontname != def_font)
833     free (fontname);
834
835   gcv.font = font->fid;
836   fg = gcv.foreground = get_pixel_resource("amiga.foreground",
837                                            "Amiga.Foreground",
838                                            dpy, xgwa.colormap);
839   bg = gcv.background = get_pixel_resource("amiga.background",
840                                            "Amiga.Background",
841                                            dpy, xgwa.colormap);
842   bg2 = get_pixel_resource("amiga.background2", "Amiga.Background",
843                            dpy, xgwa.colormap);
844   XSetWindowBackground(dpy, window, bg2);
845   XClearWindow(dpy, window);
846
847   gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
848   gcv.background = fg; gcv.foreground = bg;
849   gc2 = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
850
851   height = (font->ascent + font->descent) * 6;
852
853 #if defined(HAVE_GDK_PIXBUF) || defined (HAVE_XPM)
854   pixmap = xpm_data_to_pixmap (dpy, window, (char **) amiga_hand,
855                                &pix_w, &pix_h, 0);
856 #endif /* HAVE_GDK_PIXBUF || HAVE_XPM */
857
858   if (pixmap && xgwa.height > 600)      /* scale up the bitmap */
859     {
860       pixmap = double_pixmap(dpy, gc, xgwa.visual, xgwa.depth,
861                              pixmap, pix_w, pix_h);
862       pix_w *= 2;
863       pix_h *= 2;
864     }
865
866   if (pixmap)
867     {
868       int x = (xgwa.width - pix_w) / 2;
869       int y = ((xgwa.height - pix_h) / 2);
870       XCopyArea(dpy, pixmap, window, gc, 0, 0, pix_w, pix_h, x, y);
871
872       XSync(dpy, False);
873       bsod_sleep(dpy, 2);
874
875       XCopyArea(dpy, pixmap, window, gc, 0, 0, pix_w, pix_h, x, y + height);
876       XClearArea(dpy, window, 0, 0, xgwa.width, y + height, False);
877       XFreePixmap(dpy, pixmap);
878     }
879
880   XFillRectangle(dpy, window, gc2, 0, 0, xgwa.width, height);
881   margin = font->ascent;
882   string_width = draw_string(dpy, window, gc, &gcv, font,
883                              margin, 0,
884                              xgwa.width - (margin * 2), height,
885                              string, 0);
886   {
887     GC gca = gc;
888     while (delay > 0)
889       {
890         int x2;
891         XFillRectangle(dpy, window, gca, 0, 0, xgwa.width, margin);
892         XFillRectangle(dpy, window, gca, 0, 0, margin, height);
893         XFillRectangle(dpy, window, gca,
894                        0, height - margin, xgwa.width, margin);
895         x2 = margin + string_width;
896         if (x2 < xgwa.width - margin) x2 = xgwa.width - margin;
897         XFillRectangle(dpy, window, gca, x2, 0, margin, height);
898
899         gca = (gca == gc ? gc2 : gc);
900         XSync(dpy, False);
901         if (bsod_sleep(dpy, 1))
902           break;
903         delay--;
904       }
905   }
906
907   XFreeGC(dpy, gc);
908   XFreeGC(dpy, gc2);
909   XSync(dpy, False);
910   XClearWindow(dpy, window);
911   XFreeFont(dpy, font);
912 }
913
914
915 /* Atari ST, by Marcus Herbert <rhoenie@nobiscum.de>
916    Marcus had this to say:
917
918         Though I still have my Atari somewhere, I hardly remember
919         the meaning of the bombs. I think 9 bombs was "bus error" or
920         something like that.  And you often had a few bombs displayed
921         quickly and then the next few ones coming up step by step.
922         Perhaps somebody else can tell you more about it..  its just
923         a quick hack :-}
924  */
925 static void
926 atari (Display *dpy, Window window, int delay)
927 {
928         
929   XGCValues gcv;
930   XWindowAttributes xgwa;
931   const char *def_font = "fixed";
932   XFontStruct *font;
933   GC gc;
934   Pixmap pixmap = 0;
935   int pix_w = atari_width;
936   int pix_h = atari_height;
937   int offset;
938   int i, x, y;
939
940   XGetWindowAttributes (dpy, window, &xgwa);
941
942   font = XLoadQueryFont (dpy, def_font);
943   if (!font) exit(-1);
944                 
945   gcv.font = font->fid;
946   gcv.foreground = get_pixel_resource("atari.foreground", "Atari.Foreground",
947                                       dpy, xgwa.colormap);
948   gcv.background = get_pixel_resource("atari.background", "Atari.Background",
949                                       dpy, xgwa.colormap);
950
951   XSetWindowBackground(dpy, window, gcv.background);
952   XClearWindow(dpy, window);
953
954   gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
955
956   pixmap = XCreatePixmapFromBitmapData(dpy, window, (char *) atari_bits,
957                                        pix_w, pix_h,
958                                        gcv.foreground, gcv.background,
959                                        xgwa.depth);
960   pixmap = double_pixmap(dpy, gc, xgwa.visual, xgwa.depth,
961                          pixmap, pix_w, pix_h);
962   pix_w *= 2;
963   pix_h *= 2;
964
965   offset = pix_w + 2;
966   x = 5;
967   y = (xgwa.height - (xgwa.height / 5));
968   if (y < 0) y = 0;
969
970   for (i=0 ; i<7 ; i++) {
971     XCopyArea(dpy, pixmap, window, gc, 0, 0, pix_w, pix_h,
972               (x + (i*offset)), y);
973   }  
974   
975   for (i=7 ; i<10 ; i++) {
976     if (bsod_sleep(dpy, 1))
977       goto DONE;
978     XCopyArea(dpy, pixmap, window, gc, 0, 0, pix_w, pix_h,
979               (x + (i*offset)), y);
980   }
981
982   bsod_sleep(dpy, delay);
983  DONE:
984   XFreePixmap(dpy, pixmap);
985   XFreeGC(dpy, gc);
986   XSync(dpy, False);
987   XClearWindow(dpy, window);
988   XFreeFont(dpy, font);
989 }
990
991
992 static void
993 mac (Display *dpy, Window window, int delay)
994 {
995   XGCValues gcv;
996   XWindowAttributes xgwa;
997   char *fontname;
998   const char *def_font = "fixed";
999   XFontStruct *font;
1000   GC gc;
1001   Pixmap pixmap = 0;
1002   int pix_w = mac_width;
1003   int pix_h = mac_height;
1004   int offset = mac_height * 4;
1005   int i;
1006
1007   const char *string = ("0 0 0 0 0 0 0 F\n"
1008                         "0 0 0 0 0 0 0 3");
1009
1010   XGetWindowAttributes (dpy, window, &xgwa);
1011
1012   fontname = get_string_resource ("mac.font", "Mac.Font");
1013   if (!fontname || !*fontname) fontname = (char *)def_font;
1014   font = XLoadQueryFont (dpy, fontname);
1015   if (!font) font = XLoadQueryFont (dpy, def_font);
1016   if (!font) exit(-1);
1017   if (fontname && fontname != def_font)
1018     free (fontname);
1019
1020   gcv.font = font->fid;
1021   gcv.foreground = get_pixel_resource("mac.foreground", "Mac.Foreground",
1022                                       dpy, xgwa.colormap);
1023   gcv.background = get_pixel_resource("mac.background", "Mac.Background",
1024                                       dpy, xgwa.colormap);
1025   XSetWindowBackground(dpy, window, gcv.background);
1026   XClearWindow(dpy, window);
1027
1028   gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
1029
1030   pixmap = XCreatePixmapFromBitmapData(dpy, window, (char *) mac_bits,
1031                                        mac_width, mac_height,
1032                                        gcv.foreground,
1033                                        gcv.background,
1034                                        xgwa.depth);
1035
1036   for(i = 0; i < 2; i++)
1037     {
1038       pixmap = double_pixmap(dpy, gc, xgwa.visual, xgwa.depth,
1039                              pixmap, pix_w, pix_h);
1040       pix_w *= 2; pix_h *= 2;
1041     }
1042
1043   {
1044     int x = (xgwa.width - pix_w) / 2;
1045     int y = (((xgwa.height + offset) / 2) -
1046              pix_h -
1047              (font->ascent + font->descent) * 2);
1048     if (y < 0) y = 0;
1049     XCopyArea(dpy, pixmap, window, gc, 0, 0, pix_w, pix_h, x, y);
1050     XFreePixmap(dpy, pixmap);
1051   }
1052
1053   draw_string(dpy, window, gc, &gcv, font, 0, 0,
1054               xgwa.width, xgwa.height + offset, string, 0);
1055
1056   XFreeGC(dpy, gc);
1057   XSync(dpy, False);
1058   bsod_sleep(dpy, delay);
1059   XClearWindow(dpy, window);
1060   XFreeFont(dpy, font);
1061 }
1062
1063 static void
1064 macsbug (Display *dpy, Window window, int delay)
1065 {
1066   XGCValues gcv;
1067   XWindowAttributes xgwa;
1068   char *fontname;
1069   const char *def_font = "fixed";
1070   XFontStruct *font;
1071   GC gc, gc2;
1072
1073   int char_width, line_height;
1074   int col_right, row_top, row_bottom, page_right, page_bottom, body_top;
1075   int xoff, yoff;
1076
1077 # ifdef __GNUC__
1078   __extension__   /* don't warn about "string length is greater than the
1079                      length ISO C89 compilers are required to support"
1080                      in the following string constant... */
1081 # endif
1082
1083   const char *left = ("    SP     \n"
1084                       " 04EB0A58  \n"
1085                       "58 00010000\n"
1086                       "5C 00010000\n"
1087                       "   ........\n"
1088                       "60 00000000\n"
1089                       "64 000004EB\n"
1090                       "   ........\n"
1091                       "68 0000027F\n"
1092                       "6C 2D980035\n"
1093                       "   ....-..5\n"
1094                       "70 00000054\n"
1095                       "74 0173003E\n"
1096                       "   ...T.s.>\n"
1097                       "78 04EBDA76\n"
1098                       "7C 04EBDA8E\n"
1099                       "   .S.L.a.U\n"
1100                       "80 00000000\n"
1101                       "84 000004EB\n"
1102                       "   ........\n"
1103                       "88 00010000\n"
1104                       "8C 00010000\n"
1105                       "   ...{3..S\n"
1106                       "\n"
1107                       "\n"
1108                       " CurApName \n"
1109                       "  Finder   \n"
1110                       "\n"
1111                       " 32-bit VM \n"
1112                       "SR Smxnzvc0\n"
1113                       "D0 04EC0062\n"
1114                       "D1 00000053\n"
1115                       "D2 FFFF0100\n"
1116                       "D3 00010000\n"
1117                       "D4 00010000\n"
1118                       "D5 04EBDA76\n"
1119                       "D6 04EBDA8E\n"
1120                       "D7 00000001\n"
1121                       "\n"
1122                       "A0 04EBDA76\n"
1123                       "A1 04EBDA8E\n"
1124                       "A2 A0A00060\n"
1125                       "A3 027F2D98\n"
1126                       "A4 027F2E58\n"
1127                       "A5 04EC04F0\n"
1128                       "A6 04EB0A86\n"
1129                       "A7 04EB0A58");
1130   const char *bottom = ("  _A09D\n"
1131                         "     +00884    40843714     #$0700,SR         "
1132                         "                  ; A973        | A973\n"
1133                         "     +00886    40843765     *+$0400           "
1134                         "                                | 4A1F\n"
1135                         "     +00888    40843718     $0004(A7),([0,A7[)"
1136                         "                  ; 04E8D0AE    | 66B8");
1137
1138 #if 0
1139   const char *body = ("Bus Error at 4BF6D6CC\n"
1140                       "while reading word from 4BF6D6CC in User data space\n"
1141                       " Unable to access that address\n"
1142                       "  PC: 2A0DE3E6\n"
1143                       "  Frame Type: B008");
1144 #else
1145
1146 # ifdef __GNUC__
1147   __extension__   /* don't warn about "string length is greater than the
1148                      length ISO C89 compilers are required to support"
1149                      in the following string constant... */
1150 # endif
1151
1152   const char * body = ("PowerPC unmapped memory exception at 003AFDAC "
1153                                                 "BowelsOfTheMemoryMgr+04F9C\n"
1154                       " Calling chain using A6/R1 links\n"
1155                       "  Back chain  ISA  Caller\n"
1156                       "  00000000    PPC  28C5353C  __start+00054\n"
1157                       "  24DB03C0    PPC  28B9258C  main+0039C\n"
1158                       "  24DB0350    PPC  28B9210C  MainEvent+00494\n"
1159                       "  24DB02B0    PPC  28B91B40  HandleEvent+00278\n"
1160                       "  24DB0250    PPC  28B83DAC  DoAppleEvent+00020\n"
1161                       "  24DB0210    PPC  FFD3E5D0  "
1162                                                 "AEProcessAppleEvent+00020\n"
1163                       "  24DB0132    68K  00589468\n"
1164                       "  24DAFF8C    68K  00589582\n"
1165                       "  24DAFF26    68K  00588F70\n"
1166                       "  24DAFEB3    PPC  00307098  "
1167                                                 "EmToNatEndMoveParams+00014\n"
1168                       "  24DAFE40    PPC  28B9D0B0  DoScript+001C4\n"
1169                       "  24DAFDD0    PPC  28B9C35C  RunScript+00390\n"
1170                       "  24DAFC60    PPC  28BA36D4  run_perl+000E0\n"
1171                       "  24DAFC10    PPC  28BC2904  perl_run+002CC\n"
1172                       "  24DAFA80    PPC  28C18490  Perl_runops+00068\n"
1173                       "  24DAFA30    PPC  28BE6CC0  Perl_pp_backtick+000FC\n"
1174                       "  24DAF9D0    PPC  28BA48B8  Perl_my_popen+00158\n"
1175                       "  24DAF980    PPC  28C5395C  sfclose+00378\n"
1176                       "  24DAF930    PPC  28BA568C  free+0000C\n"
1177                       "  24DAF8F0    PPC  28BA6254  pool_free+001D0\n"
1178                       "  24DAF8A0    PPC  FFD48F14  DisposePtr+00028\n"
1179                       "  24DAF7C9    PPC  00307098  "
1180                                                 "EmToNatEndMoveParams+00014\n"
1181                       "  24DAF780    PPC  003AA180  __DisposePtr+00010");
1182 #endif
1183
1184   const char *s;
1185   int body_lines = 1;
1186
1187   for (s = body; *s; s++) if (*s == '\n') body_lines++;
1188
1189   XGetWindowAttributes (dpy, window, &xgwa);
1190
1191   fontname = get_string_resource ((xgwa.height > 850
1192                                    ? "macsbug.font3"
1193                                    : (xgwa.height > 700
1194                                       ? "macsbug.font2"
1195                                       : "macsbug.font")),
1196                                   "MacsBug.Font");
1197   if (!fontname || !*fontname) fontname = (char *)def_font;
1198   font = XLoadQueryFont (dpy, fontname);
1199   if (!font) font = XLoadQueryFont (dpy, def_font);
1200   if (!font) exit(-1);
1201   if (fontname && fontname != def_font)
1202     free (fontname);
1203
1204   gcv.font = font->fid;
1205   gcv.foreground = get_pixel_resource("macsbug.foreground",
1206                                       "MacsBug.Foreground",
1207                                       dpy, xgwa.colormap);
1208   gcv.background = get_pixel_resource("macsbug.background",
1209                                       "MacsBug.Background",
1210                                       dpy, xgwa.colormap);
1211
1212   gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
1213
1214   gcv.foreground = gcv.background;
1215   gc2 = XCreateGC(dpy, window, GCForeground, &gcv);
1216
1217   XSetWindowBackground(dpy, window,
1218                        get_pixel_resource("macsbug.borderColor",
1219                                           "MacsBug.BorderColor",
1220                                           dpy, xgwa.colormap));
1221   XClearWindow(dpy, window);
1222
1223   char_width = (font->per_char
1224                 ? font->per_char['n'-font->min_char_or_byte2].width
1225                 : font->min_bounds.width);
1226   line_height = font->ascent + font->descent + 1;
1227
1228   col_right = char_width * 12;
1229   page_bottom = line_height * 47;
1230
1231   if (page_bottom > xgwa.height) page_bottom = xgwa.height;
1232
1233   row_bottom = page_bottom - line_height;
1234   row_top = row_bottom - (line_height * 4);
1235   page_right = col_right + (char_width * 88);
1236   body_top = row_top - (line_height * body_lines);
1237
1238   page_bottom += 2;
1239   row_bottom += 2;
1240   body_top -= 4;
1241
1242   xoff = (xgwa.width - page_right) / 2;
1243   yoff = (xgwa.height - page_bottom) / 2;
1244   if (xoff < 0) xoff = 0;
1245   if (yoff < 0) yoff = 0;
1246
1247   XFillRectangle(dpy, window, gc2, xoff, yoff, page_right, page_bottom);
1248
1249   draw_string(dpy, window, gc, &gcv, font, xoff, yoff, 10, 10, left, 0);
1250   draw_string(dpy, window, gc, &gcv, font, xoff+col_right, yoff+row_top,
1251               10, 10, bottom, 0);
1252
1253   XFillRectangle(dpy, window, gc, xoff + col_right, yoff, 2, page_bottom);
1254   XDrawLine(dpy, window, gc,
1255             xoff+col_right, yoff+row_top, xoff+page_right, yoff+row_top);
1256   XDrawLine(dpy, window, gc,
1257             xoff+col_right, yoff+row_bottom, xoff+page_right, yoff+row_bottom);
1258   XDrawRectangle(dpy, window, gc,  xoff, yoff, page_right, page_bottom);
1259
1260   if (body_top > 4)
1261     body_top = 4;
1262
1263   draw_string(dpy, window, gc, &gcv, font,
1264               xoff + col_right + char_width, yoff + body_top, 10, 10, body,
1265               500);
1266
1267   while (delay > 0)
1268     {
1269       XDrawLine(dpy, window, gc,
1270                 xoff+col_right+(char_width/2)+2, yoff+row_bottom+3,
1271                 xoff+col_right+(char_width/2)+2, yoff+page_bottom-3);
1272       XSync(dpy, False);
1273       usleep(666666L);
1274       XDrawLine(dpy, window, gc2,
1275                 xoff+col_right+(char_width/2)+2, yoff+row_bottom+3,
1276                 xoff+col_right+(char_width/2)+2, yoff+page_bottom-3);
1277       XSync(dpy, False);
1278       usleep(333333L);
1279       if (bsod_sleep(dpy, 0))
1280         break;
1281       delay--;
1282     }
1283
1284   XFreeGC(dpy, gc);
1285   XFreeGC(dpy, gc2);
1286   XClearWindow(dpy, window);
1287   XFreeFont(dpy, font);
1288 }
1289
1290 static void
1291 mac1 (Display *dpy, Window window, int delay)
1292 {
1293   XGCValues gcv;
1294   XWindowAttributes xgwa;
1295   GC gc;
1296   Pixmap pixmap = 0;
1297   int pix_w = macbomb_width;
1298   int pix_h = macbomb_height;
1299
1300   XGetWindowAttributes (dpy, window, &xgwa);
1301
1302   gcv.foreground = get_pixel_resource("mac1.foreground", "Mac.Foreground",
1303                                       dpy, xgwa.colormap);
1304   gcv.background = get_pixel_resource("mac1.background", "Mac.Background",
1305                                       dpy, xgwa.colormap);
1306   XSetWindowBackground(dpy, window, gcv.background);
1307   XClearWindow(dpy, window);
1308
1309   gc = XCreateGC(dpy, window, GCForeground|GCBackground, &gcv);
1310
1311   pixmap = XCreatePixmapFromBitmapData(dpy, window, (char *) macbomb_bits,
1312                                        macbomb_width, macbomb_height,
1313                                        gcv.foreground,
1314                                        gcv.background,
1315                                        xgwa.depth);
1316
1317   {
1318     int x = (xgwa.width - pix_w) / 2;
1319     int y = (xgwa.height - pix_h) / 2;
1320     if (y < 0) y = 0;
1321     XFillRectangle (dpy, window, gc, 0, 0, xgwa.width, xgwa.height);
1322     XSync(dpy, False);
1323     if (bsod_sleep(dpy, 1))
1324       goto DONE;
1325     XCopyArea(dpy, pixmap, window, gc, 0, 0, pix_w, pix_h, x, y);
1326   }
1327
1328  DONE:
1329   XFreeGC(dpy, gc);
1330   XFreePixmap(dpy, pixmap);
1331   XSync(dpy, False);
1332   bsod_sleep(dpy, delay);
1333   XClearWindow(dpy, window);
1334 }
1335
1336
1337 static void
1338 macx (Display *dpy, Window window, int delay)
1339 {
1340   XGCValues gcv;
1341   XWindowAttributes xgwa;
1342   char *fontname = 0;
1343   const char *def_font = "fixed";
1344   XFontStruct *font;
1345   GC gc;
1346
1347 # ifdef __GNUC__
1348   __extension__   /* don't warn about "string length is greater than the
1349                      length ISO C89 compilers are required to support"
1350                      in the following string constant... */
1351 # endif
1352
1353   const char *macx_panic =
1354    ("panic(cpu 0): Unable to find driver for this platform: "
1355     "\"PowerMac 3,5\".\n"
1356     "\n"
1357     "backtrace: 0x0008c2f4 0x0002a7a0 0x001f0204 0x001d4e4c 0x001d4c5c "
1358     "0x001a56cc 0x01d5dbc 0x001c621c 0x00037430 0x00037364\n"
1359     "\n"
1360     "\n"
1361     "\n"
1362     "No debugger configured - dumping debug information\n"
1363     "\n"
1364     "version string : Darwin Kernel Version 1.3:\n"
1365     "Thu Mar  1 06:56:40 PST 2001; root:xnu/xnu-123.5.obj~1/RELEASE_PPC\n"
1366     "\n"
1367     "\n"
1368     "\n"
1369     "\n"
1370     "DBAT0: 00000000 00000000\n"
1371     "DBAT1: 00000000 00000000\n"
1372     "DBAT2: 80001FFE 8000003A\n"
1373     "DBAT3: 90001FFE 9000003A\n"
1374     "MSR=00001030\n"
1375     "backtrace: 0x0008c2f4 0x0002a7a0 0x001f0204 0x001d4e4c 0x001d4c5c "
1376     "0x001a56cc 0x01d5dbc 0x001c621c 0x00037430 0x00037364\n"
1377     "\n"
1378     "panic: We are hanging here...\n");
1379
1380   XGetWindowAttributes (dpy, window, &xgwa);
1381
1382   gcv.background = get_pixel_resource("macX.background",
1383                                       "MacX.Background",
1384                                       dpy, xgwa.colormap);
1385   XSetWindowBackground(dpy, window, gcv.background);
1386   XClearWindow(dpy, window);
1387
1388   fontname = get_string_resource ((xgwa.height > 900
1389                                    ? "macX.font2"
1390                                    : "macX.font"),
1391                                   "MacX.Font");
1392   if (!fontname || !*fontname) fontname = (char *)def_font;
1393   font = XLoadQueryFont (dpy, fontname);
1394   if (!font) font = XLoadQueryFont (dpy, def_font);
1395   if (!font) exit(-1);
1396   if (fontname && fontname != def_font)
1397     free (fontname);
1398
1399   gcv.font = font->fid;
1400   gcv.foreground = get_pixel_resource("macsbug.foreground",
1401                                       "MacsBug.Foreground",
1402                                       dpy, xgwa.colormap);
1403   gcv.background = get_pixel_resource("macsbug.background",
1404                                       "MacsBug.Background",
1405                                       dpy, xgwa.colormap);
1406
1407
1408   gcv.foreground = get_pixel_resource("macX.textForeground",
1409                                       "MacX.TextForeground",
1410                                       dpy, xgwa.colormap);
1411   gcv.background = get_pixel_resource("macX.textBackground",
1412                                       "MacX.TextBackground",
1413                                       dpy, xgwa.colormap);
1414   gc = XCreateGC(dpy, window, GCForeground|GCBackground|GCFont, &gcv);
1415
1416 #if defined(HAVE_GDK_PIXBUF) || defined (HAVE_XPM)
1417   {
1418     Pixmap pixmap = 0;
1419     Pixmap mask = 0;
1420     int x, y, pix_w, pix_h;
1421     pixmap = xpm_data_to_pixmap (dpy, window, (char **) happy_mac,
1422                                  &pix_w, &pix_h, &mask);
1423
1424     x = (xgwa.width - pix_w) / 2;
1425     y = (xgwa.height - pix_h) / 2;
1426     if (y < 0) y = 0;
1427     XSync(dpy, False);
1428     bsod_sleep(dpy, 2);
1429     XSetClipMask (dpy, gc, mask);
1430     XSetClipOrigin (dpy, gc, x, y);
1431     XCopyArea (dpy, pixmap, window, gc, 0, 0, pix_w, pix_h, x, y);
1432     XSetClipMask (dpy, gc, None);
1433     XFreePixmap (dpy, pixmap);
1434   }
1435 #endif /* HAVE_GDK_PIXBUF || HAVE_XPM */
1436
1437   bsod_sleep(dpy, 3);
1438
1439   {
1440     const char *s;
1441     int x = 0, y = 0;
1442     int char_width, line_height;
1443     char_width = (font->per_char
1444                   ? font->per_char['n'-font->min_char_or_byte2].width
1445                   : font->min_bounds.width);
1446     line_height = font->ascent + font->descent;
1447
1448     s = macx_panic;
1449     y = font->ascent;
1450     while (*s)
1451       {
1452         int ox = x;
1453         int oy = y;
1454         if (*s == '\n' || x + char_width >= xgwa.width)
1455           {
1456             x = 0;
1457             y += line_height;
1458           }
1459
1460         if (*s == '\n')
1461           {
1462             /* Note that to get this goofy effect, they must be actually
1463                emitting LF CR at the end of each line instead of CR LF!
1464              */
1465             XDrawImageString (dpy, window, gc, ox, oy, " ", 1);
1466             XDrawImageString (dpy, window, gc, ox, y, " ", 1);
1467           }
1468         else
1469           {
1470             XDrawImageString (dpy, window, gc, x, y, s, 1);
1471             x += char_width;
1472           }
1473         s++;
1474       }
1475   }
1476
1477   XFreeGC(dpy, gc);
1478   XSync(dpy, False);
1479   bsod_sleep(dpy, delay);
1480   XClearWindow(dpy, window);
1481 }
1482
1483 \f
1484 /* blit damage
1485  *
1486  * by Martin Pool <mbp@samba.org>, Feb 2000.
1487  *
1488  * This is meant to look like the preferred failure mode of NCD
1489  * Xterms.  The parameters for choosing what to copy where might not
1490  * be quite right, but it looks about ugly enough.
1491  */
1492 static void
1493 blitdamage (Display *dpy, Window window, int delay)
1494 {
1495   XGCValues gcv;
1496   XWindowAttributes xwa;
1497   GC gc0;
1498   int i;
1499   int delta_x = 0, delta_y = 0;
1500   int w, h;
1501   int chunk_h, chunk_w;
1502   int steps;
1503   long gc_mask = 0;
1504   int src_x, src_y;
1505   int x, y;
1506   
1507   XGetWindowAttributes(dpy, window, &xwa);
1508
1509   load_random_image (xwa.screen, window, window, NULL);
1510
1511   w = xwa.width;
1512   h = xwa.height;
1513
1514   gc_mask = GCForeground;
1515   
1516   gcv.plane_mask = random();
1517   gc_mask |= GCPlaneMask;
1518   
1519   gc0 = XCreateGC(dpy, window, gc_mask, &gcv);
1520
1521   steps = 50;
1522   chunk_w = w / (random() % 1 + 1);
1523   chunk_h = h / (random() % 1 + 1);
1524   if (random() & 0x1000) 
1525     delta_y = random() % 600;
1526   if (!delta_y || (random() & 0x2000))
1527     delta_x = random() % 600;
1528   src_x = 0; 
1529   src_y = 0; 
1530   x = 0;
1531   y = 0;
1532   
1533   for (i = 0; i < steps; i++) {
1534     if (x + chunk_w > w) 
1535       x -= w;
1536     else
1537       x += delta_x;
1538     
1539     if (y + chunk_h > h)
1540       y -= h;
1541     else
1542       y += delta_y;
1543     
1544     XCopyArea(dpy, window, window, gc0,
1545               src_x, src_y, 
1546               chunk_w, chunk_h,
1547               x, y);
1548
1549     if (bsod_sleep(dpy, 0))
1550       goto DONE;
1551   }
1552
1553   bsod_sleep(dpy, delay);
1554
1555  DONE:
1556   XFreeGC(dpy, gc0);
1557 }
1558
1559 \f
1560 /*
1561  * SPARC Solaris panic. Should look pretty authentic on Solaris boxes.
1562  * Anton Solovyev <solovam@earthlink.net>
1563  */ 
1564
1565 typedef struct
1566 {
1567   Display *dpy;
1568   Window window;
1569   GC gc, erase_gc;
1570   XFontStruct *xfs;
1571   int sub_width;                /* Text subwindow width in pixels */
1572   int sub_height;               /* Text subwindow height in pixels */
1573   int sub_x;                    /* upper left corner of the text subwindow */
1574   int sub_y;                    /* upper left corner of the text subwindow */
1575   int char_width;               /* Char width in pixels */
1576   int line_height;              /* Line height in pixels */
1577   int columns;                  /* Number of columns in the text screen */
1578   int x;                        /* horizontal position of the cursor */
1579 } scrolling_window;
1580
1581
1582 static scrolling_window *
1583 make_scrolling_window (Display *dpy, Window window,
1584                        const char *name,
1585                        Bool grab_screen_p)
1586 {
1587   const char *def_font = "fixed";
1588   scrolling_window* ts;
1589   XWindowAttributes xgwa;
1590   XGCValues gcv;
1591   char* fn;
1592   char buf1[100], buf2[100];
1593
1594   ts = malloc (sizeof (*ts));
1595   ts->window = window;
1596   ts->dpy = dpy;
1597
1598   ts->x = 0;
1599
1600   XGetWindowAttributes (dpy, window, &xgwa);
1601
1602   if (grab_screen_p)
1603     {
1604       ts->sub_width = xgwa.width * 0.8;
1605       ts->sub_height = xgwa.height * 0.8;
1606     }
1607   else
1608     {
1609       ts->sub_width  = xgwa.width - 20;
1610       ts->sub_height = xgwa.height - 20;
1611       if (ts->sub_width  < 20) ts->sub_width  = 20;
1612       if (ts->sub_height < 20) ts->sub_height = 20;
1613     }
1614
1615   sprintf (buf1, "%.50s.font", name);
1616   sprintf (buf2, "%.50s.Font", name);
1617   fn = get_string_resource (buf1, buf2);
1618   ts->xfs = XLoadQueryFont (dpy, fn);
1619   if (!ts->xfs)
1620     {
1621       sprintf (buf1, "%.50s.font2", name);
1622       fn = get_string_resource(buf1, buf2);
1623       ts->xfs = XLoadQueryFont(dpy, fn);
1624     }
1625   if (!ts->xfs)
1626     ts->xfs = XLoadQueryFont(dpy, def_font);
1627   if (!ts->xfs)
1628     exit (1);
1629   gcv.font = ts->xfs->fid;
1630   ts->char_width = (ts->xfs->per_char
1631                     ? ts->xfs->per_char['n'-ts->xfs->min_char_or_byte2].width
1632                     : ts->xfs->min_bounds.width);
1633   ts->line_height = ts->xfs->ascent + ts->xfs->descent + 1;
1634
1635   ts->columns = ts->sub_width / ts->char_width;
1636
1637   ts->sub_x = (xgwa.width - ts->sub_width) / 2;
1638   ts->sub_y = (xgwa.height - ts->sub_height) / 2;
1639
1640   if (!grab_screen_p) ts->sub_height += ts->sub_y, ts->sub_y = 0;
1641
1642   if (grab_screen_p)
1643     load_random_image (xgwa.screen, window, window, NULL);
1644
1645   sprintf (buf1, "%.50s.background", name);
1646   sprintf (buf2, "%.50s.Background", name);
1647   gcv.background = get_pixel_resource (buf1, buf2, dpy, xgwa.colormap);
1648
1649   sprintf (buf1, "%.50s.foreground", name);
1650   sprintf (buf2, "%.50s.Foreground", name);
1651   gcv.foreground = get_pixel_resource (buf1, buf2, dpy, xgwa.colormap);
1652
1653   ts->gc = XCreateGC (dpy, window,
1654                       GCForeground | GCBackground | GCFont,
1655                       &gcv);
1656   gcv.foreground = gcv.background;
1657   ts->erase_gc = XCreateGC (dpy, window,
1658                             GCForeground | GCBackground,
1659                             &gcv);
1660   XSetWindowBackground (dpy, window, gcv.background);
1661   return(ts);
1662 }
1663
1664 static void
1665 free_scrolling_window (scrolling_window* ts)
1666 {
1667   XFreeGC (ts->dpy, ts->gc);
1668   XFreeGC (ts->dpy, ts->erase_gc);
1669   XFreeFont (ts->dpy, ts->xfs);
1670   free (ts);
1671 }
1672
1673 static void
1674 scrolling_putc (scrolling_window* ts, const char aChar)
1675 {
1676   switch (aChar)
1677     {
1678     case '\n':
1679       ts->x = 0;
1680       XCopyArea (ts->dpy, ts->window, ts->window, ts->gc,
1681                  ts->sub_x, ts->sub_y + ts->line_height,
1682                  ts->sub_width, ts->sub_height,
1683                  ts->sub_x, ts->sub_y);
1684       XFillRectangle (ts->dpy, ts->window, ts->erase_gc,
1685                       ts->sub_x, ts->sub_y + ts->sub_height - ts->line_height,
1686                       ts->sub_width, ts->line_height);
1687       break;
1688     case '\r':
1689       ts->x = 0;
1690     case '\b':
1691       if(ts->x > 0)
1692         ts->x--;
1693       break;
1694     default:
1695       if (ts->x >= ts->columns)
1696         scrolling_putc (ts, '\n');
1697       XDrawImageString (ts->dpy, ts->window, ts->gc,
1698                         (ts->sub_x +
1699                          (ts->x * ts->char_width)
1700                          - ts->xfs->min_bounds.lbearing),
1701                         (ts->sub_y + ts->sub_height - ts->xfs->descent),
1702                         &aChar, 1);
1703       ts->x++;
1704       break;
1705     }
1706 }
1707
1708 static Bool
1709 scrolling_puts (scrolling_window *ts, const char* aString, int delay)
1710 {
1711   const char *c;
1712   for (c = aString; *c; ++c)
1713     {
1714       scrolling_putc (ts, *c);
1715       if (delay)
1716         {
1717           XSync(ts->dpy, 0);
1718           usleep(delay);
1719           if (bsod_sleep (ts->dpy, 0))
1720             return True;
1721         }
1722     }
1723   XSync (ts->dpy, 0);
1724   return False;
1725 }
1726
1727 static void
1728 sparc_solaris (Display* dpy, Window window, int delay)
1729 {
1730 # ifdef __GNUC__
1731   __extension__   /* don't warn about "string length is greater than the
1732                      length ISO C89 compilers are required to support"
1733                      in the following string constant... */
1734 # endif
1735
1736   const char *msg1 =
1737     "BAD TRAP: cpu=0 type=0x31 rp=0x2a10043b5e0 addr=0xf3880 mmu_fsr=0x0\n"
1738     "BAD TRAP occured in module \"unix\" due to an illegal access to a"
1739     " user address.\n"
1740     "adb: trap type = 0x31\n"
1741     "addr=0xf3880\n"
1742     "pid=307, pc=0x100306e4, sp=0x2a10043ae81, tstate=0x4480001602,"
1743     " context=0x87f\n"
1744     "g1-g7: 1045b000, 32f, 10079440, 180, 300000ebde8, 0, 30000953a20\n"
1745     "Begin traceback... sp = 2a10043ae81\n"
1746     "Called from 100bd060, fp=2a10043af31, args=f3700 300008cc988 f3880 0"
1747     " 1 300000ebde0.\n"
1748     "Called from 101fe1bc, fp=2a10043b011, args=3000045a240 104465a0"
1749     " 300008e47d0 300008e48fa 300008ae350 300008ae410\n"
1750     "Called from 1007c520, fp=2a10043b0c1, args=300008e4878 300003596e8 0"
1751     " 3000045a320 0 3000045a220\n"
1752     "Called from 1007c498, fp=2a10043b171, args=1045a000 300007847f0 20"
1753     " 3000045a240 1 0\n"
1754     "Called from 1007972c, fp=2a10043b221, args=1 300009517c0 30000951e58 1"
1755     " 300007847f0 0\n"
1756     "Called from 10031e10, fp=2a10043b2d1, args=3000095b0c8 0 300009396a8"
1757     " 30000953a20 0 1\n"
1758     "Called from 10000bdd8, fp=ffffffff7ffff1c1, args=0 57 100131480"
1759     " 100131480 10012a6e0 0\n"
1760     "End traceback...\n"
1761     "panic[cpu0]/thread=30000953a20: trap\n"
1762     "syncing file systems...";
1763   const char *msg2 =
1764     " 1 done\n"
1765     "dumping to /dev/dsk/c0t0d0s3, offset 26935296\n";
1766   const char *msg3 =
1767     ": 2803 pages dumped, compression ratio 2.88, dump succeeded\n";
1768   const char *msg4 =
1769     "rebooting...\n"
1770     "Resetting ...";
1771
1772   scrolling_window *ts;
1773   int i;
1774   char buf[256];
1775
1776   ts = make_scrolling_window (dpy, window, "Solaris", True);
1777
1778   scrolling_puts (ts, msg1, 0);
1779   if (bsod_sleep (dpy, 3))
1780     goto DONE;
1781
1782   scrolling_puts (ts, msg2, 0);
1783   if (bsod_sleep (dpy, 2))
1784     goto DONE;
1785
1786   for (i = 1; i <= 100; ++i)
1787     {
1788       sprintf(buf, "\b\b\b\b\b\b\b\b\b\b\b%3d%% done", i);
1789       scrolling_puts (ts, buf, 0);
1790       if (bsod_sleep (dpy, -1))
1791         goto DONE;
1792     }
1793
1794   scrolling_puts (ts, msg3, 0);
1795   if (bsod_sleep (dpy, 2))
1796     goto DONE;
1797
1798   scrolling_puts (ts, msg4, 0);
1799   if (bsod_sleep(dpy, 3))
1800     goto DONE;
1801
1802   bsod_sleep (dpy, 3);
1803
1804  DONE:
1805   free_scrolling_window (ts);
1806 }
1807
1808 /* Linux panic and fsck, by jwz
1809  */
1810 static void
1811 linux_fsck (Display *dpy, Window window, int delay)
1812 {
1813   XWindowAttributes xgwa;
1814   scrolling_window *ts;
1815   int i;
1816   const char *sysname;
1817   char buf[1024];
1818
1819   const char *linux_panic[] = {
1820    " kernel: Unable to handle kernel paging request at virtual "
1821      "address 0000f0ad\n",
1822    " kernel:  printing eip:\n",
1823    " kernel: c01becd7\n",
1824    " kernel: *pde = 00000000\n",
1825    " kernel: Oops: 0000\n",
1826    " kernel: CPU:    0\n",
1827    " kernel: EIP:    0010:[<c01becd7>]    Tainted: P \n",
1828    " kernel: EFLAGS: 00010286\n",
1829    " kernel: eax: 0000ff00   ebx: ca6b7e00   ecx: ce1d7a60   edx: ce1d7a60\n",
1830    " kernel: esi: ca6b7ebc   edi: 00030000   ebp: d3655ca0   esp: ca6b7e5c\n",
1831    " kernel: ds: 0018   es: 0018   ss: 0018\n",
1832    " kernel: Process crond (pid: 1189, stackpage=ca6b7000)\n",
1833    " kernel: Stack: d3655ca0 ca6b7ebc 00030054 ca6b7e7c c01c1e5b "
1834        "00000287 00000020 c01c1fbf \n",
1835    "",
1836    " kernel:        00005a36 000000dc 000001f4 00000000 00000000 "
1837        "ce046d40 00000001 00000000 \n",
1838    "", "", "",
1839    " kernel:        ffffffff d3655ca0 d3655b80 00030054 c01bef93 "
1840        "d3655ca0 ca6b7ebc 00030054 \n",
1841    "", "", "",
1842    " kernel: Call Trace:    [<c01c1e5b>] [<c01c1fbf>] [<c01bef93>] "
1843        "[<c01bf02b>] [<c0134c4f>]\n",
1844    "", "", "",
1845    " kernel:   [<c0142562>] [<c0114f8c>] [<c0134de3>] [<c010891b>]\n",
1846    " kernel: \n",
1847    " kernel: Code: 2a 00 75 08 8b 44 24 2c 85 c0 74 0c 8b 44 24 58 83 48 18 "
1848       "08 \n",
1849    0
1850   };
1851
1852   XGetWindowAttributes (dpy, window, &xgwa);
1853   XSetWindowBackground (dpy, window, 
1854                         get_pixel_resource("Linux.background",
1855                                            "Linux.Background",
1856                                            dpy, xgwa.colormap));
1857   XClearWindow(dpy, window);
1858
1859   sysname = "linux";
1860 # ifdef HAVE_UNAME
1861   {
1862     struct utsname uts;
1863     char *s;
1864     if (uname (&uts) >= 0)
1865       sysname = uts.nodename;
1866     s = strchr (sysname, '.');
1867     if (s) *s = 0;
1868   }
1869 # endif /* !HAVE_UNAME */
1870
1871
1872   ts = make_scrolling_window (dpy, window, "Linux", False);
1873
1874   scrolling_puts (ts, "waiting for X server to shut down ", 0);
1875   usleep (100000);
1876   if (bsod_sleep (dpy, 0))
1877     goto PANIC;
1878   scrolling_puts (ts,
1879                   "XIO:  fatal IO error 2 (broken pipe) on X server \":0.0\"\n"
1880                   "        after 339471 requests (339471 known processed) "
1881                   "with 0 events remaining\n",
1882                   0);
1883   if (scrolling_puts (ts, ".........\n", 300000))
1884     goto PANIC;
1885   if (bsod_sleep (dpy, 0))
1886     goto PANIC;
1887   scrolling_puts (ts,
1888                   "xinit:  X server slow to shut down, sending KILL signal.\n",
1889                   0);
1890   scrolling_puts (ts, "waiting for server to die ", 0);
1891   if (scrolling_puts (ts, "...\n", 300000))
1892     goto PANIC;
1893   if (bsod_sleep (dpy, 0))
1894     goto PANIC;
1895   scrolling_puts (ts, "xinit:  Can't kill server\n", 0);
1896
1897   if (bsod_sleep (dpy, 2))
1898     goto PANIC;
1899
1900   sprintf (buf, "\n%s Login: ", sysname);
1901   scrolling_puts (ts, buf, 0);
1902   if (bsod_sleep (dpy, 1))
1903     goto PANIC;
1904   scrolling_puts (ts,
1905     "\n\n"
1906     "Parallelizing fsck version 1.22 (22-Jun-2001)\n"
1907     "e2fsck 1.22, 22-Jun-2001 for EXT2 FS 0.5b, 95/08/09\n"
1908     "Warning!  /dev/hda1 is mounted.\n"
1909     "/dev/hda1 contains a file system with errors, check forced.\n",
1910                 0);
1911   if (bsod_sleep (dpy, 1))
1912     goto PANIC;
1913
1914   if (0 == random() % 2)
1915   scrolling_puts (ts,
1916      "Couldn't find ext2 superblock, trying backup blocks...\n"
1917      "The filesystem size (according to the superblock) is 3644739 blocks\n"
1918      "The physical size of the device is 3636706 blocks\n"
1919      "Either the superblock or the partition table is likely to be corrupt!\n"
1920      "Abort<y>? no\n",
1921                 0);
1922   if (bsod_sleep (dpy, 1))
1923     goto PANIC;
1924
1925  AGAIN:
1926
1927   scrolling_puts (ts, "Pass 1: Checking inodes, blocks, and sizes\n", 0);
1928   if (bsod_sleep (dpy, 2))
1929     goto PANIC;
1930
1931   i = (random() % 60) - 20;
1932   while (--i > 0)
1933     {
1934       int b = random() % 0xFFFF;
1935       sprintf (buf, "Deleted inode %d has zero dtime.  Fix<y>? yes\n\n", b);
1936       scrolling_puts (ts, buf, 0);
1937     }
1938
1939   i = (random() % 40) - 10;
1940   if (i > 0)
1941     {
1942       int g = random() % 0xFFFF;
1943       int b = random() % 0xFFFFFFF;
1944
1945       if (bsod_sleep (dpy, 1))
1946         goto PANIC;
1947
1948       sprintf (buf, "Warning: Group %d's copy of the group descriptors "
1949                "has a bad block (%d).\n", g, b);
1950       scrolling_puts (ts, buf, 0);
1951
1952       b = random() % 0x3FFFFF;
1953       while (--i > 0)
1954         {
1955           b += random() % 0xFFFF;
1956           sprintf (buf,
1957                    "Error reading block %d (Attempt to read block "
1958                    "from filesystem resulted in short read) while doing "
1959                    "inode scan.  Ignore error<y>?",
1960                    b);
1961           scrolling_puts (ts, buf, 0);
1962           usleep (10000);
1963           scrolling_puts (ts, " yes\n\n", 0);
1964         }
1965     }
1966
1967   if (0 == (random() % 10))
1968     {
1969
1970       if (bsod_sleep (dpy, 1))
1971         goto PANIC;
1972
1973       i = 3 + (random() % 10);
1974       while (--i > 0)
1975         scrolling_puts (ts, "Could not allocate 256 block(s) for inode table: "
1976                         "No space left on device\n", 0);
1977       scrolling_puts (ts, "Restarting e2fsck from the beginning...\n", 0);
1978
1979       if (bsod_sleep (dpy, 2))
1980         goto PANIC;
1981
1982       goto AGAIN;
1983     }
1984
1985   i = (random() % 20) - 5;
1986
1987   if (i > 0)
1988     if (bsod_sleep (dpy, 1))
1989       goto PANIC;
1990
1991   while (--i > 0)
1992     {
1993       int j = 5 + (random() % 10);
1994       int w = random() % 4;
1995
1996       while (--j > 0)
1997         {
1998           int b = random() % 0xFFFFF;
1999           int g = random() % 0xFFF;
2000
2001           if (0 == (random() % 10))
2002             b = 0;
2003           else if (0 == (random() % 10))
2004             b = -1;
2005
2006           if (w == 0)
2007             sprintf (buf,
2008                      "Inode table for group %d not in group.  (block %d)\n"
2009                      "WARNING: SEVERE DATA LOSS POSSIBLE.\n"
2010                      "Relocate<y>?",
2011                      g, b);
2012           else if (w == 1)
2013             sprintf (buf,
2014                      "Block bitmap for group %d not in group.  (block %d)\n"
2015                      "Relocate<y>?",
2016                      g, b);
2017           else if (w == 2)
2018             sprintf (buf,
2019                      "Inode bitmap %d for group %d not in group.\n"
2020                      "Continue<y>?",
2021                      b, g);
2022           else /* if (w == 3) */
2023             sprintf (buf,
2024                      "Bad block %d in group %d's inode table.\n"
2025                      "WARNING: SEVERE DATA LOSS POSSIBLE.\n"
2026                      "Relocate<y>?",
2027                      b, g);
2028
2029           scrolling_puts (ts, buf, 0);
2030           scrolling_puts (ts, " yes\n\n", 0);
2031         }
2032       if (bsod_sleep (dpy, 0))
2033         goto PANIC;
2034       usleep (1000);
2035     }
2036
2037
2038   if (0 == random() % 10) goto PANIC;
2039   scrolling_puts (ts, "Pass 2: Checking directory structure\n", 0);
2040   if (bsod_sleep (dpy, 2))
2041     goto PANIC;
2042
2043   i = (random() % 20) - 5;
2044   while (--i > 0)
2045     {
2046       int n = random() % 0xFFFFF;
2047       int o = random() % 0xFFF;
2048       sprintf (buf, "Directory inode %d, block 0, offset %d: "
2049                "directory corrupted\n"
2050                "Salvage<y>? ",
2051                n, o);
2052       scrolling_puts (ts, buf, 0);
2053       usleep (1000);
2054       scrolling_puts (ts, " yes\n\n", 0);
2055
2056       if (0 == (random() % 100))
2057         {
2058           sprintf (buf, "Missing '.' in directory inode %d.\nFix<y>?", n);
2059           scrolling_puts (ts, buf, 0);
2060           usleep (1000);
2061           scrolling_puts (ts, " yes\n\n", 0);
2062         }
2063
2064       if (bsod_sleep (dpy, 0))
2065         goto PANIC;
2066     }
2067
2068   if (0 == random() % 10) goto PANIC;
2069   scrolling_puts (ts,
2070                   "Pass 3: Checking directory connectivity\n"
2071                   "/lost+found not found.  Create? yes\n",
2072                 0);
2073   if (bsod_sleep (dpy, 2))
2074     goto PANIC;
2075
2076   /* Unconnected directory inode 4949 (/var/spool/squid/06/???)
2077      Connect to /lost+found<y>? yes
2078
2079      '..' in /var/spool/squid/06/08 (20351) is <The NULL inode> (0), should be 
2080      /var/spool/squid/06 (20350).
2081      Fix<y>? yes
2082
2083      Unconnected directory inode 128337 (/var/spool/squid/06/???)
2084      Connect to /lost+found<y>? yes
2085    */
2086
2087
2088   if (0 == random() % 10) goto PANIC;
2089   scrolling_puts (ts, "Pass 4: Checking reference counts\n", 0);
2090   if (bsod_sleep (dpy, 2))
2091     goto PANIC;
2092
2093   /* Inode 2 ref count is 19, should be 20.  Fix<y>? yes
2094
2095      Inode 4949 ref count is 3, should be 2.  Fix<y>? yes
2096
2097         ...
2098
2099      Inode 128336 ref count is 3, should be 2.  Fix<y>? yes
2100
2101      Inode 128337 ref count is 3, should be 2.  Fix<y>? yes
2102
2103    */
2104
2105
2106   if (0 == random() % 10) goto PANIC;
2107   scrolling_puts (ts, "Pass 5: Checking group summary information\n", 0);
2108   if (bsod_sleep (dpy, 2))
2109     goto PANIC;
2110
2111   i = (random() % 200) - 50;
2112   if (i > 0)
2113     {
2114       scrolling_puts (ts, "Block bitmap differences: ", 0);
2115       while (--i > 0)
2116         {
2117           sprintf (buf, " %d", -(random() % 0xFFF));
2118           scrolling_puts (ts, buf, 0);
2119           usleep (1000);
2120         }
2121       scrolling_puts (ts, "\nFix? yes\n\n", 0);
2122     }
2123
2124
2125   i = (random() % 100) - 50;
2126   if (i > 0)
2127     {
2128       scrolling_puts (ts, "Inode bitmap differences: ", 0);
2129       while (--i > 0)
2130         {
2131           sprintf (buf, " %d", -(random() % 0xFFF));
2132           scrolling_puts (ts, buf, 0);
2133           usleep (1000);
2134         }
2135       scrolling_puts (ts, "\nFix? yes\n\n", 0);
2136     }
2137
2138   i = (random() % 20) - 5;
2139   while (--i > 0)
2140     {
2141       int g = random() % 0xFFFF;
2142       int c = random() % 0xFFFF;
2143       sprintf (buf,
2144                "Free blocks count wrong for group #0 (%d, counted=%d).\nFix? ",
2145                g, c);
2146       scrolling_puts (ts, buf, 0);
2147       usleep (1000);
2148       scrolling_puts (ts, " yes\n\n", 0);
2149       if (bsod_sleep (dpy, 0))
2150         goto PANIC;
2151     }
2152
2153  PANIC:
2154
2155   i = 0;
2156   scrolling_puts (ts, "\n\n", 0);
2157   while (linux_panic[i])
2158     {
2159       time_t t = time ((time_t *) 0);
2160       struct tm *tm = localtime (&t);
2161       char prefix[100];
2162
2163       if (*linux_panic[i])
2164         {
2165           strftime (prefix, sizeof(prefix)-1, "%b %d %H:%M:%S ", tm);
2166           scrolling_puts (ts, prefix, 0);
2167           scrolling_puts (ts, sysname, 0);
2168           scrolling_puts (ts, linux_panic[i], 0);
2169           XSync(dpy, False);
2170           usleep(1000);
2171         }
2172       else
2173         usleep (300000);
2174
2175       if (bsod_sleep (dpy, 0))
2176         goto DONE;
2177       i++;
2178     }
2179
2180   if (bsod_sleep (dpy, 4))
2181     goto DONE;
2182
2183
2184   XSync(dpy, False);
2185   bsod_sleep(dpy, delay);
2186
2187  DONE:
2188   free_scrolling_window (ts);
2189   XClearWindow(dpy, window);
2190 }
2191
2192 /* VMS by jwz (text sent by Roland Barmettler <roli@barmettler.net>)
2193  */
2194 static void
2195 vms (Display *dpy, Window window, int delay)
2196 {
2197   XWindowAttributes xgwa;
2198   scrolling_window *ts;
2199   const char *sysname;
2200   int char_delay = 0;
2201   int dot_delay = 40000;
2202   int chunk_delay = 500000;
2203   char *s, *s1;
2204   int i;
2205   int arg_count;
2206
2207 # ifdef __GNUC__
2208   __extension__   /* don't warn about "string length is greater than the
2209                      length ISO C89 compilers are required to support"
2210                      in the following string constant... */
2211 # endif
2212
2213   const char *lines[] = {
2214     "%CNXMAN,  Lost connection to system #\n"
2215     "%SHADOW-I-VOLPROC, DSA0: shadow master has changed.  "
2216     "Dump file WILL be written if system crashes.\n"
2217     "\n",
2218     "",
2219
2220     "%CNXMAN,  Quorum lost, blocking activity\n"
2221     "%CNXMAN,  Timed-out lost connection to system #\n"
2222     "%CNXMAN,  Timed-out lost connection to system #\n"
2223     "%CNXMAN,  Timed-out lost connection to system #\n"
2224     "%CNXMAN,  Proposing reconfiguration of the VMScluster\n",
2225     "",
2226
2227     "%CNXMAN,  Removed from VMScluster system #\n"
2228     "%CNXMAN,  Removed from VMScluster system #\n"
2229     "%CNXMAN,  Removed from VMScluster system #\n"
2230     "%CNXMAN,  Completing VMScluster state transition\n",
2231
2232     "\n"
2233     "**** OpenVMS (TM) Alpha Operating system V7.3-1   - BUGCHECK ****\n"
2234     "\n"
2235     "** Bugcheck code = 000005DC: CLUEXIT, Node voluntarily exiting "
2236     "VMScluster\n"
2237     "** Crash CPU: 00    Primary CPU: 00    Active CPUs: 00000001\n"
2238     "** Current Process = NULL\n"
2239     "** Current PSB ID = 00000001\n"
2240     "** Image Name =\n"
2241     "\n"
2242     "** Dumping error log buffers to HBVS unit 0\n"
2243     "**** Unable to dump error log buffers to remaining shadow set members\n"
2244     "** Error log buffers not dumped to HBVS unit 200\n"
2245     "\n"
2246     "** Dumping memory to HBVS unit 0\n"
2247     "**** Starting compressed selective memory dump at #...\n",
2248
2249     "...",
2250
2251     "\n"
2252     "**** Memory dump complete - not all processes or global pages saved\n",
2253
2254     "\n"
2255     "halted CPU 0\n",
2256     "",
2257
2258     "\n"
2259     "halt code = 5\n"
2260     "HALT instruction executed\n"
2261     "PC = ffffffff800c3884\n",
2262
2263     "\n"
2264     "CPU 0 booting\n",
2265
2266     "\n"
2267     "resetting all I/O buses\n"
2268     "\n"
2269     "\n"
2270     };
2271   char *args[8];
2272   int ids[3];
2273
2274   XGetWindowAttributes (dpy, window, &xgwa);
2275   ts = make_scrolling_window (dpy, window, "VMS", False);
2276   XClearWindow(dpy,window);
2277   ts->sub_x = 0;
2278   ts->sub_y = 0;
2279   ts->sub_width = xgwa.width;
2280   ts->sub_height = xgwa.height;
2281
2282   sysname = "VMS001";
2283 # ifdef HAVE_UNAME
2284   {
2285     struct utsname uts;
2286     if (uname (&uts) >= 0)
2287       sysname = uts.nodename;
2288     s = strchr (sysname, '.');
2289     if (s) *s = 0;
2290   }
2291 # endif /* !HAVE_UNAME */
2292
2293   args[0] = malloc (strlen(sysname) + 7);
2294   strcpy (args[0], sysname);
2295   args[0][5] = 0;
2296
2297   /* Pick three numbers, 1-9, no overlaps. */
2298   ids[0] = 1 + (random() % 9);
2299   do { ids[1] = 1 + (random() % 9); } while (ids[1]==ids[0]);
2300   do { ids[2] = 1 + (random() % 9); } while (ids[2]==ids[0] || ids[2]==ids[1]);
2301
2302   i = strlen(args[0])-1;
2303   if (i < 6) i++;
2304   args[0][i] = '0' + ids[0];
2305   args[0][i+1] = 0;
2306
2307   for (s = args[0]; *s; s++)
2308     if (isalpha(*s)) *s = toupper (*s);
2309
2310   args[1] = strdup (args[0]);
2311   args[2] = strdup (args[0]); args[2][i] = '0' + ids[1];
2312   args[3] = strdup (args[0]); args[3][i] = '0' + ids[2];
2313
2314   args[4] = strdup (args[1]);
2315   args[5] = strdup (args[2]);
2316   args[6] = strdup (args[3]);
2317
2318   {
2319     time_t t = time ((time_t *) 0);
2320     struct tm *tm = localtime (&t);
2321     args[7] = malloc (30);
2322     strftime (args[7], 29, "%d-%b-%Y %H:%M", tm);
2323     for (s = args[7]; *s; s++)
2324       if (isalpha(*s)) *s = toupper (*s);
2325   }
2326
2327   arg_count = 0;
2328   for (i = 0; i < countof(lines); i++)
2329     {
2330       const char *fmt = lines[i];
2331       if (! strcmp (fmt, "..."))
2332         {
2333           int steps = 180 + (random() % 60);
2334           while (--steps >= 0)
2335             {
2336               scrolling_puts (ts, ".", 0);
2337               XSync (dpy, False);
2338               usleep (dot_delay);
2339               if (bsod_sleep (dpy, 0))
2340                 goto DONE;
2341             }
2342         }
2343       else
2344         {
2345           char *fmt2 = malloc (strlen (fmt) * 2 + 1);
2346           for (s = (char *) fmt, s1 = fmt2; *s; s++)
2347             {
2348               if (*s == '#')
2349                 {
2350                   strcpy (s1, args[arg_count++]);
2351                   s1 += strlen(s1);
2352                 }
2353               else
2354                 *s1++ = *s;
2355             }
2356           *s1 = 0;
2357           scrolling_puts (ts, fmt2, char_delay);
2358           free (fmt2);
2359           usleep (chunk_delay);
2360           if (bsod_sleep (dpy, 0))
2361             goto DONE;
2362         }
2363     }
2364
2365   XSync(dpy, False);
2366   bsod_sleep(dpy, delay);
2367
2368  DONE:
2369   free_scrolling_window (ts);
2370   for (i = 0; i < countof (args); i++)
2371     free (args[i]);
2372 }
2373
2374
2375 /* HVX (formerly GCOS6) and TPS6 crash
2376    by Brian Garratt <brian-m.garratt@bull.co.uk>
2377
2378    GCOS6 is a Unix-like operating system developed by Honeywell in the
2379    1970s in collaboration with MIT and AT&T (who called their version
2380    UNIX).  Both are very much like MULTICS which Honeywell got from GE.
2381
2382    HVX ("High-performance Virtual System on Unix") is an AIX application
2383    which emulates GCOS6 hardware on RS6000-like machines.
2384  */
2385 static void
2386 hvx (Display *dpy, Window window, int delay)
2387 {
2388   XWindowAttributes xgwa;
2389   scrolling_window *ts;
2390
2391   int delay1 = 10000;
2392   int delay2 = 100000;
2393   const char *hvx_panic_1 =
2394     ("(TP) Trap no E   Effective address 00000000   Instruction D7DE\n"
2395      "(TP)  Registers :\n"
2396      "(TP)  B1 -> B7  03801B02  00000000  03880D45  038BABDB  0388AFFD"
2397      "  0389B3F8  03972317\n"
2398      "(TP)  R1 -> R7  0001  0007  F10F  090F  0020  0106  0272\n"
2399      "(TP)  P I Z M1  0388A18B  3232  0000 FF00\n"
2400      "(TP) Program counter is at offset 0028 from string YTPAD\n"
2401      "(TP) User id of task which trapped is LT 626\n"
2402      "(TP)?\n"
2403      );
2404   const char *hvx_panic_2 =
2405     ("\n"
2406      "(TP)?\n"
2407      "Core dumps initiated for selected HVX processes ...\n"
2408      "Core dumps complete.\n"
2409      "Fri Jul 19 15:53:09 2002\n"
2410      "Live registers for cp 0:\n"
2411      " P    =     7de3  IW=0000     I=32    CI=30000000   S=80006013"
2412      "   IV=aa0      Level=13\n"
2413      " R1-7 =       1f      913       13        4        8        0        0\n"
2414      " B1-7 =   64e71b      a93      50e   64e73c     6c2c     7000      b54\n"
2415      "Memory dump starting to file /var/hvx/dp01/diag/Level2 ...\n"
2416      "Memory dump complete.\n"
2417     );
2418
2419   XGetWindowAttributes (dpy, window, &xgwa);
2420   ts = make_scrolling_window (dpy, window, "HVX", False);
2421   XClearWindow(dpy, window);
2422
2423   scrolling_puts (ts, hvx_panic_1,         delay1);
2424   if (bsod_sleep(dpy, 1)) goto DONE;
2425   scrolling_puts (ts, " TP CLOSE ALL",     delay2);
2426   scrolling_puts (ts, "\n(TP)?\n",         delay1);
2427   if (bsod_sleep(dpy, 1)) goto DONE;
2428   scrolling_puts (ts, " TP ABORT -LT ALL", delay2);
2429   scrolling_puts (ts, "\n(TP)?\n",         delay1);
2430   if (bsod_sleep(dpy, 1)) goto DONE;
2431   scrolling_puts (ts, "  TP STOP KILL",    delay2);
2432   scrolling_puts (ts, hvx_panic_2,         delay1);
2433
2434   bsod_sleep(dpy, delay);
2435  DONE:
2436   XClearWindow(dpy, window);
2437 }
2438
2439
2440 \f
2441
2442 /* HPUX panic, by Tobias Klausmann <klausman@schwarzvogel.de>
2443  */
2444
2445 static void
2446 hpux (Display* dpy, Window window, int delay)
2447 {
2448   XWindowAttributes xgwa;
2449   scrolling_window *ts;
2450   const char *sysname;
2451   char buf[2048];
2452
2453 # ifdef __GNUC__
2454   __extension__   /* don't warn about "string length is greater than the
2455                      length ISO C89 compilers are required to support"
2456                      in the following string constant... */
2457 # endif
2458
2459   const char *msg1 =
2460    "Console Login:\n"
2461    "\n"
2462    "     ******* Unexpected HPMC/TOC. Processor HPA FFFFFFFF'"
2463    "FFFA0000 *******\n"
2464    "                              GENERAL REGISTERS:\n"
2465    "r00/03 00000000'00000000 00000000'00000000 00000000'00000000 00000000'"
2466    "006C76C0\n"
2467    "r04/07 00000000'00000001 00000000'0126E328 00000000'00000000 00000000'"
2468    "0122B640\n"
2469    "r08/11 00000000'00000000 00000000'0198CFC0 00000000'000476FE 00000000'"
2470    "00000001\n"
2471    "r12/15 00000000'40013EE8 00000000'08000080 00000000'4002530C 00000000'"
2472    "4002530C\n"
2473    "r16/19 00000000'7F7F2A00 00000000'00000001 00000000'00000000 00000000'"
2474    "00000000\n"
2475    "r20/23 00000000'006C8048 00000000'00000001 00000000'00000000 00000000'"
2476    "00000000\n"
2477    "r24/27 00000000'00000000 00000000'00000000 00000000'00000000 00000000'"
2478    "00744378\n"
2479    "r28/31 00000000'00000000 00000000'007DD628 00000000'0199F2B0 00000000'"
2480    "00000000\n"
2481    "                              CONTROL REGISTERS:\n"
2482    "sr0/3  00000000'0F3B4000 00000000'0C2A2000 00000000'016FF800 00000000'"
2483    "00000000\n"
2484    "sr4/7  00000000'00000000 00000000'016FF800 00000000'0DBF1400 00000000'"
2485    "00000000\n"
2486    "pcq =  00000000'00000000.00000000'00104950 00000000'00000000.00000000'"
2487    "00104A14\n"
2488    "isr =  00000000'10240006 ior = 00000000'67D9E220 iir = 08000240 rctr = "
2489    "7FF10BB6\n"
2490    "\n"
2491    "pid reg cr8/cr9    00007700'0000B3A9 00000000'0000C5D8\n"
2492    "pid reg cr12/cr13  00000000'00000000 00000000'00000000\n"
2493    "ipsw = 000000FF'080CFF1F iva = 00000000'0002C000 sar = 3A ccr = C0\n"
2494    "tr0/3  00000000'006C76C0 00000000'00000001 00000000'00000000 00000000'"
2495    "7F7CE000\n"
2496    "tr4/7  00000000'03790000 0000000C'4FB68340 00000000'C07EE13F 00000000'"
2497    "0199F2B0\n"
2498    "eiem = FFFFFFF0'FFFFFFFF eirr = 80000000'00000000 itmr = 0000000C'"
2499    "4FD8EDE1\n"
2500    "cr1/4  00000000'00000000 00000000'00000000 00000000'00000000 00000000'"
2501    "00000000\n"
2502    "cr5/7  00000000'00000000 00000000'00000000 00000000'"
2503    "00000000\n"
2504    "                           MACHINE CHECK PARAMETERS:\n"
2505    "Check Type = 00000000 CPU STATE = 9E000001 Cache Check = 00000000\n"
2506    "TLB Check = 00000000 Bus Check = 00000000 PIM State = ? SIU "
2507    "Status = ????????\n"
2508    "Assists = 00000000 Processor = 00000000\n"
2509    "Slave Addr = 00000000'00000000 Master Addr = 00000000'00000000\n"
2510    "\n"
2511    "\n"
2512    "TOC,    pcsq.pcoq = 0'0.0'104950   , isr.ior = 0'10240006.0'67d9e220\n"
2513    "@(#)B2352B/9245XB HP-UX (B.11.00) #1: Wed Nov  5 22:38:19 PST 1997\n"
2514    "Transfer of control: (display==0xd904, flags==0x0)\n"
2515    "\n"
2516    "\n"
2517    "\n"
2518    "*** A system crash has occurred.  (See the above messages for details.)\n"
2519    "*** The system is now preparing to dump physical memory to disk, for use\n"
2520    "*** in debugging the crash.\n"
2521    "\n"
2522    "*** The dump will be a SELECTIVE dump:  40 of 256 megabytes.\n"
2523    "*** To change this dump type, press any key within 10 seconds.\n"
2524    "*** Proceeding with selective dump.\n"
2525    "\n"
2526    "*** The dump may be aborted at any time by pressing ESC.\n";
2527   const char *msg2 =
2528    "\n*** System rebooting.\n";
2529
2530   XGetWindowAttributes (dpy, window, &xgwa);
2531   ts = make_scrolling_window (dpy, window, "HPUX", False);
2532   XClearWindow(dpy,window);
2533   ts->columns = 10000;  /* never wrap */
2534   ts->sub_x = 0;
2535   ts->sub_y = 0;
2536   ts->sub_width = xgwa.width;
2537   ts->sub_height = xgwa.height;
2538
2539   sysname = "HPUX";
2540 # ifdef HAVE_UNAME
2541   {
2542     struct utsname uts;
2543     char *s;
2544     if (uname (&uts) >= 0)
2545       sysname = uts.nodename;
2546     s = strchr (sysname, '.');
2547     if (s) *s = 0;
2548   }
2549 # endif /* !HAVE_UNAME */
2550
2551   if (bsod_sleep (dpy, 1))
2552     goto DONE;
2553   
2554   scrolling_puts (ts,
2555                   "                                                       "
2556                   "                                                       "
2557                   "                                                       \n",
2558                   0);
2559   sprintf (buf, "%.100s [HP Release B.11.00] (see /etc/issue)\n", sysname);
2560   scrolling_puts (ts, buf, 0);
2561   if (bsod_sleep (dpy, 1))
2562     goto DONE;
2563   scrolling_puts (ts, msg1, 0);
2564   {
2565     int i;
2566     int steps = 11;
2567     int size = 40;
2568     for (i = 0; i <= steps; i++)
2569       {
2570         if (i > steps) i = steps;
2571         sprintf (buf, 
2572                "*** Dumping: %3d%% complete (%d of 40 MB) (device 64:0x2)\r",
2573                  i * 100 / steps,
2574                  i * size / steps);
2575         scrolling_puts (ts, buf, 0);
2576         XSync (dpy, False);
2577         usleep (1500000);
2578         if (bsod_sleep (dpy, 0))
2579           goto DONE;
2580       }
2581   }
2582
2583   scrolling_puts (ts, msg2, 0);
2584
2585   XSync(dpy, False);
2586   bsod_sleep(dpy, delay);
2587
2588  DONE:
2589   free_scrolling_window (ts);
2590 }
2591
2592 \f
2593
2594 /* IBM OS/390 aka MVS aka z/OS.
2595    Text from Dan Espen <dane@mk.telcordia.com>.
2596    Apparently this isn't actually a crash, just a random session...
2597    But who can tell.
2598  */
2599
2600 static void
2601 os390 (Display* dpy, Window window, int delay)
2602 {
2603   GC gc;
2604   XGCValues gcv;
2605   XWindowAttributes xgwa;
2606   scrolling_window *ts;
2607   int i;
2608
2609   const char *msg[] = {
2610    "* ISPF Subtask abend *\n",
2611    "SPF      ENDED DUE TO ERROR+\n",
2612    "READY\n",
2613    "\n",
2614    "IEA995I SYMPTOM DUMP OUTPUT\n",
2615    "  USER COMPLETION CODE=0222\n",
2616    " TIME=23.00.51  SEQ=03210  CPU=0000  ASID=00AE\n",
2617    " PSW AT TIME OF ERROR  078D1000   859DAF18  ILC 2  INTC 0D\n",
2618    "   NO ACTIVE MODULE FOUND\n",
2619    "   NAME=UNKNOWN\n",
2620    "   DATA AT PSW  059DAF12 - 00181610  0A0D9180  70644710\n",
2621    "   AR/GR 0: 00000000/80000000   1: 00000000/800000DE\n",
2622    "         2: 00000000/196504DC   3: 00000000/00037A78\n",
2623    "         4: 00000000/00037B78   5: 00000000/0003351C\n",
2624    "         6: 00000000/0000F0AD   7: 00000000/00012000\n",
2625    "         8: 00000000/059DAF10   9: 00000000/0002D098\n",
2626    "         A: 00000000/059D9F10   B: 00000000/059D8F10\n",
2627    "         C: 00000000/859D7F10   D: 00000000/00032D60\n",
2628    "         E: 00000000/00033005   F: 01000002/00000041\n",
2629    " END OF SYMPTOM DUMP\n",
2630    "ISPS014 - ** Logical screen request failed - abend 0000DE **\n",
2631    "ISPS015 - ** Contact your system programmer or dialog developer.**\n",
2632    "*** ISPF Main task abend ***\n",
2633    "IEA995I SYMPTOM DUMP OUTPUT\n",
2634    "  USER COMPLETION CODE=0222\n",
2635    " TIME=23.00.52  SEQ=03211  CPU=0000  ASID=00AE\n",
2636    " PSW AT TIME OF ERROR  078D1000   8585713C  ILC 2  INTC 0D\n",
2637    "   ACTIVE LOAD MODULE           ADDRESS=05855000  OFFSET=0000213C\n",
2638    "   NAME=ISPMAIN\n",
2639    "   DATA AT PSW  05857136 - 00181610  0A0D9180  D3304770\n",
2640    "   GR 0: 80000000   1: 800000DE\n",
2641    "      2: 00015260   3: 00000038\n",
2642    "      4: 00012508   5: 00000000\n",
2643    "      6: 000173AC   7: FFFFFFF8\n",
2644    "      8: 05858000   9: 00012CA0\n",
2645    "      A: 05857000   B: 05856000\n",
2646    "      C: 85855000   D: 00017020\n",
2647    "      E: 85857104   F: 00000000\n",
2648    " END OF SYMPTOM DUMP\n",
2649    "READY\n",
2650    "***_\n"
2651   };
2652
2653   XGetWindowAttributes (dpy, window, &xgwa);
2654   ts = make_scrolling_window (dpy, window, "OS390", False);
2655   ts->columns = 10000;  /* never wrap */
2656   ts->sub_x = 0;
2657   ts->sub_y = 0;
2658   ts->sub_width = xgwa.width;
2659   ts->sub_height = xgwa.height;
2660
2661   gcv.foreground = get_pixel_resource ("390.background", "390.Background",
2662                                        dpy, xgwa.colormap);
2663   gc = XCreateGC (dpy, window, GCForeground, &gcv);
2664   XFillRectangle (dpy, window, gc, 0, 0, xgwa.width, xgwa.height);
2665   XFreeGC (dpy, gc);
2666
2667   for (i = 0; i < countof (msg); i++)
2668     {
2669       scrolling_puts (ts, msg[i], 0);
2670       usleep (100000);
2671       if (bsod_sleep(dpy, 0)) goto DONE;
2672     }
2673
2674   XSync(dpy, False);
2675   bsod_sleep(dpy, delay);
2676 DONE:
2677   free_scrolling_window (ts);
2678 }
2679
2680
2681 \f
2682 /*
2683  * Simulate various Apple ][ crashes. The memory map encouraged many programs
2684  * to use the primary hi-res video page for various storage, and the secondary
2685  * hi-res page for active display. When it crashed into Applesoft or the
2686  * monitor, it would revert to the primary page and you'd see memory garbage on
2687  * the screen. Also, it was common for copy-protected games to use the primary
2688  * text page for important code, because that made it really hard to
2689  * reverse-engineer them. The result often looked like what this generates.
2690  *
2691  * The Apple ][ logic and video hardware is in apple2.c. The TV is emulated by
2692  * analogtv.c for maximum realism
2693  *
2694  * Trevor Blackwell <tlb@tlb.org> 
2695  */
2696
2697 static char * apple2_basic_errors[]={
2698   "BREAK",
2699   "NEXT WITHOUT FOR",
2700   "SYNTAX ERROR",
2701   "RETURN WITHOUT GOSUB",
2702   "ILLEGAL QUANTITY",
2703   "OVERFLOW",
2704   "OUT OF MEMORY",
2705   "BAD SUBSCRIPT ERROR",
2706   "DIVISION BY ZERO",
2707   "STRING TOO LONG",
2708   "FORMULA TOO COMPLEX",
2709   "UNDEF'D FUNCTION",
2710   "OUT OF DATA"
2711 #if 0
2712   ,
2713   "DEFAULT ARGUMENTS ARE NOT ALLOWED IN DECLARATION OF FRIEND "
2714   "TEMPLATE SPECIALIZATION"
2715 #endif
2716
2717 };
2718 static char * apple2_dos_errors[]={
2719   "VOLUME MISMATCH",
2720   "I/O ERROR",
2721   "DISK FULL",
2722   "NO BUFFERS AVAILABLE",
2723   "PROGRAM TOO LARGE",
2724 };
2725
2726 void a2controller_crash(apple2_sim_t *sim, int *stepno,
2727                         double *next_actiontime)
2728 {
2729   apple2_state_t *st=sim->st;
2730   char *s;
2731   int i;
2732
2733   struct mydata {
2734     int fillptr;
2735     int fillbyte;
2736   } *mine;
2737
2738   if (!sim->controller_data)
2739     sim->controller_data = calloc(sizeof(struct mydata),1);
2740   mine=(struct mydata *) sim->controller_data;
2741   
2742   switch(*stepno) {
2743   case 0:
2744     
2745     a2_init_memory_active(sim);
2746     sim->dec->powerup = 1000.0;
2747
2748     if (random()%3==0) {
2749       st->gr_mode=0;
2750       *next_actiontime+=0.4;
2751       *stepno=100;
2752     }
2753     else if (random()%4==0) {
2754       st->gr_mode=A2_GR_LORES;
2755       if (random()%3==0) st->gr_mode |= A2_GR_FULL;
2756       *next_actiontime+=0.4;
2757       *stepno=100;
2758     }
2759     else if (random()%2==0) {
2760       st->gr_mode=A2_GR_HIRES;
2761       *stepno=300;
2762     }
2763     else {
2764       st->gr_mode=A2_GR_HIRES;
2765       *next_actiontime+=0.4;
2766       *stepno=100;
2767     }
2768     break;
2769
2770   case 100:
2771     /* An illegal instruction or a reset caused it to drop into the
2772        assembly language monitor, where you could disassemble code & view
2773        data in hex. */
2774     if (random()%3==0) {
2775       char ibytes[128];
2776       char itext[128];
2777       int addr=0xd000+random()%0x3000;
2778       sprintf(ibytes,
2779               "%02X",random()%0xff);
2780       sprintf(itext,
2781               "???");
2782       sprintf(sim->printing_buf,
2783               "\n\n"
2784               "%04X: %-15s %s\n"
2785               " A=%02X X=%02X Y=%02X S=%02X F=%02X\n"
2786               "*",
2787               addr,ibytes,itext,
2788               random()%0xff, random()%0xff,
2789               random()%0xff, random()%0xff,
2790               random()%0xff);
2791       sim->printing=sim->printing_buf;
2792       a2_goto(st,23,1);
2793       if (st->gr_mode) {
2794         *stepno=180;
2795       } else {
2796         *stepno=200;
2797       }
2798       sim->prompt='*';
2799       *next_actiontime += 2.0 + (random()%1000)*0.0002;
2800     }
2801     else {
2802       /* Lots of programs had at least their main functionality in
2803          Applesoft Basic, which had a lot of limits (memory, string
2804          length, etc) and would sometimes crash unexpectedly. */
2805       sprintf(sim->printing_buf,
2806               "\n"
2807               "\n"
2808               "\n"
2809               "?%s IN %d\n"
2810               "\001]",
2811               apple2_basic_errors[random() %
2812                                   (sizeof(apple2_basic_errors)
2813                                    /sizeof(char *))],
2814               (1000*(random()%(random()%59+1)) +
2815                100*(random()%(random()%9+1)) +
2816                5*(random()%(random()%199+1)) +
2817                1*(random()%(random()%(random()%2+1)+1))));
2818       sim->printing=sim->printing_buf;
2819       a2_goto(st,23,1);
2820       *stepno=110;
2821       sim->prompt=']';
2822       *next_actiontime += 2.0 + (random()%1000)*0.0002;
2823     }
2824     break;
2825
2826   case 110:
2827     if (random()%3==0) {
2828       /* This was how you reset the Basic interpreter. The sort of
2829          incantation you'd have on a little piece of paper taped to the
2830          side of your machine */
2831       sim->typing="CALL -1370";
2832       *stepno=120;
2833     }
2834     else if (random()%2==0) {
2835       sim->typing="CATALOG\n";
2836       *stepno=170;
2837     }
2838     else {
2839       *next_actiontime+=1.0;
2840       *stepno=999;
2841     }
2842     break;
2843
2844   case 120:
2845     *stepno=130;
2846     *next_actiontime += 0.5;
2847     break;
2848
2849   case 130:
2850     st->gr_mode=0;
2851     a2_cls(st);
2852     a2_goto(st,0,16);
2853     for (s="APPLE ]["; *s; s++) a2_printc(st,*s);
2854     a2_goto(st,23,0);
2855     a2_printc(st,']');
2856     *next_actiontime+=1.0;
2857     *stepno=999;
2858     break;
2859
2860   case 170:
2861     if (random()%50==0) {
2862       sprintf(sim->printing_buf,
2863               "\nDISK VOLUME 254\n\n"
2864               " A 002 HELLO\n"
2865               "\n"
2866               "]");
2867       sim->printing=sim->printing_buf;
2868     }
2869     else {
2870       sprintf(sim->printing_buf,"\n?%s\n]",
2871               apple2_dos_errors[random()%
2872                                 (sizeof(apple2_dos_errors) /
2873                                  sizeof(char *))]);
2874       sim->printing=sim->printing_buf;
2875     }
2876     *stepno=999;
2877     *next_actiontime+=1.0;
2878     break;
2879
2880   case 180:
2881     if (random()%2==0) {
2882       /* This was how you went back to text mode in the monitor */
2883       sim->typing="FB4BG";
2884       *stepno=190;
2885     } else {
2886       *next_actiontime+=1.0;
2887       *stepno=999;
2888     }
2889     break;
2890
2891   case 190:
2892     st->gr_mode=0;
2893     a2_invalidate(st);
2894     a2_printc(st,'\n');
2895     a2_printc(st,'*');
2896     *stepno=200;
2897     *next_actiontime+=2.0;
2898     break;
2899
2900   case 200:
2901     /* This reset things into Basic */
2902     if (random()%2==0) {
2903       sim->typing="FAA6G";
2904       *stepno=120;
2905     }
2906     else {
2907       *stepno=999;
2908       *next_actiontime+=sim->delay;
2909     }
2910     break;
2911
2912   case 300:
2913     for (i=0; i<1500; i++) {
2914       a2_poke(st, mine->fillptr, mine->fillbyte);
2915       mine->fillptr++;
2916       mine->fillbyte = (mine->fillbyte+1)&0xff;
2917     }
2918     *next_actiontime += 0.08;
2919     /* When you hit c000, it changed video settings */
2920     if (mine->fillptr>=0xc000) {
2921       a2_invalidate(st);
2922       st->gr_mode=0;
2923     }
2924     /* And it seemed to reset around here, I dunno why */
2925     if (mine->fillptr>=0xcf00) *stepno=130;
2926     break;
2927
2928   case 999:
2929     break;
2930
2931   case A2CONTROLLER_FREE:
2932     free(mine);
2933     break;
2934   }
2935 }
2936
2937 static void
2938 apple2crash (Display* dpy, Window window, int delay)
2939 {
2940   apple2 (dpy, window, delay, a2controller_crash);
2941 }
2942
2943 char *progclass = "BSOD";
2944
2945 char *defaults [] = {
2946   "*delay:                 30",
2947
2948   "*doOnly:                ",
2949   "*doWindows:             True",
2950   "*doNT:                  True",
2951   "*doWin2K:               True",
2952   "*doAmiga:               True",
2953   "*doMac:                 True",
2954   "*doMacsBug:             True",
2955   "*doMac1:                True",
2956   "*doMacX:                True",
2957   "*doSCO:                 True",
2958   "*doAtari:               False",      /* boring */
2959   "*doBSD:                 False",      /* boring */
2960   "*doLinux:               True",
2961   "*doSparcLinux:          False",      /* boring */
2962   "*doBlitDamage:          True",
2963   "*doSolaris:             True",
2964   "*doHPUX:                True",
2965   "*doApple2:              True",
2966   "*doOS390:               True",
2967   "*doVMS:                 True",
2968   "*doHVX:                 True",
2969
2970   ".Windows.font:          -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
2971   ".Windows.font2:         -*-courier-bold-r-*-*-*-180-*-*-m-*-*-*",
2972   ".Windows.foreground:    White",
2973   ".Windows.background:    #0000AA",    /* EGA color 0x01. */
2974
2975   ".Amiga.font:            -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
2976   ".Amiga.font2:           -*-courier-bold-r-*-*-*-180-*-*-m-*-*-*",
2977   ".Amiga.foreground:      Red",
2978   ".Amiga.background:      Black",
2979   ".Amiga.background2:     White",
2980
2981   ".Mac.font:              -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
2982   ".Mac.foreground:        PaleTurquoise1",
2983   ".Mac.background:        Black",
2984
2985   ".Atari.foreground:      Black",
2986   ".Atari.background:      White",
2987
2988   ".MacsBug.font:          -*-courier-medium-r-*-*-*-100-*-*-m-*-*-*",
2989   ".MacsBug.font2:         -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
2990   ".MacsBug.font3:         -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
2991   ".MacsBug.foreground:    Black",
2992   ".MacsBug.background:    White",
2993   ".MacsBug.borderColor:   #AAAAAA",
2994
2995   ".mac1.foreground:       Black",
2996   ".mac1.background:       White",
2997
2998   ".macX.textForeground:   White",
2999   ".macX.textBackground:   Black",
3000   ".macX.background:       #888888",
3001   ".macX.font:             -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
3002   ".macX.font2:            -*-courier-bold-r-*-*-*-240-*-*-m-*-*-*",
3003
3004   ".SCO.font:              -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
3005   ".SCO.font2:             -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
3006   ".SCO.foreground:        White",
3007   ".SCO.background:        Black",
3008
3009   ".HVX.font:              -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
3010   ".HVX.font2:             -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
3011   ".HVX.foreground:        White",
3012   ".HVX.background:        Black",
3013
3014   ".Linux.font:            9x15bold",
3015   ".Linux.font2:           -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
3016   ".Linux.foreground:      White",
3017   ".Linux.background:      Black",
3018
3019   ".SparcLinux.font:       -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
3020   ".SparcLinux.font2:      -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
3021   ".SparcLinux.foreground: White",
3022   ".SparcLinux.background: Black",
3023
3024   ".BSD.font:              vga",
3025   ".BSD.font:              -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
3026   ".BSD.font2:             -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
3027 /* ".BSD.font2:            -sun-console-medium-r-*-*-22-*-*-*-m-*-*-*", */
3028   ".BSD.foreground:        #c0c0c0",
3029   ".BSD.background:        Black",
3030
3031   ".Solaris.font:          -sun-gallant-*-*-*-*-19-*-*-*-*-120-*-*",
3032   ".Solaris.font2:         -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
3033   ".Solaris.foreground:    Black",
3034   ".Solaris.background:    White",
3035   "*dontClearRoot:         True",
3036
3037   ".HPUX.font:             9x15bold",
3038   ".HPUX.font2:            -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
3039   ".HPUX.foreground:       White",
3040   ".HPUX.background:       Black",
3041
3042   ".OS390.font:            9x15bold",
3043   ".OS390.font2:           -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
3044   ".OS390.background:      Black",
3045   ".OS390.foreground:      Red",
3046
3047   "*apple2TVColor:         50",
3048   "*apple2TVTint:          5",
3049   "*apple2TVBrightness:    10",
3050   "*apple2TVContrast:      90",
3051   "*apple2SimulateUser:    True",
3052
3053   ".VMS.font:              9x15bold",
3054   ".VMS.font2:             -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
3055   ".VMS.foreground:        White",
3056   ".VMS.background:        Black",
3057
3058   ANALOGTV_DEFAULTS
3059
3060 #ifdef HAVE_XSHM_EXTENSION
3061   "*useSHM:                True",
3062 #endif
3063   0
3064 };
3065
3066 XrmOptionDescRec options [] = {
3067   { "-delay",           ".delay",               XrmoptionSepArg, 0 },
3068   { "-only",            ".doOnly",              XrmoptionSepArg, 0 },
3069   { "-windows",         ".doWindows",           XrmoptionNoArg,  "True"  },
3070   { "-no-windows",      ".doWindows",           XrmoptionNoArg,  "False" },
3071   { "-nt",              ".doNT",                XrmoptionNoArg,  "True"  },
3072   { "-no-nt",           ".doNT",                XrmoptionNoArg,  "False" },
3073   { "-2k",              ".doWin2K",             XrmoptionNoArg,  "True"  },
3074   { "-no-2k",           ".doWin2K",             XrmoptionNoArg,  "False" },
3075   { "-amiga",           ".doAmiga",             XrmoptionNoArg,  "True"  },
3076   { "-no-amiga",        ".doAmiga",             XrmoptionNoArg,  "False" },
3077   { "-mac",             ".doMac",               XrmoptionNoArg,  "True"  },
3078   { "-no-mac",          ".doMac",               XrmoptionNoArg,  "False" },
3079   { "-mac1",            ".doMac1",              XrmoptionNoArg,  "True"  },
3080   { "-no-mac1",         ".doMac1",              XrmoptionNoArg,  "False" },
3081   { "-macx",            ".doMacX",              XrmoptionNoArg,  "True"  },
3082   { "-no-macx",         ".doMacX",              XrmoptionNoArg,  "False" },
3083   { "-atari",           ".doAtari",             XrmoptionNoArg,  "True"  },
3084   { "-no-atari",        ".doAtari",             XrmoptionNoArg,  "False" },
3085   { "-macsbug",         ".doMacsBug",           XrmoptionNoArg,  "True"  },
3086   { "-no-macsbug",      ".doMacsBug",           XrmoptionNoArg,  "False" },
3087   { "-apple2",          ".doApple2",            XrmoptionNoArg,  "True"  },
3088   { "-no-apple2",       ".doApple2",            XrmoptionNoArg,  "False" },
3089   { "-sco",             ".doSCO",               XrmoptionNoArg,  "True"  },
3090   { "-no-sco",          ".doSCO",               XrmoptionNoArg,  "False" },
3091   { "-hvx",             ".doHVX",               XrmoptionNoArg,  "True"  },
3092   { "-no-hvx",          ".doHVX",               XrmoptionNoArg,  "False" },
3093   { "-bsd",             ".doBSD",               XrmoptionNoArg,  "True"  },
3094   { "-no-bsd",          ".doBSD",               XrmoptionNoArg,  "False" },
3095   { "-linux",           ".doLinux",             XrmoptionNoArg,  "True"  },
3096   { "-no-linux",        ".doLinux",             XrmoptionNoArg,  "False" },
3097   { "-sparclinux",      ".doSparcLinux",        XrmoptionNoArg,  "True"  },
3098   { "-no-sparclinux",   ".doSparcLinux",        XrmoptionNoArg,  "False" },
3099   { "-blitdamage",      ".doBlitDamage",        XrmoptionNoArg,  "True"  },
3100   { "-no-blitdamage",   ".doBlitDamage",        XrmoptionNoArg,  "False" },
3101   { "-solaris",         ".doSolaris",           XrmoptionNoArg,  "True"  },
3102   { "-no-solaris",      ".doSolaris",           XrmoptionNoArg,  "False" },
3103   { "-hpux",            ".doHPUX",              XrmoptionNoArg,  "True"  },
3104   { "-no-hpux",         ".doHPUX",              XrmoptionNoArg,  "False" },
3105   { "-os390",           ".doOS390",             XrmoptionNoArg,  "True"  },
3106   { "-no-os390",        ".doOS390",             XrmoptionNoArg,  "False" },
3107   { "-vms",             ".doVMS",               XrmoptionNoArg,  "True"  },
3108   { "-no-vms",          ".doVMS",               XrmoptionNoArg,  "False" },
3109   ANALOGTV_OPTIONS
3110   { 0, 0, 0, 0 }
3111 };
3112
3113
3114 static struct {
3115   const char *name;
3116   void (*fn) (Display *, Window, int delay);
3117 } all_modes[] = {
3118   { "Windows",          windows_31 },
3119   { "NT",              windows_nt },
3120   { "Win2K",           windows_2k },
3121   { "Amiga",            amiga },
3122   { "Mac",              mac },
3123   { "MacsBug",          macsbug },
3124   { "Mac1",             mac1 },
3125   { "MacX",             macx },
3126   { "SCO",              sco },
3127   { "HVX",              hvx },
3128   { "SparcLinux",       sparc_linux },
3129   { "BSD",              bsd },
3130   { "Atari",            atari },
3131   { "BlitDamage",       blitdamage },
3132   { "Solaris",          sparc_solaris },
3133   { "Linux",            linux_fsck },
3134   { "HPUX",             hpux },
3135   { "OS390",            os390 },
3136   { "Apple2",           apple2crash },
3137   { "VMS",              vms },
3138 };
3139
3140
3141 void
3142 screenhack (Display *dpy, Window window)
3143 {
3144   int loop = 0;
3145   int i = -1;
3146   int j = -1;
3147   int only = -1;
3148   int delay = get_integer_resource ("delay", "Integer");
3149   if (delay < 3) delay = 3;
3150
3151   {
3152     char *s = get_string_resource("doOnly", "DoOnly");
3153     if (s && *s)
3154       {
3155         int count = countof(all_modes);
3156         for (only = 0; only < count; only++)
3157           if (!strcasecmp (s, all_modes[only].name))
3158             break;
3159         if (only >= count)
3160           {
3161             fprintf (stderr, "%s: unknown -only mode: \"%s\"\n", progname, s);
3162             only = -1;
3163           }
3164       }
3165     if (s) free (s);
3166   }
3167
3168   if (!get_boolean_resource ("root", "Boolean"))
3169     {
3170       XWindowAttributes xgwa;
3171       XGetWindowAttributes (dpy, window, &xgwa);
3172       XSelectInput (dpy, window,
3173                     xgwa.your_event_mask |
3174                     KeyPressMask | ButtonPressMask | ExposureMask);
3175     }
3176
3177   while (1)
3178     {
3179       Bool did;
3180       int count = countof(all_modes);
3181       char name[100], class[100];
3182
3183       if (only > 0)
3184         i = only;
3185       else
3186         do {  i = (random() & 0xFF) % count; } while (i == j);
3187
3188       sprintf (name,  "do%s", all_modes[i].name);
3189       sprintf (class, "Do%s", all_modes[i].name);
3190
3191       did = False;
3192       if (only > 0 || get_boolean_resource(name, class))
3193         {
3194           all_modes[i].fn (dpy, window, delay);
3195           did = True;
3196         }
3197
3198       loop++;
3199       if (loop > 100) j = -1;
3200       if (loop > 200)
3201         {
3202           fprintf (stderr, "%s: no display modes enabled?\n", progname);
3203           exit(-1);
3204         }
3205       if (!did) continue;
3206       XSync (dpy, False);
3207       j = i;
3208       loop = 0;
3209     }
3210 }