diff --git a/xtrn/bullshit/bullshit.ini b/xtrn/bullshit/bullshit.ini
index e020d38ef2cbe928e5e857391ad990534613121a..050ed417092e08afae89245ad1f2942a0e6c2cbb 100644
--- a/xtrn/bullshit/bullshit.ini
+++ b/xtrn/bullshit/bullshit.ini
@@ -1,13 +1,14 @@
-; Internal code of the message area containing your bulletins
-messageBase = BULLSHIT
-
-; See sbbsdefs.js for valid colors to specify here
-titleColor = WHITE
-headingColor = DARKGRAY
-textColor = LIGHTGRAY
-footerColor = WHITE
-lightbarForeground = LIGHTCYAN
-lightbarBackground = BG_CYAN
-listForeground = LIGHTGRAY
-; borderColor may be a comma-separated list if you want a gradient
-borderColor = LIGHTBLUE,CYAN,LIGHTCYAN,LIGHTGRAY,WHITE
+messageBase = BULLSHIT
+maxMessages = 0
+
+[colors]
+title = WHITE
+text = LIGHTGRAY
+heading = DARKGRAY
+lightbarForeground = LIGHTCYAN
+lightbarBackground = BG_CYAN
+listForeground = LIGHTGRAY
+footer = WHITE
+border = LIGHTBLUE,CYAN,LIGHTCYAN,LIGHTGRAY,WHITE
+
+[files]
diff --git a/xtrn/bullshit/bullshit.js b/xtrn/bullshit/bullshit.js
index 122297710047fe15ba0c9cfcf61142ee326db920..14ae4b72afa7a3c96c8ae61a7aa37e6da95b29b6 100644
--- a/xtrn/bullshit/bullshit.js
+++ b/xtrn/bullshit/bullshit.js
@@ -1,186 +1,388 @@
-load("sbbsdefs.js");
-load("frame.js");
-load("tree.js");
-load("scrollbar.js");
-load("funclib.js");
-
-js.branch_limit = 0;
-
-var frame,
-	titleFrame,
-	listFrame,
-	footerFrame,
-	tree,
-	ini,
-	msgBase,
-	treeScroll;
-
-/*	drawFrameBorder(frame, color, gradient)
-	Draws a border of color 'color' around Frame object 'frame'
-	If 'gradient' is true, 'color' must be an array of colors to draw in order
-	See sbbsdefs.js for valid colors	*/
-var drawFrameBorder = function(frame, color) {
-	var theColor = color;
-	if(color instanceof Array)
-		var sectionLength = Math.round(frame.width / color.length);
-	for(var y = 1; y <= frame.height; y++) {
-		for(var x = 1; x <= frame.width; x++) {
-			if(x > 1 && x < frame.width && y > 1 && y < frame.height)
-				continue;
-			var msg = false;
-			frame.gotoxy(x, y);
-			if(y == 1 && x == 1)
-				msg = ascii(218);
-			else if(y == 1 && x == frame.width)
-				msg = ascii(191);
-			else if(y == frame.height && x == 1)
-				msg = ascii(192);
-			else if(y == frame.height && x == frame.width)
-				msg = ascii(217);
-			else if(x == 1 || x == frame.width)
-				msg = ascii(179);
-			else
-				msg = ascii(196);
-			if(color instanceof Array) {
-				if(x == 1)
-					theColor = color[0];
-				else if(x % sectionLength == 0 && x < frame.width)
-					theColor = color[x / sectionLength];
-				else if(x == frame.width)
-					theColor = color[color.length - 1];
-			}
-			frame.putmsg(msg, theColor);
-		}
-	}
-}
-
-var showMsg = function(msg) {
-	try {
-		var readerFrame = new Frame(2, 5, console.screen_columns - 2, console.screen_rows - 8, BG_BLACK|WHITE, frame);
-		readerFrame.open();
-		msgBase.open();
-		var h = msgBase.get_msg_header(msg);
-		var b = msgBase.get_msg_body(msg);
-		msgBase.close();
-		readerFrame.putmsg(
-			format(
-				"%-52s%s\r\n\r\n",
-				h.subject.substr(0, console.screen_columns - 30),
-				system.timestr(h.when_written_time)
-			),
-			getColor(ini.titleColor)
-		);
-		readerFrame.putmsg(word_wrap(b, console.screen_columns - 2), getColor(ini.textColor));
-		readerFrame.scrollTo(0, 0);
-		var scroller = new ScrollBar(readerFrame, { autohide : true });
-		scroller.open();
-		scroller.cycle();
-	} catch(err) {
-		log(LOG_ERR, err);
-		return false;
-	}
-	while(!js.terminated) {
-		if(frame.cycle()) {
-			scroller.cycle();
-			console.gotoxy(console.screen_columns, console.screen_rows);
-		}
-		var userInput = console.inkey(K_NONE, 5);
-		if(userInput.toUpperCase() == "Q" || ascii(userInput) == 27)
-			break;
-		else if(userInput == KEY_UP && readerFrame.data_height > readerFrame.height)
-			readerFrame.scroll(0, -1);
-		else if(userInput == KEY_DOWN && readerFrame.data_height > readerFrame.height)
-			readerFrame.scroll(0, 1);
-	}
-	readerFrame.close();
-	readerFrame.delete();
-	return true;
-}
-
-var init = function() {
-	try {
-		var f = new File(js.exec_dir + "bullshit.ini");
-		f.open("r");
-		ini = f.iniGetObject();
-		f.close();
-		ini.borderColor = ini.borderColor.toUpperCase().split(",");
-		if(ini.borderColor.length > 1) {
-			for(var b = 0; b < ini.borderColor.length; b++)
-				ini.borderColor[b] = getColor(ini.borderColor[b]);
-		} else {
-			ini.borderColor = getColor(ini.borderColor[0]);
-		}
-		ini.lightbarForeground = getColor(ini.lightbarForeground);
-		ini.lightbarBackground = getColor(ini.lightbarBackground);
-	
-		frame = new Frame(1, 1, console.screen_columns, console.screen_rows, BG_BLACK|WHITE);
-		titleFrame = new Frame(1, 1, console.screen_columns, 3, BG_BLACK|WHITE, frame);
-		listFrame = new Frame(1, 4, console.screen_columns, console.screen_rows - 6, BG_BLACK|WHITE, frame);
-		listTreeFrame = new Frame(2, 6, console.screen_columns - 2, console.screen_rows - 9, BG_BLACK|WHITE, listFrame);
-		footerFrame = new Frame(1, console.screen_rows - 2, console.screen_columns, 3, BG_BLACK|WHITE, frame);
-		drawFrameBorder(titleFrame, ini.borderColor);
-		drawFrameBorder(listFrame, ini.borderColor);
-		drawFrameBorder(footerFrame, ini.borderColor);
-		tree = new Tree(listTreeFrame);
-		tree.colors.lfg = ini.lightbarForeground;
-		tree.colors.lbg = ini.lightbarBackground;
-
-		var titleLen = console.screen_columns - 29;
-		msgBase = new MsgBase(ini.messageBase);
-		msgBase.open();
-		for(var m = msgBase.last_msg; m >= msgBase.first_msg; m = m - 1) {
-			try {
-				var h = msgBase.get_msg_header(m);
-				if(h === null)
-					throw "Header is null";
-				tree.addItem(
-					format(
-						"%-" + titleLen + "s%s",
-						h.subject.substr(0, console.screen_columns - 29),
-						system.timestr(h.when_written_time)
-					),
-					showMsg,
-					m
-				);
-			} catch(err) {
-				continue;
-			}
-		}
-		msgBase.close();
-
-		titleFrame.gotoxy(3, 2);
-		titleFrame.putmsg("Bulletins", getColor(ini.titleColor));
-		titleFrame.gotoxy(console.screen_columns - 25, 2);
-		titleFrame.putmsg("bullshit v2 by echicken", DARKGRAY);
-		listFrame.gotoxy(3, 2);
-		listFrame.putmsg(format("%-" + titleLen + "s%s", "Title", "Date"), getColor(ini.headingColor));
-		footerFrame.gotoxy(3, 2);
-		footerFrame.putmsg("[ESC] or Q to quit, Up/Down arrows to scroll", getColor(ini.footerColor));
-		treeScroll = new ScrollBar(tree);
-		frame.open();
-		tree.open();
-	} catch(err) {
-		log(LOG_ERR, err);
-		return false;	
-	}
-	return true;
-}
-
-var main = function() {
-	while(!js.terminated) {
-		var userInput = console.inkey(K_NONE, 5);
-		if(userInput.toUpperCase() == "Q" || ascii(userInput) == 27)
-			break;
-		tree.getcmd(userInput);
-		if(frame.cycle()) {
-			treeScroll.cycle();
-			console.gotoxy(console.screen_columns, console.screen_rows);
-		}
-	}
-}
-
-if(init()) {
-	main();
-	frame.close();
-}
-exit();
+load('sbbsdefs.js');
+load('frame.js');
+load('tree.js');
+load('scrollbar.js');
+load('funclib.js');
+
+js.branch_limit = 0;
+js.time_limit = 0;
+
+var settings, frame, tree, treeScroll, viewer;
+
+Frame.prototype.drawBorder = function(color, title) {
+	this.pushxy();
+	var theColor = color;
+	if (Array.isArray(color)) {
+		var sectionLength = Math.round(this.width / color.length);
+	}
+	for (var y = 1; y <= this.height; y++) {
+		for (var x = 1; x <= this.width; x++) {
+			if (x > 1 && x < this.width && y > 1 && y < this.height) continue;
+			var msg;
+			this.gotoxy(x, y);
+			if (y === 1 && x === 1) {
+				msg = ascii(218);
+			} else if (y === 1 && x === this.width) {
+				msg = ascii(191);
+			} else if (y === this.height && x === 1) {
+				msg = ascii(192);
+			} else if (y === this.height && x === this.width) {
+				msg = ascii(217);
+			} else if (x === 1 || x === this.width) {
+				msg = ascii(179);
+			} else {
+				msg = ascii(196);
+			}
+			if (Array.isArray(color)) {
+				if (x === 1) {
+					theColor = color[0];
+				} else if (x % sectionLength === 0 && x < this.width) {
+					theColor = color[x / sectionLength];
+				} else if (x === this.width) {
+					theColor = color[color.length - 1];
+				}
+			}
+			this.putmsg(msg, theColor);
+		}
+	}
+	if (typeof title === 'object') {
+		this.gotoxy(title.x, title.y);
+		this.attr = title.attr;
+		this.putmsg(ascii(180) + title.text + ascii(195));
+	}
+	this.popxy();
+}
+
+var Viewer = function (item) {
+
+	var frames = {
+		top : null,
+		title : null,
+		content : null
+	};
+
+	frames.top = new Frame(
+		frame.x,
+		frame.y + 3,
+		frame.width,
+		frame.height - 6,
+		WHITE,
+		frame
+	);
+	frames.top.drawBorder(settings.colors.border);
+
+	frames.title = new Frame(
+		frames.top.x + 1,
+		frames.top.y + 1,
+		frames.top.width - 2,
+		1,
+		settings.colors.title,
+		frames.top
+	);
+
+	frames.content = new Frame(
+		frames.top.x + 1,
+		frames.title.y + frames.title.height + 1,
+		frames.top.width - 2,
+		frames.top.height - frames.title.height - 3,
+		settings.colors.text,
+		frames.top
+	);
+
+	if (typeof item === 'number') {
+
+		var msgBase = new MsgBase(settings.messageBase);
+		msgBase.open();
+		var header = msgBase.get_msg_header(item);
+		var body = msgBase.get_msg_body(item);
+		msgBase.close();
+
+		frames.title.putmsg(
+			format(
+				'%-' + (frame.width - 29) + 's%s',
+				header.subject.substr(0, frame.width - 30),
+				system.timestr(header.when_written_time)
+			),
+			settings.colors.title
+		);
+		frames.content.putmsg(word_wrap(body, frames.content.width));
+
+	} else {
+
+		frames.title.putmsg(
+			format(
+				'%-' + (frame.width - 29) + 's%s',
+				item.substr(0, frame.width - 30),
+				system.timestr(file_date(settings.files[item]))
+			),
+			settings.colors.title
+		);
+
+		frames.content.x = frames.top.x;
+		frames.content.width = frames.top.width;
+
+		try {
+			frames.content.load(settings.files[item]);
+		} catch (err) {
+			log(LOG_ERR, err);
+		}
+
+		frames.content.width = frames.top.width - 2;
+		frames.content.x = frames.top.x + 1;
+
+	}
+
+	frames.content.scrollTo(0, 0);
+	frames.content.h_scroll = true;
+
+	var scrollbar = new ScrollBar(frames.content);
+	frames.top.open();
+
+	this.getcmd = function (cmd) {
+
+		var ret = true;
+		switch (cmd.toUpperCase()) {
+			case '\x1B':
+			case 'Q':
+				ret = false;
+				frames.top.close();
+				break;
+			case KEY_UP:
+				if (frames.content.data_height > frames.content.height &&
+					frames.content.offset.y >= 1
+				) {
+					frames.content.scroll(0, -1);
+				}
+				break;
+			case KEY_DOWN:
+				if (frames.content.data_height > frames.content.height &&
+					frames.content.data_height - frames.content.offset.y >
+						frames.content.height
+				) {
+					frames.content.scroll(0, 1);
+				}
+				break;
+			case KEY_LEFT:
+				if (frames.content.data_width > frames.content.width &&
+					frames.content.offset.x >= 1
+				) {
+					frames.content.scroll(-1, 0);
+				}
+				break;
+			case KEY_RIGHT:
+				if (frames.content.data_width > frames.content.width &&
+					frames.content.data_width - frames.content.offset.x >
+						frames.content.width
+				) {
+					frames.content.scroll(1, 0);
+				}
+				break;
+			default:
+				break;
+		}
+
+		return ret;
+
+	}
+
+	this.cycle = function () {
+		scrollbar.cycle();
+	}
+
+}
+
+function loadSettings() {
+
+	var f = new File(js.exec_dir + 'bullshit.ini');
+	if (!f.open('r')) throw 'Failed to open bullshit.ini.';
+	var settings = f.iniGetObject();
+	settings.colors = f.iniGetObject('colors');
+	settings.files = f.iniGetObject('files');
+	f.close();
+
+	Object.keys(settings.colors).forEach(
+		function (k) {
+			settings.colors[k] = settings.colors[k].toUpperCase().split(',');
+			if (settings.colors[k].length > 1) {
+				settings.colors[k].forEach(
+					function (e, i, a) { a[i] = getColor(e); }
+				);
+			} else {
+				settings.colors[k] = getColor(settings.colors[k][0]);
+			}
+		}
+	);
+
+	return settings;
+
+}
+
+function loadList() {
+
+	Object.keys(settings.files).forEach(
+		function (key) {
+			if (!file_exists(settings.files[key])) return;
+			tree.addItem(
+				format (
+					'%-' + (frame.width - 29) + 's%s',
+					key, system.timestr(file_date(settings.files[key]))
+				),
+				key
+			);
+		}
+	);
+
+	var msgBase = new MsgBase(settings.messageBase);
+	msgBase.open();
+	var shown = 0;
+	for (var m = msgBase.last_msg; m >= msgBase.first_msg; m = m - 1) {
+		try {
+			var h = msgBase.get_msg_header(m);
+		} catch (err) {
+			continue;
+		}
+		if (h === null) continue;
+		tree.addItem(
+			format(
+				'%-' + (frame.width - 29) + 's%s',
+				h.subject.substr(0, frame.width - 30),
+				system.timestr(h.when_written_time)
+			),
+			m
+		);
+		shown++;
+		if (settings.maxMessages > 0 && shown >= settings.maxMessages) break;
+	}
+	msgBase.close();
+
+	tree.open();
+
+}
+
+function initDisplay() {
+
+	frame = new Frame(
+		1,
+		1,
+		console.screen_columns,
+		console.screen_rows,
+		WHITE
+	);
+
+	var titleFrame = new Frame(
+		frame.x,
+		frame.y,
+		frame.width,
+		3,
+		WHITE,
+		frame
+	);
+
+	var footerFrame = new Frame(
+		frame.x,
+		frame.y + frame.height - 3,
+		frame.width,
+		3,
+		WHITE,
+		frame
+	);
+
+	var treeFrame = new Frame(
+		frame.x,
+		titleFrame.y + titleFrame.height,
+		frame.width,
+		frame.height - titleFrame.height - footerFrame.height,
+		WHITE,
+		frame
+	);
+
+	var treeSubFrame = new Frame(
+		treeFrame.x + 1,
+		treeFrame.y + 2,
+		treeFrame.width - 2,
+		treeFrame.height - 3,
+		WHITE,
+		treeFrame
+	);
+
+	titleFrame.drawBorder(settings.colors.border);
+	treeFrame.drawBorder(settings.colors.border);
+	footerFrame.drawBorder(settings.colors.border);
+
+	titleFrame.gotoxy(3, 2);
+	titleFrame.putmsg('Bulletins', settings.colors.title);
+	titleFrame.gotoxy(frame.width - 25, 2);
+	titleFrame.putmsg('bullshit v3 by echicken', settings.colors.heading);
+
+	treeFrame.gotoxy(3, 2);
+	treeFrame.putmsg('Title', settings.colors.heading);
+	treeFrame.gotoxy(treeFrame.x + treeFrame.width - 27, 2);
+	treeFrame.putmsg('Date', settings.colors.heading);
+
+	footerFrame.gotoxy(3, 2);
+	footerFrame.putmsg(
+		'Q to quit, Up/Down arrows to scroll', settings.colors.footer
+	);
+
+	tree = new Tree(treeSubFrame);
+	tree.colors.lfg = settings.colors.lightbarForeground;
+	tree.colors.lbg = settings.colors.lightbarBackground;
+	tree.colors.fg = settings.colors.listForeground;
+
+	treeScroll = new ScrollBar(tree);
+
+	frame.open();
+
+}
+
+function init() {
+	settings = loadSettings();
+	initDisplay();
+	loadList();
+}
+
+function main() {
+
+	while (!js.terminated) {
+
+		var userInput = console.inkey(K_NONE, 5);
+
+		if (typeof viewer !== 'undefined') {
+
+			var ret = viewer.getcmd(userInput);
+			viewer.cycle();
+			if (!ret) viewer = undefined;
+
+		} else {
+
+			if (userInput.toUpperCase() === 'Q' || userInput == '\x1B') {
+				break;
+			} else {
+				var ret = tree.getcmd(userInput);
+				treeScroll.cycle();
+				if (typeof ret === 'number' || typeof ret === 'string') {
+					viewer = new Viewer(ret);
+				}
+			}
+
+		}
+
+		if (frame.cycle()) {
+			console.gotoxy(console.screen_columns, console.screen_rows);
+		}
+
+	}
+
+}
+
+function cleanUp() {
+	frame.close();
+}
+
+try {
+	init();
+	main();
+	cleanUp();
+} catch (err) {
+	log(LOG_ERR, err);
+}
\ No newline at end of file
diff --git a/xtrn/bullshit/readme.txt b/xtrn/bullshit/readme.txt
index 1ccc060653b0140039a33a9966b30dc584f8382e..82755507f8bb1af95b94d1fc5830751218ef560c 100644
--- a/xtrn/bullshit/readme.txt
+++ b/xtrn/bullshit/readme.txt
@@ -1,53 +1,152 @@
-Bullshit 2.0
--=-=-=-=-=-=
+Bullshit 3.0
 by echicken -at- bbs.electronicchicken.com
 
-Bullshit is a bulletin listing/reading module for Synchronet BBS 3.16+.  It
-uses a sysops-only message base on your BBS as a storage back-end.  Adding
-new bulletins to your system becomes as easy as posting a message.
+Contents
 
+	1) About
+	2) Setup
+	3) Customization
+	4) Bullshit for the web
+	5) Support
 
-Installation:
--=-=-=-=-=-=-
 
-Launch SCFG (BBS->Configure in the Synchronet Control Panel on Windows.)
+1) About
 
-In 'Message Areas', select your local message group, and create a new sub with
-the following details:
+	Bullshit is a lightbar bulletin lister/reader for Synchronet BBS 3.16+.
+	A message sub-board is used as a storage back-end, so that you can add a
+	new bulletin to the list just by posting a message.  You can also include
+	.ANS or .TXT files - such as door game score files - as pinned items at the
+	top of the list.
 
-Long Name                  Bulletins
-Short Name                 Bulletins
-QWK Name                   BULLSHIT
-Internal Code              BULLSHIT
-Access Requirements        LEVEL 90
-Reading Requirements       LEVEL 90
-Posting Requirements       LEVEL 90
 
-In the "Toggle Options" for the sub, ensure that "Default on for new scan",
-"Forced on for new scan", and "Default on for your scan" are set to 'No'.
+2) Setup
 
-(You can set the Access, Reading, and Posting requirements to any ARS value
-that you want.  Ideally, only the Sysop should be able to see or post to this
-sub, and Bullshit will be the interface by which users view messages here.)
+	2.1) Create a message area
 
-Return to the main menu of SCFG, go to 'External Programs', then to
-'Online Programs (Doors)'.  Select whatever externals section you want to
-place Bullshit in ('Main' might be a good choice) and then add a new item
-with the following details:
+		Launch SCFG (BBS->Configure in the Synchronet Control Panel on Windows.)
 
-Name                       Bullshit
-Internal Code              BULLSHIT
-Start-up Directory         /sbbs/xtrn/bullshit
-Command Line               ?bullshit.js
-Multiple Concurrent Users  Yes
+		In 'Message Areas', select your local message group, and create a new
+		sub	with the following details:
 
-If you want Bullshit to run during your logon process, set the following:
+			Long Name                  Bulletins
+			Short Name                 Bulletins
+			QWK Name                   BULLSHIT
+			Internal Code              BULLSHIT
+			Access Requirements        LEVEL 90
+			Reading Requirements       LEVEL 90
+			Posting Requirements       LEVEL 90
 
-Execute on Event			logon
+			Toggle Options...
 
-Next you can edit 'bullshit.ini' to your liking.  It contains some options for
-colors and such.
+				Default on for new scan		No
+				Forced on for new scan		No
+				Default on for your scan	No
 
-Now go ahead and start posting messages in the Bulletins sub-board that you
-created.  The subject line of each message will appear as the bulletin title,
-and the message body will be the text of the bulletin.
\ No newline at end of file
+		Note: You can name this message area whatever you want, and you can use
+		an existing message area if you wish.  Ideally only the sysop will be
+		able to read or post to this area, and it won't be included in the new
+		message scan.
+
+
+	2.2) Create an External Program entry
+
+		Still in SCFG, return to the main menu, select 'External Programs',
+		then 'Online Programs (Doors)', choose the section you wish to add
+		Bullshit to, then create a new entry with the following details:
+
+			Name                       Bullshit
+			Internal Code              BULLSHIT
+			Start-up Directory         /sbbs/xtrn/bullshit
+			Command Line               ?bullshit.js
+			Multiple Concurrent Users  Yes
+
+		If you want Bullshit to run during your logon process, set the
+		following:
+
+			Execute on Event			logon
+
+		All other options can be left at their default settings.
+
+
+3) Customization
+
+	Some customization settings are available in 'bullshit.ini':
+
+	In the root section:
+
+		-	The 'messageBase' setting specifies the internal code of the
+			message sub-board that Bullshit should load.
+		-	The 'maxMessages' setting specifies how many of the most recent
+			messages in this area should be listed. (Use 0 for no limit.)
+
+
+	In the 'colors' section:
+
+		- 	'title' and 'text' are the colors used when viewing an item
+		-	'heading' controls color or the 'Title' and 'Date' column headings
+		-	'lightbarForeground' and 'lightbarBackground' control the color of
+			a highlighted item in the list
+		-	'listForeground' controls the color of a non-highlighted item
+		-	'footer' controls the color of the 'Q to quit ...' text
+		-	'border' can be a single color, or a comma-separated list
+
+	The 'files' section is empty by default.  Here you can add any number of
+	entries for files that you wish to include in the list.  The key will be
+	used as the item's title in the list, while the value must be the path to
+	the file, for example:
+
+		LORD Scores = /sbbs/xtrn/lord/score.ans
+
+	At the moment, only files with .ANS and .TXT extensions can be loaded.  If
+	that's a huge pain for you, let me know and I'll maybe do something about
+	it at some point.
+
+
+4) Bullshit for the web
+
+	The included '999-bullshit.xjs' file is compatible with my "new" web UI for
+	Synchronet (https://github.com/echicken/synchronet-web-v4).  You can add it
+	to your site by copying it to the 'pages' subdirectory, renaming it as
+	needed.  You could also just copy the contents of this file into another of
+	your pages if you wish for bulletins to show up there (000-home.xjs, for
+	example.)
+
+	This will probably work with ecweb v3 as well, but I haven't bothered to
+	test it.
+
+	For cosmetic and snobbish design reasons, your pinned 'files' list will not
+	be displayed in the web UI.  You're better off creating a 'Scores' page of
+	some kind for this purpose.
+
+
+5) Support
+
+	You can contact me for support via any of the following means, in the
+	following order of preference:
+
+	DOVE-Net:
+
+		Post a message to 'echicken' in the 'Synchronet Sysops' sub-board.
+		Unless I'm dead or on vacation, I'll probably get back to you within a
+		day or so.
+
+
+	electronic chicken bbs:
+
+		Post a message in the 'Support' sub-board of the 'Local' message group
+		on my BBS, bbs.electronicchicken.com
+
+
+	IRC : #synchronet on irc.synchro.net:
+
+		I'm not always in front of a computer, so you won't always receive an
+		immediate response if you contact me on IRC.  That said, if you stay
+		online and idle, I'll probably see your message and respond eventually.
+
+
+	Email:
+
+		You can email me at echicken -at- bbs.electronicchicken.com, however I
+		prefer to discuss problems & provide support in a public forum in case
+		any information that comes up can be of benefit to somebody else in the
+		future.