diff -Nupr src/Makefile.amiga src.new/Makefile.amiga
--- src/Makefile.amiga	Tue Nov  3 12:58:04 1998
+++ src.new/Makefile.amiga	Mon Dec  9 13:56:35 2002
@@ -24,7 +24,7 @@ OBJFILES = comm.o act.comm.o act.informa
 	castle.o class.o config.o constants.o db.o fight.o graph.o handler.o \
 	house.o interpreter.o limits.o magic.o mail.o mobact.o modify.o \
 	objsave.o olc.o shop.o spec_assign.o spec_procs.o spell_parser.o \
-	spells.o utils.o weather.o alias.o
+	spells.o utils.o weather.o alias.o client.o
 
 default: .accepted
 	$(MAKE) ../bin/circle
@@ -210,3 +210,5 @@ utils.o: utils.c conf.h sysdep.h structs
 weather.o: weather.c conf.h sysdep.h structs.h utils.h comm.h handler.h \
   interpreter.h db.h
 	$(CC) -c $(CFLAGS) weather.c
+client.o: conf.h sysdep.h structs.h
+	$(CC) -c $(CFLAGS) client.c
diff -Nupr src/Makefile.bcc src.new/Makefile.bcc
--- src/Makefile.bcc	Sun Apr 11 21:18:59 1999
+++ src.new/Makefile.bcc	Mon Dec  9 13:58:13 2002
@@ -79,7 +79,8 @@ Dep_circledexe = \
    spec_procs.obj\
    spec_assign.obj\
    utils.obj\
-   weather.obj
+   weather.obj\
+   client.obj
 
 circle.exe : $(Dep_circledexe)
   $(TLINK32) @&&|
@@ -121,7 +122,8 @@ spell_parser.obj+
 spec_procs.obj+
 spec_assign.obj+
 utils.obj+
-weather.obj
+weather.obj+
+client.obj
 $<,$*
 C:\BC5\LIB\bidsfi.lib+
 C:\BC5\LIB\import32.lib+
@@ -312,6 +314,11 @@ utils.obj :  utils.c
 weather.obj :  weather.c
   $(BCC32) -P- -c @&&|
  $(CompOptsAt_circledexe) $(CompInheritOptsAt_circledexe) -o$@ weather.c
+|
+
+client.obj : client.c
+  $(BCC32) -P- -c @&&|
+ $(CompOptsAt_circledexe) $(CompInheritOptsAt_circledexe) -o$@ client.c
 |
 
 # Compiler configuration file
diff -Nupr src/Makefile.bcc55 src.new/Makefile.bcc55
--- src/Makefile.bcc55	Thu May 24 08:37:13 2001
+++ src.new/Makefile.bcc55	Mon Dec  9 13:58:12 2002
@@ -80,7 +80,8 @@ Dep_circledexe = \
    spec_procs.obj\
    spec_assign.obj\
    utils.obj\
-   weather.obj
+   weather.obj\
+   client.obj
 
 circle.exe : $(Dep_circledexe)
   $(TLINK32) @&&|
@@ -122,7 +123,8 @@ spell_parser.obj+
 spec_procs.obj+
 spec_assign.obj+
 utils.obj+
-weather.obj
+weather.obj+
+client.obj
 $<,$*
 C:\BORLAND\BCC55\LIB\import32.lib+
 C:\BORLAND\BCC55\LIB\cw32i.lib
@@ -311,6 +313,11 @@ utils.obj :  utils.c
 weather.obj :  weather.c
   $(BCC32) -P- -c @&&|
  $(CompOptsAt_circledexe) $(CompInheritOptsAt_circledexe) -o$@ weather.c
+|
+
+client.obj : client.c
+  $(BCC32) -P- -c @&&|
+ $(CompOptsAt_circledexe) $(CompInheritOptsAt_circledexe) -o$@ client.c
 |
 
 # Compiler configuration file
diff -Nupr src/Makefile.in src.new/Makefile.in
--- src/Makefile.in	Mon Apr 15 22:22:12 2002
+++ src.new/Makefile.in	Mon Dec  9 13:54:04 2002
@@ -29,7 +29,7 @@ OBJFILES = act.comm.o act.informative.o 
 	graph.o handler.o house.o interpreter.o limits.o magic.o mail.o \
 	mobact.o modify.o objsave.o olc.o random.o shop.o spec_assign.o \
 	spec_procs.o spell_parser.o spells.o utils.o weather.o \
-	bsd-snprintf.o
+	bsd-snprintf.o client.o
 
 CXREF_FILES = act.comm.c act.informative.c act.item.c act.movement.c \
 	act.offensive.c act.other.c act.social.c act.wizard.c alias.c ban.c \
@@ -204,3 +204,5 @@ weather.o: weather.c conf.h sysdep.h str
 	$(CC) -c $(CFLAGS) weather.c
 bsd-snprintf.o: bsd-snprintf.c conf.h sysdep.h
 	$(CC) -c $(CFLAGS) bsd-snprintf.c
+client.o: conf.h sysdep.h structs.h
+	$(CC) -c $(CFLAGS) client.c
diff -Nupr src/Makefile.lcc src.new/Makefile.lcc
--- src/Makefile.lcc	Tue Jan 15 22:11:13 2002
+++ src.new/Makefile.lcc	Mon Dec  9 13:59:45 2002
@@ -52,7 +52,8 @@ OBJS=\
 	act.item.obj \
 	act.informative.obj \
 	act.comm.obj \
-	alias.obj
+	alias.obj \
+	client.obj
 
 LIBS=$(LCCDIR)\lib\wsock32.lib
 
@@ -563,4 +564,13 @@ ALIAS_C=\
 
 alias.obj: $(ALIAS_C) $(DISTDIR)\src\alias.c
     $(CC)  $(CFLAGS) $(DISTDIR)\src\alias.c
+
+# BUILD CLIENT.C
+CLIENT_C=\
+    $(DISTDIR)\src\sysdep.h\
+    $(DISTDIR)\src\structs.h\
+
+client.obj: $(CLIENT_C) $(DISTDIR)\src\client.c
+    $(CC)  $(CFLAGS) $(DISTDIR)\src\client.c
+
 
diff -Nupr src/Makefile.msvc src.new/Makefile.msvc
--- src/Makefile.msvc	Tue Nov  3 12:58:06 1998
+++ src.new/Makefile.msvc	Mon Dec  9 13:53:36 2002
@@ -40,7 +40,7 @@ OBJFILES = comm.obj act.comm.obj act.inf
         castle.obj class.obj config.obj constants.obj db.obj fight.obj graph.obj handler.obj \
         house.obj interpreter.obj limits.obj magic.obj mail.obj mobact.obj modify.obj \
         objsave.obj olc.obj shop.obj spec_assign.obj spec_procs.obj spell_parser.obj \
-        spells.obj utils.obj weather.obj random.obj alias.obj
+        spells.obj utils.obj weather.obj random.obj alias.obj client.obj
 
 default: circle.exe
         $(MAKE) circle.exe
@@ -156,3 +156,5 @@ utils.obj: utils.c conf.h sysdep.h struc
 weather.obj: weather.c conf.h sysdep.h structs.h utils.h comm.h handler.h \
   interpreter.h db.h
 	$(CC) -c $(CFLAGS) weather.c
+client.obj: conf.h sysdep.h structs.h
+	$(CC) -c $(CFLAGS) client.c
diff -Nupr src/Makefile.os2 src.new/Makefile.os2
--- src/Makefile.os2	Tue Nov  3 12:58:06 1998
+++ src.new/Makefile.os2	Mon Dec  9 13:55:01 2002
@@ -26,7 +26,7 @@ OBJFILES = comm.o act.comm.o act.informa
         castle.o class.o config.o constants.o db.o fight.o graph.o handler.o \
         house.o interpreter.o limits.o magic.o mail.o mobact.o modify.o \
         objsave.o olc.o shop.o spec_assign.o spec_procs.o spell_parser.o \
-        spells.o utils.o weather.o random.o alias.o
+        spells.o utils.o weather.o random.o alias.o client.o
 
 default: .accepted
         $(MAKE) ../bin/circle
@@ -212,3 +212,5 @@ utils.o: utils.c conf.h sysdep.h structs
 weather.o: weather.c conf.h sysdep.h structs.h utils.h comm.h handler.h \
   interpreter.h db.h
         $(CC) -c $(CFLAGS) weather.c
+client.o: conf.h sysdep.h structs.h
+	$(CC) -c $(CFLAGS) client.c
diff -Nupr src/Smakefile src.new/Smakefile
--- src/Smakefile	Wed Oct 29 00:16:20 1997
+++ src.new/Smakefile	Mon Dec  9 14:00:52 2002
@@ -202,4 +202,5 @@ utils.o: utils.c conf.h sysdep.h structs
 weather.o: weather.c conf.h sysdep.h structs.h utils.h comm.h handler.h \
   interpreter.h db.h
 	$(CC) $(CFLAGS) weather.c
-
+client.o: client.c conf.h sysdep.h structs.h
+	$(CC) $(CFLAGS) client.c
diff -Nupr src/client.c src.new/client.c
--- src/client.c	Wed Dec 31 19:00:00 1969
+++ src.new/client.c	Mon Dec  9 13:52:09 2002
@@ -0,0 +1,290 @@
+/*
+ * client.c: The routines for the metaserver reporting.
+ * :::NOTE:::
+ * If you use this software, send me an email letting me know, so
+ * I can keep you informed of updates.
+ * The current version is displayed when you telnet to the server,
+ * but I'd prefer to be able just to send out one bulk mail to let
+ * everyone using it know at the same time.  I make some small attempt to
+ * maintain backwards compatibility, but in no way guarantee it, so I do
+ * recommend you keep up on the current version.
+ *
+ * For those who don't understand RCS variable expansion, the version number
+ * is here
+ *		   vvv
+ * $Id$
+ */
+
+#include "conf.h"
+#include "sysdep.h"
+
+#include "structs.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+
+/*
+ * Error conditions stored in report.ok
+ * For the most part they're to help with debugging, since only
+ * REPORT_OK, RETRY, FAILED would suffice, but they help track down
+ * where the error occurred from.
+ */
+typedef enum {
+	REPORT_OK, SOCKET, RETRY, GETHOSTBYNAME, CONNECT, UNINITIALIZED
+} rpt_err;
+#define MINUTES *60
+
+struct report_data {
+	rpt_err ok;    /* Is everything set up properly? */
+	int socket; /* persistent udp socket */
+	time_t update; /* last time the dns information was updated. */
+	struct sockaddr_in addr; /* Store this stuff for the sendto() call */
+	struct hostent *serv_data;
+} report;
+
+/*
+ * Uncomment this next line if you want to limit the number of times it will try
+ * to re-initialize itself in case of errors.
+ */
+/* #define MAX_FAILED_UPDATES 5 */
+#ifdef MAX_FAILED_UPDATES
+byte failed_updates = 0;
+#endif
+
+/*
+ * This determines if you want a persistent connection and just use send()
+ * or just to let sendto() handle the connecting.  If you have some minor
+ * hangs when the mud tries to report, you'll want a persistent connection,
+ * since it only has to connect one time.
+ * If you want a persistent connection, uncomment the following line.
+ */
+/* #define PERSISTENT */
+
+extern ush_int DFLT_PORT;  /* The default port the mud is running on. */
+void nonblock(int);
+extern struct descriptor_data *descriptor_list;
+void basic_mud_log(const char *, ...);  /* Why include utils.h just for this? */
+#define log basic_mud_log
+
+/*
+ * For cygwin
+ * I don't have cygwin.  I don't know if it even supports this.  If it doesn't,
+ * then there's a chance that the send() or sendto() could block.  This COULD
+ * create some annoying pauses.  I'm not sure of that since I also set the socket
+ * to nonblocking, at least for persistent connections.  If you notice this happening
+ * and aren't using a persistent one, try it again with that define uncommented and
+ * see if it goes away.
+ */
+#ifndef MSG_DONTWAIT
+#define MSG_DONTWAIT 0x40
+#endif
+
+#ifndef MAX
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+/*
+ * Uncomment the following define and replace BOGUS_MUDNAME with the name of your
+ * mud.  Failure to uncomment it will stop it from compiling.  Failure to change
+ * it from the default will keep you from being listed.
+ */
+/* #define MUDNAME "BOGUS_MUDNAME" */
+#if !defined(MUDNAME)
+#error "You must uncomment the above line which defines MUDNAME and replace"
+#error "'BOGUS_MUDNAME' with the name of your mud.  It must not contain a '*'"
+#endif
+
+/*
+ * If you have some dynamic dns you use, set it here.
+ * Leaving this as the default value will result in your fqdn being listed as
+ * whatever your ip resolves to (which is often pretty ugly looking.)
+ * This information IS verified.  First I take the address from the packet your
+ * mud sends me.  Then I resolve whatever you fill in here.  If they don't match,
+ * you don't get listed.  I don't check for aliases or multiple addresses, so this
+ * had better resolve directly back to the ip your mud is running on.
+ */
+#define MUDDNS "BOGUS.DNS.NET"
+
+/*
+ * Do NOT change this.
+ */
+#define SERVER "velgarian.sytes.net"
+
+
+void init_report_socket(void)
+{
+	/* create the socket */
+	if((report.socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
+		log("SYSERR: Can't open status socket: %s", strerror(errno));
+		report.ok = SOCKET;
+#ifdef MAX_FAILED_UPDATES
+		failed_updates++;
+#endif
+		return FALSE;
+	}
+	/* make sure it's non-blocking */
+	nonblock(report.socket);
+
+	return TRUE;
+}
+
+
+void setup_report(void)
+{
+	static bool first = TRUE;
+
+#ifdef MAX_FAILED_UPDATES
+	if(failed_updates > MAX_FAILED_UPDATES) return;
+#endif
+
+	memset(&report.addr, 0, sizeof(report.addr));
+
+	/*
+	 * If this is the first time it's been called, set report.ok to UNINITIALIZED.
+	 */
+	if(first) {
+		report.ok = UNINITIALIZED;
+		first = FALSE;
+	}
+
+	report.update = time(0);
+
+	/* get hostent info for the server */
+	if(!(report.serv_data = gethostbyname(SERVER))) {
+		switch(h_errno) {
+		case TRY_AGAIN: /* A temporary error occured. */
+		case NO_DATA:  /* Valid name but no IP address. Let's try it again later anyway. */
+			if(report.ok != RETRY) { /* Avoid spamming the logs with "resource temp unavail" errors. */
+				/* Yeah, hstrerror obsolete but it's more accurate */
+				log("SYSERR: Can't get address of status server: %s.  Trying again later", hstrerror(h_errno));
+				report.ok = RETRY; /* It is a retryable error. */
+			}
+#ifdef PERSISTENT
+			close(report.socket);
+#endif
+			break;
+		default: /* A non-recoverable error occured */
+			log("SYSERR: Fatal error in gethostbyname: %s", hstrerror(h_errno));
+			report.ok = GETHOSTBYNAME;
+#ifdef PERSISTENT
+			close(report.socket);
+#endif
+			break;
+		}
+#ifdef MAX_FAILED_UPDATES
+		failed_updates++;
+#endif
+		return;
+	}
+
+	/* set up report.addr with all the info */
+	report.addr.sin_family = AF_INET;
+	report.addr.sin_port = htons(5000);
+	memcpy(&report.addr.sin_addr, report.serv_data->h_addr, report.serv_data->h_length);
+
+#ifdef PERSISTENT
+
+	if(!init_report_socket()) return;
+
+	/* Now connect to it. */
+	if(connect(report.socket, (struct sockaddr *)&report.addr, sizeof(report.addr)) < 0) {
+		log("SYSERR: Can't connect: %s", strerror(errno));
+		close(report.socket);
+		report.ok = CONNECT;
+#ifdef MAX_FAILED_UPDATES
+		failed_updates++;
+#endif
+		return;
+	}
+#endif
+
+	/* if we got this far, then everything is (hopefully) set up ok */
+	report.ok = REPORT_OK;
+#ifdef MAX_FAILED_UPDATES
+	failed_updates = 0;
+#endif
+}
+
+void reset_report(void)
+{
+#ifdef PERSISTENT
+	if(report.ok == REPORT_OK) {
+		close(report.socket);
+	}
+#endif
+
+	setup_report();
+}
+
+/*
+ * This defines the maximum length of the UDP packet sent.
+ * 1024 is probably excessive, but it's also the largest one
+ * that I'll receive.  The actual size of the packet sent is
+ * set to the length of the report string that's built.
+ */
+#define BUFLEN 1024
+#if BUFLEN > 1024
+#error "BUFLEN must be 1024 or less."
+#endif
+
+void report_status(void)
+{
+	char stats[BUFLEN];
+	extern time_t boot_time;
+	struct descriptor_data *d;
+	int users = 0;
+
+	/*
+	 * if everything isn't set up ok, report.ok is false, so just return
+	 * Unless we have gethostbyname() return TRY_AGAIN, then we give it another
+	 * shot.  Also, once we're set up and running, if send()/sendto() fails, we set
+	 * report.ok to RETRY and set everything up again, in case something changed.
+	 * The 60 minute wait is so we don't slow things down with constant calls to
+	 * gethostbyname() which tends to annoyingly block.  The only way around that is
+	 * to thread the call, and I don't think most people want me threading their muds,
+	 * although it's very simple, and does have a number of benefits here & there, but
+	 * you also REALLY need to know what you're doing.
+	 */
+	if(report.ok != REPORT_OK) {
+		switch(report.ok) {
+		case RETRY:
+			if((time(0) - report.update) > (60 MINUTES))
+				reset_report();
+			break;
+		default:
+			return;
+		}
+		return;
+	}
+
+	/* count the connected users */
+	for(d = descriptor_list; d; d = d->next, users++);
+
+	/* make the status string to send */
+	memset(stats, 0, BUFLEN);
+	snprintf(stats, BUFLEN, "%s*%ld*%d*%d*%s", MUDNAME, boot_time, users, DFLT_PORT, MUDDNS);
+	
+	/*
+	 * Send the packet.  If we have a persistent connection, just use send.  Otherwise,
+	 * use sendto() since it takes care of connecting for us.
+	 */
+#ifdef PERSISTENT
+	if(send(report.socket, stats, (size_t)MIN(1024, strlen(stats)), MSG_DONTWAIT) < 0) {
+#else
+	if(!init_report_socket()) return;
+	
+	if(sendto(report.socket, stats, (size_t)MIN(1024, strlen(stats)), MSG_DONTWAIT,
+				(struct sockaddr *)&report.addr, sizeof(report.addr)) < 0) {
+#endif
+		log("SYSERR: report_status sending: %s", strerror(errno));
+		if((errno != EAGAIN) && (errno != EWOULDBLOCK)) {
+			report.ok = RETRY;
+		}
+		return;
+	}
+#ifndef PERSISTENT
+	close(report.socket);
+#endif
+}
diff -Nupr src/comm.c src.new/comm.c
--- src/comm.c	Mon Dec  9 13:51:21 2002
+++ src.new/comm.c	Mon Dec  9 13:51:48 2002
@@ -162,6 +162,8 @@ void free_messages(void);
 void Board_clear_all(void);
 void free_social_messages(void);
 void Free_Invalid_List(void);
+void setup_report(void);
+void report_status(void);
 
 #ifdef __CXREF__
 #undef FD_ZERO
@@ -608,15 +610,37 @@ void game_loop(socket_t mother_desc)
 
     /* Sleep if we don't have any connections */
     if (descriptor_list == NULL) {
+      int _retval = 0;
+      struct timeval _tv;
+
       log("No connections.  Going to sleep.");
+loop: /*
+       * Re-entry point after timer expires. _tv is undefined at that point so re-initialize it.
+       * As it is, this gives you a 300 second pause between reports.  You can change this to any
+       * number up to 15 minutes.  5 or 10 minutes (300 or 600 seconds) should be sufficient.
+       */
+      _tv.tv_sec = 300;
+      _tv.tv_usec = 0;
+      
       FD_ZERO(&input_set);
       FD_SET(mother_desc, &input_set);
-      if (select(mother_desc + 1, &input_set, (fd_set *) 0, (fd_set *) 0, NULL) < 0) {
+      /*
+       * Have select expire after _tv.tv_sec seconds.  When it does, hop back up to reinitialize _tv.
+       */
+      if ((_retval = select(mother_desc + 1, &input_set, (fd_set *) 0, (fd_set *) 0, &_tv)) < 0) {
 	if (errno == EINTR)
 	  log("Waking up to process signal.");
 	else
 	  perror("SYSERR: Select coma");
-      } else
+      } else if(_retval == 0) { /* _retval = 0, timer expired */
+          report_status();
+          /*
+	   * At this point, _tv is undefined, go back and re-initialize it and go back to sleep.
+	   * I use goto rather than continue so the log doesn't get hammered logging "No connections.  Going to sleep"
+	   * every time we report.
+	   */
+	  goto loop; 
+      } else 
 	log("New connection.  Waking up.");
       gettimeofday(&last_time, (struct timezone *) 0);
     }
