diff --exclude-from=dont-diff -u src/act_wiz.c src.copyover/act_wiz.c
--- src/act_wiz.c	Tue Jun  4 16:33:07 1996
+++ src.copyover/act_wiz.c	Wed Jan 29 00:43:56 1997
@@ -4394,3 +4394,187 @@
 
     ch->prefix = str_dup(argument);
 }
+
+#define CH(descriptor)  ((descriptor)->original ? \
+(descriptor)->original : (descriptor)->character)
+
+/* This file holds the copyover data */
+#define COPYOVER_FILE "copyover.data"
+
+/* This is the executable file */
+#define EXE_FILE	  "../src/rom"
+
+
+/*  Copyover - Original idea: Fusion of MUD++
+ *  Adapted to Diku by Erwin S. Andreasen, <erwin@pip.dknet.dk>
+ *  http://pip.dknet.dk/~pip1773
+ *  Changed into a ROM patch after seeing the 100th request for it :)
+ */
+void do_copyover (CHAR_DATA *ch, char * argument)
+{
+	FILE *fp;
+	DESCRIPTOR_DATA *d, *d_next;
+	char buf [100], buf2[100];
+	extern int port,control; /* db.c */
+	
+	fp = fopen (COPYOVER_FILE, "w");
+	
+	if (!fp)
+	{
+		send_to_char ("Copyover file not writeable, aborted.\n\r",ch);
+		logf ("Could not write to copyover file: %s", COPYOVER_FILE);
+		perror ("do_copyover:fopen");
+		return;
+	}
+	
+	/* Consider changing all saved areas here, if you use OLC */
+	
+	/* do_asave (NULL, ""); - autosave changed areas */
+	
+	
+	sprintf (buf, "\n\r *** COPYOVER by %s - please remain seated!\n\r", ch->name);
+	
+	/* For each playing descriptor, save its state */
+	for (d = descriptor_list; d ; d = d_next)
+	{
+		CHAR_DATA * och = CH (d);
+		d_next = d->next; /* We delete from the list , so need to save this */
+		
+		if (!d->character || d->connected > CON_PLAYING) /* drop those logging on */
+		{
+			write_to_descriptor (d->descriptor, "\n\rSorry, we are rebooting. Come back in a few minutes.\n\r", 0);
+			close_socket (d); /* throw'em out */
+		}
+		else
+		{
+			fprintf (fp, "%d %s %s\n", d->descriptor, och->name, d->host);
+
+#if 0			 /* This is not necessary for ROM */
+			if (och->level == 1)
+			{
+				write_to_descriptor (d->descriptor, "Since you are level one, and level one characters do not save, you gain a free level!\n\r", 0);
+				advance_level (och);
+				och->level++; /* Advance_level doesn't do that */
+			}
+#endif			
+			save_char_obj (och);
+			
+			write_to_descriptor (d->descriptor, buf, 0);
+		}
+	}
+	
+	fprintf (fp, "-1\n");
+	fclose (fp);
+	
+	/* Close reserve and other always-open files and release other resources */
+	
+	fclose (fpReserve);
+	
+	/* exec - descriptors are inherited */
+	
+	sprintf (buf, "%d", port);
+	sprintf (buf2, "%d", control);
+	execl (EXE_FILE, "rom", buf, "copyover", buf2, (char *) NULL);
+
+	/* Failed - sucessful exec will not return */
+	
+	perror ("do_copyover: execl");
+	send_to_char ("Copyover FAILED!\n\r",ch);
+	
+	/* Here you might want to reopen fpReserve */
+	fpReserve = fopen (NULL_FILE, "r");
+}
+
+/* Recover from a copyover - load players */
+void copyover_recover ()
+{
+	DESCRIPTOR_DATA *d;
+	FILE *fp;
+	char name [100];
+	char host[MSL];
+	int desc;
+	bool fOld;
+	
+	logf ("Copyover recovery initiated");
+	
+	fp = fopen (COPYOVER_FILE, "r");
+	
+	if (!fp) /* there are some descriptors open which will hang forever then ? */
+	{
+		perror ("copyover_recover:fopen");
+		logf ("Copyover file not found. Exitting.\n\r");
+		exit (1);
+	}
+
+	unlink (COPYOVER_FILE); /* In case something crashes - doesn't prevent reading	*/
+	
+	for (;;)
+	{
+		fscanf (fp, "%d %s %s\n", &desc, name, host);
+		if (desc == -1)
+			break;
+
+		/* Write something, and check if it goes error-free */		
+		if (!write_to_descriptor (desc, "\n\rRestoring from copyover...\n\r",0))
+		{
+			close (desc); /* nope */
+			continue;
+		}
+		
+		d = new_descriptor();
+		d->descriptor = desc;
+		
+		d->host = str_dup (host);
+		d->next = descriptor_list;
+		descriptor_list = d;
+		d->connected = CON_COPYOVER_RECOVER; /* -15, so close_socket frees the char */
+		
+	
+		/* Now, find the pfile */
+		
+		fOld = load_char_obj (d, name);
+		
+		if (!fOld) /* Player file not found?! */
+		{
+			write_to_descriptor (desc, "\n\rSomehow, your character was lost in the copyover. Sorry.\n\r", 0);
+			close_socket (d);			
+		}
+		else /* ok! */
+		{
+			write_to_descriptor (desc, "\n\rCopyover recovery complete.\n\r",0);
+	
+			/* Just In Case */
+			if (!d->character->in_room)
+				d->character->in_room = get_room_index (ROOM_VNUM_TEMPLE);
+
+			/* Insert in the char_list */
+			d->character->next = char_list;
+			char_list = d->character;
+
+			char_to_room (d->character, d->character->in_room);
+			do_look (d->character, "auto");
+			act ("$n materializes!", d->character, NULL, NULL, TO_ROOM);
+			d->connected = CON_PLAYING;
+
+			if (d->character->pet != NULL)
+			{
+			    char_to_room(d->character->pet,d->character->in_room);
+			    act("$n materializes!.",d->character->pet,NULL,NULL,TO_ROOM);
+			}
+		}
+		
+	}
+   fclose (fp);
+	
+	
+}
+
+
+
+
+
+
+
+
+
+
+
diff --exclude-from=dont-diff -u src/comm.c src.copyover/comm.c
--- src/comm.c	Tue Jun  4 16:33:07 1996
+++ src.copyover/comm.c	Tue Jan 28 23:33:04 1997
@@ -56,6 +56,7 @@
 #include <string.h>
 #include <stdlib.h>
 #include <time.h>
+#include <stdarg.h>
 
 #include "merc.h"
 #include "recycle.h"
@@ -165,8 +166,6 @@
 #endif
 
 #if	defined(linux)
-int	accept		args( ( int s, struct sockaddr *addr, int *addrlen ) );
-int	bind		args( ( int s, struct sockaddr *name, int namelen ) );
 int	close		args( ( int fd ) );
 int	getpeername	args( ( int s, struct sockaddr *name, int *namelen ) );
 int	getsockname	args( ( int s, struct sockaddr *name, int *namelen ) );
@@ -337,15 +336,13 @@
 void	stop_idling		args( ( CHAR_DATA *ch ) );
 void    bust_a_prompt           args( ( CHAR_DATA *ch ) );
 
+/* Needs to be global because of do_copyover */
+int port, control;
 
 int main( int argc, char **argv )
 {
     struct timeval now_time;
-    int port;
-
-#if defined(unix)
-    int control;
-#endif
+    bool fCopyOver = FALSE;
 
     /*
      * Memory debugging if needed.
@@ -396,22 +393,39 @@
 	    fprintf( stderr, "Port number must be above 1024.\n" );
 	    exit( 1 );
 	}
+	
+	/* Are we recovering from a copyover? */
+ 	if (argv[2] && argv[2][0])
+ 	{
+ 		fCopyOver = TRUE;
+ 		control = atoi(argv[3]);
+ 	}
+ 	else
+ 		fCopyOver = FALSE;
+	
     }
 
     /*
      * Run the game.
      */
 #if defined(macintosh) || defined(MSDOS)
-    boot_db( );
+    boot_db();
     log_string( "Merc is ready to rock." );
     game_loop_mac_msdos( );
 #endif
 
 #if defined(unix)
-    control = init_socket( port );
-    boot_db( );
+
+	if (!fCopyOver)
+	    control = init_socket( port );
+	    
+    boot_db();
     sprintf( log_buf, "ROM is ready to rock on port %d.", port );
     log_string( log_buf );
+    
+    if (fCopyOver)
+    	copyover_recover();
+    
     game_loop_unix( control );
     close (control);
 #endif
@@ -850,6 +864,7 @@
 
 
 #if defined(unix)
+
 void init_descriptor( int control )
 {
     char buf[MAX_STRING_LENGTH];
@@ -880,14 +895,8 @@
     /*
      * Cons a new descriptor.
      */
-    dnew = new_descriptor();
-
-    dnew->descriptor	= desc;
-    dnew->connected	= CON_GET_NAME;
-    dnew->showstr_head	= NULL;
-    dnew->showstr_point = NULL;
-    dnew->outsize	= 2000;
-    dnew->outbuf	= alloc_mem( dnew->outsize );
+    dnew = new_descriptor(); /* new_descriptor now also allocates things */
+    dnew->descriptor = desc;
 
     size = sizeof(sock);
     if ( getpeername( desc, (struct sockaddr *) &sock, &size ) < 0 )
@@ -2552,3 +2561,15 @@
     tp->tv_usec = 0;
 }
 #endif
+
+void logf (char * fmt, ...)
+{
+	char buf [2*MSL];
+	va_list args;
+	va_start (args, fmt);
+	vsprintf (buf, fmt, args);
+	va_end (args);
+	
+	log_string (buf);
+}
+
diff --exclude-from=dont-diff -u src/db.c src.copyover/db.c
--- src/db.c	Tue Jun  4 16:33:07 1996
+++ src.copyover/db.c	Tue Jan 28 23:23:54 1997
@@ -232,7 +232,7 @@
 /*
  * Big mama top level function.
  */
-void boot_db( void )
+void boot_db()
 {
 
     /*
@@ -388,7 +388,7 @@
 	load_bans();
 	load_songs();
     }
-
+    
     return;
 }
 
diff --exclude-from=dont-diff -u src/interp.c src.copyover/interp.c
--- src/interp.c	Tue Jun  4 16:33:08 1996
+++ src.copyover/interp.c	Tue Jan 28 23:16:41 1997
@@ -289,6 +289,7 @@
      * Immortal commands.
      */
     { "advance",	do_advance,	POS_DEAD,	ML,  LOG_ALWAYS, 1 },
+    { "copyover",	do_copyover,POS_DEAD,   ML,  LOG_ALWAYS, 1 },
     { "dump",		do_dump,	POS_DEAD,	ML,  LOG_ALWAYS, 0 },
     { "trust",		do_trust,	POS_DEAD,	ML,  LOG_ALWAYS, 1 },
     { "violate",	do_violate,	POS_DEAD,	ML,  LOG_ALWAYS, 1 },
diff --exclude-from=dont-diff -u src/interp.h src.copyover/interp.h
--- src/interp.h	Tue Jun  4 16:33:08 1996
+++ src.copyover/interp.h	Tue Jan 28 23:15:15 1997
@@ -101,6 +101,7 @@
 DECLARE_DO_FUN( do_compact	);
 DECLARE_DO_FUN(	do_compare	);
 DECLARE_DO_FUN(	do_consider	);
+DECLARE_DO_FUN(	do_copyover	);
 DECLARE_DO_FUN( do_count	);
 DECLARE_DO_FUN(	do_credits	);
 DECLARE_DO_FUN( do_deaf		);
diff --exclude-from=dont-diff -u src/merc.h src.copyover/merc.h
--- src/merc.h	Tue Jun  4 16:33:09 1996
+++ src.copyover/merc.h	Tue Jan 28 23:25:47 1997
@@ -121,6 +121,10 @@
 #define MAX_INPUT_LENGTH	  256
 #define PAGELEN			   22
 
+/* I am lazy :) */
+#define MSL MAX_STRING_LENGTH
+#define MIL MAX_INPUT_LENGTH
+
 
 
 /*
@@ -241,7 +245,7 @@
 #define CON_READ_IMOTD			13
 #define CON_READ_MOTD			14
 #define CON_BREAK_CONNECT		15
-
+#define CON_COPYOVER_RECOVER    16
 
 
 /*
@@ -2123,6 +2127,8 @@
 void 	nuke_pets	args( ( CHAR_DATA *ch ) );
 void	die_follower	args( ( CHAR_DATA *ch ) );
 bool	is_same_group	args( ( CHAR_DATA *ach, CHAR_DATA *bch ) );
+void 	logf 			args((char * fmt, ...));
+
 
 /* act_enter.c */
 RID  *get_random_room   args ( (CHAR_DATA *ch) );
@@ -2142,6 +2148,8 @@
 /* act_wiz.c */
 void wiznet		args( (char *string, CHAR_DATA *ch, OBJ_DATA *obj,
 			       long flag, long flag_skip, int min_level ) );
+void copyover_recover args((void));
+			       
 /* alias.c */
 void 	substitute_alias args( (DESCRIPTOR_DATA *d, char *input) );
 
Only in src.copyover: mob_cmds.c
Only in src.copyover: mob_cmds.h
Only in src.copyover: mob_prog.c
diff --exclude-from=dont-diff -u src/recycle.c src.copyover/recycle.c
--- src/recycle.c	Mon Oct 23 18:52:29 1995
+++ src.copyover/recycle.c	Tue Jan 28 23:30:16 1997
@@ -125,6 +125,13 @@
 	
     *d = d_zero;
     VALIDATE(d);
+    
+    d->connected	= CON_GET_NAME;
+    d->showstr_head	= NULL;
+    d->showstr_point = NULL;
+    d->outsize	= 2000;
+    d->outbuf	= alloc_mem( d->outsize );
+    
     return d;
 }
 
