diff --exclude .cvsignore --exclude CVS --exclude 'strl*.c' -urN dgamelaunch-1.3.10/Bugs dgamelaunch/Bugs
--- dgamelaunch-1.3.10/Bugs	2003-08-24 11:55:54.000000000 -0700
+++ dgamelaunch/Bugs	2004-01-02 12:31:31.000000000 -0800
@@ -1,5 +1,5 @@
-* Only the first 15 games in progress are shown on the games in progress
-screen.
+* On some (X11?) terminals changing the window size closes the dgamelaunch
+session, probably because of sending negotation strings it doesn't understand?
 
 * Since virus kept calling alarm() on itself, I removed SIGALRM handling
 altogether, which breaks occasional refresh of the bottom status line.
diff --exclude .cvsignore --exclude CVS --exclude 'strl*.c' -urN dgamelaunch-1.3.10/Changelog dgamelaunch/Changelog
--- dgamelaunch-1.3.10/Changelog	2003-10-22 12:09:26.000000000 -0700
+++ dgamelaunch/Changelog	2004-01-02 16:26:29.000000000 -0800
@@ -1,3 +1,32 @@
+1.3.10.1 (2003/12/27)
+	* Merry Christmas, dtype...
+	* Major cleanups - remove most uses of strcpy() and strcat(), except
+	  in virus.c, replace with snprintf.
+	* Add support for mailing users while they are playing.
+	  [nh343-simple_mail.diff is needed]
+	* Rip out some crazy getopt code that was causing virus to go crazy
+	  after a "q!" Since dgamelaunch only passes up to argv[1] to virus
+	  *ever*, just make it use argv[1] and panic if argc < 2, which should
+	  never happen anyway.
+	* Add a confirmation to the change password screen so people like me
+	  don't change their passwords by accident all the time.
+	* Removed strl{cat,cpy}.c, as they're not used by ttyrec even though
+	  they are included.
+	* Remove many unused variables and make some functions void because
+	  they don't return anything.
+	* Add some function prototypes in dgamelaunch.c to quell warnings.
+	* Make some vars unsigned to quell warnings.
+	* 'capital letter. experimental' section made irrelevant by use of
+	  tolower(3) around getch()
+	* Change big conditional block to use a switch.
+	* Replace a global with a static variable within the function.
+	* Replace the giant size 64000 static buffers with dynamically
+	  allocated structs
+	* Checking for colons in user fields is made simpler using strstr(3)
+	* Allow page up and page down on the watch games menu
+	* Merge BSD compatibility patches
+	* All licenses in source code mentioned in COPYING
+
 1.3.10 (2003/10/22)
 	* Added a mode flag to the open call for inprogress lock files.
 	  (jilles)
diff --exclude .cvsignore --exclude CVS --exclude 'strl*.c' -urN dgamelaunch-1.3.10/COPYING dgamelaunch/COPYING
--- dgamelaunch-1.3.10/COPYING	2003-08-14 22:17:20.000000000 -0700
+++ dgamelaunch/COPYING	2004-01-02 14:01:16.000000000 -0800
@@ -1,3 +1,5 @@
+dgamelaunch itself, virus.c, and last_char_is.c fall under the GNU
+General Public License, which follows here.
 
 		    GNU GENERAL PUBLIC LICENSE
 		       Version 2, June 1991
@@ -337,3 +339,136 @@
 consider it more useful to permit linking proprietary applications with the
 library.  If this is what you want to do, use the GNU Library General
 Public License instead of this License.
+
+ttyplay.c and ttyrec.c fall under a 4-clause BSD license,
+which follows.
+
+Copyright (c) 2000 Satoru Takabayashi <satoru@namazu.org>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+3. All advertising materials mentioning features or use of this software
+   must display the following acknowledgement:
+	This product includes software developed by the University of
+	California, Berkeley and its contributors.
+4. Neither the name of the University nor the names of its contributors
+   may be used to endorse or promote products derived from this software
+   without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
+stripgfx.c is derived from drawing.c in the NetHack source distribution,
+and falls under the NetHack General Public License, which follows.
+
+                    NETHACK GENERAL PUBLIC LICENSE
+                    (Copyright 1989 M. Stephenson)
+.
+               (Based on the BISON general public license,
+                   copyright 1988 Richard M. Stallman)
+
+ Everyone is permitted to copy and distribute verbatim copies of this
+ license, but changing it is not allowed.  You can also use this wording to
+ make the terms for other programs.
+
+  The license agreements of most software companies keep you at the mercy of
+those companies.  By contrast, our general public license is intended to give
+everyone the right to share NetHack.  To make sure that you get the rights we
+want you to have, we need to make restrictions that forbid anyone to deny you
+these rights or to ask you to surrender the rights.  Hence this license
+agreement.
+
+  Specifically, we want to make sure that you have the right to give away
+copies of NetHack, that you receive source code or else can get it if you
+want it, that you can change NetHack or use pieces of it in new free
+programs, and that you know you can do these things.
+
+  To make sure that everyone has such rights, we have to forbid you to
+deprive anyone else of these rights.  For example, if you distribute copies
+of NetHack, you must give the recipients all the rights that you have.  You
+must make sure that they, too, receive or can get the source code.  And you
+must tell them their rights.
+
+  Also, for our own protection, we must make certain that everyone finds out
+that there is no warranty for NetHack.  If NetHack is modified by someone
+else and passed on, we want its recipients to know that what they have is
+not what we distributed.
+
+  Therefore we (Mike Stephenson and other holders of NetHack copyrights) make
+the following terms which say what you must do to be allowed to distribute or
+change NetHack.
+
+
+                        COPYING POLICIES
+
+  1. You may copy and distribute verbatim copies of NetHack source code as
+you receive it, in any medium, provided that you keep intact the notices on
+all files that refer to copyrights, to this License Agreement, and to the
+absence of any warranty; and give any other recipients of the NetHack
+program a copy of this License Agreement along with the program.
+
+  2. You may modify your copy or copies of NetHack or any portion of it, and
+copy and distribute such modifications under the terms of Paragraph 1 above
+(including distributing this License Agreement), provided that you also do the
+following:
+
+    a) cause the modified files to carry prominent notices stating that you
+    changed the files and the date of any change; and
+
+    b) cause the whole of any work that you distribute or publish, that in
+    whole or in part contains or is a derivative of NetHack or any part
+    thereof, to be licensed at no charge to all third parties on terms
+    identical to those contained in this License Agreement (except that you
+    may choose to grant more extensive warranty protection to some or all
+    third parties, at your option)
+
+    c) You may charge a distribution fee for the physical act of
+    transferring a copy, and you may at your option offer warranty protection
+    in exchange for a fee.
+
+  3. You may copy and distribute NetHack (or a portion or derivative of it,
+under Paragraph 2) in object code or executable form under the terms of
+Paragraphs 1 and 2 above provided that you also do one of the following:
+
+    a) accompany it with the complete machine-readable source code, which
+    must be distributed under the terms of Paragraphs 1 and 2 above; or,
+
+    b) accompany it with full information as to how to obtain the complete
+    machine-readable source code from an appropriate archive site.  (This
+    alternative is allowed only for noncommercial distribution.)
+
+For these purposes, complete source code means either the full source
+distribution as originally released over Usenet or updated copies of the
+files in this distribution used to create the object code or executable.
+
+  4. You may not copy, sublicense, distribute or transfer NetHack except as
+expressly provided under this License Agreement.  Any attempt otherwise to
+copy, sublicense, distribute or transfer NetHack is void and your rights to
+use the program under this License agreement shall be automatically
+terminated.  However, parties who have received computer software programs
+from you with this License Agreement will not have their licenses terminated
+so long as such parties remain in full compliance.
+
+
+Stated plainly:  You are permitted to modify NetHack, or otherwise use parts
+of NetHack, provided that you comply with the conditions specified above;
+in particular, your modified NetHack or program containing parts of NetHack
+must remain freely available as provided in this License Agreement.  In
+other words, go ahead and share NetHack, but don't try to stop anyone else
+from sharing it farther.
diff --exclude .cvsignore --exclude CVS --exclude 'strl*.c' -urN dgamelaunch-1.3.10/dgamelaunch.c dgamelaunch/dgamelaunch.c
--- dgamelaunch-1.3.10/dgamelaunch.c	2003-10-29 07:52:15.000000000 -0800
+++ dgamelaunch/dgamelaunch.c	2004-01-02 18:39:19.000000000 -0800
@@ -30,41 +30,57 @@
  * is very small.
  */
 
+#define _GNU_SOURCE
+#include "dgamelaunch.h"
+
 /* a request from the author: please leave some remnance of
  * 'based on dgamelaunch version xxx' in any derivative works, or
  * even keep the line the same altogether. I'm probably happy 
  * to make any changes you need. */
 
-#define VERLINES 7							/* number of lines in this vanity text */
-#define VER1 "## dgamelaunch - network console game launcher\n"
-#define VER2 "## version 1.3.10\n"
-#define VER3 "## \n"
-#define VER4 "## (c)2001-3 M. Drew Streib. This program's source is released under the GPL.\n"
-#define VER5 "## Send mail to <dtype@dtype.org> for details or a copy of the source code.\n"
-#define VER6 "## ** Games on this server are recorded for in-progress viewing and playback!\n"
-#define VER7 "## Server info is at http://alt.org/nethack/"
-
 /* ************************************************************* */
 /* ************************************************************* */
 /* ************************************************************* */
 
 /* program stuff */
 
-#include "dgamelaunch.h"
 #include <stdlib.h>
 #include <curses.h>
-#include <crypt.h>
 #include <sys/types.h>
 #include <sys/file.h>						/* for flock() */
+#include <sys/time.h>
+
+#ifndef __FreeBSD__
+# include <crypt.h>
+#else
+# include <libutil.h>
+#endif
+
+#ifdef __linux__
+# include <pty.h>
+# include <libiberty.h>
+#endif
+
+#ifndef ARRAY_SIZE
+# define ARRAY_SIZE(x) sizeof(x) / sizeof(x[0])
+#endif
+
+#include <grp.h>
+#include <time.h>
+#include <sys/resource.h>
 #include <sys/ioctl.h>					/* ttyrec */
 #include <errno.h>
-#include <time.h>
 #include <dirent.h>
 #include <string.h>
 #include <sys/stat.h>
-#include <sys/signal.h>
+#include <signal.h>
+#include <assert.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <termios.h>
 
 extern int vi_main (int argc, char **argv);
+extern int ttyplay_main (char *ttyfile, int mode, int rstripgfx);
 extern int ttyrec_main (char *);
 extern int master;
 extern int slave;
@@ -73,26 +89,16 @@
 
 /* global variables */
 
-int caught_sighup = 0;
 int pid_game = 0;
 int loggedin = 0;
-char my_name[21];
-char my_email[81];
-char my_pw[21];
-char my_env[1025];
 char rcfilename[80];
 char ttyrec_filename[100];
+char *chosen_name;
 
-/* preallocate this mem. bad, but ohwell. is only for pointers */
-/* makes a max number of users compiled in */
 int f_num = 0;
-char *f_name[MAXUSERS];
-char *f_email[MAXUSERS];
-char *f_pw[MAXUSERS];
-char *f_env[MAXUSERS];
-
-int loopcontrol1 = 0;
-int loopcontrol2 = 0;
+struct dg_user **users = NULL;
+struct dg_user *me = NULL;
+struct dg_banner banner;
 
 /* ************************************************************* */
 /* for ttyrec */
@@ -102,10 +108,12 @@
 {
 	(void) tcgetattr (0, &tt);
 	(void) ioctl (0, TIOCGWINSZ, (char *) &win);
+#ifdef USE_OPENPTY
+	if (openpty (&master, &slave, NULL, &tt, &win) == -1)
+#else
 	if ((master = open ("/dev/ptmx", O_RDWR)) < 0)
-		{
-			exit (62);
-		}
+#endif
+		exit (62);
 }
 
 /* ************************************************************* */
@@ -113,31 +121,15 @@
 void
 gen_ttyrec_filename ()
 {
-	char spbuf[20];
 	time_t rawtime;
 	struct tm *ptm;
 
 	/* append time to filename */
 	time (&rawtime);
 	ptm = gmtime (&rawtime);
-	sprintf (spbuf, "%04i", ptm->tm_year + 1900);
-	strncpy (ttyrec_filename, spbuf, 4);
-	strcat (ttyrec_filename, "-");
-	sprintf (spbuf, "%02i", ptm->tm_mon + 1);
-	strncat (ttyrec_filename, spbuf, 2);
-	strcat (ttyrec_filename, "-");
-	sprintf (spbuf, "%02i", ptm->tm_mday);
-	strncat (ttyrec_filename, spbuf, 2);
-	strcat (ttyrec_filename, ".");
-	sprintf (spbuf, "%02i", ptm->tm_hour);
-	strncat (ttyrec_filename, spbuf, 2);
-	strcat (ttyrec_filename, ":");
-	sprintf (spbuf, "%02i", ptm->tm_min);
-	strncat (ttyrec_filename, spbuf, 2);
-	strcat (ttyrec_filename, ":");
-	sprintf (spbuf, "%02i", ptm->tm_sec);
-	strncat (ttyrec_filename, spbuf, 2);
-	strcat (ttyrec_filename, ".ttyrec");
+	snprintf (ttyrec_filename, 100, "%04i-%02i-%02i.%02i:%02i:%02i.ttyrec",
+						ptm->tm_year + 1900, ptm->tm_mon + 1, ptm->tm_mday,
+						ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
 }
 
 /* ************************************************************* */
@@ -148,10 +140,8 @@
 	char lockfile[130];
 	int fd;
 
-	strcpy (lockfile, LOC_INPROGRESSDIR);
-	strcat (lockfile, my_name);
-	strcat (lockfile, ":");
-	strcat (lockfile, ttyrec_filename);
+	snprintf (lockfile, 130, "%s%s:%s", LOC_INPROGRESSDIR,
+						me->username, ttyrec_filename);
 
 	fd = open (lockfile, O_WRONLY | O_CREAT, 0644);
 	if (flock (fd, LOCK_EX))
@@ -161,9 +151,8 @@
 /* ************************************************************* */
 
 void
-catch_sighup ()
+catch_sighup (int signum)
 {
-	caught_sighup = 1;
 	if (pid_game)
 		{
 			sleep (10);
@@ -176,127 +165,250 @@
 /* ************************************************************* */
 
 void
-inprogressmenu ()
+loadbanner (struct dg_banner *ban)
 {
-	int i;
+	FILE *bannerfile;
+	char buf[80];
+
+	memset (buf, 0, 80);
+
+	bannerfile = fopen (LOC_BANNER, "r");
+
+	if (!bannerfile)
+		{
+			ban->len = 2;
+			ban->lines = malloc (sizeof (char *));
+			ban->lines[0] =
+				strdup ("### dgamelaunch " VERSION
+								" - network console game launcher");
+			ban->lines[1] =
+				strdup
+				("### NOTE: administrator has not installed a /dgl-banner file");
+			return;
+		}
+
+	ban->len = 0;
+
+	while (fgets (buf, 80, bannerfile) != NULL)
+		{
+			char *loc;
+
+			ban->len++;
+			ban->lines = realloc (ban->lines, sizeof (char *) * ban->len);
+
+			if ((loc = strstr (buf, "$VERSION")) != NULL)
+				{
+					char bufnew[80];
+					char *b = buf;
+					int i;
+
+					memset (bufnew, 0, 80);
+
+					for (i = 0; i < 80; i++)
+						{
+							if (loc != b)
+								bufnew[i] = *(b++);
+							else
+								{
+									strncat (bufnew, VERSION, 80 - i);
+									b += 8;				/* skip the whole $VERSION string */
+									i += ARRAY_SIZE (VERSION);
+								}
+
+							if (strlen (b) == 0)
+								break;
+						}
+
+					ban->lines[ban->len - 1] = strdup (bufnew);
+				}
+			else
+				ban->lines[ban->len - 1] = strdup (buf);
+
+			memset (buf, 0, 80);
+
+			if (ban->len == 14)				/* menu itself needs 10 lines, 24 - 10 */
+				break;
+		}
+
+	fclose (bannerfile);
+}
+
+void
+drawbanner (unsigned int start_line, unsigned int howmany)
+{
+	static short loaded_banner = 0;
+	unsigned int i;
+
+	if (!loaded_banner)
+		{
+			loadbanner (&banner);
+			loaded_banner = 1;
+		}
+
+	if (howmany > banner.len || howmany == 0)
+		howmany = banner.len;
+
+	for (i = 0; i < howmany; i++)
+		mvaddstr (start_line + i, 1, banner.lines[i]);
+}
+
+struct dg_game **
+populate_games (int *l)
+{
+	int fd, len;
 	DIR *pdir;
 	struct dirent *pdirent;
-	int fd;
 	struct stat pstat;
-	char buf[20];
-	char printline[130];
-	char fullname[130];
-	char ttyrecname[130];
+	char fullname[130], ttyrecname[130];
 	char *replacestr;
-	char *games[15];
-	char m_name[26], m_date[11], m_time[9];
-	int m_namelen;
+	struct dg_game **games = NULL;
+
+	len = 0;
+
+	if (!(pdir = opendir (LOC_INPROGRESSDIR)))
+		exit (140);
+
+	while ((pdirent = readdir (pdir)))
+		{
+			snprintf (fullname, 130, "%s%s", LOC_INPROGRESSDIR, pdirent->d_name);
+
+			fd = 0;
+			fd = open (fullname, O_RDONLY);
+			if ((fd > 0) && flock (fd, LOCK_EX | LOCK_NB))
+				{
+
+					/* stat to check idle status */
+					snprintf (ttyrecname, 130, "%s%s", LOC_TTYRECDIR, pdirent->d_name);
+					replacestr = strchr (ttyrecname, ':');
+					if (!replacestr)
+						exit (145);
+					replacestr[0] = '/';
+					if (!stat (ttyrecname, &pstat))
+						{
+							/* now it's a valid game for sure */
+							games = realloc (games, sizeof (struct dg_game) * (len + 1));
+							games[len] = malloc (sizeof (struct dg_game));
+							games[len]->ttyrec_fn = strdup (pdirent->d_name);
+
+							if (!(replacestr = strchr (pdirent->d_name, ':')))
+								exit (146);
+							else
+								*replacestr = '\0';
+
+							games[len]->name = malloc (strlen (pdirent->d_name) + 1);
+							strncpy (games[len]->name, pdirent->d_name,
+											 strlen (pdirent->d_name) + 1);
+
+							games[len]->date = malloc (11);
+							strncpy (games[len]->date, replacestr + 1, 10);
+
+							games[len]->time = malloc (9);
+							strncpy (games[len]->time, replacestr + 12, 8);
+
+							games[len]->idle_time = pstat.st_mtime;
+
+							len++;
+						}
+				}
+			else
+				{
+					/* clean dead ones */
+					unlink (fullname);
+				}
+			flock (fd, LOCK_UN | LOCK_NB);
+			close (fd);
+		}
+
+	closedir (pdir);
+	*l = len;
+	return games;
+}
+
+
+void
+inprogressmenu ()
+{
+	int i, menuchoice, len = 20, offset = 0;
 	time_t ctime;
-	int menuchoice;
+	struct dg_game **games;
+	char ttyrecname[130], *replacestr = NULL;
 
+	games = populate_games (&len);
 
-	do
+	while (1)
 		{
 			clear ();
-			mvaddstr (1, 1, VER1);
-			mvaddstr (3, 1,
-								"(Press 'q' during game playback to return to this menu.)");
+			drawbanner (1, 1);
+			mvprintw (3, 1,
+								"During playback, hit 'q' to return here%s.",
+								loggedin ? ", 'm' to contact the player" : "");
 			mvaddstr (4, 1,
 								"(Use capital letter of selection to strip DEC graphics, VERY experimental!)");
 			mvaddstr (5, 1, "The following games are in progress:");
 
 			/* clean old games and list good ones */
 			i = 0;
-			pdir = opendir (LOC_INPROGRESSDIR);
-			if (!pdir)
-				exit (140);
-
-			while ((pdirent = readdir (pdir)) && (i <= 14))
-				{
-					strcpy (fullname, LOC_INPROGRESSDIR);
-					strncat (fullname, pdirent->d_name, 100);
-
-					fd = 0;
-					fd = open (fullname, O_RDONLY);
-					if ((fd > 0) && flock (fd, LOCK_EX | LOCK_NB))
-						{
 
-							/* stat to check idle status */
-							strcpy (ttyrecname, LOC_TTYRECDIR);
-							strncat (ttyrecname, pdirent->d_name, 100);
-							replacestr = strstr (ttyrecname, ":");
-							if (!replacestr)
-								exit (145);
-							replacestr[0] = '/';
-							if (!stat (ttyrecname, &pstat))
-								{
-									games[i] = pdirent->d_name;
+			for (i = 0; i < 14; i++)
+				{
+					if (i + offset >= len)
+						break;
 
-									memset (m_name, 0, 26);
-									memset (m_date, 0, 11);
-									memset (m_time, 0, 9);
-									m_namelen =
-										replacestr - ttyrecname - strlen (LOC_TTYRECDIR);
-									strncpy (m_name, pdirent->d_name, m_namelen);
-									strncpy (m_date, replacestr + 1, 10);
-									strncpy (m_time, replacestr + 12, 8);
-
-									sprintf (printline, "%c) %-15s %s %s (%im %is idle)",
-													 i + 97, m_name, m_date, m_time,
-													 (time (&ctime) - pstat.st_mtime) / 60,
-													 (time (&ctime) - pstat.st_mtime) % 60);
-									mvaddstr (7 + i++, 1, printline);
-								}
-						}
-					else
-						{
-							unlink (fullname);
-						}
-					flock (fd, LOCK_UN | LOCK_NB);
-					close (fd);
+					mvprintw (7 + i, 1, "%c) %-15s %s %s (%ldm %lds idle)",
+										i + 97, games[i + offset]->name,
+										games[i + offset]->date, games[i + offset]->time,
+										(time (&ctime) - games[i + offset]->idle_time) / 60,
+										(time (&ctime) - games[i + offset]->idle_time) % 60);
 				}
 
-			mvaddstr (23, 1, "Watch which game? (r to refresh, q to quit) => ");
+			mvaddstr (23, 1,
+								"Watch which game? (r refreshes, q quits, d/u for more/less) => ");
 			refresh ();
 
-			menuchoice = getch ();
-
-			if ((menuchoice - 97) >= 0 && (menuchoice - 97) < i)
+			switch ((menuchoice = tolower (getch ())))
 				{
-					/* valid choice has been made */
-					strcpy (ttyrecname, LOC_TTYRECDIR);
-					strncat (ttyrecname, games[menuchoice - 97], 100);
-					replacestr = strstr (ttyrecname, ":");
-					if (!replacestr)
-						exit (145);
-					replacestr[0] = '/';
+				case 'd':
+					if ((offset + 14) >= len)
+						break;
+					else
+						offset += 14;
+					break;
 
-					clear ();
-					refresh ();
-					endwin ();
-					ttyplay_main (ttyrecname, 1, 0);
-				}
+				case 'u':
+					if ((offset - 14) < 0)
+						break;
+					else
+						offset -= 14;
+					break;
 
-			/* capital lettter. experimental */
-			if ((menuchoice - 65) >= 0 && (menuchoice - 65) < i)
-				{
-					/* valid choice has been made */
-					strcpy (ttyrecname, LOC_TTYRECDIR);
-					strncat (ttyrecname, games[menuchoice - 65], 100);
-					replacestr = strstr (ttyrecname, ":");
-					if (!replacestr)
-						exit (145);
-					replacestr[0] = '/';
+				case 'q':
+					return;
 
-					clear ();
-					refresh ();
-					endwin ();
-					ttyplay_main (ttyrecname, 1, 1);
+				default:
+					if ((menuchoice - 97) >= 0 && (menuchoice - 97) < i)
+						{
+							/* valid choice has been made */
+							snprintf (ttyrecname, 130, "%s%s", LOC_TTYRECDIR,
+												games[menuchoice - 97]->ttyrec_fn);
+							chosen_name = strdup (games[menuchoice - 97 + offset]->name);
+
+							/* reuse thie char* */
+							replacestr = strchr (ttyrecname, ':');
+
+							if (!replacestr)
+								exit (145);
+
+							replacestr[0] = '/';
+
+							clear ();
+							refresh ();
+							endwin ();
+							ttyplay_main (ttyrecname, 1, 0);
+						}
 				}
 
-			closedir (pdir);
+			games = populate_games (&len);
 		}
-	while (menuchoice != 'q');
 }
 
 /* ************************************************************* */
@@ -305,87 +417,174 @@
 changepw ()
 {
 	char buf[21];
-	int i;
+	int error = 2;
 
-	if (!loggedin)
-		return;
-	clear ();
+	/* A precondiction is that struct `me' exists because we can be not-yet-logged-in. */
+	if (!me)
+		exit (122);									/* Die. */
+
+	while (error)
+		{
+			char repeatbuf[21];
+			clear ();
 
-	mvaddstr (1, 1, VER1);
+			drawbanner (1, 1);
 
-	mvaddstr (5, 1,
-						"Please enter a new password. Remember that this is sent over the net");
-	mvaddstr (6, 1,
-						"in plaintext, so make it something new and expect it to be relatively");
-	mvaddstr (7, 1, "insecure.");
-	mvaddstr (8, 1, "20 character max. No ':' characters.");
-	mvaddstr (10, 1, "=> ");
+			mvprintw (5, 1,
+								"Please enter a%s password. Remember that this is sent over the net",
+								loggedin ? " new" : "");
+			mvaddstr (6, 1,
+								"in plaintext, so make it something new and expect it to be relatively");
+			mvaddstr (7, 1, "insecure.");
+			mvaddstr (8, 1,
+								"20 character max. No ':' characters. Blank line to abort.");
+			mvaddstr (10, 1, "=> ");
 
-	refresh ();
-	getnstr (buf, 20);
+			if (error == 1)
+				{
+					mvaddstr (15, 1, "Sorry, the passwords don't match. Try again.");
+					move (10, 4);
+				}
 
-	for (i = 0; i < strlen (buf); i++)
-		{
-			/* we warned em */
-			if (buf[i] == ':')
+			refresh ();
+
+			noecho ();
+			getnstr (buf, 20);
+			echo ();									/* Putting echo back on just for saftey and because it can't hurt. */
+
+			if (buf && *buf == '\0')
+				return;
+
+			if (strchr (buf, ':') != NULL)
 				exit (112);
+
+			mvaddstr (12, 1, "And again:");
+			mvaddstr (13, 1, "=> ");
+
+			noecho ();
+			getnstr (repeatbuf, 20);
+			echo ();									/* Here is the important echo(); if the former is removed. */
+
+			if (!strcmp (buf, repeatbuf))
+				error = 0;
+			else
+				error = 1;
 		}
 
-	strncpy (my_pw, crypt (buf, buf), 14);
+	me->password = strdup (crypt (buf, buf));
 	writefile (0);
 }
 
 /* ************************************************************* */
 
 void
+domailuser (char *username)
+{
+	unsigned int len, i;
+	char *spool_fn, message[80];
+	FILE *user_spool = NULL;
+	time_t now;
+	int mail_empty = 1;
+	struct flock fl = { F_WRLCK, SEEK_SET, 0, 0, getpid () };
+
+	assert (loggedin);
+
+	len = ARRAY_SIZE (LOC_SPOOLDIR) + strlen (username) + 1;
+	spool_fn = malloc (len + 1);
+	time (&now);
+	snprintf (spool_fn, len, "%s/%s", LOC_SPOOLDIR, username);
+
+	/* print the enter your message line */
+	clear ();
+	drawbanner (1, 1);
+	mvaddstr (5, 1,
+						"Enter your message here. It is to be one line only and 80 characters or less.");
+	mvaddstr (7, 1, "=> ");
+
+	getnstr (message, 80);
+
+	for (i = 0; i < strlen (message); i++)
+		{
+			if (message[i] != ' ' && message[i] != '\n' && message[i] != '\t')
+				mail_empty = 0;
+		}
+
+	if (mail_empty)
+		{
+			mvaddstr (9, 1, "This scroll appears to be blank.--More--");
+			mvaddstr (10, 1, "(Aborting your message.)");
+			getch ();
+			return;
+		}
+
+	if ((user_spool = fopen (spool_fn, "a")) == NULL)
+		{
+			mvaddstr (9, 1,
+								"You fall into the water! You sink like a rock.--More--");
+			mvprintw (10, 1,
+								"(I couldn't open %s'%c spool file for some reason, so I'm giving up.)",
+								username, (username[strlen (username) - 1] != 's') ? 's' : 0);
+			getch ();
+			return;
+		}
+
+	mvaddstr (9, 1, "Getting a lock on the mailspool...");
+	refresh ();
+
+	while (fcntl (fileno (user_spool), F_SETLK, &fl) == -1);
+
+	fprintf (user_spool, "%s:%s\n", me->username, message);
+
+	fl.l_type = F_UNLCK;
+
+	if (fcntl (fileno (user_spool), F_UNLCK, &fl) == -1)
+		mvaddstr (10, 1, "Couldn't unlock the file! Oh well.");
+
+	fclose (user_spool);
+
+	return;
+}
+
+void
 drawmenu ()
 {
-	char buf[80];
+	static int flood = 0;
 
 	clear ();
 
-	mvaddstr (1, 1, VER1);
-	mvaddstr (2, 1, VER2);
-	mvaddstr (3, 1, VER3);
-	mvaddstr (4, 1, VER4);
-	mvaddstr (5, 1, VER5);
-	mvaddstr (6, 1, VER6);
-	mvaddstr (7, 1, VER7);
+	drawbanner (1, 0);
 
 	if (loggedin)
 		{
-			mvaddstr (VERLINES + 2, 1, "Logged in as:");
-			sprintf (buf, "%s", my_name);
-			mvaddstr (VERLINES + 2, 15, buf);
-
-			mvaddstr (VERLINES + 4, 1, "c) Change password");
-			mvaddstr (VERLINES + 5, 1, "o) Edit option file (requires vi use)");
-			mvaddstr (VERLINES + 6, 1, "w) Watch games in progress");
-			mvaddstr (VERLINES + 7, 1, "p) Play nethack!");
-			mvaddstr (VERLINES + 8, 1, "q) Quit");
-			mvaddstr (VERLINES + 10, 1, "=> ");
+			mvprintw (banner.len + 2, 1, "Logged in as: %s", me->username);
+			mvaddstr (banner.len + 4, 1, "c) Change password");
+			mvaddstr (banner.len + 5, 1, "o) Edit option file (requires vi use)");
+			mvaddstr (banner.len + 6, 1, "w) Watch games in progress");
+			mvaddstr (banner.len + 7, 1, "p) Play nethack!");
+			mvaddstr (banner.len + 8, 1, "q) Quit");
+			mvaddstr (banner.len + 10, 1, "=> ");
 		}
 	else
 		{
-			mvaddstr (VERLINES + 2, 1, "Not logged in.");
-			mvaddstr (VERLINES + 4, 1, "l) Login");
-			mvaddstr (VERLINES + 5, 1, "r) Register new user");
-			mvaddstr (VERLINES + 6, 1, "w) Watch games in progress");
-			mvaddstr (VERLINES + 7, 1, "q) Quit");
-			mvaddstr (VERLINES + 9, 1, "=> ");
+			mvaddstr (banner.len + 2, 1, "Not logged in.");
+			mvaddstr (banner.len + 4, 1, "l) Login");
+			mvaddstr (banner.len + 5, 1, "r) Register new user");
+			mvaddstr (banner.len + 6, 1, "w) Watch games in progress");
+			mvaddstr (banner.len + 7, 1, "q) Quit");
+			mvaddstr (banner.len + 9, 1, "=> ");
 		}
 
 	refresh ();
 
 	/* for retarded clients */
-	loopcontrol1++;
-	if (loopcontrol1 >= 20)
+	flood++;
+	if (flood >= 20)
 		exit (119);
 }
 
 /* ************************************************************* */
 
-int
+void
 freefile ()
 {
 	int i;
@@ -393,12 +592,17 @@
 	/* free existing mem, clear existing entries */
 	for (i = 0; i < f_num; i++)
 		{
-			free (f_name[i]);
-			free (f_email[i]);
-			free (f_pw[i]);
-			free (f_env[i]);
+			free (users[i]->password);
+			free (users[i]->username);
+			free (users[i]->email);
+			free (users[i]->env);
+			free (users[i]);
 		}
 
+	if (users)
+		free (users);
+
+	users = NULL;
 	f_num = 0;
 }
 
@@ -417,22 +621,25 @@
 
 /* ************************************************************* */
 
-void
-initvars ()
+struct dg_user *
+deep_copy (struct dg_user *src)
 {
-	memset (my_name, 21, 0);
-	memset (my_pw, 21, 0);
-	memset (my_email, 81, 0);
-	memset (my_env, 1025, 0);
-}
+	struct dg_user *dest = malloc (sizeof (struct dg_user));
 
-/* ************************************************************* */
+	dest->username = strdup (src->username);
+	dest->email = strdup (src->email);
+	dest->env = strdup (src->env);
+	dest->password = strdup (src->password);
+	dest->flags = src->flags;
+
+	return dest;
+}
 
 void
-login ()
+loginprompt ()
 {
-	char buf[1025];
-	int error = 2;
+	char user_buf[22], pw_buf[22];
+	int error = 2, me_index = -1;
 
 	loggedin = 0;
 
@@ -440,9 +647,10 @@
 		{
 			clear ();
 
-			mvaddstr (1, 1, VER1);
+			drawbanner (1, 1);
 
-			mvaddstr (5, 1, "Please enter your username.");
+			mvaddstr (5, 1,
+								"Please enter your username. (blank entry returns to main menu)");
 			mvaddstr (7, 1, "=> ");
 
 			if (error == 1)
@@ -453,17 +661,23 @@
 
 			refresh ();
 
-			getnstr (buf, 20);
+			getnstr (user_buf, 20);
+
+			if (user_buf && *user_buf == '\0')
+				return;
+
 			error = 1;
-			if (userexist (buf))
-				error = 0;
-		}
 
-	strncpy (my_name, buf, 20);
+			if ((me_index = userexist (user_buf)) != -1)
+				{
+					me = deep_copy (users[me_index]);
+					error = 0;
+				}
+		}
 
 	clear ();
 
-	mvaddstr (1, 1, VER1);
+	drawbanner (1, 1);
 
 	mvaddstr (5, 1, "Please enter your password.");
 	mvaddstr (7, 1, "=> ");
@@ -471,16 +685,13 @@
 	refresh ();
 
 	noecho ();
-	getnstr (buf, 20);
+	getnstr (pw_buf, 20);
 	echo ();
-	strncpy (my_pw, buf, 20);
 
-	if (passwordgood (my_name, my_pw))
+	if (passwordgood (pw_buf))
 		{
 			loggedin = 1;
-			strcpy (rcfilename, LOC_DGLDIR);
-			strcat (rcfilename, my_name);
-			strcat (rcfilename, ".nethackrc");
+			snprintf (rcfilename, 80, "%s%s.nethackrc", LOC_DGLDIR, me->username);
 		}
 }
 
@@ -491,15 +702,20 @@
 {
 	char buf[1024];
 	int error = 2;
-	int i;
+	unsigned int i;
 
 	loggedin = 0;
 
+	if (me)
+		free (me);
+
+	me = malloc (sizeof (struct dg_user));
+
 	while (error)
 		{
 			clear ();
 
-			mvaddstr (1, 1, VER1);
+			drawbanner (1, 1);
 
 			mvaddstr (5, 1, "Welcome new user. Please enter a username.");
 			mvaddstr (6, 1,
@@ -516,8 +732,10 @@
 			refresh ();
 
 			getnstr (buf, 20);
-			if (!userexist (buf))
+			if (userexist (buf) == -1)
 				error = 0;
+			else
+				error = 1;
 
 			for (i = 0; i < strlen (buf); i++)
 				{
@@ -536,38 +754,19 @@
 				return;
 		}
 
-	strncpy (my_name, buf, 20);
+	me->username = strdup (buf);
 
 	/* password step */
 
 	clear ();
 
-	mvaddstr (1, 1, VER1);
-
-	mvaddstr (5, 1, "Please enter a password.");
-	mvaddstr (6, 1,
-						"This is only trivially encoded at the server. Please use something");
-	mvaddstr (7, 1, "new and expect it to be relatively insecure.");
-	mvaddstr (8, 1, "20 character max. No ':' characters.");
-	mvaddstr (10, 1, "=> ");
-
-	refresh ();
-	getnstr (buf, 20);
-
-	for (i = 0; i < strlen (buf); i++)
-		{
-			/* we warned em */
-			if (buf[i] == ':')
-				exit (112);
-		}
-
-	strncpy (my_pw, crypt (buf, buf), 14);
+	changepw ();									/* Calling changepw instead to prompt twice. */
 
 	/* email step */
 
 	clear ();
 
-	mvaddstr (1, 1, VER1);
+	drawbanner (1, 1);
 
 	mvaddstr (5, 1, "Please enter your email address.");
 	mvaddstr (6, 1,
@@ -580,20 +779,16 @@
 	refresh ();
 	getnstr (buf, 80);
 
-	for (i = 0; i < strlen (buf); i++)
-		{
-			/* we warned em */
-			if (buf[i] == ':')
-				exit (113);
-		}
+	if (strchr (buf, ':') != NULL)
+		exit (113);
 
-	strncpy (my_email, buf, 80);
+	me->email = strdup (buf);
+	me->env = calloc (1, 1);
 
 	loggedin = 1;
 
-	strcpy (rcfilename, LOC_DGLDIR);
-	strcat (rcfilename, my_name);
-	strcat (rcfilename, ".nethackrc");
+	snprintf (rcfilename, 80, "%s%s.nethackrc", LOC_DGLDIR, me->username);
+	write_canned_rcfile (rcfilename);
 
 	writefile (1);
 }
@@ -601,22 +796,15 @@
 /* ************************************************************* */
 
 int
-passwordgood (char *cname, char *cpw)
+passwordgood (char *cpw)
 {
-	int i;
+	if (me == NULL)
+		return 1;
 
-	for (i = 0; i < f_num; i++)
-		{
-			if (!strncasecmp (cname, f_name[i], 20))
-				{
-
-					/* first check crypt() version, then plaintext */
-					if (!strncmp (crypt (cpw, cpw), f_pw[i], 13))
-						return 1;
-					if (!strncmp (cpw, f_pw[i], 20))
-						return 1;
-				}
-		}
+	if (!strncmp (crypt (cpw, cpw), me->password, 13))
+		return 1;
+	if (!strncmp (cpw, me->password, 20))
+		return 1;
 
 	return 0;
 }
@@ -626,7 +814,7 @@
 int
 readfile (int nolock)
 {
-	FILE *fp, *fpl;
+	FILE *fp = NULL, *fpl = NULL;
 	char buf[1200];
 
 	memset (buf, 1024, 0);
@@ -651,10 +839,12 @@
 		{
 			char *b = buf, *n = buf;
 
-			f_name[f_num] = (char *) calloc (22, sizeof (char));
-			f_email[f_num] = (char *) calloc (82, sizeof (char));
-			f_pw[f_num] = (char *) calloc (22, sizeof (char));
-			f_env[f_num] = (char *) calloc (1026, sizeof (char));
+			users = realloc (users, sizeof (struct dg_user *) * (f_num + 1));
+			users[f_num] = malloc (sizeof (struct dg_user));
+			users[f_num]->username = (char *) calloc (22, sizeof (char));
+			users[f_num]->email = (char *) calloc (82, sizeof (char));
+			users[f_num]->password = (char *) calloc (22, sizeof (char));
+			users[f_num]->env = (char *) calloc (1026, sizeof (char));
 
 			/* name field, must be valid */
 			while (*b != ':')
@@ -662,7 +852,7 @@
 					if (!(((*b >= 'a') && (*b <= 'z')) || ((*b >= 'A') && (*b <= 'Z'))
 								|| ((*b >= '0') && (*b <= '9'))))
 						return 1;
-					f_name[f_num][(b - n)] = *b;
+					users[f_num]->username[(b - n)] = *b;
 					b++;
 					if ((b - n) >= 21)
 						exit (100);
@@ -675,7 +865,7 @@
 			/* email field */
 			while (*b != ':')
 				{
-					f_email[f_num][(b - n)] = *b;
+					users[f_num]->email[(b - n)] = *b;
 					b++;
 					if ((b - n) > 80)
 						exit (101);
@@ -688,7 +878,7 @@
 			/* pw field */
 			while (*b != ':')
 				{
-					f_pw[f_num][(b - n)] = *b;
+					users[f_num]->password[(b - n)] = *b;
 					b++;
 					if ((b - n) >= 20)
 						exit (102);
@@ -701,7 +891,7 @@
 			/* env field */
 			while ((*b != '\n') && (*b != 0) && (*b != EOF))
 				{
-					f_env[f_num][(b - n)] = *b;
+					users[f_num]->env[(b - n)] = *b;
 					b++;
 					if ((b - n) >= 1024)
 						exit (102);
@@ -731,62 +921,66 @@
 
 	for (i = 0; i < f_num; i++)
 		{
-			if (!strncasecmp (cname, f_name[i], 20))
-				return 1;
+			if (!strncasecmp (cname, users[i]->username, 20))
+				return i;
 		}
 
-	return 0;
+	return -1;
 }
 
 /* ************************************************************* */
 
-int
-editoptions ()
+void
+write_canned_rcfile (char *target)
 {
-	FILE *rcfile;
-	char *myargv[3];
+	FILE *canned, *newfile;
+	char buf[1024];
+	size_t bytes;
 
-	rcfile = fopen (rcfilename, "r");
-	printf (" read");
-	if (!rcfile)
+	if (!(newfile = fopen (target, "w")))
 		{
-			rcfile = fopen (rcfilename, "w");
-			if (!rcfile)
+		bail:
+			mvaddstr (13, 1,
+								"You don't know how to write that! You write \"%s\" was here and the scroll disappears.");
+			mvaddstr (14, 1,
+								"(Sorry, but I couldn't open one of the nethackrc files. This is a bug.)");
+			return;
+		}
+
+	if (!(canned = fopen (LOC_CANNED, "r")))
+		goto bail;
+
+	while ((bytes = fread (buf, 1, 1024, canned)) > 0)
+		{
+			if (fwrite (buf, 1, bytes, newfile) != bytes)
 				{
-					exit (76);
+					if (ferror (newfile))
+						{
+							mvaddstr (13, 1, "Your hand slips while engraving.");
+							mvaddstr (14, 1,
+												"(Encountered a problem writing the new file. This is a bug.)");
+							fclose (canned);
+							fclose (newfile);
+							return;
+						}
 				}
-
-			fprintf (rcfile,
-							 "# This is your personal nethackrc file. It is in the same format as default\n");
-			fprintf (rcfile,
-							 "# nethack options files. Optionally uncomment the following lines as a\n");
-			fprintf (rcfile,
-							 "# starter. This editor is vi-like. Type ESC a couple times, then ':q!'\n");
-			fprintf (rcfile, "# (without quotes) to exit if you get stuck.\n");
-			fprintf (rcfile, "#\n");
-			fprintf (rcfile,
-							 "# See the following link for more options information:\n");
-			fprintf (rcfile,
-							 "# http://www.nethack.org/v341/Guidebook.html#_TOCentry_40\n");
-			fprintf (rcfile, "#\n");
-			fprintf (rcfile, "# OPTIONS=showexp,showscore,time\n");
-			fprintf (rcfile, "# OPTIONS=!autopickup,color\n");
-			fprintf (rcfile,
-							 "# OPTIONS=catname:catfoo,dogname:dogfoo,horsename:horsefoo\n");
-			fprintf (rcfile, "#\n");
-			fprintf (rcfile,
-							 "# The following lines are necessary if you want to use the menucolors option.\n");
-			fprintf (rcfile, "# OPTIONS=menucolors\n");
-			fprintf (rcfile, "# MENUCOLOR=\" blessed \"=green\n");
-			fprintf (rcfile, "# MENUCOLOR=\" holy \"=green\n");
-			fprintf (rcfile, "# MENUCOLOR=\" uncursed \"=yellow\n");
-			fprintf (rcfile, "# MENUCOLOR=\" cursed \"=red\n");
-			fprintf (rcfile, "# MENUCOLOR=\" unholy \"=red\n");
-			fprintf (rcfile,
-							 "# MENUCOLOR=\" cursed .* (being worn)\"=orange&underline\n");
 		}
 
-	fclose (rcfile);
+	fclose (canned);
+	fclose (newfile);
+}
+
+
+void
+editoptions ()
+{
+	FILE *rcfile;
+	char *myargv[3];
+
+	rcfile = fopen (rcfilename, "r");
+	printf (" read");
+	if (!rcfile)									/* should not really happen except for old users */
+		write_canned_rcfile (rcfilename);
 
 	/* use virus to edit */
 
@@ -801,7 +995,7 @@
 
 /* ************************************************************* */
 
-int
+void
 writefile (int requirenew)
 {
 	FILE *fp, *fpl;
@@ -823,7 +1017,7 @@
 
 	for (i = 0; i < f_num; i++)
 		{
-			if (loggedin && !strncasecmp (my_name, f_name[i], 20))
+			if (loggedin && !strncasecmp (me->username, users[i]->username, 20))
 				{
 					if (requirenew)
 						{
@@ -831,18 +1025,20 @@
 							 * as someone else. just die. */
 							exit (111);
 						}
-					fprintf (fp, "%s:%s:%s:%s\n", my_name, my_email, my_pw, my_env);
+					fprintf (fp, "%s:%s:%s:%s\n", me->username, me->email, me->password,
+									 me->env);
 					my_done = 1;
 				}
 			else
 				{
-					fprintf (fp, "%s:%s:%s:%s\n", f_name[i], f_email[i], f_pw[i],
-									 f_env[i]);
+					fprintf (fp, "%s:%s:%s:%s\n", users[i]->username, users[i]->email,
+									 users[i]->password, users[i]->env);
 				}
 		}
 	if (loggedin && !my_done)
 		{														/* new entry */
-			fprintf (fp, "%s:%s:%s:%s\n", my_name, my_email, my_pw, my_env);
+			fprintf (fp, "%s:%s:%s:%s\n", me->username, me->email, me->password,
+							 me->env);
 		}
 
 	flock (fileno (fpl), LOCK_UN);
@@ -855,45 +1051,66 @@
 /* ************************************************************* */
 
 int
-main (int argc, char **argv)
+main (void)
 {
 	/* for chroot and program execution */
-	char *argv1 = LOC_NETHACK;
-	char *argv2 = "-u";
-	char *myargv[10];
 	uid_t newuid = SHED_UID;
 	gid_t newgid = SHED_GID;
-	char atrcfilename[81];
+	char atrcfilename[81], *spool;
+	unsigned int len;
+	struct rlimit rl = { RLIM_INFINITY, RLIM_INFINITY };
 
-	/* for login */
-	char inbuf[1024];							/* always check for overruns */
-	int userchoice;
+	int userchoice = 0;
+
+	/* coredumper */
+	setrlimit (RLIMIT_CORE, &rl);
 
 	/* signal handlers */
 	signal (SIGHUP, catch_sighup);
 
 	/* get master tty just before chroot (lives in /dev) */
 	ttyrec_getmaster ();
+#ifndef USE_OPENPTY
 	grantpt (master);
 	unlockpt (master);
 	if ((slave = open ((const char *) ptsname (master), O_RDWR)) < 0)
 		{
 			exit (65);
 		}
+#endif
 
 
 	/* chroot */
 	if (chroot (LOC_CHROOT))
-		error (1, errno, "cannot change root directory");
+		{
+			perror ("cannot change root directory");
+			exit (1);
+		}
 
 	if (chdir ("/"))
-		error (1, errno, "cannot chdir to root directory");
+		{
+			perror ("cannot chdir to root directory");
+			exit (1);
+		}
 
 	/* shed privs. this is done immediately after chroot. */
-	setgid (newgid);
-	setuid (newuid);
+	if (setgroups (1, &newgid) == -1)
+		{
+			perror ("setgroups");
+			exit (1);
+		}
+
+	if (setgid (newgid) == -1)
+		{
+			perror ("setgid");
+			exit (1);
+		}
 
-	initvars ();
+	if (setuid (newuid) == -1)
+		{
+			perror ("setuid");
+			exit (1);
+		}
 
 	/* simple login routine, uses ncurses */
 	if (readfile (0))
@@ -904,54 +1121,67 @@
 		{
 			drawmenu ();
 			userchoice = getch ();
-			if (userchoice == 'c')
-				{
-					changepw ();
-				}
-			if (userchoice == 'w')
+			switch (tolower (userchoice))
 				{
+				case 'c':
+					if (loggedin)
+						changepw ();
+					break;
+				case 'w':
 					inprogressmenu ();
-				}
-			if (userchoice == 'o' && loggedin)
-				{
-					editoptions ();
-				}
-			if (userchoice == 'q')
-				{
+					break;
+				case 'o':
+					if (loggedin)
+						editoptions ();
+					break;
+				case 'q':
 					endwin ();
-					exit (1);
-				}
-			if (userchoice == 'r')
-				{
-					newuser ();
-				}
-			if (userchoice == 'l')
-				{
-					login ();
+					return 0;
+					/* break; */
+				case 'r':
+					if (!loggedin)				/*not visible to loggedin */
+						newuser ();
+					break;
+				case 'l':
+					if (!loggedin)				/* not visible to loggedin */
+						loginprompt ();
+					break;
 				}
 		}
 
-	freefile ();
+	assert (loggedin);
+
 	endwin ();
 
 	/* environment */
-	strcpy (atrcfilename, "@");
-	strcat (atrcfilename, rcfilename);
+	snprintf (atrcfilename, 81, "@%s", rcfilename);
+
+	len = ARRAY_SIZE (LOC_SPOOLDIR) + strlen (me->username) + 1;
+	spool = malloc (len + 1);
+	snprintf (spool, len, "%s/%s", LOC_SPOOLDIR, me->username);
+
 	setenv ("NETHACKOPTIONS", atrcfilename, 1);
+	setenv ("MAIL", spool, 1);
+	setenv ("SIMPLEMAIL", "1", 1);
+
+	/* don't let the mail file grow */
+	if (access (spool, F_OK) == 0)
+		unlink (spool);
+
+	free (spool);
 
 	/* lock */
 	gen_ttyrec_filename ();
 	gen_inprogress_lock ();
 
 	/* launch program */
-	ttyrec_main (my_name);
-	/* myargv[0] = argv1;
-	   myargv[1] = argv2;
-	   myargv[2] = my_name;
-	   myargv[3] = 0;
-	   execvp (LOC_NETHACK, myargv);
-	   error (1, errno, "cannot execute %s", argv[0]);
-	 */
+	ttyrec_main (me->username);
+
+	/* NOW we can safely kill this */
+	freefile ();
+
+	if (me)
+		free (me);
 
 	exit (1);
 	return 1;
diff --exclude .cvsignore --exclude CVS --exclude 'strl*.c' -urN dgamelaunch-1.3.10/dgamelaunch.h dgamelaunch/dgamelaunch.h
--- dgamelaunch-1.3.10/dgamelaunch.h	2003-08-30 18:36:43.000000000 -0700
+++ dgamelaunch/dgamelaunch.h	2004-01-02 18:39:20.000000000 -0800
@@ -3,14 +3,72 @@
 #ifndef __DGAMELAUNCH_H
 #define __DGAMELAUNCH_H
 
-#define SHED_UID 1031						/* the uid to shed privs to */
-#define SHED_GID 1031						/* the gid to shed privs to */
+#include <time.h>
+
+/* Default - should work everywhere */
+#define USE_OPENPTY
+#define NOSTREAMS
+
+struct dg_user
+{
+	char *username;
+	char *email;
+	char *env;
+	char *password;
+	int flags;
+};
+
+struct dg_banner
+{
+	char **lines;
+	unsigned int len;
+};
+
+struct dg_game
+{
+	char *ttyrec_fn;
+	char *name;
+	char *date;
+	char *time;
+	time_t idle_time;
+};
+
+#define SHED_UID 5							/* the uid to shed privs to */
+#define SHED_GID 60							/* the gid to shed privs to */
 #define MAXUSERS 64000					/* solves some preallocation issues. */
 
-#define LOC_CHROOT "/opt/nethack/nethack.dtype.org"
-#define LOC_NETHACK "/bin/nethack"
-#define LOC_DGLDIR "/dgldir/rcfiles/"
-#define LOC_TTYRECDIR "/dgldir/ttyrec/"
-#define LOC_INPROGRESSDIR "/dgldir/inprogress/"
+#define LOC_CHROOT		"/var/lib/dgamelaunch/"
+#define LOC_NETHACK		"/bin/nethack"
+#define LOC_DGLROOT		"/dgldir/"
+#define LOC_DGLDIR		LOC_DGLROOT "rcfiles/"
+#define LOC_TTYRECDIR		LOC_DGLROOT "ttyrec/"
+#define LOC_INPROGRESSDIR	LOC_DGLROOT "inprogress/"
+#define LOC_SPOOLDIR		"/var/mail"
+#define LOC_CANNED		"/dgl-default-rcfile"
+#define LOC_BANNER		"/dgl-banner"
+
+/* dgamelaunch.c function prototypes */
+extern void ttyrec_getmaster (void);
+extern void gen_ttyrec_filename (void);
+extern void gen_inprogress_lock (void);
+extern void catch_sighup (int signum);
+extern void loadbanner (struct dg_banner *ban);
+extern void drawbanner (unsigned int start_line, unsigned int howmany);
+extern struct dg_game **populate_games (int *l);
+extern void inprogressmenu (void);
+extern void changepw (void);
+extern void domailuser (char *username);
+extern void drawmenu (void);
+extern void freefile (void);
+extern void initncurses (void);
+extern struct dg_user *deep_copy (struct dg_user *src);
+extern void loginprompt (void);
+extern void newuser (void);
+extern int passwordgood (char *cpw);
+extern int readfile (int nolock);
+extern int userexist (char *cname);
+extern void write_canned_rcfile (char *target);
+extern void editoptions (void);
+extern void writefile (int requirenew);
 
 #endif
diff --exclude .cvsignore --exclude CVS --exclude 'strl*.c' -urN dgamelaunch-1.3.10/dgl-banner dgamelaunch/dgl-banner
--- dgamelaunch-1.3.10/dgl-banner	1969-12-31 16:00:00.000000000 -0800
+++ dgamelaunch/dgl-banner	2003-12-31 11:13:00.000000000 -0800
@@ -0,0 +1,7 @@
+## dgamelaunch - network console game launcher
+## version $VERSION
+##
+## (c)2001-3 M. Drew Streib. This program's source is released under the GPL.
+## Send mail to <dtype@dtype.org> for details or a copy of the source code.
+## ** Games on this server are recorded for in-progress viewing and playback!
+## Server info is at http://alt.org/nethack/
diff --exclude .cvsignore --exclude CVS --exclude 'strl*.c' -urN dgamelaunch-1.3.10/dgl-create-chroot dgamelaunch/dgl-create-chroot
--- dgamelaunch-1.3.10/dgl-create-chroot	1969-12-31 16:00:00.000000000 -0800
+++ dgamelaunch/dgl-create-chroot	2003-12-31 13:41:04.000000000 -0800
@@ -0,0 +1,58 @@
+#!/bin/sh
+
+set -e
+
+CHROOT_PATH=/var/lib/dgamelaunch
+
+# Only in the chroot
+CHROOT_UID=5
+CHROOT_GID=60
+
+echo "Setting up the chroot in: $CHROOT_PATH"
+
+mkdir -p $CHROOT_PATH/lib $CHROOT_PATH/bin $CHROOT_PATH/etc $CHROOT_PATH/var/mail
+
+# Required libraries
+cp -L /lib/libc.so.6 $CHROOT_PATH/lib
+cp -L /lib/libncurses.so.5 $CHROOT_PATH/lib
+cp -L /lib/ld-linux.so.2 $CHROOT_PATH/lib
+
+# Passwd file
+echo "games:!:5:60:games:/nonexistent:/bin/sh" > $CHROOT_PATH/etc/passwd
+echo "games:x:60:" > $CHROOT_PATH/etc/group
+
+# Dungeon directory setup
+mkdir -p $CHROOT_PATH/dgldir/inprogress
+mkdir -p $CHROOT_PATH/dgldir/rcfiles
+mkdir -p $CHROOT_PATH/dgldir/ttyrec
+chown -R $CHROOT_UID:$CHROOT_GID $CHROOT_PATH/dgldir
+chown -R $CHROOT_UID:$CHROOT_GID $CHROOT_PATH/var/mail
+touch $CHROOT_PATH/dgl-login
+touch $CHROOT_PATH/dgl-lock
+
+# Might want to remove these two for packaging?
+cp dgl-default-rcfile $CHROOT_PATH/
+cp dgl-banner $CHROOT_PATH/
+
+chown $CHROOT_UID:$CHROOT_GID $CHROOT_PATH/dgl-*
+
+# Needs gzip to compress
+cp /bin/gzip $CHROOT_PATH/bin
+
+# Copy the nethack binary over (Debian specific for now)
+cp /usr/lib/games/nethack/nethack-console $CHROOT_PATH/bin/nethack
+
+# ...and all the data it needs
+mkdir -p $CHROOT_PATH/var/games/nethack/save
+mkdir -p $CHROOT_PATH/usr/lib/games/nethack
+touch $CHROOT_PATH/var/games/nethack/record
+touch $CHROOT_PATH/var/games/nethack/perm
+touch $CHROOT_PATH/var/games/nethack/logfile
+
+chown -R $CHROOT_UID:$CHROOT_GID $CHROOT_PATH/var/games/nethack
+cp -L /usr/lib/games/nethack/license $CHROOT_PATH/usr/lib/games/nethack
+cp -L /usr/lib/games/nethack/nhdat $CHROOT_PATH/usr/lib/games/nethack
+
+# Curses junk
+mkdir -p $CHROOT_PATH/usr/share
+cp -Lr /usr/share/terminfo $CHROOT_PATH/usr/share
diff --exclude .cvsignore --exclude CVS --exclude 'strl*.c' -urN dgamelaunch-1.3.10/dgl-default-rcfile dgamelaunch/dgl-default-rcfile
--- dgamelaunch-1.3.10/dgl-default-rcfile	1969-12-31 16:00:00.000000000 -0800
+++ dgamelaunch/dgl-default-rcfile	2003-12-30 12:30:55.000000000 -0800
@@ -0,0 +1,20 @@
+# This is your personal nethackrc file. It is in the same format as default
+# nethack options files. Optionally uncomment the following lines as a
+# starter. This editor is vi-like. Type ESC a couple times, then ':q!'
+# (without quotes) to exit if you get stuck.
+#
+# See the following link for more options information:
+# http://www.nethack.org/v341/Guidebook.html#_TOCentry_40
+#
+# OPTIONS=showexp,showscore,time
+# OPTIONS=!autopickup,color
+# OPTIONS=catname:catfoo,dogname:dogfoo,horsename:horsefoo
+#
+# The following lines are necessary if you want to use the menucolors option.
+# OPTIONS=menucolors
+# MENUCOLOR=" blessed "=green
+# MENUCOLOR=" holy "=green
+# MENUCOLOR=" uncursed "=yellow
+# MENUCOLOR=" cursed "=red
+# MENUCOLOR=" unholy "=red
+# MENUCOLOR=" cursed .* (being worn)"=orange&underline
diff --exclude .cvsignore --exclude CVS --exclude 'strl*.c' -urN dgamelaunch-1.3.10/Makefile dgamelaunch/Makefile
--- dgamelaunch-1.3.10/Makefile	2003-08-30 15:14:52.000000000 -0700
+++ dgamelaunch/Makefile	2004-01-02 18:39:18.000000000 -0800
@@ -1,12 +1,47 @@
-LDFLAGS = -static
-all: dgamelaunch
-dgamelaunch: dgamelaunch.c /usr/lib/libncurses.a /usr/lib/libcrypt.a virus.o ttyrec.o io.o ttyplay.o stripgfx.o
+VERSION = 1.3.10.1
+NAME = dgamelaunch
+exclusions = CVS .cvsignore tags
+
+ifndef optimize
+  optimize = -O0
+endif
+
+CC = gcc
+LDFLAGS = 
+CFLAGS = -g3 $(optimize) -Wall $(DEFS)
+DEFS = -DVERSION=\"$(VERSION)\"
+SRCS = virus.c ttyrec.c dgamelaunch.c io.c ttyplay.c stripgfx.c
+OBJS = $(SRCS:.c=.o)
+LIBS = -lncurses -lcrypt -lutil
+
+all: $(NAME)
+
+$(NAME): $(OBJS)
+	$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS)
+
 clean:
 	rm -f dgamelaunch
-	rm -f *.o
+	rm -f *.o .#* *~
+	
 install:
-	cp dgamelaunch /opt/nethack/nethack.dtype.org/
+	cp dgamelaunch /usr/sbin
+	
 indent:
 	indent -ts2 *.c *.h
-	rm *~
-release: clean indent
+	rm -f *~
+
+dist: clean indent
+	rm -rf $(NAME)-$(VERSION)
+	(cd .. && ln -sf $(CURDIR) $(NAME)-$(VERSION))
+	(cd .. && tar $(addprefix --exclude ,$(exclusions)) -chzf $(NAME)-$(VERSION).tar.gz $(NAME)-$(VERSION))
+	rm -f ../$(NAME)-$(VERSION)
+	@echo "Created source release $(NAME)-$(VERSION).tar.gz"
+	
+# Dependencies - we may auto-generate later
+dgamelaunch.o: dgamelaunch.c dgamelaunch.h
+io.o: io.c ttyrec.h
+last_char_is.o: last_char_is.c
+stripgfx.o: stripgfx.c stripgfx.h
+ttyplay.o: ttyplay.c ttyrec.h io.h stripgfx.h
+ttyrec.o: ttyrec.c dgamelaunch.h ttyrec.h io.h
+virus.o: virus.c last_char_is.c
diff --exclude .cvsignore --exclude CVS --exclude 'strl*.c' -urN dgamelaunch-1.3.10/README dgamelaunch/README
--- dgamelaunch-1.3.10/README	2003-08-30 14:30:15.000000000 -0700
+++ dgamelaunch/README	2004-01-02 16:50:48.000000000 -0800
@@ -22,6 +22,11 @@
 and 'inprogress' directories, in the dgldir. Also touch the files
 'dgl-login' and 'dgl-lock' in the main chroot directory.
 
+3) Copy the dgl-banner and dgl-default-rcfile files into the main 
+chroot directory  and optionally modify them. If these files aren't
+available in the package simply touch the files in the main chroot
+directory. 
+
 Your directories/files should now look like this:
 
 /chrootdir/bin/
@@ -34,6 +39,8 @@
 /chrootdir/dgldir/rcfiles/
 /chrootdir/dgl-login (empty)
 /chrootdir/dgl-lock (empty)
+/chrootdir/dgl-banner
+/chrootdir/dgl-default-rcfile
 
 They should all be owned by the user you intend to run this as.
 
@@ -69,11 +76,19 @@
   wait      = no
   user      = root
   server    = /usr/sbin/in.telnetd
-  server_args     = -L /opt/nethack/nethack.dtype.org/dgamelaunch
+  server_args     = -h -L /opt/nethack/nethack.dtype.org/dgamelaunch
   rlimit_cpu      = 3600
   bind      = 64.71.163.206
 }
 
+An classic inetd line would look like this
+
+telnet stream tcp nowait root.root /usr/sbin/tcpd /usr/sbin/in.telnetd -h -L /usr/sbin/dgamelaunch
+
+In both cases, the -L specifies an alternate login program (telnetlogin is
+invoked by default) and -h prevents revealing of a login banner (for example,
+"Debian GNU/Linux testing/unstable influx") before starting the login shell.
+
 6) Populate /chrootdir/etc/terminfo with terminfo files. I think that most
 modern ncurses will default to terminfo when it is available. Mine seemed
 to. This also makes it easy to add term types on the fly.
diff --exclude .cvsignore --exclude CVS --exclude 'strl*.c' -urN dgamelaunch-1.3.10/stripgfx.c dgamelaunch/stripgfx.c
--- dgamelaunch-1.3.10/stripgfx.c	2003-08-30 19:23:20.000000000 -0700
+++ dgamelaunch/stripgfx.c	2004-01-02 18:39:19.000000000 -0800
@@ -2,6 +2,7 @@
 /* Copyright (c) NetHack Development Team 1992.			  */
 /* NetHack may be freely redistributed.  See license for details. */
 
+#include <string.h>
 #include "stripgfx.h"
 
 #define MAXPCHARS 92
@@ -356,11 +357,11 @@
 		}
 
 	/*
-	endwin();
-	for (i=0;i<256;i++) {
-		printf("%X:%X ",i,gfx_map[i]);
-	}
-	exit(1);  */
+	   endwin();
+	   for (i=0;i<256;i++) {
+	   printf("%X:%X ",i,gfx_map[i]);
+	   }
+	   exit(1);  */
 }
 
 unsigned char
diff --exclude .cvsignore --exclude CVS --exclude 'strl*.c' -urN dgamelaunch-1.3.10/TODO dgamelaunch/TODO
--- dgamelaunch-1.3.10/TODO	1969-12-31 16:00:00.000000000 -0800
+++ dgamelaunch/TODO	2004-01-02 12:31:31.000000000 -0800
@@ -0,0 +1,9 @@
+- Flags for operators/staff/admins or (optionally) user-bans.
+
+- Put 'terminate' option in user's menu to end disconnected sessions.
+  (Suggested by Sebbe in #nethack on freenode)
+
+- Localization of variables, code clean up
+
+- Allow a runtime-read configuration file to specify all the stuff
+  that is currently hardcoded into dgamelaunch.h.
diff --exclude .cvsignore --exclude CVS --exclude 'strl*.c' -urN dgamelaunch-1.3.10/ttyplay.c dgamelaunch/ttyplay.c
--- dgamelaunch-1.3.10/ttyplay.c	2003-09-06 21:02:49.000000000 -0700
+++ dgamelaunch/ttyplay.c	2004-01-02 18:39:19.000000000 -0800
@@ -40,14 +40,21 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <string.h>
-
+#include <curses.h>
 #include "ttyrec.h"
 #include "io.h"
 #include "stripgfx.h"
 
-extern int caught_sighup;
+extern void domailuser (char *);
+extern void initncurses (void);
+extern char *chosen_name;
+extern int loggedin;
+
+int ttyplay_main (char *ttyfile, int mode, int rstripgfx);
+
 off_t seek_offset_clrscr;
 int bstripgfx;
+char *ttyfile_local;
 
 typedef double (*WaitFunc) (struct timeval prev,
 														struct timeval cur, double speed);
@@ -126,7 +133,6 @@
 int
 ttyread (FILE * fp, Header * h, char **buf, int pread)
 {
-	int counter = 0;
 	long offset;
 
 	/* do this BEFORE header read, hlen bug */
@@ -198,6 +204,16 @@
 						case 'q':
 							return 0;
 							break;
+						case 'm':
+							if (loggedin)
+								{
+									initncurses ();
+									domailuser (chosen_name);
+									endwin ();
+									ttyplay_main (ttyfile_local, 1, 0);
+									return 0;
+								}
+							break;
 						}
 				}
 		}
@@ -267,11 +283,9 @@
 void
 set_seek_offset_clrscr (FILE * fp)
 {
-	off_t last_header_offset = 0;
 	off_t raw_seek_offset = 0;
 	char *buf;
 	struct stat mystat;
-	char s_clrscr[4];
 	int state = 0;
 	int i;
 	int bytesread;
@@ -364,16 +378,6 @@
 }
 
 
-void
-usage (void)
-{
-	printf ("Usage: ttyplay [OPTION] [FILE]\n");
-	printf ("  -s SPEED Set speed to SPEED [1.0]\n");
-	printf ("  -n       No wait mode\n");
-	printf ("  -p       Peek another person's ttyrecord\n");
-	exit (EXIT_FAILURE);
-}
-
 int
 ttyplay_main (char *ttyfile, int mode, int rstripgfx)
 {
@@ -384,6 +388,8 @@
 	FILE *input = stdin;
 	struct termios old, new;
 
+	ttyfile_local = ttyfile;
+
 	/* strip graphics mode flag */
 	bstripgfx = rstripgfx;
 	if (bstripgfx)
diff --exclude .cvsignore --exclude CVS --exclude 'strl*.c' -urN dgamelaunch-1.3.10/ttyrec.c dgamelaunch/ttyrec.c
--- dgamelaunch-1.3.10/ttyrec.c	2003-09-05 11:44:10.000000000 -0700
+++ dgamelaunch/ttyrec.c	2004-01-02 18:39:19.000000000 -0800
@@ -49,19 +49,24 @@
 #include <sys/ioctl.h>
 #include <time.h>
 #include <sys/file.h>
-#include <sys/signal.h>
+#include <signal.h>
 #include <stdio.h>
 #include <unistd.h>
 #include <string.h>
-
+#ifndef NOSTREAMS
+# include <stropts.h>
+#endif
 #include <stdlib.h>
 #include <fcntl.h>
-#include <stropts.h>
 
 #include <sys/time.h>
 #include "ttyrec.h"
 #include "io.h"
 
+#ifndef XCASE
+# define XCASE 0
+#endif
+
 #define HAVE_inet_aton
 #define HAVE_scsi_h
 #define HAVE_kd_h
@@ -75,7 +80,6 @@
 #define CDEL _POSIX_VDISABLE
 
 extern char ttyrec_filename[100];
-extern int caught_sighup;
 extern int pid_game;
 
 void done (void);
@@ -102,20 +106,16 @@
 int
 ttyrec_main (char *username)
 {
-	int ch;
 	void finish ();
-	char *getenv ();
-	char *command = NULL;
 	char dirname[100];
 
+	snprintf (dirname, 100, "%s%s", LOC_TTYRECDIR, username);
 
-	strcpy (dirname, LOC_TTYRECDIR);
-	strncat (dirname, username, 30);
-	/* create if it doesn't exist */
-	mkdir (dirname, 0755);
+	if (access (dirname, F_OK) != 0)
+		mkdir (dirname, 0755);
 
-	strcat (dirname, "/");
-	strcat (dirname, ttyrec_filename);
+	snprintf (dirname, 100, "%s%s/%s", LOC_TTYRECDIR, username,
+						ttyrec_filename);
 
 	if ((fscript = fopen (dirname, "w")) == NULL)
 		{
@@ -306,6 +306,7 @@
 	myargv[1] = argv2;
 	myargv[2] = username;
 	myargv[3] = 0;
+
 	execvp (LOC_NETHACK, myargv);
 
 	fail ();
@@ -368,6 +369,7 @@
 	   perror("open(fd, O_RDWR)");
 	   fail();
 	   } */
+#ifndef NOSTREAMS
 	if (isastream (slave))
 		{
 			if (ioctl (slave, I_PUSH, "ptem") < 0)
@@ -387,6 +389,7 @@
 					fail ();
 				}
 #endif
-			(void) ioctl (0, TIOCGWINSZ, (char *) &win);
 		}
+#endif /* !NOSTREAMS */
+	(void) ioctl (0, TIOCGWINSZ, (char *) &win);
 }
diff --exclude .cvsignore --exclude CVS --exclude 'strl*.c' -urN dgamelaunch-1.3.10/ttyrec.h dgamelaunch/ttyrec.h
--- dgamelaunch-1.3.10/ttyrec.h	2003-08-30 18:36:43.000000000 -0700
+++ dgamelaunch/ttyrec.h	2004-01-02 18:39:20.000000000 -0800
@@ -1,12 +1,13 @@
 #ifndef __TTYREC_H__
 #define __TTYREC_H__
 
-#include "sys/time.h"
+#include <sys/time.h>
+#include <sys/types.h>
 
 typedef struct header
 {
 	struct timeval tv;
-	int len;
+	size_t len;
 }
 Header;
 
diff --exclude .cvsignore --exclude CVS --exclude 'strl*.c' -urN dgamelaunch-1.3.10/virus.c dgamelaunch/virus.c
--- dgamelaunch-1.3.10/virus.c	2003-09-05 11:26:02.000000000 -0700
+++ dgamelaunch/virus.c	2004-01-02 18:39:19.000000000 -0800
@@ -83,8 +83,6 @@
 #include <stdarg.h>
 
 #include "last_char_is.c"
-#include "strlcat.c"
-#include "strlcpy.c"
 
 #ifndef TRUE
 #define TRUE			((int)1)
@@ -307,8 +305,6 @@
 extern int
 vi_main (int argc, char **argv)
 {
-	int c;
-
 #ifdef BB_FEATURE_VI_YANKMARK
 	int i;
 #endif /* BB_FEATURE_VI_YANKMARK */
@@ -348,55 +344,17 @@
 	modifying_cmds = (Byte *) "aAcCdDiIJoOpPrRsxX<>~";	// cmds modifying text[]
 #endif /* BB_FEATURE_VI_DOT_CMD */
 
-	//  1-  process $HOME/.exrc file
-	//  2-  process EXINIT variable from environment
-	//  3-  process command line args
-	while ((c = getopt (argc, argv, "hCR")) != -1)
+	if (argc >= 2)
 		{
-			switch (c)
-				{
-#ifdef BB_FEATURE_VI_CRASHME
-				case 'C':
-					crashme = 1;
-					break;
-#endif /* BB_FEATURE_VI_CRASHME */
-#ifdef BB_FEATURE_VI_READONLY
-				case 'R':							// Read-only flag
-					readonly = TRUE;
-					break;
-#endif /* BB_FEATURE_VI_READONLY */
-					//case 'r':     // recover flag-  ignore- we don't use tmp file
-					//case 'x':     // encryption flag- ignore
-					//case 'c':     // execute command first
-					//case 'h':     // help -- just use default
-				default:
-					show_help ();
-					return 1;
-				}
-		}
-
-	// The argv array can be used by the ":next"  and ":rewind" commands
-	// save optind.
-	fn_start = optind;						// remember first file name for :next and :rew
-	save_argc = argc;
-
-	//----- This is the main file handling loop --------------
-	if (optind >= argc)
-		{
-			editing = 1;							// 0= exit,  1= one file,  2= multiple files
-			edit_file (0);
+			cfn = (Byte *) strdup (argv[1]);
+			edit_file (cfn);
 		}
 	else
 		{
-			for (; optind < argc; optind++)
-				{
-					editing = 1;					// 0=exit, 1=one file, 2+ =many files
-					if (cfn != 0)
-						free (cfn);
-					cfn = (Byte *) strdup (argv[optind]);
-					edit_file (cfn);
-				}
+			fprintf (stderr, "%s: no file to edit, bailing out\n", argv[0]);
+			exit (1);
 		}
+
 	//-----------------------------------------------------------
 
 
@@ -883,7 +841,6 @@
 			goto dc1;
 		}
 
-key_cmd_mode:
 	switch (c)
 		{
 			//case 0x01:    // soh
@@ -3762,7 +3719,8 @@
 readit (void)										// read (maybe cursor) key from stdin
 {
 	Byte c;
-	int i, bufsiz, cnt, cmdindex;
+	int i, bufsiz, cnt;
+	unsigned int cmdindex;
 	struct esc_cmds
 	{
 		Byte *seq;
