X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?p=xscreensaver;a=blobdiff_plain;f=hacks%2Fbsod.c;h=a38f151fe54d986ce6f9c7c364daaa7b1d367e4b;hp=bbbc2ca29b011d4ac3b1fb2b22d88822b6e9d8c7;hb=c494fd2e6b3b25582375d62e40f4f5cc984ca424;hpb=df7adbee81405e2849728a24b498ad2117784b1f diff --git a/hacks/bsod.c b/hacks/bsod.c index bbbc2ca2..a38f151f 100644 --- a/hacks/bsod.c +++ b/hacks/bsod.c @@ -1,4 +1,4 @@ -/* xscreensaver, Copyright (c) 1998 Jamie Zawinski +/* xscreensaver, Copyright (c) 1998-2006 Jamie Zawinski * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that @@ -11,120 +11,715 @@ * Blue Screen of Death: the finest in personal computer emulation. * Concept cribbed from Stephen Martin ; * this version written by jwz, 4-Jun-98. - * - * TODO: - * - Should simulate a Unix kernel panic and reboot. - * - Making various boot noises would be fun, too. - * - Maybe scatter some random bits across the screen, - * to simulate corruption of video ram? - * - Should randomize the various hex numbers printed. + * Mostly rewritten by jwz, 20-Feb-2006. + */ + + +/* To add a new mode: + + - Define a function `new_os(dpy,win)' that returns a `bsod_state' struct. + - Draw on the window to set up its frame-zero state. This must be fast: + no sleeping or long loops! + - Populate the bsod_state structure with additional actions to take by + using the various BSOD_ macros. Note that you can control the delays + when printing text on a per-character or per-line basis. + - Insert your function in the `all_modes' table. + - Add a `doXXX' entry to `bsod_defaults'. + - Add fonts or colors to `bsod_defaults' if necessary. + + Look at windows_31() for a simple example. + + Look at linux_fsck() for a more complicated example with random behavior. + + Or, you can bypass all that: look at nvidia() for a really hairy example. */ + #include "screenhack.h" -#include -#include +#include "xpm-pixmap.h" +#include "apple2.h" -#ifdef HAVE_XPM -# include -# include "images/amiga.xpm" +#include + +#ifdef HAVE_XSHM_EXTENSION +#include "xshm.h" +#endif + +#ifdef HAVE_UNAME +# include +#endif /* HAVE_UNAME */ + +#if defined(HAVE_GDK_PIXBUF) || defined(HAVE_XPM) || defined(HAVE_COCOA) +# define DO_XPM #endif +#ifdef DO_XPM +# include "images/amiga.xpm" +# include "images/hmac.xpm" +# include "images/osx_10_2.xpm" +# include "images/osx_10_3.xpm" +#endif #include "images/atari.xbm" #include "images/mac.xbm" +#include "images/macbomb.xbm" + +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#undef EOF +typedef enum { EOF=0, + LEFT, CENTER, RIGHT, + LEFT_FULL, CENTER_FULL, RIGHT_FULL, + COLOR, INVERT, MOVETO, MARGINS, + CURSOR_BLOCK, CURSOR_LINE, RECT, COPY, PIXMAP, IMG, + PAUSE, CHAR_DELAY, LINE_DELAY, + LOOP +} bsod_event_type; + +struct bsod_event { + bsod_event_type type; + void *arg1, *arg2, *arg3, *arg4, *arg5, *arg6; +}; + +struct bsod_state { + Display *dpy; + Window window; + XWindowAttributes xgwa; + XFontStruct *font; + unsigned long fg, bg; + GC gc; + int left_margin, right_margin; /* for text wrapping */ + int top_margin, bottom_margin; /* for text scrolling */ + Bool wrap_p; + Bool scroll_p; + + Pixmap pixmap; /* Source image used by BSOD_PIXMAP */ + + int x, y; /* current text-drawing position */ + int current_left; /* don't use this */ + + int pos; /* position in queue */ + int queue_size; + struct bsod_event *queue; + + unsigned long char_delay; /* delay between printing characters */ + unsigned long line_delay; /* delay between printing lines */ + + Bool macx_eol_kludge; + + void *closure; + int (*draw_cb) (struct bsod_state *); + void (*free_cb) (struct bsod_state *); + + async_load_state *img_loader; +}; + + +# if !defined(__GNUC__) && !defined(__extension__) + /* don't warn about "string length is greater than the length ISO C89 + compilers are required to support" in these string constants... */ +# define __extension__ /**/ +# endif + + +/* Draw text at the current position; align is LEFT, CENTER, RIGHT, or *_FULL + (meaning to clear the whole line margin to margin). + */ +#define BSOD_TEXT(bst,align,string) do { \ + ensure_queue (bst); \ + (bst)->queue[(bst)->pos].type = (align); \ + (bst)->queue[(bst)->pos].arg1 = (void *) strdup (__extension__ (string)); \ + (bst)->queue[(bst)->pos].arg2 = (bst)->queue[(bst)->pos].arg1; \ + (bst)->queue[(bst)->pos].arg3 = (void *) 0; \ + (bst)->pos++; \ + } while (0) + +/* Flip the foreground and background colors + */ +#define BSOD_INVERT(bst) do { \ + ensure_queue (bst); \ + (bst)->queue[(bst)->pos].type = INVERT; \ + (bst)->pos++; \ + } while (0) + +/* Set the foreground and background colors to the given pixels + */ +#define BSOD_COLOR(bst,fg,bg) do { \ + ensure_queue (bst); \ + (bst)->queue[(bst)->pos].type = COLOR; \ + (bst)->queue[(bst)->pos].arg1 = (void *) fg; \ + (bst)->queue[(bst)->pos].arg2 = (void *) bg; \ + (bst)->pos++; \ + } while (0) + +/* Set the position of the next text. + Note that this is the baseline: lower left corner of next char printed. + */ +#define BSOD_MOVETO(bst,x,y) do { \ + ensure_queue (bst); \ + (bst)->queue[(bst)->pos].type = MOVETO; \ + (bst)->queue[(bst)->pos].arg1 = (void *) ((long) (x)); \ + (bst)->queue[(bst)->pos].arg2 = (void *) ((long) (y)); \ + (bst)->pos++; \ + } while (0) + +/* Delay for at least the given number of microseconds. + */ +#define BSOD_PAUSE(bst,usec) do { \ + ensure_queue (bst); \ + (bst)->queue[(bst)->pos].type = PAUSE; \ + (bst)->queue[(bst)->pos].arg1 = (void *) ((long) (usec)); \ + (bst)->pos++; \ + } while (0) + +/* Set the delay after each character is printed. + */ +#define BSOD_CHAR_DELAY(bst,usec) do { \ + ensure_queue (bst); \ + (bst)->queue[(bst)->pos].type = CHAR_DELAY; \ + (bst)->queue[(bst)->pos].arg1 = (void *) ((long) (usec)); \ + (bst)->pos++; \ + } while (0) + +/* Set the delay after each newline. + */ +#define BSOD_LINE_DELAY(bst,usec) do { \ + ensure_queue (bst); \ + (bst)->queue[(bst)->pos].type = LINE_DELAY; \ + (bst)->queue[(bst)->pos].arg1 = (void *) (usec); \ + (bst)->pos++; \ + } while (0) + +/* Set the prevailing left/right margins (used when strings have + embedded newlines, and when centering or right-justifying text.) + */ +#define BSOD_MARGINS(bst,left,right) do { \ + ensure_queue (bst); \ + (bst)->queue[(bst)->pos].type = MARGINS; \ + (bst)->queue[(bst)->pos].arg1 = (void *) ((long) (left)); \ + (bst)->queue[(bst)->pos].arg2 = (void *) ((long) (right)); \ + (bst)->pos++; \ + } while (0) + +/* Draw a blinking cursor; type is CURSOR_BLOCK or CURSOR_LINE. + usec is how long 1/2 of a cycle is. count is how many times to blink. + (You can pass a gigantic number if this is the last thing in your mode.) + */ +#define BSOD_CURSOR(bst,ctype,usec,count) do { \ + ensure_queue (bst); \ + (bst)->queue[(bst)->pos].type = (ctype); \ + (bst)->queue[(bst)->pos].arg1 = (void *) (usec); \ + (bst)->queue[(bst)->pos].arg2 = (void *) (count); \ + (bst)->pos++; \ + } while (0) + +/* Draw or fill a rectangle. You can set line-width in the GC. + */ +#define BSOD_RECT(bst,fill,x,y,w,h) do { \ + ensure_queue (bst); \ + (bst)->queue[(bst)->pos].type = RECT; \ + (bst)->queue[(bst)->pos].arg1 = (void *) ((long) (fill)); \ + (bst)->queue[(bst)->pos].arg2 = (void *) ((long) (x)); \ + (bst)->queue[(bst)->pos].arg3 = (void *) ((long) (y)); \ + (bst)->queue[(bst)->pos].arg4 = (void *) ((long) (w)); \ + (bst)->queue[(bst)->pos].arg5 = (void *) ((long) (h)); \ + (bst)->pos++; \ + } while (0) + +/* Copy a rect from the window, to the window. + */ +#define BSOD_COPY(bst,srcx,srcy,w,h,tox,toy) do { \ + ensure_queue (bst); \ + (bst)->queue[(bst)->pos].type = COPY; \ + (bst)->queue[(bst)->pos].arg1 = (void *) ((long) (srcx)); \ + (bst)->queue[(bst)->pos].arg2 = (void *) ((long) (srcy)); \ + (bst)->queue[(bst)->pos].arg3 = (void *) ((long) (w)); \ + (bst)->queue[(bst)->pos].arg4 = (void *) ((long) (h)); \ + (bst)->queue[(bst)->pos].arg5 = (void *) ((long) (tox)); \ + (bst)->queue[(bst)->pos].arg6 = (void *) ((long) (toy)); \ + (bst)->pos++; \ + } while (0) + +/* Copy a rect from bst->pixmap to the window. + */ +#define BSOD_PIXMAP(bst,srcx,srcy,w,h,tox,toy) do { \ + BSOD_COPY(bst,srcx,srcy,w,h,tox,toy); \ + (bst)->queue[(bst)->pos-1].type = PIXMAP; \ + } while (0) + +/* Load a random image (or the desktop) onto the window. + */ +#define BSOD_IMG(bst) do { \ + ensure_queue (bst); \ + (bst)->queue[(bst)->pos].type = IMG; \ + (bst)->pos++; \ + } while (0) + +/* Jump around in the state table. You can use this as the last thing + in your state table to repeat the last N elements forever. + */ +#define BSOD_LOOP(bst,off) do { \ + ensure_queue (bst); \ + (bst)->queue[(bst)->pos].type = LOOP; \ + (bst)->queue[(bst)->pos].arg1 = (void *) (off); \ + (bst)->pos++; \ + } while (0) static void -draw_string (Display *dpy, Window window, GC gc, XGCValues *gcv, - XFontStruct *font, - int xoff, int yoff, - int win_width, int win_height, - const char *string, int delay) +ensure_queue (struct bsod_state *bst) { - int x, y; - int width = 0, height = 0, cw = 0; - int char_width, line_height; + int n; + if (bst->pos + 1 < bst->queue_size) + return; + + n = bst->queue_size + 10; + if (n < 100) n *= 2; + n *= 1.2; + + bst->queue = (struct bsod_event *) + realloc (bst->queue, n * sizeof(*bst->queue)); + if (!bst->queue) abort(); + memset (bst->queue + bst->queue_size, 0, + (n - bst->queue_size) * sizeof(*bst->queue)); + bst->queue_size = n; +} + + +static void +position_for_text (struct bsod_state *bst, const char *line) +{ + int max_width = 0; + + const char *start = line; + + if (bst->queue[bst->pos].type != LEFT && + bst->queue[bst->pos].type != LEFT_FULL) + while (*start) + { + int dir, ascent, descent; + XCharStruct ov; + const char *end = start; + while (*end && *end != '\r' && *end != '\n') + end++; + + XTextExtents (bst->font, start, end-start, + &dir, &ascent, &descent, &ov); + if (ov.width > max_width) + max_width = ov.width; + if (!*end) break; + start = end+1; + } + + switch (bst->queue[bst->pos].type) { + case LEFT: + case LEFT_FULL: + bst->current_left = bst->left_margin; + break; + case RIGHT: + case RIGHT_FULL: + bst->x = max_width - bst->right_margin; + bst->current_left = bst->x; + break; + case CENTER: + case CENTER_FULL: + { + int w = (bst->xgwa.width - bst->left_margin - bst->right_margin - + max_width); + if (w < 0) w = 0; + bst->x = bst->left_margin + (w / 2); + bst->current_left = bst->x; + break; + } + default: + abort(); + } +} + + +static void +bst_crlf (struct bsod_state *bst) +{ + int lh = bst->font->ascent + bst->font->descent; + bst->x = bst->current_left; + if (!bst->scroll_p || + bst->y + lh < bst->xgwa.height - bst->bottom_margin) + bst->y += lh; + else + { + int w = bst->xgwa.width - bst->right_margin - bst->left_margin; + int h = bst->xgwa.height - bst->top_margin - bst->bottom_margin; + XCopyArea (bst->dpy, bst->window, bst->window, bst->gc, + bst->left_margin, + bst->top_margin + lh, + w, h - lh, + bst->left_margin, + bst->top_margin); + XClearArea (bst->dpy, bst->window, + bst->left_margin, bst->top_margin + h - lh, w, lh, False); + } +} + + +static void +draw_char (struct bsod_state *bst, char c) +{ + if (!c) + abort(); + else if (c == '\r') + { + bst->x = bst->current_left; + } + else if (c == '\n') + { + if (bst->macx_eol_kludge) + { + /* Special case for the weird way OSX crashes print newlines... */ + XDrawImageString (bst->dpy, bst->window, bst->gc, + bst->x, bst->y, " ", 1); + XDrawImageString (bst->dpy, bst->window, bst->gc, + bst->x, + bst->y + bst->font->ascent + bst->font->descent, + " ", 1); + } + bst_crlf (bst); + } + else if (c == '\b') /* backspace */ + { + int cw = (bst->font->per_char + ? bst->font->per_char['n'-bst->font->min_char_or_byte2].width + : bst->font->min_bounds.width); + bst->x -= cw; + if (bst->x < bst->left_margin) + bst->x = bst->left_margin; + } + else + { + int dir, ascent, descent; + XCharStruct ov; + XTextExtents (bst->font, &c, 1, &dir, &ascent, &descent, &ov); + + if (bst->wrap_p && + bst->x + ov.width > bst->xgwa.width - bst->right_margin) + bst_crlf (bst); + + XDrawImageString (bst->dpy, bst->window, bst->gc, + bst->x, bst->y, &c, 1); + bst->x += ov.width; + } +} + + +static long +bsod_pop (struct bsod_state *bst) +{ + bsod_event_type type = bst->queue[bst->pos].type; + + if (bst->draw_cb) + return bst->draw_cb (bst); - const char *s = string; - const char *se = string; + if (bst->pos < 0) /* already done */ + abort(); - /* This pretty much assumes fixed-width fonts */ - char_width = (font->per_char - ? font->per_char['n'-font->min_char_or_byte2].width - : font->min_bounds.width); - line_height = font->ascent + font->descent + 1; + switch (type) { - while (1) + case LEFT: case LEFT_FULL: + case CENTER: case CENTER_FULL: + case RIGHT: case RIGHT_FULL: { - if (*s == '\n' || !*s) - { - height++; - if (cw > width) width = cw; - cw = 0; - if (!*s) break; - } + const char *s = (const char *) bst->queue[bst->pos].arg2; + char c; + + if (! *s) + { + long delay = bst->line_delay; + bst->pos++; + bst->current_left = bst->left_margin; + return delay; + } + + if (! bst->queue[bst->pos].arg3) /* "done once" */ + { + position_for_text (bst, s); + bst->queue[bst->pos].type = LEFT; + + if (type == CENTER_FULL || + type == LEFT_FULL || + type == RIGHT_FULL) + { + XSetForeground (bst->dpy, bst->gc, bst->bg); + XFillRectangle (bst->dpy, bst->window, bst->gc, + 0, + bst->y - bst->font->ascent, + bst->xgwa.width, + bst->font->ascent + bst->font->descent); + XSetForeground (bst->dpy, bst->gc, bst->fg); + } + } + + c = *s++; + draw_char (bst, c); + bst->queue[bst->pos].arg2 = (void *) s; + bst->queue[bst->pos].arg3 = (void *) 1; /* "done once" */ + + return (c == '\r' || c == '\n' + ? bst->line_delay + : bst->char_delay); + } + case INVERT: + { + unsigned long swap = bst->fg; + bst->fg = bst->bg; + bst->bg = swap; + XSetForeground (bst->dpy, bst->gc, bst->fg); + XSetBackground (bst->dpy, bst->gc, bst->bg); + bst->pos++; + return 0; + } + case COLOR: + { + bst->fg = (unsigned long) bst->queue[bst->pos].arg1; + bst->bg = (unsigned long) bst->queue[bst->pos].arg2; + XSetForeground (bst->dpy, bst->gc, bst->fg); + XSetBackground (bst->dpy, bst->gc, bst->bg); + bst->pos++; + return 0; + } + case MOVETO: + { + bst->x = (long) bst->queue[bst->pos].arg1; + bst->y = (long) bst->queue[bst->pos].arg2; + bst->pos++; + return 0; + } + case RECT: + { + int f = (long) bst->queue[bst->pos].arg1; + int x = (long) bst->queue[bst->pos].arg2; + int y = (long) bst->queue[bst->pos].arg3; + int w = (long) bst->queue[bst->pos].arg4; + int h = (long) bst->queue[bst->pos].arg5; + if (f) + XFillRectangle (bst->dpy, bst->window, bst->gc, x, y, w, h); else - cw++; - s++; + XDrawRectangle (bst->dpy, bst->window, bst->gc, x, y, w, h); + bst->pos++; + return 0; + } + case COPY: + case PIXMAP: + { + int srcx = (long) bst->queue[bst->pos].arg1; + int srcy = (long) bst->queue[bst->pos].arg2; + int w = (long) bst->queue[bst->pos].arg3; + int h = (long) bst->queue[bst->pos].arg4; + int tox = (long) bst->queue[bst->pos].arg5; + int toy = (long) bst->queue[bst->pos].arg6; + XCopyArea (bst->dpy, + (type == PIXMAP ? bst->pixmap : bst->window), + bst->window, bst->gc, + srcx, srcy, w, h, tox, toy); + bst->pos++; + return 0; + } + case IMG: + { + if (bst->img_loader) abort(); + bst->img_loader = load_image_async_simple (0, bst->xgwa.screen, + bst->window, bst->window, + 0, 0); + bst->pos++; + return 0; + } + case PAUSE: + { + long delay = (long) bst->queue[bst->pos].arg1; + bst->pos++; + return delay; + } + case CHAR_DELAY: + { + bst->char_delay = (long) bst->queue[bst->pos].arg1; + bst->pos++; + return 0; + } + case LINE_DELAY: + { + bst->line_delay = (long) bst->queue[bst->pos].arg1; + bst->pos++; + return 0; + } + case MARGINS: + { + bst->left_margin = (long) bst->queue[bst->pos].arg1; + bst->right_margin = (long) bst->queue[bst->pos].arg2; + bst->pos++; + return 0; } + case CURSOR_BLOCK: + case CURSOR_LINE: + { + long delay = (long) bst->queue[bst->pos].arg1; + long count = (long) bst->queue[bst->pos].arg2; + int ox = bst->x; - x = (win_width - (width * char_width)) / 2; - y = (win_height - (height * line_height)) / 2; + if (type == CURSOR_BLOCK) + { + unsigned long swap = bst->fg; + bst->fg = bst->bg; + bst->bg = swap; + XSetForeground (bst->dpy, bst->gc, bst->fg); + XSetBackground (bst->dpy, bst->gc, bst->bg); + draw_char (bst, ' '); + } + else + { + draw_char (bst, (count & 1 ? ' ' : '_')); + draw_char (bst, ' '); + } + + bst->x = ox; - if (x < 0) x = 2; - if (y < 0) y = 2; + count--; + bst->queue[bst->pos].arg2 = (void *) count; + if (count <= 0) + bst->pos++; + + return delay; + } + case LOOP: + { + long off = (long) bst->queue[bst->pos].arg1; + bst->pos += off; + if (bst->pos < 0 || bst->pos >= bst->queue_size) + abort(); + return 0; + } + case EOF: + { + bst->pos = -1; + return -1; + } + default: + break; + } + abort(); +} - x += xoff; - y += yoff; - se = s = string; - while (1) +static struct bsod_state * +make_bsod_state (Display *dpy, Window window, + const char *name, const char *class) +{ + XGCValues gcv; + struct bsod_state *bst; + char buf1[1024], buf2[1024]; + char buf3[1024], buf4[1024]; + const char *font1, *font2; + + bst = (struct bsod_state *) calloc (1, sizeof (*bst)); + bst->queue_size = 10; + bst->queue = (struct bsod_event *) calloc (bst->queue_size, + sizeof (*bst->queue)); + bst->dpy = dpy; + bst->window = window; + XGetWindowAttributes (dpy, window, &bst->xgwa); + + /* If the window is small: + use ".font" if it is loadable, else use ".font2". + + If the window is big: + use ".bigFont" if it is loadable, else use ".bigFont2". + */ + if (bst->xgwa.height < 640) { - if (*s == '\n' || !*s) - { - int off = 0; - Bool flip = False; - - if (*se == '@' || *se == '_') - { - if (*se == '@') flip = True; - se++; - off = (char_width * (width - (s - se))) / 2; - } - - if (flip) - { - XSetForeground(dpy, gc, gcv->background); - XSetBackground(dpy, gc, gcv->foreground); - } - - if (s != se) - XDrawImageString(dpy, window, gc, x+off, y+font->ascent, se, s-se); - - if (flip) - { - XSetForeground(dpy, gc, gcv->foreground); - XSetBackground(dpy, gc, gcv->background); - } - - se = s; - y += line_height; - if (!*s) break; - se = s+1; - - if (delay) - { - XSync(dpy, False); - usleep(delay); - } - } - s++; + sprintf (buf1, "%.100s.font", name); + sprintf (buf2, "%.100s.font", class); + sprintf (buf3, "%.100s.font2", name); + sprintf (buf4, "%.100s.font2", class); } + else + { + sprintf (buf1, "%.100s.bigFont", name); + sprintf (buf2, "%.100s.bigFont", class); + sprintf (buf3, "%.100s.bigFont2", name); + sprintf (buf4, "%.100s.bigFont2", class); + } + + font1 = get_string_resource (dpy, buf1, buf2); + font2 = get_string_resource (dpy, buf3, buf4); + + if (font1) + bst->font = XLoadQueryFont (dpy, font1); + if (! bst->font && font2) + bst->font = XLoadQueryFont (dpy, font2); + + /* If neither of those worked, try some defaults. */ + + if (! bst->font) + bst->font = XLoadQueryFont (dpy,"-*-courier-bold-r-*-*-*-120-*-*-m-*-*-*"); + if (! bst->font) + bst->font = XLoadQueryFont (dpy, "fixed"); + if (! bst->font) + abort(); + + gcv.font = bst->font->fid; + + sprintf (buf1, "%.100s.foreground", name); + sprintf (buf2, "%.100s.Foreground", class); + bst->fg = gcv.foreground = get_pixel_resource (dpy, bst->xgwa.colormap, + buf1, buf2); + sprintf (buf1, "%.100s.background", name); + sprintf (buf2, "%.100s.Background", class); + bst->bg = gcv.background = get_pixel_resource (dpy, bst->xgwa.colormap, + buf1, buf2); + bst->gc = XCreateGC (dpy, window, GCFont|GCForeground|GCBackground, &gcv); + +#ifdef HAVE_COCOA + jwxyz_XSetAntiAliasing (dpy, bst->gc, False); +#endif + + bst->left_margin = bst->right_margin = 10; + bst->x = bst->left_margin; + bst->y = bst->font->ascent + bst->left_margin; + + XSetWindowBackground (dpy, window, gcv.background); + return bst; +} + + +static void +free_bsod_state (struct bsod_state *bst) +{ + int i; + + if (bst->free_cb) + bst->free_cb (bst); + if (bst->pixmap) + XFreePixmap(bst->dpy, bst->pixmap); + + XFreeFont (bst->dpy, bst->font); + XFreeGC (bst->dpy, bst->gc); + + for (i = 0; i < bst->queue_size; i++) + switch (bst->queue[i].type) { + case LEFT: case LEFT_FULL: + case RIGHT: case RIGHT_FULL: + case CENTER: case CENTER_FULL: + free ((char *) bst->queue[i].arg1); + break; + default: + break; + } + + free (bst->queue); + free (bst); } static Pixmap -double_pixmap(Display *dpy, GC gc, Visual *visual, int depth, Pixmap pixmap, - int pix_w, int pix_h) +double_pixmap (Display *dpy, GC gc, Visual *visual, int depth, Pixmap pixmap, + int pix_w, int pix_h) { int x, y; Pixmap p2 = XCreatePixmap(dpy, pixmap, pix_w*2, pix_h*2, depth); @@ -151,74 +746,43 @@ double_pixmap(Display *dpy, GC gc, Visual *visual, int depth, Pixmap pixmap, } -/* Sleep for N seconds and return False. But if a key or mouse event is - seen, discard all pending key or mouse events, and return True. - */ -static Bool -bsod_sleep(Display *dpy, int seconds) -{ - int q = seconds * 4; - int quantum = 250000; - - if (seconds == -1) - q = 1, quantum = 100000; - - do - { - XSync(dpy, False); - while (XPending (dpy)) - { - XEvent event; - XNextEvent (dpy, &event); - if (event.xany.type == ButtonPress) - return True; - if (event.xany.type == KeyPress) - { - KeySym keysym; - char c = 0; - XLookupString (&event.xkey, &c, 1, &keysym, 0); - if (c == ' ' || c == '\t' || c == '\r' || c == '\n') - return True; - } - screenhack_handle_event (dpy, &event); - } - - if (q > 0) - { - q--; - usleep(quantum); - } - } - while (q > 0); +/***************************************************************************** + *****************************************************************************/ - return False; +static struct bsod_state * +windows_31 (Display *dpy, Window window) +{ + struct bsod_state *bst = make_bsod_state (dpy, window, "windows", "Windows"); + BSOD_INVERT (bst); + BSOD_TEXT (bst, CENTER, "Windows\n"); + BSOD_INVERT (bst); + BSOD_TEXT (bst, CENTER, + "A fatal exception 0E has occured at F0AD:42494C4C\n" + "the current application will be terminated.\n" + "\n" + "* Press any key to terminate the current application.\n" + "* Press CTRL+ALT+DELETE again to restart your computer.\n" + " You will lose any unsaved information in all applications.\n" + "\n" + "\n"); + BSOD_TEXT (bst, CENTER, "Press any key to continue"); + + bst->y = ((bst->xgwa.height - + ((bst->font->ascent + bst->font->descent) * 9)) + / 2); + + XClearWindow (dpy, window); + return bst; } -static Bool -windows (Display *dpy, Window window, int delay, Bool w95p) +static struct bsod_state * +windows_nt (Display *dpy, Window window) { - XGCValues gcv; - XWindowAttributes xgwa; - char *fontname; - const char *def_font = "fixed"; - XFontStruct *font; - GC gc; - - const char *w95 = - ("@Windows\n" - "A fatal exception 0E has occured at F0AD:42494C4C\n" - "the current application will be terminated.\n" - "\n" - "* Press any key to terminate the current application.\n" - "* Press CTRL+ALT+DELETE again to restart your computer.\n" - " You will lose any unsaved information in all applications.\n" - "\n" - "\n" - "_Press any key to continue"); + struct bsod_state *bst = make_bsod_state (dpy, window, "windows", "Windows"); - const char *wnt = - ("*** STOP: 0x0000001E (0x80000003,0x80106fc0,0x8025ea21,0xfd6829e8)\n" + BSOD_TEXT (bst, LEFT, + "*** STOP: 0x0000001E (0x80000003,0x80106fc0,0x8025ea21,0xfd6829e8)\n" "Unhandled Kernel exception c0000047 from fa8418b4 (8025ea21,fd6829e8)\n" "\n" "Dll Base Date Stamp - Name Dll Base Date Stamp - Name\n" @@ -261,74 +825,182 @@ windows (Display *dpy, Window window, int delay, Bool w95p) "Restart and set the recovery options in the system control panel\n" "or the /CRASHDEBUG system start option. If this message reappears,\n" "contact your system administrator or technical support group." - ); + ); - if (!get_boolean_resource((w95p? "doWindows" : "doNT"), "DoWindows")) - return False; + bst->line_delay = 750; - XGetWindowAttributes (dpy, window, &xgwa); - - fontname = get_string_resource ((xgwa.height > 600 - ? (w95p - ? "windows95.font2" - : "windowsNT.font2") - : (w95p - ? "windows95.font" - : "windowsNT.font")), - "Windows.Font"); - if (!fontname || !*fontname) fontname = (char *)def_font; - font = XLoadQueryFont (dpy, fontname); - if (!font) font = XLoadQueryFont (dpy, def_font); - if (!font) exit(-1); - if (fontname && fontname != def_font) - free (fontname); - - gcv.font = font->fid; - gcv.foreground = get_pixel_resource((w95p - ? "windows95.foreground" - : "windowsNT.foreground"), - "Windows.Foreground", - dpy, xgwa.colormap); - gcv.background = get_pixel_resource((w95p - ? "windows95.background" - : "windowsNT.background"), - "Windows.Background", - dpy, xgwa.colormap); - XSetWindowBackground(dpy, window, gcv.background); - XClearWindow(dpy, window); + XClearWindow (dpy, window); + return bst; +} - gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv); - if (w95p) - draw_string(dpy, window, gc, &gcv, font, - 0, 0, xgwa.width, xgwa.height, w95, 0); - else - draw_string(dpy, window, gc, &gcv, font, 0, 0, 10, 10, wnt, 750); +static struct bsod_state * +windows_2k (Display *dpy, Window window) +{ + struct bsod_state *bst = make_bsod_state (dpy, window, "windows", "Windows"); + + BSOD_TEXT (bst, LEFT, + "*** STOP: 0x000000D1 (0xE1D38000,0x0000001C,0x00000000,0xF09D42DA)\n" + "DRIVER_IRQL_NOT_LESS_OR_EQUAL \n" + "\n" + "*** Address F09D42DA base at F09D4000, DateStamp 39f459ff - CRASHDD.SYS\n" + "\n" + "Beginning dump of physical memory\n"); + BSOD_PAUSE (bst, 4000000); + BSOD_TEXT (bst, LEFT, + "Physical memory dump complete. Contact your system administrator or\n" + "technical support group.\n"); + + bst->left_margin = 40; + bst->y = (bst->font->ascent + bst->font->descent) * 10; + bst->line_delay = 750; + + XClearWindow (dpy, window); + return bst; +} - XFreeGC(dpy, gc); - XSync(dpy, False); - bsod_sleep(dpy, delay); - XClearWindow(dpy, window); - XFreeFont(dpy, font); - return True; + +static struct bsod_state * +windows_me (Display *dpy, Window window) +{ + struct bsod_state *bst = make_bsod_state (dpy, window, "windows", "Windows"); + + BSOD_TEXT (bst, LEFT, + "Windows protection error. You need to restart your computer.\n\n" + "System halted."); + BSOD_CURSOR (bst, CURSOR_LINE, 120000, 999999); + + bst->left_margin = 40; + bst->y = ((bst->xgwa.height - + ((bst->font->ascent + bst->font->descent) * 3)) + / 2); + + XClearWindow (dpy, window); + return bst; +} + + +static struct bsod_state * +windows_xp (Display *dpy, Window window) +{ + struct bsod_state *bst = make_bsod_state (dpy, window, "windows", "Windows"); + + BSOD_TEXT (bst, LEFT, /* From Wm. Rhodes */ + "A problem has been detected and windows has been shut down to prevent " + "damage\n" + "to your computer.\n" + "\n" + "If this is the first time you've seen this Stop error screen,\n" + "restart your computer. If this screen appears again, follow\n" + "these steps:\n" + "\n" + "Check to be sure you have adequate disk space. If a driver is\n" + "identified in the Stop message, disable the driver or check\n" + "with the manufacturer for driver updates. Try changing video\n" + "adapters.\n" + "\n" + "Check with your hardware vendor for any BIOS updates. Disable\n" + "BIOS memory options such as caching or shadowing. If you need\n" + "to use Safe Mode to remove or disable components, restart your\n" + "computer, press F8 to select Advanced Startup Options, and then\n" + "select Safe Mode.\n" + "\n" + "Technical information:\n" + "\n" + "*** STOP: 0x0000007E (0xC0000005,0xF88FF190,0x0xF8975BA0,0xF89758A0)\n" + "\n" + "\n" + "*** EPUSBDSK.sys - Address F88FF190 base at FF88FE000, datestamp " + "3b9f3248\n" + "\n" + "Beginning dump of physical memory\n"); + BSOD_PAUSE (bst, 4000000); + BSOD_TEXT (bst, LEFT, + "Physical memory dump complete.\n" + "Contact your system administrator or technical support group for " + "further\n" + "assitance.\n"); + + XClearWindow (dpy, window); + return bst; +} + + +static struct bsod_state * +windows_lh (Display *dpy, Window window) +{ + struct bsod_state *bst = + make_bsod_state (dpy, window, "windowslh", "WindowsLH"); + + unsigned long fg = bst->fg; + unsigned long bg = bst->bg; + unsigned long bg2 = get_pixel_resource (dpy, bst->xgwa.colormap, + "windowslh.background2", + "WindowsLH.Background"); + + /* The "RSOD" that appeared with "Windows Longhorn 5048.050401-0536_x86fre" + As reported by http://joi.ito.com/RedScreen.jpg + */ + BSOD_COLOR (bst, bg, bg2); + BSOD_TEXT (bst, CENTER_FULL, "Windows Boot Error\n"); + BSOD_COLOR (bst, fg, bg); + BSOD_TEXT (bst, CENTER, + "\n" + "Windows Boot Manager has experienced a problem.\n" + "\n" + "\n" + " Status: 0xc000000f\n" + "\n" + "\n" + "\n" + " Info: An error occurred transferring exectuion." /* (sic) */ + "\n" + "\n" + "\n" + "You can try to recover the system with the Microsoft Windows " + "System Recovery\n" + "Tools. (You might need to restart the system manually.)\n" + "\n" + "If the problem continues, please contact your system administrator " + "or computer\n" + "manufacturer.\n" + ); + BSOD_MOVETO (bst, bst->left_margin, bst->xgwa.height - bst->font->descent); + BSOD_COLOR (bst, bg, bg2); + BSOD_TEXT (bst, LEFT_FULL, " SPACE=Continue\n"); + + bst->y = bst->font->ascent; + + XClearWindow (dpy, window); + return bst; } + +static struct bsod_state * +windows_other (Display *dpy, Window window) +{ + /* Lump all of the 2K-ish crashes together and select them randomly... + */ + int which = (random() % 4); + switch (which) { + case 0: return windows_2k (dpy, window); break; + case 1: return windows_me (dpy, window); break; + case 2: return windows_xp (dpy, window); break; + case 3: return windows_lh (dpy, window); break; + default: abort(); break; + } +} + + /* SCO OpenServer 5 panic, by Tom Kelly */ -static Bool -sco (Display *dpy, Window window, int delay) +static struct bsod_state * +sco (Display *dpy, Window window) { - XGCValues gcv; - XWindowAttributes xgwa; - char *fontname; - const char *def_font = "fixed"; - XFontStruct *font; - GC gc; - int lines_1 = 0, lines_2 = 0, lines_3 = 0, lines_4 = 0; - const char *s; + struct bsod_state *bst = make_bsod_state (dpy, window, "sco", "SCO"); - const char *sco_panic_1 = - ("Unexpected trap in kernel mode:\n" + BSOD_TEXT (bst, LEFT, + "Unexpected trap in kernel mode:\n" "\n" "cr0 0x80010013 cr2 0x00000014 cr3 0x00000000 tlb 0x00000000\n" "ss 0x00071054 uesp 0x00012055 efl 0x00080888 ipl 0x00000005\n" @@ -340,114 +1012,43 @@ sco (Display *dpy, Window window, int delay) "PANIC: k_trap - kernel mode trap type 0x0000000E\n" "Trying to dump 5023 pages to dumpdev hd (1/41), 63 pages per '.'\n" ); - const char *sco_panic_2 = - ("...............................................................................\n" + BSOD_CHAR_DELAY (bst, 100000); + BSOD_TEXT (bst, LEFT, + "................................................................." + "..............\n" ); - const char *sco_panic_3 = - ("5023 pages dumped\n" + BSOD_CHAR_DELAY (bst, 0); + BSOD_TEXT (bst, LEFT, + "5023 pages dumped\n" "\n" "\n" ); - const char *sco_panic_4 = - ("** Safe to Power Off **\n" + BSOD_PAUSE (bst, 2000000); + BSOD_TEXT (bst, LEFT, + "** Safe to Power Off **\n" " - or -\n" "** Press Any Key to Reboot **\n" ); - if (!get_boolean_resource("doSCO", "DoSCO")) - return False; - - for (s = sco_panic_1; *s; s++) if (*s == '\n') lines_1++; - for (s = sco_panic_2; *s; s++) if (*s == '\n') lines_2++; - for (s = sco_panic_3; *s; s++) if (*s == '\n') lines_3++; - for (s = sco_panic_4; *s; s++) if (*s == '\n') lines_4++; - - XGetWindowAttributes (dpy, window, &xgwa); - - fontname = get_string_resource ((xgwa.height > 600 - ? "sco.font2" - : "sco.font"), - "SCO.Font"); - if (!fontname || !*fontname) fontname = (char *)def_font; - font = XLoadQueryFont (dpy, fontname); - if (!font) font = XLoadQueryFont (dpy, def_font); - if (!font) exit(-1); - if (fontname && fontname != def_font) - free (fontname); - - gcv.font = font->fid; - gcv.foreground = get_pixel_resource(("sco.foreground"), - "SCO.Foreground", - dpy, xgwa.colormap); - gcv.background = get_pixel_resource(("sco.background"), - "SCO.Background", - dpy, xgwa.colormap); - XSetWindowBackground(dpy, window, gcv.background); - XClearWindow(dpy, window); - - gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv); + bst->y = ((bst->xgwa.height - + ((bst->font->ascent + bst->font->descent) * 18))); - draw_string(dpy, window, gc, &gcv, font, - 10, xgwa.height - ((lines_1 + lines_2 + lines_3 + lines_4 + 1) * - (font->ascent + font->descent + 1)), - 10, 10, - sco_panic_1, 0); - XSync(dpy, False); - for (s = sco_panic_2; *s; s++) - { - char *ss = strdup(sco_panic_2); - ss[s - sco_panic_2] = 0; - draw_string(dpy, window, gc, &gcv, font, - 10, xgwa.height - ((lines_2 + lines_3 + lines_4 + 1) * - (font->ascent + font->descent + 1)), - 10, 10, - ss, 0); - XSync(dpy, False); - free(ss); - if (bsod_sleep (dpy, -1)) - goto DONE; - } - - draw_string(dpy, window, gc, &gcv, font, - 10, xgwa.height - ((lines_3 + lines_4 + 1) * - (font->ascent + font->descent + 1)), - 10, 10, - sco_panic_3, 0); - XSync(dpy, False); - if (bsod_sleep(dpy, 1)) - goto DONE; - draw_string(dpy, window, gc, &gcv, font, - 10, xgwa.height - ((lines_4 + 1) * - (font->ascent + font->descent + 1)), - 10, 10, - sco_panic_4, 0); - XSync(dpy, False); - - bsod_sleep(dpy, delay); - DONE: - XClearWindow(dpy, window); - XFreeGC(dpy, gc); - XFreeFont(dpy, font); - return True; + XClearWindow (dpy, window); + return bst; } /* Linux (sparc) panic, by Tom Kelly */ -static Bool -sparc_linux (Display *dpy, Window window, int delay) +static struct bsod_state * +sparc_linux (Display *dpy, Window window) { - XGCValues gcv; - XWindowAttributes xgwa; - char *fontname; - const char *def_font = "fixed"; - XFontStruct *font; - GC gc; - int lines = 1; - const char *s; + struct bsod_state *bst = make_bsod_state (dpy, window, "sco", "SCO"); + bst->scroll_p = True; + bst->y = bst->xgwa.height - bst->font->ascent - bst->font->descent; - const char *linux_panic = - ("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n" + BSOD_TEXT (bst, LEFT, + "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n" "Unable to handle kernel paging request at virtual address f0d4a000\n" "tsk->mm->context = 00000014\n" "tsk->mm->pgd = f26b0000\n" @@ -468,183 +1069,137 @@ sparc_linux (Display *dpy, Window window, int delay) "Instruction DUMP:\n" ); - if (!get_boolean_resource("doSparcLinux", "DoSparcLinux")) - return False; + XClearWindow (dpy, window); + return bst; +} - for (s = linux_panic; *s; s++) if (*s == '\n') lines++; - - XGetWindowAttributes (dpy, window, &xgwa); - - fontname = get_string_resource ((xgwa.height > 600 - ? "sparclinux.font2" - : "sparclinux.font"), - "SparcLinux.Font"); - if (!fontname || !*fontname) fontname = (char *)def_font; - font = XLoadQueryFont (dpy, fontname); - if (!font) font = XLoadQueryFont (dpy, def_font); - if (!font) exit(-1); - if (fontname && fontname != def_font) - free (fontname); - - gcv.font = font->fid; - gcv.foreground = get_pixel_resource(("sparclinux.foreground"), - "SparcLinux.Foreground", - dpy, xgwa.colormap); - gcv.background = get_pixel_resource(("sparclinux.background"), - "SparcLinux.Background", - dpy, xgwa.colormap); - XSetWindowBackground(dpy, window, gcv.background); - XClearWindow(dpy, window); - gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv); +/* BSD Panic by greywolf@starwolf.com - modeled after the Linux panic above. + By Grey Wolf + */ +static struct bsod_state * +bsd (Display *dpy, Window window) +{ + struct bsod_state *bst = make_bsod_state (dpy, window, "bsd", "BSD"); + + const char * const panicstr[] = { + "panic: ifree: freeing free inode\n", + "panic: blkfree: freeing free block\n", + "panic: improbability coefficient below zero\n", + "panic: cgsixmmap\n", + "panic: crazy interrupts\n", + "panic: nmi\n", + "panic: attempted windows install\n", + "panic: don't\n", + "panic: free inode isn't\n", + "panic: cpu_fork: curproc\n", + "panic: malloc: out of space in kmem_map\n", + "panic: vogon starship detected\n", + "panic: teleport chamber: out of order\n", + "panic: Brain fried - core dumped\n" + }; + int i, n, b; + char syncing[80], bbuf[5]; + + for (i = 0; i < sizeof(syncing); i++) + syncing[i] = 0; + + i = (random() % (sizeof(panicstr) / sizeof(*panicstr))); + BSOD_TEXT (bst, LEFT, panicstr[i]); + BSOD_TEXT (bst, LEFT, "Syncing disks: "); + + b = (random() % 40); + for (n = 0; (n < 20) && (b > 0); n++) + { + if (i) + { + i = (random() & 0x7); + b -= (random() & 0xff) % 20; + if (b < 0) + b = 0; + } + sprintf (bbuf, "%d ", b); + BSOD_TEXT (bst, LEFT, bbuf); + BSOD_PAUSE (bst, 1000000); + } + + BSOD_TEXT (bst, LEFT, "\n"); + BSOD_TEXT (bst, LEFT, (b ? "damn!" : "sunk!")); + BSOD_TEXT (bst, LEFT, "\nRebooting\n"); - draw_string(dpy, window, gc, &gcv, font, - 10, xgwa.height - (lines * (font->ascent + font->descent + 1)), - 10, 10, - linux_panic, 0); - XFreeGC(dpy, gc); - XSync(dpy, False); - bsod_sleep(dpy, delay); - XClearWindow(dpy, window); - XFreeFont(dpy, font); - return True; + bst->y = ((bst->xgwa.height - + ((bst->font->ascent + bst->font->descent) * 4))); + + XClearWindow (dpy, window); + return bst; } -static Bool -amiga (Display *dpy, Window window, int delay) + +static struct bsod_state * +amiga (Display *dpy, Window window) { - XGCValues gcv; - XWindowAttributes xgwa; - char *fontname; - const char *def_font = "fixed"; - XFontStruct *font; - GC gc, gc2; - int height; - unsigned long fg, bg, bg2; + struct bsod_state *bst = make_bsod_state (dpy, window, "amiga", "Amiga"); + Pixmap pixmap = 0; int pix_w = 0, pix_h = 0; + int height; + int lw = 10; - const char *string = - ("_Software failure. Press left mouse button to continue.\n" - "_Guru Meditation #00000003.00C01570"); - - if (!get_boolean_resource("doAmiga", "DoAmiga")) - return False; + unsigned long bg2 = get_pixel_resource (dpy, bst->xgwa.colormap, + "amiga.background2", + "Amiga.Background"); - XGetWindowAttributes (dpy, window, &xgwa); - - fontname = get_string_resource ((xgwa.height > 600 - ? "amiga.font2" : "amiga.font"), - "Amiga.Font"); - if (!fontname || !*fontname) fontname = (char *)def_font; - font = XLoadQueryFont (dpy, fontname); - if (!font) font = XLoadQueryFont (dpy, def_font); - if (!font) exit(-1); - if (fontname && fontname != def_font) - free (fontname); - - gcv.font = font->fid; - fg = gcv.foreground = get_pixel_resource("amiga.foreground", - "Amiga.Foreground", - dpy, xgwa.colormap); - bg = gcv.background = get_pixel_resource("amiga.background", - "Amiga.Background", - dpy, xgwa.colormap); - bg2 = get_pixel_resource("amiga.background2", "Amiga.Background", - dpy, xgwa.colormap); - XSetWindowBackground(dpy, window, bg2); - XClearWindow(dpy, window); +# ifdef DO_XPM + pixmap = xpm_data_to_pixmap (dpy, window, (char **) amiga_hand, + &pix_w, &pix_h, 0); +# endif /* DO_XPM */ - gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv); - gcv.background = fg; gcv.foreground = bg; - gc2 = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv); + if (pixmap && bst->xgwa.height > 600) /* scale up the bitmap */ + { + pixmap = double_pixmap (dpy, bst->gc, bst->xgwa.visual, bst->xgwa.depth, + pixmap, pix_w, pix_h); + pix_w *= 2; + pix_h *= 2; + } - height = (font->ascent + font->descent) * 6; + XSetLineAttributes (dpy, bst->gc, lw, LineSolid, CapButt, JoinMiter); -#ifdef HAVE_XPM - { - XpmAttributes xpmattrs; - int result; - xpmattrs.valuemask = 0; + height = (bst->font->ascent + bst->font->descent) * 6; -# ifdef XpmCloseness - xpmattrs.valuemask |= XpmCloseness; - xpmattrs.closeness = 40000; -# endif -# ifdef XpmVisual - xpmattrs.valuemask |= XpmVisual; - xpmattrs.visual = xgwa.visual; -# endif -# ifdef XpmDepth - xpmattrs.valuemask |= XpmDepth; - xpmattrs.depth = xgwa.depth; -# endif -# ifdef XpmColormap - xpmattrs.valuemask |= XpmColormap; - xpmattrs.colormap = xgwa.colormap; -# endif + BSOD_PAUSE (bst, 2000000); + BSOD_COPY (bst, 0, 0, bst->xgwa.width, bst->xgwa.height - height, 0, height); - result = XpmCreatePixmapFromData(dpy, window, amiga_hand, - &pixmap, 0 /* mask */, &xpmattrs); - if (!pixmap || (result != XpmSuccess && result != XpmColorError)) - pixmap = 0; - pix_w = xpmattrs.width; - pix_h = xpmattrs.height; - } -#endif /* HAVE_XPM */ + BSOD_INVERT (bst); + BSOD_RECT (bst, True, 0, 0, bst->xgwa.width, height); + BSOD_INVERT (bst); + BSOD_TEXT (bst, CENTER, + "\n" + "Software failure. Press left mouse button to continue.\n" + "Guru Meditation #00000003.00C01570" + ); + BSOD_RECT (bst, False, lw/2, lw/2, bst->xgwa.width - lw, height); + BSOD_PAUSE (bst, 1000000); + BSOD_INVERT (bst); + BSOD_LOOP (bst, -3); - if (pixmap && xgwa.height > 600) /* scale up the bitmap */ - { - pixmap = double_pixmap(dpy, gc, xgwa.visual, xgwa.depth, - pixmap, pix_w, pix_h); - pix_w *= 2; - pix_h *= 2; - } + XSetWindowBackground (dpy, window, bg2); + XClearWindow (dpy, window); + XSetWindowBackground (dpy, window, bst->bg); if (pixmap) { - int x = (xgwa.width - pix_w) / 2; - int y = ((xgwa.height - pix_h) / 2); - XCopyArea(dpy, pixmap, window, gc, 0, 0, pix_w, pix_h, x, y); - - XSync(dpy, False); - bsod_sleep(dpy, 2); - - XCopyArea(dpy, pixmap, window, gc, 0, 0, pix_w, pix_h, x, y + height); - XClearArea(dpy, window, 0, 0, xgwa.width, y + height, False); - XFreePixmap(dpy, pixmap); + int x = (bst->xgwa.width - pix_w) / 2; + int y = ((bst->xgwa.height - pix_h) / 2); + XCopyArea (dpy, pixmap, bst->window, bst->gc, 0, 0, pix_w, pix_h, x, y); } - XFillRectangle(dpy, window, gc2, 0, 0, xgwa.width, height); - draw_string(dpy, window, gc, &gcv, font, 0, 0, xgwa.width, height, string,0); - - { - GC gca = gc; - while (delay > 0) - { - XFillRectangle(dpy, window, gca, 0, 0, xgwa.width, font->ascent); - XFillRectangle(dpy, window, gca, 0, 0, font->ascent, height); - XFillRectangle(dpy, window, gca, xgwa.width-font->ascent, 0, - font->ascent, height); - XFillRectangle(dpy, window, gca, 0, height-font->ascent, xgwa.width, - font->ascent); - gca = (gca == gc ? gc2 : gc); - XSync(dpy, False); - if (bsod_sleep(dpy, 1)) - break; - delay--; - } - } + bst->y += lw; - XFreeGC(dpy, gc); - XFreeGC(dpy, gc2); - XSync(dpy, False); - XClearWindow(dpy, window); - XFreeFont(dpy, font); - return True; + return bst; } + /* Atari ST, by Marcus Herbert Marcus had this to say: @@ -655,86 +1210,52 @@ amiga (Display *dpy, Window window, int delay) Perhaps somebody else can tell you more about it.. its just a quick hack :-} */ -static Bool -atari (Display *dpy, Window window, int delay) +static struct bsod_state * +atari (Display *dpy, Window window) { - - XGCValues gcv; - XWindowAttributes xgwa; - const char *def_font = "fixed"; - XFontStruct *font; - GC gc; + struct bsod_state *bst = make_bsod_state (dpy, window, "atari", "Atari"); + Pixmap pixmap = 0; int pix_w = atari_width; int pix_h = atari_height; int offset; int i, x, y; - if (!get_boolean_resource("doAtari", "DoAtari")) - return False; - - XGetWindowAttributes (dpy, window, &xgwa); - - font = XLoadQueryFont (dpy, def_font); - if (!font) exit(-1); - - gcv.font = font->fid; - gcv.foreground = get_pixel_resource("atari.foreground", "Atari.Foreground", - dpy, xgwa.colormap); - gcv.background = get_pixel_resource("atari.background", "Atari.Background", - dpy, xgwa.colormap); - - XSetWindowBackground(dpy, window, gcv.background); - XClearWindow(dpy, window); - - gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv); - - pixmap = XCreatePixmapFromBitmapData(dpy, window, (char *) atari_bits, - pix_w, pix_h, - gcv.foreground, gcv.background, - xgwa.depth); - pixmap = double_pixmap(dpy, gc, xgwa.visual, xgwa.depth, - pixmap, pix_w, pix_h); + pixmap = XCreatePixmapFromBitmapData (dpy, window, (char *) atari_bits, + pix_w, pix_h, + bst->fg, bst->bg, bst->xgwa.depth); + pixmap = double_pixmap (dpy, bst->gc, bst->xgwa.visual, bst->xgwa.depth, + pixmap, pix_w, pix_h); pix_w *= 2; pix_h *= 2; - offset = pix_w + 2; - x = 5; - y = (xgwa.height - (xgwa.height / 5)); + offset = pix_w; + x = 0; + y = bst->xgwa.height/2; if (y < 0) y = 0; - for (i=0 ; i<7 ; i++) { - XCopyArea(dpy, pixmap, window, gc, 0, 0, pix_w, pix_h, - (x + (i*offset)), y); - } - - for (i=7 ; i<10 ; i++) { - if (bsod_sleep(dpy, 1)) - goto DONE; - XCopyArea(dpy, pixmap, window, gc, 0, 0, pix_w, pix_h, - (x + (i*offset)), y); - } + for (i = 1; i< 7; i++) + BSOD_COPY (bst, x, y, pix_w, pix_h, (x + (i*offset)), y); - bsod_sleep(dpy, delay); - DONE: - XFreePixmap(dpy, pixmap); - XFreeGC(dpy, gc); - XSync(dpy, False); - XClearWindow(dpy, window); - XFreeFont(dpy, font); - return True; + for (; i< 10; i++) + { + BSOD_PAUSE (bst, 1000000); + BSOD_COPY (bst, x, y, pix_w, pix_h, (x + (i*offset)), y); + } + + XClearWindow (dpy, window); + XCopyArea (dpy, pixmap, window, bst->gc, 0, 0, pix_w, pix_h, x, y); + XFreePixmap (dpy, pixmap); + + return bst; } -static Bool -mac (Display *dpy, Window window, int delay) +static struct bsod_state * +mac (Display *dpy, Window window) { - XGCValues gcv; - XWindowAttributes xgwa; - char *fontname; - const char *def_font = "fixed"; - XFontStruct *font; - GC gc; + struct bsod_state *bst = make_bsod_state (dpy, window, "mac", "Mac"); + Pixmap pixmap = 0; int pix_w = mac_width; int pix_h = mac_height; @@ -744,77 +1265,40 @@ mac (Display *dpy, Window window, int delay) const char *string = ("0 0 0 0 0 0 0 F\n" "0 0 0 0 0 0 0 3"); - if (!get_boolean_resource("doMac", "DoMac")) - return False; - - XGetWindowAttributes (dpy, window, &xgwa); - - fontname = get_string_resource ("mac.font", "Mac.Font"); - if (!fontname || !*fontname) fontname = (char *)def_font; - font = XLoadQueryFont (dpy, fontname); - if (!font) font = XLoadQueryFont (dpy, def_font); - if (!font) exit(-1); - if (fontname && fontname != def_font) - free (fontname); - - gcv.font = font->fid; - gcv.foreground = get_pixel_resource("mac.foreground", "Mac.Foreground", - dpy, xgwa.colormap); - gcv.background = get_pixel_resource("mac.background", "Mac.Background", - dpy, xgwa.colormap); - XSetWindowBackground(dpy, window, gcv.background); - XClearWindow(dpy, window); - - gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv); - pixmap = XCreatePixmapFromBitmapData(dpy, window, (char *) mac_bits, mac_width, mac_height, - gcv.foreground, - gcv.background, - xgwa.depth); + bst->fg, bst->bg, bst->xgwa.depth); - for(i = 0; i < 2; i++) + for (i = 0; i < 2; i++) { - pixmap = double_pixmap(dpy, gc, xgwa.visual, xgwa.depth, - pixmap, pix_w, pix_h); + pixmap = double_pixmap (dpy, bst->gc, bst->xgwa.visual, bst->xgwa.depth, + pixmap, pix_w, pix_h); pix_w *= 2; pix_h *= 2; } - { - int x = (xgwa.width - pix_w) / 2; - int y = (((xgwa.height + offset) / 2) - - pix_h - - (font->ascent + font->descent) * 2); - if (y < 0) y = 0; - XCopyArea(dpy, pixmap, window, gc, 0, 0, pix_w, pix_h, x, y); - XFreePixmap(dpy, pixmap); - } + bst->x = (bst->xgwa.width - pix_w) / 2; + bst->y = (((bst->xgwa.height + offset) / 2) - + pix_h - + (bst->font->ascent + bst->font->descent) * 2); + if (bst->y < 0) bst->y = 0; - draw_string(dpy, window, gc, &gcv, font, 0, 0, - xgwa.width, xgwa.height + offset, string, 0); + XClearWindow (dpy, window); + XCopyArea (dpy, pixmap, window, bst->gc, 0, 0, pix_w, pix_h, bst->x, bst->y); + XFreePixmap (dpy, pixmap); - XFreeGC(dpy, gc); - XSync(dpy, False); - bsod_sleep(dpy, delay); - XClearWindow(dpy, window); - XFreeFont(dpy, font); - return True; + bst->y += offset + bst->font->ascent + bst->font->descent; + BSOD_TEXT (bst, CENTER, string); + + return bst; } -static Bool -macsbug (Display *dpy, Window window, int delay) -{ - XGCValues gcv; - XWindowAttributes xgwa; - char *fontname; - const char *def_font = "fixed"; - XFontStruct *font; - GC gc, gc2; - int char_width, line_height; - int col_right, row_top, row_bottom, page_right, page_bottom, body_top; - int xoff, yoff; +static struct bsod_state * +macsbug (Display *dpy, Window window) +{ + struct bsod_state *bst = make_bsod_state (dpy, window, "macsbug", "MacsBug"); + __extension__ const char *left = (" SP \n" " 04EB0A58 \n" "58 00010000\n" @@ -869,14 +1353,7 @@ macsbug (Display *dpy, Window window, int delay) " | 4A1F\n" " +00888 40843718 $0004(A7),([0,A7[)" " ; 04E8D0AE | 66B8"); - -#if 0 - const char *body = ("Bus Error at 4BF6D6CC\n" - "while reading word from 4BF6D6CC in User data space\n" - " Unable to access that address\n" - " PC: 2A0DE3E6\n" - " Frame Type: B008"); -#else + __extension__ const char * body = ("PowerPC unmapped memory exception at 003AFDAC " "BowelsOfTheMemoryMgr+04F9C\n" " Calling chain using A6/R1 links\n" @@ -907,216 +1384,2627 @@ macsbug (Display *dpy, Window window, int delay) " 24DAF7C9 PPC 00307098 " "EmToNatEndMoveParams+00014\n" " 24DAF780 PPC 003AA180 __DisposePtr+00010"); -#endif const char *s; int body_lines = 1; - if (!get_boolean_resource("doMacsBug", "DoMacsBug")) - return False; + int char_width, line_height; + int col_right, row_top, row_bottom, page_right, page_bottom, body_top; + int xoff, yoff; - for (s = body; *s; s++) if (*s == '\n') body_lines++; + unsigned long fg = bst->fg; + unsigned long bg = bst->bg; + unsigned long bc = get_pixel_resource (dpy, bst->xgwa.colormap, + "macsbug.borderColor", + "MacsBug.BorderColor"); - XGetWindowAttributes (dpy, window, &xgwa); - - fontname = get_string_resource ((xgwa.height > 850 - ? "macsbug.font3" - : (xgwa.height > 700 - ? "macsbug.font2" - : "macsbug.font")), - "MacsBug.Font"); - if (!fontname || !*fontname) fontname = (char *)def_font; - font = XLoadQueryFont (dpy, fontname); - if (!font) font = XLoadQueryFont (dpy, def_font); - if (!font) exit(-1); - if (fontname && fontname != def_font) - free (fontname); - - gcv.font = font->fid; - gcv.foreground = get_pixel_resource("macsbug.foreground", - "MacsBug.Foreground", - dpy, xgwa.colormap); - gcv.background = get_pixel_resource("macsbug.background", - "MacsBug.Background", - dpy, xgwa.colormap); - - gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv); - - gcv.foreground = gcv.background; - gc2 = XCreateGC(dpy, window, GCForeground, &gcv); - - XSetWindowBackground(dpy, window, - get_pixel_resource("macsbug.borderColor", - "MacsBug.BorderColor", - dpy, xgwa.colormap)); - XClearWindow(dpy, window); + for (s = body; *s; s++) if (*s == '\n') body_lines++; - char_width = (font->per_char - ? font->per_char['n'-font->min_char_or_byte2].width - : font->min_bounds.width); - line_height = font->ascent + font->descent + 1; + char_width = (bst->font->per_char + ? bst->font->per_char['n'-bst->font->min_char_or_byte2].width + : bst->font->min_bounds.width); + line_height = bst->font->ascent + bst->font->descent; - col_right = char_width * 12; - page_bottom = line_height * 47; + col_right = char_width * 12; /* number of columns in `left' */ + page_bottom = line_height * 47; /* number of lines in `left' */ - if (page_bottom > xgwa.height) page_bottom = xgwa.height; + if (page_bottom > bst->xgwa.height) + page_bottom = bst->xgwa.height; row_bottom = page_bottom - line_height; - row_top = row_bottom - (line_height * 4); + row_top = row_bottom - (line_height * 4); page_right = col_right + (char_width * 88); - body_top = row_top - (line_height * body_lines); + body_top = row_top - (line_height * body_lines); page_bottom += 2; row_bottom += 2; body_top -= 4; - xoff = (xgwa.width - page_right) / 2; - yoff = (xgwa.height - page_bottom) / 2; + if (body_top > 4) + body_top = 4; + + xoff = (bst->xgwa.width - page_right) / 2; + yoff = (bst->xgwa.height - page_bottom) / 2; + if (xoff < 0) xoff = 0; if (yoff < 0) yoff = 0; - XFillRectangle(dpy, window, gc2, xoff, yoff, page_right, page_bottom); + BSOD_MARGINS (bst, xoff, yoff); + + BSOD_COLOR (bst, bc, bg); + BSOD_RECT (bst, True, 0, 0, bst->xgwa.width, bst->xgwa.height); + BSOD_COLOR (bst, bg, bg); + BSOD_RECT (bst, True, xoff-2, yoff, page_right+4, page_bottom); + BSOD_COLOR (bst, fg, bg); + + BSOD_MOVETO (bst, xoff, yoff + line_height); + BSOD_TEXT (bst, LEFT, left); + BSOD_MOVETO (bst, xoff+col_right, yoff + row_top + line_height); + BSOD_TEXT (bst, LEFT, bottom); + + BSOD_RECT (bst, True, xoff + col_right, yoff, 2, page_bottom); + BSOD_RECT (bst, True, xoff + col_right, yoff + row_top, + page_right - col_right, 1); + BSOD_RECT (bst, True, xoff + col_right, yoff + row_bottom, + page_right - col_right, 1); + BSOD_RECT (bst, False, xoff-2, yoff, page_right+4, page_bottom); + + BSOD_LINE_DELAY (bst, 500); + BSOD_MOVETO (bst, + xoff + col_right + char_width, + yoff + body_top + line_height); + BSOD_MARGINS (bst, xoff + col_right + char_width, yoff); + BSOD_TEXT (bst, LEFT, body); + + BSOD_RECT (bst, False, xoff-2, yoff, page_right+4, page_bottom); /* again */ + + BSOD_RECT (bst, False, + xoff + col_right + (char_width/2)+2, + yoff + row_bottom + 2, + 0, + page_bottom - row_bottom - 4); + + BSOD_PAUSE (bst, 666666); + BSOD_INVERT (bst); + BSOD_LOOP (bst, -3); + + XClearWindow (dpy, window); + return bst; +} - draw_string(dpy, window, gc, &gcv, font, xoff, yoff, 10, 10, left, 0); - draw_string(dpy, window, gc, &gcv, font, xoff+col_right, yoff+row_top, - 10, 10, bottom, 0); - XFillRectangle(dpy, window, gc, xoff + col_right, yoff, 2, page_bottom); - XDrawLine(dpy, window, gc, - xoff+col_right, yoff+row_top, xoff+page_right, yoff+row_top); - XDrawLine(dpy, window, gc, - xoff+col_right, yoff+row_bottom, xoff+page_right, yoff+row_bottom); - XDrawRectangle(dpy, window, gc, xoff, yoff, page_right, page_bottom); +static struct bsod_state * +mac1 (Display *dpy, Window window) +{ + struct bsod_state *bst = make_bsod_state (dpy, window, "mac1", "Mac1"); - if (body_top > 4) - body_top = 4; + Pixmap pixmap = 0; + int pix_w = macbomb_width; + int pix_h = macbomb_height; + int x, y; - draw_string(dpy, window, gc, &gcv, font, - xoff + col_right + char_width, yoff + body_top, 10, 10, body, - 500); + pixmap = XCreatePixmapFromBitmapData (dpy, window, (char *) macbomb_bits, + macbomb_width, macbomb_height, + bst->fg, bst->bg, bst->xgwa.depth); - while (delay > 0) + x = (bst->xgwa.width - pix_w) / 2; + y = (bst->xgwa.height - pix_h) / 2; + if (y < 0) y = 0; + + XClearWindow (dpy, window); + XCopyArea (dpy, pixmap, window, bst->gc, 0, 0, pix_w, pix_h, x, y); + + return bst; +} + + +/* This is what kernel panics looked like on MacOS X 10.0 through 10.1.5. + In later releases, it's a graphic of a power button with text in + English, French, German, and Japanese overlayed transparently. + */ +static struct bsod_state * +macx_10_0 (Display *dpy, Window window) +{ + struct bsod_state *bst = make_bsod_state (dpy, window, "macx", "MacX"); + + XClearWindow (dpy, window); + XSetForeground (dpy, bst->gc, + get_pixel_resource (dpy, bst->xgwa.colormap, + "macx.textForeground", + "MacX.TextForeground")); + XSetBackground (dpy, bst->gc, + get_pixel_resource (dpy, bst->xgwa.colormap, + "macx.textBackground", + "MacX.TextBackground")); + +# ifdef DO_XPM + { + Pixmap pixmap = 0; + Pixmap mask = 0; + int x, y, pix_w, pix_h; + pixmap = xpm_data_to_pixmap (dpy, window, (char **) happy_mac, + &pix_w, &pix_h, &mask); + + x = (bst->xgwa.width - pix_w) / 2; + y = (bst->xgwa.height - pix_h) / 2; + if (y < 0) y = 0; + XSetClipMask (dpy, bst->gc, mask); + XSetClipOrigin (dpy, bst->gc, x, y); + XCopyArea (dpy, pixmap, window, bst->gc, 0, 0, pix_w, pix_h, x, y); + XSetClipMask (dpy, bst->gc, None); + XFreePixmap (dpy, pixmap); + } +#endif /* DO_XPM */ + + bst->left_margin = 0; + bst->right_margin = 0; + bst->y = bst->font->ascent; + bst->macx_eol_kludge = True; + bst->wrap_p = True; + + BSOD_PAUSE (bst, 3000000); + BSOD_TEXT (bst, LEFT, + "panic(cpu 0): Unable to find driver for this platform: " + "\"PowerMac 3,5\".\n" + "\n" + "backtrace: 0x0008c2f4 0x0002a7a0 0x001f0204 0x001d4e4c 0x001d4c5c " + "0x001a56cc 0x01d5dbc 0x001c621c 0x00037430 0x00037364\n" + "\n" + "\n" + "\n" + "No debugger configured - dumping debug information\n" + "\n" + "version string : Darwin Kernel Version 1.3:\n" + "Thu Mar 1 06:56:40 PST 2001; root:xnu/xnu-123.5.obj~1/RELEASE_PPC\n" + "\n" + "\n" + "\n" + "\n" + "DBAT0: 00000000 00000000\n" + "DBAT1: 00000000 00000000\n" + "DBAT2: 80001FFE 8000003A\n" + "DBAT3: 90001FFE 9000003A\n" + "MSR=00001030\n" + "backtrace: 0x0008c2f4 0x0002a7a0 0x001f0204 0x001d4e4c 0x001d4c5c " + "0x001a56cc 0x01d5dbc 0x001c621c 0x00037430 0x00037364\n" + "\n" + "panic: We are hanging here...\n"); + + return bst; +} + + +# ifdef DO_XPM +static struct bsod_state * +macx_10_2 (Display *dpy, Window window, Bool v10_3_p) +{ + struct bsod_state *bst = make_bsod_state (dpy, window, "macx", "MacX"); + + Pixmap pixmap = 0; + int pix_w = 0, pix_h = 0; + int x, y; + + pixmap = xpm_data_to_pixmap (dpy, window, + (char **) (v10_3_p ? osx_10_3 : osx_10_2), + &pix_w, &pix_h, 0); + if (! pixmap) abort(); + +#if 0 + if (bst->xgwa.height > 600) /* scale up the bitmap */ { - XDrawLine(dpy, window, gc, - xoff+col_right+(char_width/2)+2, yoff+row_bottom+3, - xoff+col_right+(char_width/2)+2, yoff+page_bottom-3); - XSync(dpy, False); - usleep(666666L); - XDrawLine(dpy, window, gc2, - xoff+col_right+(char_width/2)+2, yoff+row_bottom+3, - xoff+col_right+(char_width/2)+2, yoff+page_bottom-3); - XSync(dpy, False); - usleep(333333L); - if (bsod_sleep(dpy, 0)) - break; - delay--; - } - - XFreeGC(dpy, gc); - XFreeGC(dpy, gc2); - XClearWindow(dpy, window); - XFreeFont(dpy, font); - return True; + pixmap = double_pixmap (dpy, bst->gc, bst->xgwa.visual, bst->xgwa.depth, + pixmap, pix_w, pix_h); + if (! pixmap) abort(); + pix_w *= 2; + pix_h *= 2; + } +#endif + + BSOD_IMG (bst); + BSOD_PAUSE (bst, 2000000); + + bst->pixmap = pixmap; + + x = (bst->xgwa.width - pix_w) / 2; + y = ((bst->xgwa.height - pix_h) / 2); + BSOD_PIXMAP (bst, 0, 0, pix_w, pix_h, x, y); + + return bst; } +# endif /* DO_XPM */ + +static struct bsod_state * +macx (Display *dpy, Window window) +{ +# ifdef DO_XPM + switch (random() % 3) { + case 0: return macx_10_0 (dpy, window); break; + case 1: return macx_10_2 (dpy, window, False); break; + case 2: return macx_10_2 (dpy, window, True); break; + default: abort(); + } +# else /* !DO_XPM */ + return macx_10_0 (dpy, window); +# endif /* !DO_XPM */ +} - -char *progclass = "BSOD"; -char *defaults [] = { - "*delay: 30", +#ifndef HAVE_COCOA /* #### I have no idea how to implement this without + real plane-masks. I don't think it would look + right if done with alpha-transparency... */ +/* blit damage + * + * by Martin Pool , Feb 2000. + * + * This is meant to look like the preferred failure mode of NCD + * Xterms. The parameters for choosing what to copy where might not + * be quite right, but it looks about ugly enough. + */ +static struct bsod_state * +blitdamage (Display *dpy, Window window) +{ + struct bsod_state *bst = + make_bsod_state (dpy, window, "blitdamage", "BlitDamage"); - "*doWindows: True", - "*doNT: True", - "*doAmiga: True", - "*doMac: True", - "*doAtari: False", /* boring */ - "*doMacsBug: True", - "*doSCO: True", - "*doSparcLinux: False", /* boring */ + int i; + int delta_x = 0, delta_y = 0; + int w, h; + int chunk_h, chunk_w; + int steps; + long gc_mask = 0; + int src_x, src_y; + int x, y; + + w = bst->xgwa.width; + h = bst->xgwa.height; - ".Windows.font: -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*", - ".Windows.font2: -*-courier-bold-r-*-*-*-180-*-*-m-*-*-*", - ".Windows.foreground: White", - ".Windows.background: Blue", - - ".Amiga.font: -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*", - ".Amiga.font2: -*-courier-bold-r-*-*-*-180-*-*-m-*-*-*", - ".Amiga.foreground: Red", - ".Amiga.background: Black", - ".Amiga.background2: White", - - ".Mac.font: -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*", - ".Mac.foreground: PaleTurquoise1", - ".Mac.background: Black", - - ".Atari.foreground: Black", - ".Atari.background: White", - - ".MacsBug.font: -*-courier-medium-r-*-*-*-100-*-*-m-*-*-*", - ".MacsBug.font2: -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*", - ".MacsBug.font3: -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*", - ".MacsBug.foreground: Black", - ".MacsBug.background: White", - ".MacsBug.borderColor: #AAAAAA", + gc_mask = GCForeground; - ".SCO.font: -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*", - ".SCO.font2: -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*", - ".SCO.foreground: White", - ".SCO.background: Black", + XSetPlaneMask (dpy, bst->gc, random()); + + steps = 50; + chunk_w = w / (random() % 1 + 1); + chunk_h = h / (random() % 1 + 1); + if (random() & 0x1000) + delta_y = random() % 600; + if (!delta_y || (random() & 0x2000)) + delta_x = random() % 600; + src_x = 0; + src_y = 0; + x = 0; + y = 0; - ".SparcLinux.font: -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*", - ".SparcLinux.font2: -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*", - ".SparcLinux.foreground: White", - ".SparcLinux.background: Black", - 0 -}; + BSOD_IMG (bst); + for (i = 0; i < steps; i++) { + if (x + chunk_w > w) + x -= w; + else + x += delta_x; + + if (y + chunk_h > h) + y -= h; + else + y += delta_y; + + BSOD_COPY (bst, src_x, src_y, chunk_w, chunk_h, x, y); + BSOD_PAUSE (bst, 1000); + } -XrmOptionDescRec options [] = { - { "-delay", ".delay", XrmoptionSepArg, 0 }, - { 0, 0, 0, 0 } -}; + return bst; +} +#endif /* !HAVE_COCOA */ + + +/* + * OS/2 panics, by Knut St. Osmundsen + * + * All but one messages are real ones, some are from my test machines + * and system dumps, others are reconstructed from google results. + * Please, don't be to hard if the formatting of the earlier systems + * aren't 100% correct. + */ +static struct bsod_state * +os2 (Display *dpy, Window window) +{ + struct bsod_state *bst = make_bsod_state (dpy, window, "os2", "OS2"); + + __extension__ + static const char * const os2_panics[] = + { /* OS/2 2.0 trap - details are bogus (CR0++). */ + "TRAP 0002 ERRCD=0000 ERACC=**** ERLIM=********\n" + "EAX=7d240a58 EBX=ff202fdc ECX=00064423 EDX=00003624\n" + "ESI=fff3272c EDI=7d240004 EBP=00004a44 FLG=00003202\n" + "CS:EIP=0160:fff702a6 CSACC=c09d CSLIM=ffffffff\n" + "SS:ESP=0030:00004a38 SSACC=1097 SSLIM=00003fff\n" + "DS=0158 DSACC=c0f3 DSLIM=ffffffff CR0=fffffffb\n" + "ES=0158 ESACC=c0f3 ESLIM=ffffffff CR2=1a060014\n" + "FS=0000 FSACC=**** FSLIM=********\n" + "GS=0000 GSACC=**** GSLIM=********\n" + "\n" + "The system detected an internal processing error\n" + "at location ##0160:fff6453f - 000d:a53f\n" + "60000, 9084\n" + "\n" + "038600d1\n" + "Internal revision 6.307, 92/03/01\n" + "\n", + + /* warp 3 (early) */ + "TRAP 000e ERRCD=0000 ERACC=**** ERLIM=********\n" + "EAX=ff050c20 EBX=000000bb ECX=ffff00c1 EDx=fff379b8\n" + "ESI=ffe55a3c EDI=00000000 EBP=00004eb8 FLG=00013282\n" + "CS:EIP=0160:fff8dbb8 CSACC=c09b CSLIM=ffffffff\n" + "SS:EIP=0030:00004eb4 SSACC=1097 SSLIM=00003fff\n" + "DS=0158 DSACC=c0f3 DSLIM=ffffffff CR0=8001001b\n" + "ES=0158 DSACC=c0f3 DSLIM=ffffffff CR2=000000c7\n" + "FS=0000 FSACC=**** FSLIM=********\n" + "GS=0000 GSACC=**** GSLIM=********\n" + "\n" + "The system detected an internal processing error\n" + "at location ##0160:fff66bf0 - 000d:9bf0.\n" + "60000, 9084\n" + "\n" + "048600b4\n" + "Internal revision 8.125, 94/02/16\n" + "\n" + "The system is stopped. Record the location number of the error\n" + "and contact your service representative.\n", + + /* warp 3 */ + "TRAP 000e ERRCD=0002 ERACC=**** ERLIM=********\n" + "EAX=00000000 EBX=fdef1e0c ECX=00003824 EDX=0000edf9\n" + "ESI=fdf30e80 EDI=fc8b0000 EBP=00005658 FLG=00012246\n" + "CS:EIP=0160:fff8ada3 CSACC=c09b CSLIM=ffffffff\n" + "SS:ESP=0030:000055d4 SSACC=1097 SSLIM=0000480f\n" + "DS=0158 DSACC=c093 DSLIM=ffffffff CR0=8001001b\n" + "ES=0158 ESACC=c093 ESLIM=ffffffff CR2=fc8b0000\n" + "FS=03b8 FSACC=0093 FSLIM=00000023\n" + "GS=0000 GSACC=**** GSLIM=********\n" + "\n" + "The system detected an internal processing error\n" + "at location ##0160:fff5c364 - 000d:a364.\n" + "60000, 9084\n" + "\n" + "05860526\n" + "Internal revision 8200,94/11/07\n" + "\n" + "The system is stopped. Record all of the above information and\n" + "contact your service representative.\n", + + /* warp 3 (late) */ + "TRAP 000d ERRCD=2200 ERACC=1092 ERLIM=00010fff\n" + "EAX=0000802e EBX=fff001c8 ECX=9bd80000 EDX=00000000\n" + "ESI=fff09bd8 EDI=fdeb001b EBP=00000000 FLG=00012012\n" + "CS:EIP=0168:fff480a2 CSACC=c09b CSLIM=ffffffff\n" + "SS:ESP=00e8:00001f32 SSACC=0093 SSLIM=00001fff\n" + "DS=0940 DSACC=0093 DSLIM=00000397 CR0=8001001b\n" + "ES=00e8 ESACC=0093 ESLIM=00001fff CR2=15760008\n" + "FS=0000 FSACC=**** FSLIM=****\n" + "GS=0000 GSACC=**** GSLIM=****\n" + "\n" + "The system detected an internal processing error\n" + "at location ##0168:fff4b06e - 000e:c06e\n" + "60000, 9084\n" + "\n" + "06860652\n" + "Internal revision 8.259_uni,98/01/07\n" + "\n" + "The system is stopped. Record all of the above information and\n" + "contact your service representative.\n", + + /* Warp 4.52+ - the official r0trap.exe from the debugging classes */ + "Exception in module: OS2KRNL\n" + "TRAP 000e ERRCD=0002 ERACC=**** ERLIM=********\n" + "EAX=00000001 EBX=80010002 ECX=ffed4638 EDX=0003f17b\n" + "ESI=00000001 EDI=00000002 EBP=00005408 FLG=00012202\n" + "CS:EIP=0168:fff3cd2e CSACC=c09b CSLIM=ffffffff\n" + "SS:ESP=0030:000053ec SSACC=1097 SSLIM=000044ff\n" + "DS=0160 DSACC=c093 DSLIM=ffffffff CR0=8001001b\n" + "ES=0160 ESACC=c093 ESLIM=ffffffff CR2=00000001\n" + "FS=0000 FSACC=**** FSLIM=********\n" + "GS=0000 GSACC=**** GSLIM=********\n" + "\n" + "The system detected an internal processing error at\n" + "location ##0168:fff1e3f3 - 000e:c3f3.\n" + "60000, 9084\n" + "\n" + "068606a0\n" + "Internal revision 14.097_UNI\n" + "\n" + "The system is stopped. Record all of the above information and\n" + "contact your service representative.\n", + + /* Warp 4.52+, typical JFS problem. */ + "Exeption in module: JFS\n" + "TRAP 0003 ERRCD=0000 ERACC=**** ERLIM=********\n" + "EAX=00000000 EBX=ffffff05 ECX=00000001 EDX=f5cd8010\n" + "ESI=000000e6 EDI=000000e7 EBP=f9c7378e FLG=00002296\n" + "CS:EIP=0168:f8df3250 CSACC=c09b CSLIM=ffffffff\n" + "SS:ESP=1550:fdc73778 SSACC=c093 SSLIM=ffffffff\n" + "DS=0160 DSACC=c093 DSLIM=ffffffff CR0=80010016\n" + "ES=0160 ESACC=c093 DSLIM=ffffffff CR2=05318000\n" + "FS=03c0 FSACC=0093 DSLIM=00000023\n" + "GS=0160 GSACC=c093 DSLIM=ffffffff\n" + "\n" + "The system detected an internal processing error\n" + "at location ##0168:fff1e2ab - 000e:c2ab.\n" + "60000, 9084\n" + "\n" + "07860695\n" + "\n" + "Internal revision 14.100c_UNI\n" + "\n" + "The system is stopped. Record all of the above information and\n" + "contact your service representative.\n" + }; + + BSOD_TEXT (bst, LEFT, os2_panics[random() % countof(os2_panics)]); + BSOD_CURSOR (bst, CURSOR_LINE, 240000, 999999); + + XClearWindow (dpy, window); + return bst; +} -void -screenhack (Display *dpy, Window window) +/* SPARC Solaris panic. Should look pretty authentic on Solaris boxes. + * Anton Solovyev + */ +static struct bsod_state * +sparc_solaris (Display *dpy, Window window) { - int loop = 0; - int i = -1; - int j = -1; - int delay = get_integer_resource ("delay", "Integer"); - if (delay < 3) delay = 3; + struct bsod_state *bst = make_bsod_state (dpy, window, "solaris", "Solaris"); + int i; + + bst->scroll_p = True; + bst->wrap_p = True; + bst->left_margin = bst->right_margin = bst->xgwa.width * 0.07; + bst->top_margin = bst->bottom_margin = bst->xgwa.height * 0.07; + bst->y = bst->top_margin + bst->font->ascent; + + BSOD_IMG (bst); + BSOD_PAUSE (bst, 3000000); + + BSOD_INVERT(bst); + BSOD_RECT (bst, True, + bst->left_margin, bst->top_margin, + bst->xgwa.width - bst->left_margin - bst->right_margin, + bst->xgwa.height - bst->top_margin - bst->bottom_margin); + BSOD_INVERT(bst); + + BSOD_TEXT (bst, LEFT, + "BAD TRAP: cpu=0 type=0x31 rp=0x2a10043b5e0 addr=0xf3880 mmu_fsr=0x0\n" + "BAD TRAP occurred in module \"unix\" due to an illegal access to a" + " user address.\n" + "adb: trap type = 0x31\n" + "addr=0xf3880\n" + "pid=307, pc=0x100306e4, sp=0x2a10043ae81, tstate=0x4480001602," + " context=0x87f\n" + "g1-g7: 1045b000, 32f, 10079440, 180, 300000ebde8, 0, 30000953a20\n" + "Begin traceback... sp = 2a10043ae81\n" + "Called from 100bd060, fp=2a10043af31, args=f3700 300008cc988 f3880 0" + " 1 300000ebde0.\n" + "Called from 101fe1bc, fp=2a10043b011, args=3000045a240 104465a0" + " 300008e47d0 300008e48fa 300008ae350 300008ae410\n" + "Called from 1007c520, fp=2a10043b0c1, args=300008e4878 300003596e8 0" + " 3000045a320 0 3000045a220\n" + "Called from 1007c498, fp=2a10043b171, args=1045a000 300007847f0 20" + " 3000045a240 1 0\n" + "Called from 1007972c, fp=2a10043b221, args=1 300009517c0 30000951e58 1" + " 300007847f0 0\n" + "Called from 10031e10, fp=2a10043b2d1, args=3000095b0c8 0 300009396a8" + " 30000953a20 0 1\n" + "Called from 10000bdd8, fp=ffffffff7ffff1c1, args=0 57 100131480" + " 100131480 10012a6e0 0\n" + "End traceback...\n" + "panic[cpu0]/thread=30000953a20: trap\n" + "syncing file systems..."); + + BSOD_PAUSE (bst, 3000000); + + BSOD_TEXT (bst, LEFT, " 1 done\n"); + BSOD_TEXT (bst, LEFT, "dumping to /dev/dsk/c0t0d0s3, offset 26935296\n"); + BSOD_PAUSE (bst, 2000000); + + + for (i = 1; i <= 100; ++i) + { + char buf[100]; + sprintf (buf, "\b\b\b\b\b\b\b\b\b\b\b%3d%% done", i); + BSOD_TEXT (bst, LEFT, buf); + BSOD_PAUSE (bst, 100000); + } + + BSOD_TEXT (bst, LEFT, + ": 2803 pages dumped, compression ratio 2.88, dump succeeded\n"); + BSOD_PAUSE (bst, 2000000); + + BSOD_TEXT (bst, LEFT, + "rebooting...\n" + "Resetting ..."); + + return bst; +} + + +/* Linux panic and fsck, by jwz + */ +static struct bsod_state * +linux_fsck (Display *dpy, Window window) +{ + struct bsod_state *bst = make_bsod_state (dpy, window, "linux", "Linux"); + + int i; + const char *sysname; + char buf[1024]; + + const char *linux_panic[] = { + " kernel: Unable to handle kernel paging request at virtual " + "address 0000f0ad\n", + " kernel: printing eip:\n", + " kernel: c01becd7\n", + " kernel: *pde = 00000000\n", + " kernel: Oops: 0000\n", + " kernel: CPU: 0\n", + " kernel: EIP: 0010:[] Tainted: P \n", + " kernel: EFLAGS: 00010286\n", + " kernel: eax: 0000ff00 ebx: ca6b7e00 ecx: ce1d7a60 edx: ce1d7a60\n", + " kernel: esi: ca6b7ebc edi: 00030000 ebp: d3655ca0 esp: ca6b7e5c\n", + " kernel: ds: 0018 es: 0018 ss: 0018\n", + " kernel: Process crond (pid: 1189, stackpage=ca6b7000)\n", + " kernel: Stack: d3655ca0 ca6b7ebc 00030054 ca6b7e7c c01c1e5b " + "00000287 00000020 c01c1fbf \n", + "", + " kernel: 00005a36 000000dc 000001f4 00000000 00000000 " + "ce046d40 00000001 00000000 \n", + "", "", "", + " kernel: ffffffff d3655ca0 d3655b80 00030054 c01bef93 " + "d3655ca0 ca6b7ebc 00030054 \n", + "", "", "", + " kernel: Call Trace: [] [] [] " + "[] []\n", + "", "", "", + " kernel: [] [] [] []\n", + " kernel: \n", + " kernel: Code: 2a 00 75 08 8b 44 24 2c 85 c0 74 0c 8b 44 24 58 83 48 18 " + "08 \n", + 0 + }; + + bst->scroll_p = True; + bst->wrap_p = True; + bst->left_margin = bst->right_margin = 10; + bst->top_margin = bst->bottom_margin = 10; + + sysname = "linux"; +# ifdef HAVE_UNAME + { + struct utsname uts; + char *s; + if (uname (&uts) >= 0) + sysname = uts.nodename; + s = strchr (sysname, '.'); + if (s) *s = 0; + } +# endif /* !HAVE_UNAME */ + + + BSOD_TEXT (bst, LEFT, "waiting for X server to shut down "); + BSOD_PAUSE (bst, 100000); + BSOD_TEXT (bst, LEFT, + "XIO: fatal IO error 2 (broken pipe) on X server \":0.0\"\n" + " after 339471 requests (339471 known processed) " + "with 0 events remaining\n"); + BSOD_CHAR_DELAY (bst, 300000); + BSOD_TEXT (bst, LEFT, ".........\n"); + BSOD_CHAR_DELAY (bst, 0); + BSOD_TEXT (bst, LEFT, + "xinit: X server slow to shut down, sending KILL signal.\n" + "waiting for server to die "); + BSOD_CHAR_DELAY (bst, 300000); + BSOD_TEXT (bst, LEFT, "...\n"); + BSOD_CHAR_DELAY (bst, 0); + BSOD_TEXT (bst, LEFT, "xinit: Can't kill server\n"); + BSOD_PAUSE (bst, 2000000); + + sprintf (buf, "\n%s Login: ", sysname); + BSOD_TEXT (bst, LEFT, buf); + BSOD_PAUSE (bst, 1000000); + BSOD_TEXT (bst, LEFT, + "\n\n" + "Parallelizing fsck version 1.22 (22-Jun-2001)\n" + "e2fsck 1.22, 22-Jun-2001 for EXT2 FS 0.5b, 95/08/09\n" + "Warning! /dev/hda1 is mounted.\n" + "/dev/hda1 contains a file system with errors, check forced.\n"); + BSOD_PAUSE (bst, 1000000); + + if (0 == random() % 2) + BSOD_TEXT (bst, LEFT, + "Couldn't find ext2 superblock, trying backup blocks...\n" + "The filesystem size (according to the superblock) is 3644739 blocks\n" + "The physical size of the device is 3636706 blocks\n" + "Either the superblock or the partition table is likely to be corrupt!\n" + "Abort? no\n"); + BSOD_PAUSE (bst, 1000000); + + AGAIN: + + BSOD_TEXT (bst, LEFT, "Pass 1: Checking inodes, blocks, and sizes\n"); + BSOD_PAUSE (bst, 2000000); + + i = (random() % 60) - 20; + while (--i > 0) + { + int b = random() % 0xFFFF; + sprintf (buf, "Deleted inode %d has zero dtime. Fix? yes\n\n", b); + BSOD_TEXT (bst, LEFT, buf); + BSOD_PAUSE (bst, 1000); + } + + i = (random() % 40) - 10; + if (i > 0) + { + int g = random() % 0xFFFF; + int b = random() % 0xFFFFFFF; + + BSOD_PAUSE (bst, 1000000); + + sprintf (buf, "Warning: Group %d's copy of the group descriptors " + "has a bad block (%d).\n", g, b); + BSOD_TEXT (bst, LEFT, buf); + + b = random() % 0x3FFFFF; + while (--i > 0) + { + b += random() % 0xFFFF; + sprintf (buf, + "Error reading block %d (Attempt to read block " + "from filesystem resulted in short read) while doing " + "inode scan. Ignore error?", + b); + BSOD_TEXT (bst, LEFT, buf); + BSOD_PAUSE (bst, 10000); + BSOD_TEXT (bst, LEFT, " yes\n\n"); + } + } + + if (0 == (random() % 10)) + { + BSOD_PAUSE (bst, 1000000); + + i = 3 + (random() % 10); + while (--i > 0) + { + BSOD_TEXT (bst, LEFT, + "Could not allocate 256 block(s) for inode table: " + "No space left on device\n"); + BSOD_PAUSE (bst, 1000); + } + BSOD_TEXT (bst, LEFT, "Restarting e2fsck from the beginning...\n"); + BSOD_PAUSE (bst, 2000000); + + goto AGAIN; + } + + i = (random() % 20) - 5; + + if (i > 0) + BSOD_PAUSE (bst, 1000000); + + while (--i > 0) + { + int j = 5 + (random() % 10); + int w = random() % 4; + + while (--j > 0) + { + int b = random() % 0xFFFFF; + int g = random() % 0xFFF; + + if (0 == (random() % 10)) + b = 0; + else if (0 == (random() % 10)) + b = -1; + + if (w == 0) + sprintf (buf, + "Inode table for group %d not in group. (block %d)\n" + "WARNING: SEVERE DATA LOSS POSSIBLE.\n" + "Relocate?", + g, b); + else if (w == 1) + sprintf (buf, + "Block bitmap for group %d not in group. (block %d)\n" + "Relocate?", + g, b); + else if (w == 2) + sprintf (buf, + "Inode bitmap %d for group %d not in group.\n" + "Continue?", + b, g); + else /* if (w == 3) */ + sprintf (buf, + "Bad block %d in group %d's inode table.\n" + "WARNING: SEVERE DATA LOSS POSSIBLE.\n" + "Relocate?", + b, g); + + BSOD_TEXT (bst, LEFT, buf); + BSOD_TEXT (bst, LEFT, " yes\n\n"); + BSOD_PAUSE (bst, 1000); + } + } + + + if (0 == random() % 10) goto PANIC; + BSOD_TEXT (bst, LEFT, "Pass 2: Checking directory structure\n"); + BSOD_PAUSE (bst, 2000000); + + i = (random() % 20) - 5; + while (--i > 0) + { + int n = random() % 0xFFFFF; + int o = random() % 0xFFF; + sprintf (buf, "Directory inode %d, block 0, offset %d: " + "directory corrupted\n" + "Salvage? ", + n, o); + BSOD_TEXT (bst, LEFT, buf); + BSOD_PAUSE (bst, 1000); + BSOD_TEXT (bst, LEFT, " yes\n\n"); + + if (0 == (random() % 100)) + { + sprintf (buf, "Missing '.' in directory inode %d.\nFix?", n); + BSOD_TEXT (bst, LEFT, buf); + BSOD_PAUSE (bst, 1000); + BSOD_TEXT (bst, LEFT, " yes\n\n"); + } + } + + if (0 == random() % 10) + goto PANIC; + + BSOD_TEXT (bst, LEFT, + "Pass 3: Checking directory connectivity\n" + "/lost+found not found. Create? yes\n"); + BSOD_PAUSE (bst, 2000000); + + /* Unconnected directory inode 4949 (/var/spool/squid/06/???) + Connect to /lost+found? yes + + '..' in /var/spool/squid/06/08 (20351) is (0), should be + /var/spool/squid/06 (20350). + Fix? yes + + Unconnected directory inode 128337 (/var/spool/squid/06/???) + Connect to /lost+found? yes + */ + + + if (0 == random() % 10) goto PANIC; + BSOD_TEXT (bst, LEFT, "Pass 4: Checking reference counts\n"); + BSOD_PAUSE (bst, 2000000); + + /* Inode 2 ref count is 19, should be 20. Fix? yes + + Inode 4949 ref count is 3, should be 2. Fix? yes + + ... + + Inode 128336 ref count is 3, should be 2. Fix? yes + + Inode 128337 ref count is 3, should be 2. Fix? yes + + */ + + + if (0 == random() % 10) goto PANIC; + BSOD_TEXT (bst, LEFT, "Pass 5: Checking group summary information\n"); + BSOD_PAUSE (bst, 2000000); + + i = (random() % 200) - 50; + if (i > 0) + { + BSOD_TEXT (bst, LEFT, "Block bitmap differences: "); + while (--i > 0) + { + sprintf (buf, " %d", -(random() % 0xFFF)); + BSOD_TEXT (bst, LEFT, buf); + BSOD_PAUSE (bst, 1000); + } + BSOD_TEXT (bst, LEFT, "\nFix? yes\n\n"); + } + + + i = (random() % 100) - 50; + if (i > 0) + { + BSOD_TEXT (bst, LEFT, "Inode bitmap differences: "); + while (--i > 0) + { + sprintf (buf, " %d", -(random() % 0xFFF)); + BSOD_TEXT (bst, LEFT, buf); + BSOD_PAUSE (bst, 1000); + } + BSOD_TEXT (bst, LEFT, "\nFix? yes\n\n"); + } - if (!get_boolean_resource ("root", "Boolean")) + i = (random() % 20) - 5; + while (--i > 0) { - XWindowAttributes xgwa; - XGetWindowAttributes (dpy, window, &xgwa); - XSelectInput (dpy, window, - xgwa.your_event_mask | KeyPressMask | ButtonPressMask); + int g = random() % 0xFFFF; + int c = random() % 0xFFFF; + sprintf (buf, + "Free blocks count wrong for group #0 (%d, counted=%d).\nFix? ", + g, c); + BSOD_TEXT (bst, LEFT, buf); + BSOD_PAUSE (bst, 1000); + BSOD_TEXT (bst, LEFT, " yes\n\n"); } - while (1) + PANIC: + + i = 0; + BSOD_TEXT (bst, LEFT, "\n\n"); + while (linux_panic[i]) { - Bool did; - do { i = (random() & 0xFF) % 8; } while (i == j); - switch (i) - { - case 0: did = windows(dpy, window, delay, True); break; - case 1: did = windows(dpy, window, delay, False); break; - case 2: did = amiga(dpy, window, delay); break; - case 3: did = mac(dpy, window, delay); break; - case 4: did = macsbug(dpy, window, delay); break; - case 5: did = sco(dpy, window, delay); break; - case 6: did = sparc_linux(dpy, window, delay); break; - case 7: did = atari(dpy, window, delay); break; - default: abort(); break; - } - loop++; - if (loop > 100) j = -1; - if (loop > 200) exit(-1); - if (!did) continue; - XSync (dpy, False); - j = i; - loop = 0; + time_t t = time ((time_t *) 0); + struct tm *tm = localtime (&t); + char prefix[100]; + + if (*linux_panic[i]) + { + strftime (prefix, sizeof(prefix)-1, "%b %d %H:%M:%S ", tm); + BSOD_TEXT (bst, LEFT, prefix); + BSOD_TEXT (bst, LEFT, sysname); + BSOD_TEXT (bst, LEFT, linux_panic[i]); + BSOD_PAUSE (bst, 1000); + } + else + BSOD_PAUSE (bst, 300000); + + i++; } + BSOD_PAUSE (bst, 4000000); + + XClearWindow(dpy, window); + return bst; } + + +/* + * Linux (hppa) panic, by Stuart Brady + * Output courtesy of M. Grabert + */ +static struct bsod_state * +hppa_linux (Display *dpy, Window window) +{ + struct bsod_state *bst = + make_bsod_state (dpy, window, "hppalinux", "HPPALinux"); + + int i = 0; + const char *release, *sysname, *gccversion, *version; + long int linedelay = 0; + + __extension__ + struct { long int delay; const char *string; } linux_panic[] = + {{ 0, "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n" + "\n\n\n\n\n\n\n\n\n\n\n\n\n" }, + { 0, "Linux version %s (root@%s) (gcc version %s) %s\n" }, + { 4000, "FP[0] enabled: Rev 1 Model 16\n" }, + { 10, "The 32-bit Kernel has started...\n" }, + { -1, "Determining PDC firmware type: System Map.\n" }, + { -1, "model 00005bb0 00000481 00000000 00000002 7778df9f 100000f0 " + "00000008 000000b2 000000b2\n" }, + { -1, "vers 00000203\n" }, + { -1, "CPUID vers 17 rev 7 (0x00000227)\n" }, + { -1, "capabilities 0x3\n" }, + { -1, "model 9000/785/C3000\n" }, + { -1, "Total Memory: 1024 Mb\n" }, + { -1, "On node 0 totalpages: 262144\n" }, + { -1, " DMA zone: 262144 pages, LIFO batch:16\n" }, + { -1, " Normal zone: 0 pages, LIFO batch:1\n" }, + { -1, " HighMem zone: 0 pages, LIFO batch:1\n" }, + { -1, "LCD display at f05d0008,f05d0000 registered\n" }, + { -1, "Building zonelist for node : 0\n" }, + { -1, "Kernel command line: ide=nodma root=/dev/sda3 HOME=/ ip=off " + "console=ttyS0 TERM=vt102 palo_kernel=2/vmlinux-2.6\n" }, + { -1, "ide_setup: ide=nodmaIDE: Prevented DMA\n" }, + { -1, "PID hash table entries: 16 (order 4: 128 bytes)\n" }, + {500, "Console: colour dummy device 160x64\n" }, + { 10, "Memory: 1034036k available\n" }, + { -1, "Calibrating delay loop... 796.67 BogoMIPS\n" }, + { -1, "Dentry cache hash table entries: 131072 (order: 7, 524288 " + "bytes)\n" }, + { -1, "Inode-cache hash table entries: 65536 (order: 6, 262144 " + "bytes)\n" }, + { -1, "Mount-cache hash table entries: 512 (order: 0, 4096 bytes)\n" }, + { -1, "POSIX conformance testing by UNIFIX\n" }, + { -1, "NET: Registered protocol family 16\n" }, + { 100, "Searching for devices...\n" }, + { 25, "Found devices:\n" }, + { 10, "1. Astro BC Runway Port at 0xfed00000 [10] " + "{ 12, 0x0, 0x582, 0x0000b }\n" }, + { -1, "2. Elroy PCI Bridge at 0xfed30000 [10/0] " + "{ 13, 0x0, 0x782, 0x0000a }\n" }, + { -1, "3. Elroy PCI Bridge at 0xfed32000 [10/1] " + "{ 13, 0x0, 0x782, 0x0000a }\n" }, + { -1, "4. Elroy PCI Bridge at 0xfed38000 [10/4] " + "{ 13, 0x0, 0x782, 0x0000a }\n" }, + { -1, "5. Elroy PCI Bridge at 0xfed3c000 [10/6] " + "{ 13, 0x0, 0x782, 0x0000a }\n" }, + { -1, "6. AllegroHigh W at 0xfffa0000 [32] " + "{ 0, 0x0, 0x5bb, 0x00004 }\n" }, + { -1, "7. Memory at 0xfed10200 [49] { 1, 0x0, 0x086, 0x00009 }\n" }, + { -1, "CPU(s): 1 x PA8500 (PCX-W) at 400.000000 MHz\n" }, + { -1, "SBA found Astro 2.1 at 0xfed00000\n" }, + { -1, "lba version TR2.1 (0x2) found at 0xfed30000\n" }, + { -1, "lba version TR2.1 (0x2) found at 0xfed32000\n" }, + { -1, "lba version TR2.1 (0x2) found at 0xfed38000\n" }, + { -1, "lba version TR2.1 (0x2) found at 0xfed3c000\n" }, + { 100, "SCSI subsystem initialized\n" }, + { 10, "drivers/usb/core/usb.c: registered new driver usbfs\n" }, + { -1, "drivers/usb/core/usb.c: registered new driver hub\n" }, + { -1, "ikconfig 0.7 with /proc/config*\n" }, + { -1, "Initializing Cryptographic API\n" }, + { 250, "SuperIO: probe of 0000:00:0e.0 failed with error -1\n" }, + { 20, "SuperIO: Found NS87560 Legacy I/O device at 0000:00:0e.1 " + "(IRQ 64)\n" }, + { -1, "SuperIO: Serial port 1 at 0x3f8\n" }, + { -1, "SuperIO: Serial port 2 at 0x2f8\n" }, + { -1, "SuperIO: Parallel port at 0x378\n" }, + { -1, "SuperIO: Floppy controller at 0x3f0\n" }, + { -1, "SuperIO: ACPI at 0x7e0\n" }, + { -1, "SuperIO: USB regulator enabled\n" }, + { -1, "SuperIO: probe of 0000:00:0e.2 failed with error -1\n" }, + { -1, "Soft power switch enabled, polling @ 0xf0400804.\n" }, + { -1, "pty: 256 Unix98 ptys configured\n" }, + { -1, "Generic RTC Driver v1.07\n" }, + { -1, "Serial: 8250/16550 driver $Revision: 1.88 $ 13 ports, " + "IRQ sharing disabled\n" }, + { -1, "ttyS0 at I/O 0x3f8 (irq = 0) is a 16550A\n" }, + { -1, "ttyS1 at I/O 0x2f8 (irq = 0) is a 16550A\n" }, + { -1, "Linux Tulip driver version 1.1.13 (May 11, 2002)\n" }, + { 150, "tulip0: no phy info, aborting mtable build\n" }, + { 10, "tulip0: MII transceiver #1 config 1000 status 782d " + "advertising 01e1.\n" }, + { -1, "eth0: Digital DS21143 Tulip rev 65 at 0xf4008000, " + "00:10:83:F9:B4:34, IRQ 66.\n" }, + { -1, "Uniform Multi-Platform E-IDE driver Revision: 7.00alpha2\n" }, + { -1, "ide: Assuming 33MHz system bus speed for PIO modes; " + "override with idebus=xx\n" }, + { 100, "SiI680: IDE controller at PCI slot 0000:01:06.0\n" }, + { 10, "SiI680: chipset revision 2\n" }, + { -1, "SiI680: BASE CLOCK == 133\n" }, + { -1, "SiI680: 100% native mode on irq 128\n" }, + { -1, " ide0: MMIO-DMA at 0xf4800000-0xf4800007 -- " + "Error, MMIO ports already in use.\n" }, + { -1, " ide1: MMIO-DMA at 0xf4800008-0xf480000f -- " + "Error, MMIO ports already in use.\n" }, + { 5, "hda: TS130220A2, ATA DISK drive\n" }, + { -1, " _______________________________\n" }, + { -1, " < Your System ate a SPARC! Gah! >\n" }, + { -1, " -------------------------------\n" }, + { -1, " \\ ^__^\n" }, + { -1, " \\ (xx)\\_______\n" }, + { -1, " (__)\\ )\\/\\\n" }, + { -1, " U ||----w |\n" }, + { -1, " || ||\n" }, + { -1, "swapper (pid 1): Breakpoint (code 0)\n" }, + { -1, "\n" }, + { -1, " YZrvWESTHLNXBCVMcbcbcbcbOGFRQPDI\n" }, + { -1, "PSW: 00000000000001001111111100001111 Not tainted\n" }, + { -1, "r00-03 4d6f6f21 1032f010 10208f34 103fc2e0\n" }, + { -1, "r04-07 103fc230 00000001 00000001 0000000f\n" }, + { -1, "r08-11 103454f8 000f41fa 372d3980 103ee404\n" }, + { -1, "r12-15 3ccbf700 10344810 103ee010 f0400004\n" }, + { -1, "r16-19 f00008c4 f000017c f0000174 00000000\n" }, + { -1, "r20-23 fed32840 fed32800 00000000 0000000a\n" }, + { -1, "r24-27 0000ffa0 000000ff 103fc2e0 10326010\n" }, + { -1, "r28-31 00000000 00061a80 4ff98340 10208f34\n" }, + { -1, "sr0-3 00000000 00000000 00000000 00000000\n" }, + { -1, "sr4-7 00000000 00000000 00000000 00000000\n" }, + { -1, "\n" }, + { -1, "IASQ: 00000000 00000000 IAOQ: 00000000 00000004\n" }, + { -1, " IIR: 00000000 ISR: 00000000 IOR: 00000000\n" }, + { -1, " CPU: 0 CR30: 4ff98000 CR31: 1037c000\n" }, + { -1, " ORIG_R28: 55555555\n" }, + { -1, " IAOQ[0]: 0x0\n" }, + { -1, " IAOQ[1]: 0x4\n" }, + { -1, " RP(r2): probe_hwif+0x218/0x44c\n" }, + { -1, "Kernel panic: Attempted to kill init!\n" }, + { 0, NULL }}; + + bst->scroll_p = True; + bst->wrap_p = True; + bst->left_margin = bst->right_margin = 10; + bst->top_margin = bst->bottom_margin = 10; + + release = "2.6.0-test11-pa2"; + sysname = "hppa"; + version = "#2 Mon Dec 8 06:09:27 GMT 2003"; +# ifdef HAVE_UNAME + { + struct utsname uts; + char *s; + if (uname (&uts) >= 0) + { + sysname = uts.nodename; + if (!strcmp (uts.sysname, "Linux")) + { + release = uts.release; + version = uts.version; + } + } + s = strchr (sysname, '.'); + if (s) *s = 0; + } +# endif /* !HAVE_UNAME */ + +# if (defined (__GNUC__) && defined (__VERSION__)) + gccversion = __VERSION__; +# else /* !(defined (__GNUC__) && defined (__VERSION__)) */ + gccversion = "3.3.2 (Debian)"; +# endif /* !(defined (__GNUC__) && defined (__VERSION__)) */ + + /* Insert current host name into banner on line 2 */ + { + char ss[1024]; + snprintf (ss, 1024, linux_panic[1].string, + release, sysname, gccversion, version); + linux_panic[1].string = ss; + } + + BSOD_PAUSE (bst, 100000); + while (linux_panic[i].string) + { + if (linux_panic[i].delay != -1) + linedelay = linux_panic[i].delay * 1000; + BSOD_PAUSE (bst, linedelay); + BSOD_TEXT (bst, LEFT, linux_panic[i].string); + i++; + } + + bst->y = bst->xgwa.height - bst->font->ascent - bst->font->descent; + + XClearWindow(dpy, window); + return bst; +} + + +/* VMS by jwz (text sent by Roland Barmettler ) + */ +static struct bsod_state * +vms (Display *dpy, Window window) +{ + struct bsod_state *bst = make_bsod_state (dpy, window, "vms", "VMS"); + + const char *sysname; + int char_delay = 0; + int dot_delay = 40000; + int chunk_delay = 500000; + char *s, *s1; + int i; + int arg_count; + + __extension__ + + const char *lines[] = { + "%CNXMAN, Lost connection to system #\n" + "%SHADOW-I-VOLPROC, DSA0: shadow master has changed. " + "Dump file WILL be written if system crashes.\n" + "\n", + "", + + "%CNXMAN, Quorum lost, blocking activity\n" + "%CNXMAN, Timed-out lost connection to system #\n" + "%CNXMAN, Timed-out lost connection to system #\n" + "%CNXMAN, Timed-out lost connection to system #\n" + "%CNXMAN, Proposing reconfiguration of the VMScluster\n", + "", + + "%CNXMAN, Removed from VMScluster system #\n" + "%CNXMAN, Removed from VMScluster system #\n" + "%CNXMAN, Removed from VMScluster system #\n" + "%CNXMAN, Completing VMScluster state transition\n", + + "\n" + "**** OpenVMS (TM) Alpha Operating system V7.3-1 - BUGCHECK ****\n" + "\n" + "** Bugcheck code = 000005DC: CLUEXIT, Node voluntarily exiting " + "VMScluster\n" + "** Crash CPU: 00 Primary CPU: 00 Active CPUs: 00000001\n" + "** Current Process = NULL\n" + "** Current PSB ID = 00000001\n" + "** Image Name =\n" + "\n" + "** Dumping error log buffers to HBVS unit 0\n" + "**** Unable to dump error log buffers to remaining shadow set members\n" + "** Error log buffers not dumped to HBVS unit 200\n" + "\n" + "** Dumping memory to HBVS unit 0\n" + "**** Starting compressed selective memory dump at #...\n", + + "...", + + "\n" + "**** Memory dump complete - not all processes or global pages saved\n", + + "\n" + "halted CPU 0\n", + "", + + "\n" + "halt code = 5\n" + "HALT instruction executed\n" + "PC = ffffffff800c3884\n", + + "\n" + "CPU 0 booting\n", + + "\n" + "resetting all I/O buses\n" + "\n" + "\n" + }; + char *args[8]; + int ids[3]; + + bst->scroll_p = True; + bst->wrap_p = True; + bst->left_margin = bst->right_margin = 10; + bst->top_margin = bst->bottom_margin = 10; + + sysname = "VMS001"; +# ifdef HAVE_UNAME + { + struct utsname uts; + if (uname (&uts) >= 0) + sysname = uts.nodename; + s = strchr (sysname, '.'); + if (s) *s = 0; + } +# endif /* !HAVE_UNAME */ + + args[0] = malloc (strlen(sysname) + 7); + strcpy (args[0], sysname); + args[0][5] = 0; + + /* Pick three numbers, 1-9, no overlaps. */ + ids[0] = 1 + (random() % 9); + do { ids[1] = 1 + (random() % 9); } while (ids[1]==ids[0]); + do { ids[2] = 1 + (random() % 9); } while (ids[2]==ids[0] || ids[2]==ids[1]); + + i = strlen(args[0])-1; + if (i < 6) i++; + args[0][i] = '0' + ids[0]; + args[0][i+1] = 0; + + for (s = args[0]; *s; s++) + if (isalpha(*s)) *s = toupper (*s); + + args[1] = strdup (args[0]); + args[2] = strdup (args[0]); args[2][i] = '0' + ids[1]; + args[3] = strdup (args[0]); args[3][i] = '0' + ids[2]; + + args[4] = strdup (args[1]); + args[5] = strdup (args[2]); + args[6] = strdup (args[3]); + + { + time_t t = time ((time_t *) 0); + struct tm *tm = localtime (&t); + args[7] = malloc (30); + strftime (args[7], 29, "%d-%b-%Y %H:%M", tm); + for (s = args[7]; *s; s++) + if (isalpha(*s)) *s = toupper (*s); + } + + arg_count = 0; + for (i = 0; i < countof(lines); i++) + { + const char *fmt = lines[i]; + if (! strcmp (fmt, "...")) + { + int steps = 180 + (random() % 60); + while (--steps >= 0) + { + BSOD_TEXT (bst, LEFT, "."); + BSOD_PAUSE (bst, dot_delay); + } + } + else + { + char *fmt2 = malloc (strlen (fmt) * 2 + 1); + for (s = (char *) fmt, s1 = fmt2; *s; s++) + { + if (*s == '#') + { + strcpy (s1, args[arg_count++]); + s1 += strlen(s1); + } + else + *s1++ = *s; + } + *s1 = 0; + BSOD_CHAR_DELAY (bst, char_delay); + BSOD_TEXT (bst, LEFT, fmt2); + free (fmt2); + BSOD_CHAR_DELAY (bst, 0); + BSOD_PAUSE (bst, chunk_delay); + } + } + + for (i = 0; i < countof (args); i++) + free (args[i]); + + XClearWindow(dpy, window); + return bst; +} + + +/* HVX (formerly GCOS6) and TPS6 crash + by Brian Garratt + + GCOS6 is a Unix-like operating system developed by Honeywell in the + 1970s in collaboration with MIT and AT&T (who called their version + UNIX). Both are very much like MULTICS which Honeywell got from GE. + + HVX ("High-performance Virtual System on Unix") is an AIX application + which emulates GCOS6 hardware on RS6000-like machines. + */ +static struct bsod_state * +hvx (Display *dpy, Window window) +{ + struct bsod_state *bst = make_bsod_state (dpy, window, "hvx", "HVX"); + + bst->scroll_p = True; + bst->wrap_p = True; + bst->y = bst->xgwa.height - bst->bottom_margin - bst->font->ascent; + + BSOD_CHAR_DELAY (bst, 10000); + BSOD_TEXT (bst, LEFT, + "(TP) Trap no E Effective address 00000000 Instruction D7DE\n" + "(TP) Registers :\n" + "(TP) B1 -> B7 03801B02 00000000 03880D45 038BABDB 0388AFFD" + " 0389B3F8 03972317\n" + "(TP) R1 -> R7 0001 0007 F10F 090F 0020 0106 0272\n" + "(TP) P I Z M1 0388A18B 3232 0000 FF00\n" + "(TP) Program counter is at offset 0028 from string YTPAD\n" + "(TP) User id of task which trapped is LT 626\n" + "(TP)?\n" + ); + BSOD_PAUSE (bst, 1000000); + + BSOD_CHAR_DELAY (bst, 100000); + BSOD_TEXT (bst, LEFT, " TP CLOSE ALL"); + + BSOD_CHAR_DELAY (bst, 10000); + BSOD_TEXT (bst, LEFT, "\n(TP)?\n"); + BSOD_PAUSE (bst, 1000000); + + BSOD_CHAR_DELAY (bst, 100000); + BSOD_TEXT (bst, LEFT, " TP ABORT -LT ALL"); + + BSOD_CHAR_DELAY (bst, 10000); + BSOD_TEXT (bst, LEFT, "\n(TP)?\n"); + BSOD_PAUSE (bst, 1000000); + + BSOD_CHAR_DELAY (bst, 100000); + BSOD_TEXT (bst, LEFT, " TP STOP KILL"); + + BSOD_CHAR_DELAY (bst, 10000); + BSOD_TEXT (bst, LEFT, + "\n" + "(TP)?\n" + "Core dumps initiated for selected HVX processes ...\n" + "Core dumps complete.\n" + "Fri Jul 19 15:53:09 2002\n" + "Live registers for cp 0:\n" + " P = 7de3 IW=0000 I=32 CI=30000000 S=80006013" + " IV=aa0 Level=13\n" + " R1-7 = 1f 913 13 4 8 0 0\n" + " B1-7 = 64e71b a93 50e 64e73c 6c2c 7000 b54\n" + "Memory dump starting to file /var/hvx/dp01/diag/Level2 ...\n" + "Memory dump complete.\n" + ); + + XClearWindow(dpy, window); + return bst; +} + + +/* HPUX panic, by Tobias Klausmann + */ +static struct bsod_state * +hpux (Display *dpy, Window window) +{ + struct bsod_state *bst = make_bsod_state (dpy, window, "hvx", "HVX"); + const char *sysname; + char buf[2048]; + + bst->scroll_p = True; + bst->y = bst->xgwa.height - bst->bottom_margin - bst->font->ascent; + + sysname = "HPUX"; +# ifdef HAVE_UNAME + { + struct utsname uts; + char *s; + if (uname (&uts) >= 0) + sysname = uts.nodename; + s = strchr (sysname, '.'); + if (s) *s = 0; + } +# endif /* !HAVE_UNAME */ + + BSOD_TEXT (bst, LEFT, + " " + " " + " \n"); + sprintf (buf, "%.100s [HP Release B.11.00] (see /etc/issue)\n", sysname); + BSOD_TEXT (bst, LEFT, buf); + BSOD_PAUSE (bst, 1000000); + BSOD_TEXT (bst, LEFT, + "Console Login:\n" + "\n" + " ******* Unexpected HPMC/TOC. Processor HPA FFFFFFFF'" + "FFFA0000 *******\n" + " GENERAL REGISTERS:\n" + "r00/03 00000000'00000000 00000000'00000000 00000000'00000000 00000000'" + "006C76C0\n" + "r04/07 00000000'00000001 00000000'0126E328 00000000'00000000 00000000'" + "0122B640\n" + "r08/11 00000000'00000000 00000000'0198CFC0 00000000'000476FE 00000000'" + "00000001\n" + "r12/15 00000000'40013EE8 00000000'08000080 00000000'4002530C 00000000'" + "4002530C\n" + "r16/19 00000000'7F7F2A00 00000000'00000001 00000000'00000000 00000000'" + "00000000\n" + "r20/23 00000000'006C8048 00000000'00000001 00000000'00000000 00000000'" + "00000000\n" + "r24/27 00000000'00000000 00000000'00000000 00000000'00000000 00000000'" + "00744378\n" + "r28/31 00000000'00000000 00000000'007DD628 00000000'0199F2B0 00000000'" + "00000000\n" + " CONTROL REGISTERS:\n" + "sr0/3 00000000'0F3B4000 00000000'0C2A2000 00000000'016FF800 00000000'" + "00000000\n" + "sr4/7 00000000'00000000 00000000'016FF800 00000000'0DBF1400 00000000'" + "00000000\n" + "pcq = 00000000'00000000.00000000'00104950 00000000'00000000.00000000'" + "00104A14\n" + "isr = 00000000'10240006 ior = 00000000'67D9E220 iir = 08000240 rctr = " + "7FF10BB6\n" + "\n" + "pid reg cr8/cr9 00007700'0000B3A9 00000000'0000C5D8\n" + "pid reg cr12/cr13 00000000'00000000 00000000'00000000\n" + "ipsw = 000000FF'080CFF1F iva = 00000000'0002C000 sar = 3A ccr = C0\n" + "tr0/3 00000000'006C76C0 00000000'00000001 00000000'00000000 00000000'" + "7F7CE000\n" + "tr4/7 00000000'03790000 0000000C'4FB68340 00000000'C07EE13F 00000000'" + "0199F2B0\n" + "eiem = FFFFFFF0'FFFFFFFF eirr = 80000000'00000000 itmr = 0000000C'" + "4FD8EDE1\n" + "cr1/4 00000000'00000000 00000000'00000000 00000000'00000000 00000000'" + "00000000\n" + "cr5/7 00000000'00000000 00000000'00000000 00000000'" + "00000000\n" + " MACHINE CHECK PARAMETERS:\n" + "Check Type = 00000000 CPU STATE = 9E000001 Cache Check = 00000000\n" + "TLB Check = 00000000 Bus Check = 00000000 PIM State = ? SIU " + "Status = ????????\n" + "Assists = 00000000 Processor = 00000000\n" + "Slave Addr = 00000000'00000000 Master Addr = 00000000'00000000\n" + "\n" + "\n" + "TOC, pcsq.pcoq = 0'0.0'104950 , isr.ior = 0'10240006.0'67d9e220\n" + "@(#)B2352B/9245XB HP-UX (B.11.00) #1: Wed Nov 5 22:38:19 PST 1997\n" + "Transfer of control: (display==0xd904, flags==0x0)\n" + "\n" + "\n" + "\n" + "*** A system crash has occurred. (See the above messages for details.)\n" + "*** The system is now preparing to dump physical memory to disk, for use\n" + "*** in debugging the crash.\n" + "\n" + "*** The dump will be a SELECTIVE dump: 40 of 256 megabytes.\n" + "*** To change this dump type, press any key within 10 seconds.\n" + "*** Proceeding with selective dump.\n" + "\n" + "*** The dump may be aborted at any time by pressing ESC.\n"); + + { + int i; + int steps = 11; + int size = 40; + for (i = 0; i <= steps; i++) + { + if (i > steps) i = steps; + sprintf (buf, + "*** Dumping: %3d%% complete (%d of 40 MB) (device 64:0x2)\r", + i * 100 / steps, + i * size / steps); + BSOD_TEXT (bst, LEFT, buf); + BSOD_PAUSE (bst, 1500000); + } + } + + BSOD_TEXT (bst, LEFT, "\n*** System rebooting.\n"); + + XClearWindow(dpy, window); + return bst; +} + + +/* IBM OS/390 aka MVS aka z/OS. + Text from Dan Espen . + Apparently this isn't actually a crash, just a random session... + But who can tell. + */ +static struct bsod_state * +os390 (Display *dpy, Window window) +{ + struct bsod_state *bst = make_bsod_state (dpy, window, "os390", "OS390"); + + bst->scroll_p = True; + bst->y = bst->xgwa.height - bst->bottom_margin - bst->font->ascent; + + BSOD_LINE_DELAY (bst, 100000); + BSOD_TEXT (bst, LEFT, + "\n*** System rebooting.\n" + "* ISPF Subtask abend *\n" + "SPF ENDED DUE TO ERROR+\n" + "READY\n" + "\n" + "IEA995I SYMPTOM DUMP OUTPUT\n" + " USER COMPLETION CODE=0222\n" + " TIME=23.00.51 SEQ=03210 CPU=0000 ASID=00AE\n" + " PSW AT TIME OF ERROR 078D1000 859DAF18 ILC 2 INTC 0D\n" + " NO ACTIVE MODULE FOUND\n" + " NAME=UNKNOWN\n" + " DATA AT PSW 059DAF12 - 00181610 0A0D9180 70644710\n" + " AR/GR 0: 00000000/80000000 1: 00000000/800000DE\n" + " 2: 00000000/196504DC 3: 00000000/00037A78\n" + " 4: 00000000/00037B78 5: 00000000/0003351C\n" + " 6: 00000000/0000F0AD 7: 00000000/00012000\n" + " 8: 00000000/059DAF10 9: 00000000/0002D098\n" + " A: 00000000/059D9F10 B: 00000000/059D8F10\n" + " C: 00000000/859D7F10 D: 00000000/00032D60\n" + " E: 00000000/00033005 F: 01000002/00000041\n" + " END OF SYMPTOM DUMP\n" + "ISPS014 - ** Logical screen request failed - abend 0000DE **\n" + "ISPS015 - ** Contact your system programmer or dialog developer.**\n" + "*** ISPF Main task abend ***\n" + "IEA995I SYMPTOM DUMP OUTPUT\n" + " USER COMPLETION CODE=0222\n" + " TIME=23.00.52 SEQ=03211 CPU=0000 ASID=00AE\n" + " PSW AT TIME OF ERROR 078D1000 8585713C ILC 2 INTC 0D\n" + " ACTIVE LOAD MODULE ADDRESS=05855000 OFFSET=0000213C\n" + " NAME=ISPMAIN\n" + " DATA AT PSW 05857136 - 00181610 0A0D9180 D3304770\n" + " GR 0: 80000000 1: 800000DE\n" + " 2: 00015260 3: 00000038\n" + " 4: 00012508 5: 00000000\n" + " 6: 000173AC 7: FFFFFFF8\n" + " 8: 05858000 9: 00012CA0\n" + " A: 05857000 B: 05856000\n" + " C: 85855000 D: 00017020\n" + " E: 85857104 F: 00000000\n" + " END OF SYMPTOM DUMP\n" + "READY\n" + "***"); + BSOD_CURSOR (bst, CURSOR_LINE, 240000, 999999); + + XClearWindow(dpy, window); + return bst; +} + + +/* Compaq Tru64 Unix panic, by jwz as described by + Tobias Klausmann + */ +static struct bsod_state * +tru64 (Display *dpy, Window window) +{ + struct bsod_state *bst = make_bsod_state (dpy, window, "tru64", "Tru64"); + const char *sysname; + char buf[2048]; + + bst->scroll_p = True; + bst->y = bst->xgwa.height - bst->bottom_margin - bst->font->ascent; + + sysname = "127.0.0.1"; +# ifdef HAVE_UNAME + { + struct utsname uts; + if (uname (&uts) >= 0) + sysname = uts.nodename; + } +# endif /* !HAVE_UNAME */ + + sprintf (buf, + "Compaq Tru64 UNIX V5.1B (Rev. 2650) (%.100s) console\n" + "\n" + "login: ", + sysname); + BSOD_TEXT (bst, LEFT, buf); + BSOD_PAUSE (bst, 6000000); + + BSOD_TEXT (bst, LEFT, + "panic (cpu 0): trap: illegal instruction\n" + "kernel inst fault=gentrap, ps=0x5, pc=0xfffffc0000593878, inst=0xaa\n" + "kernel inst fault=gentrap, ps=0x5, pc=0xfffffc0000593878, inst=0xaa\n" + " \n" + "DUMP: blocks available: 1571600\n" + "DUMP: blocks wanted: 100802 (partial compressed dump) [OKAY]\n" + "DUMP: Device Disk Blocks Available\n" + "DUMP: ------ ---------------------\n" + "DUMP: 0x1300023 1182795 - 1571597 (of 1571598) [primary swap]\n" + "DUMP.prom: Open: dev 0x5100041, block 2102016: SCSI 0 11 0 2 200 0 0\n" + "DUMP: Writing header... [1024 bytes at dev 0x1300023, block 1571598]\n" + "DUMP: Writing data"); + + { + int i; + int steps = 4 + (random() % 8); + BSOD_CHAR_DELAY (bst, 1000000); + for (i = 0; i < steps; i++) + BSOD_TEXT (bst, LEFT, "."); + BSOD_CHAR_DELAY (bst, 0); + sprintf (buf, "[%dMB]\n", steps); + BSOD_TEXT (bst, LEFT, buf); + } + + BSOD_TEXT (bst, LEFT, + "DUMP: Writing header... [1024 bytes at dev 0x1300023, block 1571598]\n" + "DUMP: crash dump complete.\n" + "kernel inst fault=gentrap, ps=0x5, pc=0xfffffc0000593878, inst=0xaa\n" + " \n" + "DUMP: second crash dump skipped: 'dump_savecnt' enforced.\n"); + BSOD_PAUSE (bst, 4000000); + + BSOD_TEXT (bst, LEFT, + "\n" + "halted CPU 0\n" + "\n" + "halt code = 5\n" + "HALT instruction executed\n" + "PC = fffffc00005863b0\n"); + BSOD_PAUSE (bst, 3000000); + + BSOD_TEXT (bst, LEFT, + "\n" + "CPU 0 booting\n" + "\n" + "\n" + "\n"); + + XClearWindow(dpy, window); + return bst; +} + + +/* MS-DOS, by jwz + */ +static struct bsod_state * +msdos (Display *dpy, Window window) +{ + struct bsod_state *bst = make_bsod_state (dpy, window, "msdos", "MSDOS"); + + BSOD_CHAR_DELAY (bst, 10000); + BSOD_TEXT (bst, LEFT, "C:\\WINDOWS>"); + BSOD_CURSOR (bst, CURSOR_LINE, 200000, 8); + + BSOD_CHAR_DELAY (bst, 200000); + BSOD_TEXT (bst, LEFT, "dir a:"); + BSOD_PAUSE (bst, 1000000); + + BSOD_CHAR_DELAY (bst, 10000); + BSOD_TEXT (bst, LEFT, "\nNot ready reading drive A\nAbort, Retry, Fail?"); + + BSOD_CURSOR (bst, CURSOR_LINE, 200000, 10); + BSOD_CHAR_DELAY (bst, 200000); + BSOD_TEXT (bst, LEFT, "f"); + BSOD_PAUSE (bst, 1000000); + + BSOD_CHAR_DELAY (bst, 10000); + BSOD_TEXT (bst, LEFT, + "\n\n\nNot ready reading drive A\nAbort, Retry, Fail?"); + + BSOD_CURSOR (bst, CURSOR_LINE, 200000, 10); + BSOD_CHAR_DELAY (bst, 200000); + BSOD_TEXT (bst, LEFT, "f"); + BSOD_PAUSE (bst, 1000000); + + BSOD_CHAR_DELAY (bst, 10000); + BSOD_TEXT (bst, LEFT, "\nVolume in drive A has no label\n\n" + "Not ready reading drive A\nAbort, Retry, Fail?"); + + BSOD_CURSOR (bst, CURSOR_LINE, 200000, 12); + BSOD_CHAR_DELAY (bst, 200000); + BSOD_TEXT (bst, LEFT, "a"); + BSOD_PAUSE (bst, 1000000); + + BSOD_CHAR_DELAY (bst, 10000); + BSOD_TEXT (bst, LEFT, "\n\nC:\\WINDOWS>"); + + BSOD_CURSOR (bst, CURSOR_LINE, 200000, 999999); + + XClearWindow(dpy, window); + return bst; +} + + +/* nvidia, by jwz. + * + * This is what happens if an Nvidia card goes into some crazy text mode. + * Most often seen on the second screen of a dual-head system when the + * proper driver isn't loaded. + */ +typedef struct { int fg; int bg; int bit; Bool blink; } nvcell; + +static void +nvspatter (nvcell *grid, int rows, int cols, int ncolors, int nbits, + Bool fill_p) +{ + int max = rows * cols; + int from = fill_p ? 0 : random() % (max - 1); + int len = fill_p ? max : random() % (cols * 4); + int to = from + len; + int i; + Bool noisy = ((random() % 4) == 0); + Bool diag = (noisy || fill_p) ? 0 : ((random() % 4) == 0); + + int fg = random() % ncolors; + int bg = random() % ncolors; + int blink = ((random() % 4) == 0); + int bit = (random() % nbits); + + if (to > max) to = max; + + if (diag) + { + int src = random() % (rows * cols); + int len2 = (cols / 2) - (random() % 5); + int j = src; + for (i = from; i < to; i++, j++) + { + if (j > src + len2 || j >= max) + j = src; + if (i >= max) abort(); + if (j >= max) abort(); + grid[j] = grid[i]; + } + } + else + for (i = from; i < to; i++) + { + nvcell *cell = &grid[i]; + cell->fg = fg; + cell->bg = bg; + cell->bit = bit; + cell->blink = blink; + + if (noisy) + { + fg = random() % ncolors; + bg = random() % ncolors; + blink = ((random() % 8) == 0); + } + } +} + +typedef struct { + struct bsod_state *bst; + GC gc1; + Pixmap bits[5]; + int rows, cols; + int cellw, cellh; + nvcell *grid; + int ncolors; + unsigned long colors[256]; + int tick; +} nvstate; + + +static void +nvidia_free (struct bsod_state *bst) +{ + nvstate *nvs = (nvstate *) bst->closure; + int i; + XFreeColors (bst->dpy, bst->xgwa.colormap, nvs->colors, nvs->ncolors, 0); + for (i = 0; i < countof(nvs->bits); i++) + XFreePixmap (bst->dpy, nvs->bits[i]); + XFreeGC (bst->dpy, nvs->gc1); + free (nvs->grid); + free (nvs); +} + +static int +nvidia_draw (struct bsod_state *bst) +{ + nvstate *nvs = (nvstate *) bst->closure; + int x, y; + + for (y = 0; y < nvs->rows; y++) + for (x = 0; x < nvs->cols; x++) + { + nvcell *cell = &nvs->grid[y * nvs->cols + x]; + unsigned long fg = nvs->colors[cell->fg]; + unsigned long bg = nvs->colors[cell->bg]; + Bool flip = cell->blink && (nvs->tick & 1); + XSetForeground (bst->dpy, bst->gc, flip ? fg : bg); + XSetBackground (bst->dpy, bst->gc, flip ? bg : fg); + XCopyPlane (bst->dpy, nvs->bits[cell->bit], bst->window, bst->gc, + 0, 0, nvs->cellw, nvs->cellh, + x * nvs->cellw, y * nvs->cellh, 1L); + } + + nvs->tick++; + if ((random() % 5) == 0) /* change the display */ + nvspatter (nvs->grid, nvs->rows, nvs->cols, nvs->ncolors, + countof(nvs->bits), False); + + return 250000; +} + + +static struct bsod_state * +nvidia (Display *dpy, Window window) +{ + struct bsod_state *bst = make_bsod_state (dpy, window, "nvidia", "nVidia"); + nvstate *nvs = (nvstate *) calloc (1, sizeof (*nvs)); + + XGCValues gcv; + int i; + + nvs->bst = bst; + bst->closure = nvs; + bst->draw_cb = nvidia_draw; + bst->free_cb = nvidia_free; + + nvs->cols = 80; + nvs->rows = 25; + nvs->cellw = bst->xgwa.width / nvs->cols; + nvs->cellh = bst->xgwa.height / nvs->rows; + if (nvs->cellw < 8 || nvs->cellh < 18) + nvs->cellw = 8, nvs->cellh = 18; + nvs->cols = (bst->xgwa.width / nvs->cellw) + 1; + nvs->rows = (bst->xgwa.height / nvs->cellh) + 1; + + nvs->grid = (nvcell *) calloc (sizeof(*nvs->grid), nvs->rows * nvs->cols); + + /* Allocate colors + */ + nvs->ncolors = 16; + for (i = 0; i < nvs->ncolors; i++) + { + XColor c; + c.red = random() & 0xFFFF; + c.green = random() & 0xFFFF; + c.blue = random() & 0xFFFF; + c.flags = DoRed|DoGreen|DoBlue; + XAllocColor (dpy, bst->xgwa.colormap, &c); + nvs->colors[i] = c.pixel; + } + + /* Construct corrupted character bitmaps + */ + for (i = 0; i < countof(nvs->bits); i++) + { + int j; + + nvs->bits[i] = XCreatePixmap (dpy, window, nvs->cellw, nvs->cellh, 1); + if (!nvs->gc1) nvs->gc1 = XCreateGC (dpy, nvs->bits[i], 0, &gcv); + + XSetForeground (dpy, nvs->gc1, 0); + XFillRectangle (dpy, nvs->bits[i], nvs->gc1, 0, 0, + nvs->cellw, nvs->cellh); + XSetForeground (dpy, nvs->gc1, 1); + + if ((random() % 40) != 0) + for (j = 0; j < ((nvs->cellw * nvs->cellh) / 16); j++) + XFillRectangle (dpy, nvs->bits[i], nvs->gc1, + (random() % (nvs->cellw-2)) & ~1, + (random() % (nvs->cellh-2)) & ~1, + 2, 2); + } + + /* Randomize the grid + */ + nvspatter (nvs->grid, nvs->rows, nvs->cols, nvs->ncolors, + countof(nvs->bits), True); + for (i = 0; i < 20; i++) + nvspatter (nvs->grid, nvs->rows, nvs->cols, nvs->ncolors, + countof(nvs->bits), False); + + return bst; +} + + +/* + * Simulate various Apple ][ crashes. The memory map encouraged many programs + * to use the primary hi-res video page for various storage, and the secondary + * hi-res page for active display. When it crashed into Applesoft or the + * monitor, it would revert to the primary page and you'd see memory garbage on + * the screen. Also, it was common for copy-protected games to use the primary + * text page for important code, because that made it really hard to + * reverse-engineer them. The result often looked like what this generates. + * + * The Apple ][ logic and video hardware is in apple2.c. The TV is emulated by + * analogtv.c for maximum realism + * + * Trevor Blackwell + */ + +static const char * const apple2_basic_errors[]={ + "BREAK", + "NEXT WITHOUT FOR", + "SYNTAX ERROR", + "RETURN WITHOUT GOSUB", + "ILLEGAL QUANTITY", + "OVERFLOW", + "OUT OF MEMORY", + "BAD SUBSCRIPT ERROR", + "DIVISION BY ZERO", + "STRING TOO LONG", + "FORMULA TOO COMPLEX", + "UNDEF'D FUNCTION", + "OUT OF DATA" +#if 0 + , + "DEFAULT ARGUMENTS ARE NOT ALLOWED IN DECLARATION OF FRIEND " + "TEMPLATE SPECIALIZATION" +#endif + +}; +static const char * const apple2_dos_errors[]={ + "VOLUME MISMATCH", + "I/O ERROR", + "DISK FULL", + "NO BUFFERS AVAILABLE", + "PROGRAM TOO LARGE", +}; + +static void a2controller_crash(apple2_sim_t *sim, int *stepno, + double *next_actiontime) +{ + apple2_state_t *st=sim->st; + char *s; + int i; + + struct mydata { + int fillptr; + int fillbyte; + } *mine; + + if (!sim->controller_data) + sim->controller_data = calloc(sizeof(struct mydata),1); + mine=(struct mydata *) sim->controller_data; + + switch(*stepno) { + case 0: + + a2_init_memory_active(sim); + sim->dec->powerup = 1000.0; + + if (random()%3==0) { + st->gr_mode=0; + *next_actiontime+=0.4; + *stepno=100; + } + else if (random()%4==0) { + st->gr_mode=A2_GR_LORES; + if (random()%3==0) st->gr_mode |= A2_GR_FULL; + *next_actiontime+=0.4; + *stepno=100; + } + else if (random()%2==0) { + st->gr_mode=A2_GR_HIRES; + *stepno=300; + } + else { + st->gr_mode=A2_GR_HIRES; + *next_actiontime+=0.4; + *stepno=100; + } + break; + + case 100: + /* An illegal instruction or a reset caused it to drop into the + assembly language monitor, where you could disassemble code & view + data in hex. */ + if (random()%3==0) { + char ibytes[128]; + char itext[128]; + int addr=0xd000+random()%0x3000; + sprintf(ibytes, + "%02X",random()%0xff); + sprintf(itext, + "???"); + sprintf(sim->printing_buf, + "\n\n" + "%04X: %-15s %s\n" + " A=%02X X=%02X Y=%02X S=%02X F=%02X\n" + "*", + addr,ibytes,itext, + random()%0xff, random()%0xff, + random()%0xff, random()%0xff, + random()%0xff); + sim->printing=sim->printing_buf; + a2_goto(st,23,1); + if (st->gr_mode) { + *stepno=180; + } else { + *stepno=200; + } + sim->prompt='*'; + *next_actiontime += 2.0 + (random()%1000)*0.0002; + } + else { + /* Lots of programs had at least their main functionality in + Applesoft Basic, which had a lot of limits (memory, string + length, etc) and would sometimes crash unexpectedly. */ + sprintf(sim->printing_buf, + "\n" + "\n" + "\n" + "?%s IN %d\n" + "\001]", + apple2_basic_errors[random() % + (sizeof(apple2_basic_errors) + /sizeof(char *))], + (1000*(random()%(random()%59+1)) + + 100*(random()%(random()%9+1)) + + 5*(random()%(random()%199+1)) + + 1*(random()%(random()%(random()%2+1)+1)))); + sim->printing=sim->printing_buf; + a2_goto(st,23,1); + *stepno=110; + sim->prompt=']'; + *next_actiontime += 2.0 + (random()%1000)*0.0002; + } + break; + + case 110: + if (random()%3==0) { + /* This was how you reset the Basic interpreter. The sort of + incantation you'd have on a little piece of paper taped to the + side of your machine */ + sim->typing="CALL -1370"; + *stepno=120; + } + else if (random()%2==0) { + sim->typing="CATALOG\n"; + *stepno=170; + } + else { + *next_actiontime+=1.0; + *stepno=999; + } + break; + + case 120: + *stepno=130; + *next_actiontime += 0.5; + break; + + case 130: + st->gr_mode=0; + a2_cls(st); + a2_goto(st,0,16); + for (s="APPLE ]["; *s; s++) a2_printc(st,*s); + a2_goto(st,23,0); + a2_printc(st,']'); + *next_actiontime+=1.0; + *stepno=999; + break; + + case 170: + if (random()%50==0) { + sprintf(sim->printing_buf, + "\nDISK VOLUME 254\n\n" + " A 002 HELLO\n" + "\n" + "]"); + sim->printing=sim->printing_buf; + } + else { + sprintf(sim->printing_buf,"\n?%s\n]", + apple2_dos_errors[random()% + (sizeof(apple2_dos_errors) / + sizeof(char *))]); + sim->printing=sim->printing_buf; + } + *stepno=999; + *next_actiontime+=1.0; + break; + + case 180: + if (random()%2==0) { + /* This was how you went back to text mode in the monitor */ + sim->typing="FB4BG"; + *stepno=190; + } else { + *next_actiontime+=1.0; + *stepno=999; + } + break; + + case 190: + st->gr_mode=0; + a2_invalidate(st); + a2_printc(st,'\n'); + a2_printc(st,'*'); + *stepno=200; + *next_actiontime+=2.0; + break; + + case 200: + /* This reset things into Basic */ + if (random()%2==0) { + sim->typing="FAA6G"; + *stepno=120; + } + else { + *stepno=999; + *next_actiontime+=sim->delay; + } + break; + + case 300: + for (i=0; i<1500; i++) { + a2_poke(st, mine->fillptr, mine->fillbyte); + mine->fillptr++; + mine->fillbyte = (mine->fillbyte+1)&0xff; + } + *next_actiontime += 0.08; + /* When you hit c000, it changed video settings */ + if (mine->fillptr>=0xc000) { + a2_invalidate(st); + st->gr_mode=0; + } + /* And it seemed to reset around here, I dunno why */ + if (mine->fillptr>=0xcf00) *stepno=130; + break; + + case 999: + break; + + case A2CONTROLLER_FREE: + free(mine); + break; + } +} + +static int +a2_draw (struct bsod_state *bst) +{ + apple2_sim_t *sim = (apple2_sim_t *) bst->closure; + if (! sim) { + sim = apple2_start (bst->dpy, bst->window, 9999999, a2controller_crash); + bst->closure = sim; + } + + if (! apple2_one_frame (sim)) { + bst->closure = 0; + } + + return 10000; +} + +static void +a2_free (struct bsod_state *bst) +{ + apple2_sim_t *sim = (apple2_sim_t *) bst->closure; + if (sim) { + sim->stepno = A2CONTROLLER_DONE; + a2_draw (bst); /* finish up */ + if (bst->closure) abort(); /* should have been freed by now */ + } +} + + +static struct bsod_state * +apple2crash (Display *dpy, Window window) +{ + struct bsod_state *bst = make_bsod_state (dpy, window, "apple2", "Apple2"); + bst->draw_cb = a2_draw; + bst->free_cb = a2_free; + return bst; +} + + +/***************************************************************************** + *****************************************************************************/ + + +static const struct { + const char *name; + struct bsod_state * (*fn) (Display *, Window); +} all_modes[] = { + { "Windows", windows_31 }, + { "NT", windows_nt }, + { "Win2K", windows_other }, + { "Amiga", amiga }, + { "Mac", mac }, + { "MacsBug", macsbug }, + { "Mac1", mac1 }, + { "MacX", macx }, + { "SCO", sco }, + { "HVX", hvx }, + { "HPPALinux", hppa_linux }, + { "SparcLinux", sparc_linux }, + { "BSD", bsd }, + { "Atari", atari }, +#ifndef HAVE_COCOA + { "BlitDamage", blitdamage }, +#endif + { "Solaris", sparc_solaris }, + { "Linux", linux_fsck }, + { "HPUX", hpux }, + { "OS390", os390 }, + { "Tru64", tru64 }, + { "VMS", vms }, + { "OS2", os2 }, + { "MSDOS", msdos }, + { "Nvidia", nvidia }, + { "Apple2", apple2crash }, +}; + + +struct driver_state { + const char *name; + int only, which; + int delay; + time_t start; + Bool debug_p, cycle_p; + struct bsod_state *bst; +}; + + +static void +hack_title (struct driver_state *dst) +{ +# ifndef HAVE_COCOA + char *oname = 0; + XFetchName (dst->bst->dpy, dst->bst->window, &oname); + if (oname && !strncmp (oname, "BSOD: ", 6)) { + char *tail = oname + 4; + char *s = strchr (tail+1, ':'); + char *nname; + if (s) tail = s; + nname = malloc (strlen (tail) + strlen (dst->name) + 20); + sprintf (nname, "BSOD: %s%s", dst->name, tail); + XStoreName (dst->bst->dpy, dst->bst->window, nname); + free (nname); + } +# endif /* !HAVE_COCOA */ +} + +static void * +bsod_init (Display *dpy, Window window) +{ + struct driver_state *dst = (struct driver_state *) calloc (1, sizeof(*dst)); + char *s; + + dst->delay = get_integer_resource (dpy, "delay", "Integer"); + if (dst->delay < 3) dst->delay = 3; + + dst->debug_p = get_boolean_resource (dpy, "debug", "Boolean"); + + dst->only = -1; + s = get_string_resource(dpy, "doOnly", "DoOnly"); + if (s && !strcasecmp (s, "cycle")) + { + dst->which = -1; + dst->cycle_p = True; + } + else if (s && *s) + { + int count = countof(all_modes); + for (dst->only = 0; dst->only < count; dst->only++) + if (!strcasecmp (s, all_modes[dst->only].name)) + break; + if (dst->only >= count) + { + fprintf (stderr, "%s: unknown -only mode: \"%s\"\n", progname, s); + dst->only = -1; + } + } + if (s) free (s); + + dst->name = "none"; + dst->which = -1; + return dst; +} + + +static unsigned long +bsod_draw (Display *dpy, Window window, void *closure) +{ + struct driver_state *dst = (struct driver_state *) closure; + time_t now; + int time_left; + + AGAIN: + now = time ((time_t *) 0); + time_left = dst->start + dst->delay - now; + + if (dst->bst && dst->bst->img_loader) /* still loading */ + { + dst->bst->img_loader = + load_image_async_simple (dst->bst->img_loader, 0, 0, 0, 0, 0); + return 100000; + } + + if (! dst->bst && time_left > 0) /* run completed; wait out the delay */ + { + if (dst->debug_p) + fprintf (stderr, "%s: %s: %d left\n", progname, dst->name, time_left); + return 500000; + } + + else if (dst->bst) /* sub-mode currently running */ + { + int this_delay = -1; + + if (time_left > 0) + this_delay = bsod_pop (dst->bst); + + /* XSync (dpy, False); slows down char drawing too much on HAVE_COCOA */ + + if (this_delay == 0) + goto AGAIN; /* no delay, not expired: stay here */ + else if (this_delay >= 0) + return this_delay; /* return; time to sleep */ + else + { /* sub-mode run completed or expired */ + if (dst->debug_p) + fprintf (stderr, "%s: %s: done\n", progname, dst->name); + free_bsod_state (dst->bst); + dst->bst = 0; + return 0; + } + } + else /* launch a new sub-mode */ + { + if (dst->cycle_p) + dst->which = (dst->which + 1) % countof(all_modes); + else if (dst->only >= 0) + dst->which = dst->only; + else + { + int count = countof(all_modes); + int i; + + for (i = 0; i < 200; i++) + { + char name[100], class[100]; + int new_mode = (random() & 0xFF) % count; + + if (i < 100 && new_mode == dst->which) + continue; + + sprintf (name, "do%s", all_modes[new_mode].name); + sprintf (class, "Do%s", all_modes[new_mode].name); + + if (get_boolean_resource (dpy, name, class)) + { + dst->which = new_mode; + break; + } + } + + if (i >= 200) + { + fprintf (stderr, "%s: no display modes enabled?\n", progname); + /* exit (-1); */ + dst->which = dst->only = 0; + } + } + + if (dst->debug_p) + fprintf (stderr, "%s: %s: launch\n", progname, + all_modes[dst->which].name); + + /* Run the mode setup routine... + */ + if (dst->bst) abort(); + dst->name = all_modes[dst->which].name; + dst->bst = all_modes[dst->which].fn (dpy, window); + dst->start = (dst->bst ? time ((time_t *) 0) : 0); + + /* Reset the structure run state to the beginning, + and do some sanitization of the cursor position + before the first run. + */ + if (dst->bst) + { + if (dst->debug_p) + fprintf (stderr, "%s: %s: queue size: %d (%d)\n", progname, + dst->name, dst->bst->pos, dst->bst->queue_size); + + hack_title (dst); + dst->bst->pos = 0; + dst->bst->x = dst->bst->current_left = dst->bst->left_margin; + + if (dst->bst->y < dst->bst->top_margin + dst->bst->font->ascent) + dst->bst->y = dst->bst->top_margin + dst->bst->font->ascent; + } + } + + return 0; +} + + +static void +bsod_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + struct driver_state *dst = (struct driver_state *) closure; + + if (dst->bst && + w == dst->bst->xgwa.width && + h == dst->bst->xgwa.height) + return; + + if (dst->debug_p) + fprintf (stderr, "%s: %s: reshape reset\n", progname, dst->name); + + /* just pick a new mode and restart when the window is resized. */ + if (dst->bst) + free_bsod_state (dst->bst); + dst->bst = 0; + dst->start = 0; + dst->name = "none"; + XClearWindow (dpy, window); +} + + +static Bool +bsod_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + struct driver_state *dst = (struct driver_state *) closure; + Bool reset_p = False; + + /* pick a new mode and restart when mouse clicked, or certain keys typed. */ + + if (event->type == ButtonPress) + reset_p = True; + else if (event->type == KeyPress) + { + KeySym keysym; + char c = 0; + XLookupString (&event->xkey, &c, 1, &keysym, 0); + if (c == ' ' || c == '\t' || c == '\r' || c == '\n') + reset_p = True; + } + + if (reset_p) + { + if (dst->debug_p) + fprintf (stderr, "%s: %s: manual reset\n", progname, dst->name); + if (dst->bst) + free_bsod_state (dst->bst); + dst->bst = 0; + dst->start = 0; + dst->name = "none"; + XClearWindow (dpy, window); + return True; + } + else + return False; +} + + +static void +bsod_free (Display *dpy, Window window, void *closure) +{ + struct driver_state *dst = (struct driver_state *) closure; + if (dst->bst) + free_bsod_state (dst->bst); + free (dst); +} + + +static const char *bsod_defaults [] = { + "*delay: 30", + "*debug: False", + + "*doOnly: ", + "*doWindows: True", + "*doNT: True", + "*doWin2K: True", + "*doAmiga: True", + "*doMac: True", + "*doMacsBug: True", + "*doMac1: True", + "*doMacX: True", + "*doSCO: True", + "*doAtari: False", /* boring */ + "*doBSD: False", /* boring */ + "*doLinux: True", + "*doSparcLinux: False", /* boring */ + "*doHPPALinux: True", + "*doBlitDamage: True", + "*doSolaris: True", + "*doHPUX: True", + "*doTru64: True", + "*doApple2: True", + "*doOS390: True", + "*doVMS: True", + "*doHVX: True", + "*doMSDOS: True", + "*doOS2: True", + "*doNvidia: True", + + "*font: 9x15bold", + "*font2: -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*", + "*bigFont: -*-courier-bold-r-*-*-*-180-*-*-m-*-*-*", + "*bigFont2: -*-courier-bold-r-*-*-*-180-*-*-m-*-*-*", + + ".foreground: White", + ".background: Black", + + ".windows.foreground: White", + ".windows.background: #0000AA", /* EGA color 0x01. */ + + ".windowslh.foreground: White", + ".windowslh.background: #AA0000", /* EGA color 0x04. */ + ".windowslh.background2: #AAAAAA", /* EGA color 0x07. */ + + ".amiga.foreground: #FF0000", + ".amiga.background: Black", + ".amiga.background2: White", + + ".mac.foreground: #BBFFFF", + ".mac.background: Black", + + ".atari.foreground: Black", + ".atari.background: White", + + ".macsbug.font: -*-courier-medium-r-*-*-*-80-*-*-m-*-*-*", + ".macsbug.bigFont: -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*", + ".macsbug.foreground: Black", + ".macsbug.background: White", + ".macsbug.borderColor: #AAAAAA", + + ".mac1.foreground: Black", + ".mac1.background: White", + + ".macx.foreground: White", + ".macx.textForeground: White", + ".macx.textBackground: Black", + ".macx.background: #888888", + + ".sco.font: -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*", + ".sco.foreground: White", + ".sco.background: Black", + + ".hvx.font: -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*", + ".hvx.foreground: White", + ".hvx.background: Black", + + ".linux.foreground: White", + ".linux.background: Black", + + ".hppalinux.bigFont: -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*", + ".hppalinux.foreground: White", + ".hppalinux.background: Black", + + ".sparclinux.bigFont: -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*", + ".sparclinux.foreground: White", + ".sparclinux.background: Black", + + ".bsd.font: vga", + ".bsd.bigFont: -sun-console-medium-r-*-*-22-*-*-*-m-*-*-*", + ".bsd.bigFont2: -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*", + ".bsd.foreground: #c0c0c0", + ".bsd.background: Black", + + ".solaris.font: -sun-gallant-*-*-*-*-19-*-*-*-*-120-*-*", + ".solaris.foreground: Black", + ".solaris.background: White", + + ".hpux.bigFont: -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*", + ".hpux.foreground: White", + ".hpux.background: Black", + + ".os390.bigFont: -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*", + ".os390.background: Black", + ".os390.foreground: Red", + + ".tru64.bigFont: -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*", + ".tru64.foreground: White", + ".tru64.background: #0000AA", /* EGA color 0x01. */ + + ".vms.bigFont: -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*", + ".vms.foreground: White", + ".vms.background: Black", + + ".msdos.bigFont: -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*", + ".msdos.foreground: White", + ".msdos.background: Black", + + ".os2.foreground: White", + ".os2.background: Black", + + "*dontClearRoot: True", + + "*apple2TVColor: 50", + "*apple2TVTint: 5", + "*apple2TVBrightness: 10", + "*apple2TVContrast: 90", + "*apple2SimulateUser: True", + + ANALOGTV_DEFAULTS + +#ifdef HAVE_XSHM_EXTENSION + "*useSHM: True", +#endif + 0 +}; + +static const XrmOptionDescRec bsod_options [] = { + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-only", ".doOnly", XrmoptionSepArg, 0 }, + { "-debug", ".debug", XrmoptionNoArg, "True" }, + { "-windows", ".doWindows", XrmoptionNoArg, "True" }, + { "-no-windows", ".doWindows", XrmoptionNoArg, "False" }, + { "-nt", ".doNT", XrmoptionNoArg, "True" }, + { "-no-nt", ".doNT", XrmoptionNoArg, "False" }, + { "-2k", ".doWin2K", XrmoptionNoArg, "True" }, + { "-no-2k", ".doWin2K", XrmoptionNoArg, "False" }, + { "-amiga", ".doAmiga", XrmoptionNoArg, "True" }, + { "-no-amiga", ".doAmiga", XrmoptionNoArg, "False" }, + { "-mac", ".doMac", XrmoptionNoArg, "True" }, + { "-no-mac", ".doMac", XrmoptionNoArg, "False" }, + { "-mac1", ".doMac1", XrmoptionNoArg, "True" }, + { "-no-mac1", ".doMac1", XrmoptionNoArg, "False" }, + { "-macx", ".doMacX", XrmoptionNoArg, "True" }, + { "-no-macx", ".doMacX", XrmoptionNoArg, "False" }, + { "-atari", ".doAtari", XrmoptionNoArg, "True" }, + { "-no-atari", ".doAtari", XrmoptionNoArg, "False" }, + { "-macsbug", ".doMacsBug", XrmoptionNoArg, "True" }, + { "-no-macsbug", ".doMacsBug", XrmoptionNoArg, "False" }, + { "-apple2", ".doApple2", XrmoptionNoArg, "True" }, + { "-no-apple2", ".doApple2", XrmoptionNoArg, "False" }, + { "-sco", ".doSCO", XrmoptionNoArg, "True" }, + { "-no-sco", ".doSCO", XrmoptionNoArg, "False" }, + { "-hvx", ".doHVX", XrmoptionNoArg, "True" }, + { "-no-hvx", ".doHVX", XrmoptionNoArg, "False" }, + { "-bsd", ".doBSD", XrmoptionNoArg, "True" }, + { "-no-bsd", ".doBSD", XrmoptionNoArg, "False" }, + { "-linux", ".doLinux", XrmoptionNoArg, "True" }, + { "-no-linux", ".doLinux", XrmoptionNoArg, "False" }, + { "-hppalinux", ".doHPPALinux", XrmoptionNoArg, "True" }, + { "-no-hppalinux", ".doHPPALinux", XrmoptionNoArg, "False" }, + { "-sparclinux", ".doSparcLinux", XrmoptionNoArg, "True" }, + { "-no-sparclinux", ".doSparcLinux", XrmoptionNoArg, "False" }, + { "-blitdamage", ".doBlitDamage", XrmoptionNoArg, "True" }, + { "-no-blitdamage", ".doBlitDamage", XrmoptionNoArg, "False" }, + { "-nvidia", ".doNvidia", XrmoptionNoArg, "True" }, + { "-no-nvidia", ".doNvidia", XrmoptionNoArg, "False" }, + { "-solaris", ".doSolaris", XrmoptionNoArg, "True" }, + { "-no-solaris", ".doSolaris", XrmoptionNoArg, "False" }, + { "-hpux", ".doHPUX", XrmoptionNoArg, "True" }, + { "-no-hpux", ".doHPUX", XrmoptionNoArg, "False" }, + { "-os390", ".doOS390", XrmoptionNoArg, "True" }, + { "-no-os390", ".doOS390", XrmoptionNoArg, "False" }, + { "-tru64", ".doHPUX", XrmoptionNoArg, "True" }, + { "-no-tru64", ".doTru64", XrmoptionNoArg, "False" }, + { "-vms", ".doVMS", XrmoptionNoArg, "True" }, + { "-no-vms", ".doVMS", XrmoptionNoArg, "False" }, + { "-msdos", ".doMSDOS", XrmoptionNoArg, "True" }, + { "-no-msdos", ".doMSDOS", XrmoptionNoArg, "False" }, + { "-os2", ".doOS2", XrmoptionNoArg, "True" }, + { "-no-os2", ".doOS2", XrmoptionNoArg, "False" }, + ANALOGTV_OPTIONS + { 0, 0, 0, 0 } +}; + + +XSCREENSAVER_MODULE ("BSOD", bsod)