--- comm.c	Mon Jun  2 22:46:08 1997
+++ new/comm.c	Tue Jun  3 23:46:46 1997
@@ -67,6 +67,7 @@
 char		    str_boot_time[MAX_INPUT_LENGTH];
 char		    lastplayercmd[MAX_INPUT_LENGTH*2];
 time_t		    current_time;	/* Time of this pulse		*/
+int                 port;               /* Port number to be used       */
 int		    control;		/* Controlling descriptor	*/
 int		    control2;		/* Controlling descriptor #2	*/
 int		    conclient;		/* MUDClient controlling desc	*/
@@ -110,13 +111,11 @@
 
 
 void	mail_count		args( ( CHAR_DATA *ch ) );
-
-
-
+ 
 int main( int argc, char **argv )
 {
     struct timeval now_time;
-    int port;
+    bool fCopyOver = !TRUE;
 
     /*
      * Memory debugging if needed.
@@ -199,19 +198,33 @@
 	    fprintf( stderr, "Port number must be above 1024.\n" );
 	    exit( 1 );
 	}
-    }
+
+    if (argv[2] && argv[2][0])
+      {
+          fCopyOver = TRUE;
+          control = atoi(argv[3]);
+          control2 = atoi(argv[4]);
+          conclient = atoi(argv[5]);
+          conjava = atoi(argv[6]);
+      }
+    else
+          fCopyOver = FALSE;
+   } 
 
     /*
      * Run the game.
      */
     log_string("Booting Database");
-    boot_db( );
+    boot_db(fCopyOver);
     log_string("Initializing socket");
-    control  = init_socket( port   );
-    control2 = init_socket( port+1 );
-    conclient= init_socket( port+10);
-    conjava  = init_socket( port+20);
     sprintf( log_buf, "Realms of Despair ready on port %d.", port );
+    if (!fCopyOver) /* We have already the port if copyover'ed */
+     {
+        control = init_socket (port);
+        control2 = init_socket( port+1 );
+        conclient= init_socket( port+10);
+        conjava  = init_socket( port+20);
     sprintf( log_buf, "Realms of Despair ready on port %d.", port );
+     }
     log_string( log_buf );
     game_loop( );
     close( control  );
@@ -481,7 +494,6 @@
 			    continue;
 			}
 		}
-
 		/* IDENT authentication */
 	        if ( ( d->auth_fd == -1 ) && ( d->atimes < 20 ) 
 		&& !str_cmp( d->user, "unknown" ) )
@@ -644,6 +656,25 @@
     return;
 }
 
+void init_descriptor( DESCRIPTOR_DATA *dnew, int desc)
+{
+    dnew->next		= NULL;
+    dnew->descriptor	= desc;
+    dnew->connected	= CON_GET_NAME;
+    dnew->outsize	= 2000;
+    dnew->idle		= 0;
+    dnew->lines		= 0;
+    dnew->scrlen	= 24;
+    dnew->user		= STRALLOC("unknown");
+    dnew->auth_fd	= -1;
+    dnew->auth_inc	= 0;
+    dnew->auth_state	= 0;
+    dnew->newstate	= 0;
+    dnew->prevcolor	= 0x07;
+
+    CREATE( dnew->outbuf, char, dnew->outsize );
+}
+
 
 void new_descriptor( int new_desc )
 {
@@ -690,24 +721,11 @@
     }
     if ( check_bad_desc( new_desc ) )
       return;
-
     CREATE( dnew, DESCRIPTOR_DATA, 1 );
-    dnew->next		= NULL;
-    dnew->descriptor	= desc;
-    dnew->connected	= CON_GET_NAME;
-    dnew->outsize	= 2000;
-    dnew->idle		= 0;
-    dnew->lines		= 0;
-    dnew->scrlen	= 24;
-    dnew->port		= ntohs( sock.sin_port );
-    dnew->user 		= STRALLOC("unknown");
-    dnew->auth_fd	= -1;
-    dnew->auth_inc	= 0;
-    dnew->auth_state	= 0;
-    dnew->newstate	= 0;
-    dnew->prevcolor	= 0x07;
 
-    CREATE( dnew->outbuf, char, dnew->outsize );
+    init_descriptor(dnew, desc );
+    dnew->port = ntohs(sock.sin_port);
+
 
     strcpy( buf, inet_ntoa( sock.sin_addr ) );
     sprintf( log_buf, "Sock.sinaddr:  %s, port %hd.",
@@ -910,7 +928,7 @@
     }
 
 
-    if ( !DoNotUnlink )
+     if ( !DoNotUnlink )
     {
 	/* make sure loop doesn't get messed up */
 	if ( d_next == dclose )
@@ -1433,7 +1451,7 @@
 	}
 	else
 	{
-	    if ( wizlock && !IS_IMMORTAL(ch) )
+	    if ( wizlock && !IS_HERO(ch) )
 	    {
 		write_to_buffer( d, "The game is wizlocked.  Only immortals can connect now.\n\r", 0 );
 		write_to_buffer( d, "Please try back later.\n\r", 0 );
@@ -1667,6 +1685,7 @@
 	for ( iRace = 0; iRace < MAX_RACE; iRace++ )
 	{
 	  if (iRace != RACE_VAMPIRE
+	  && iRace != RACE_DEMON
 	  && race_table[iRace].race_name && race_table[iRace].race_name[0] != '\0'
 	  && !IS_SET(race_table[iRace].class_restriction, 1 << ch->class) )
 	  {
@@ -1721,6 +1740,7 @@
     if ( iRace == MAX_RACE
     ||  !race_table[iRace].race_name || race_table[iRace].race_name[0] == '\0'
     ||   iRace == RACE_VAMPIRE
+    ||   iRace == RACE_DEMON
     ||   IS_SET(race_table[iRace].class_restriction, 1 << ch->class) )
 	{
 	    write_to_buffer( d,
@@ -1969,7 +1989,7 @@
 	    ch->pcdata->prompt = STRALLOC("");
 	}
 	else
-	if ( !IS_IMMORTAL(ch) && ch->pcdata->release_date > current_time )
+	if ( !IS_GOD(ch) && ch->pcdata->release_date > current_time )
 	{
 	    char_to_room( ch, get_room_index(8) );
 	}
@@ -2446,10 +2466,23 @@
     send_to_pager(buf, ch);
 }
 
+/*  From Palan  */
 
+void log_printf(char *fmt, ...)
+{
+  char buf[MAX_STRING_LENGTH*2];
+  va_list args;
+
+  va_start(args, fmt);
+  vsprintf(buf, fmt, args);
+  va_end(args);
+
+  log_string(buf);
+}
 
 char *obj_short( OBJ_DATA *obj )
 {
+
     static char buf[MAX_STRING_LENGTH];
 
     if ( obj->count > 1 )
@@ -2741,7 +2774,7 @@
   static char buf[60];
 
   strcpy(buf, "&w<&Y%hhp ");
-  if ( IS_VAMPIRE(ch) )
+  if ( IS_VAMPIRE(ch) || IS_DEMON(ch) )
     strcat(buf, "&R%bbp");
   else
     strcat(buf, "&C%mm");
@@ -2861,26 +2894,26 @@
 	stat = ch->max_hit;
 	break;
       case 'm':
-	if ( IS_VAMPIRE(ch) )
+	if ( IS_VAMPIRE(ch) || IS_DEMON(ch) )
 	  stat = 0;
 	else
 	  stat = ch->mana;
 	break;
       case 'M':
-	if ( IS_VAMPIRE(ch) )
+	if ( IS_VAMPIRE(ch) || IS_DEMON(ch) )
 	  stat = 0;
 	else
 	  stat = ch->max_mana;
 	break;
       case 'b':
-	if ( IS_VAMPIRE(ch) )
+	if ( IS_VAMPIRE(ch) || IS_DEMON(ch) )
 	  stat = ch->pcdata->condition[COND_BLOODTHIRST];
 	else
 	  stat = 0;
 	break;
       case 'B':
-	if ( IS_VAMPIRE(ch) )
-	  stat = ch->level + 10;
+	if ( IS_VAMPIRE(ch) || IS_DEMON(ch) )
+	  stat = ch->level + 20;
 	else
 	  stat = 0;
 	break;
@@ -3127,4 +3160,167 @@
       ret = write_to_descriptor( d->descriptor, buf, 0 );
   }
   return ret;
+}
+
+void do_copyover (CHAR_DATA *ch, char * argument)
+{
+  FILE *fp;
+  DESCRIPTOR_DATA *d, *d_next;
+  char buf [100], buf2[100], buf3[100], buf4[100], buf5[100];
+
+  fp = fopen (COPYOVER_FILE, "w");
+
+  if (!fp)
+   {
+      send_to_char ("Copyover file not writeable, aborted.\n\r",ch);
+      log_printf ("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 *** WARMBOOT initated by %s - please remain seated!\n\r", ch->name);
+     /* For each playing descriptor, save its state */
+    for (d = first_descriptor; 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 < 0) /* 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, FALSE); /* throw'em out */
+          }
+        else
+          {
+             fprintf (fp, "%d %s %s\n", d->descriptor, och->name, d->host);
+             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 */
+               }
+                  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);
+        fclose (fpLOG);
+
+        /* exec - descriptors are inherited */
+
+        sprintf (buf, "%d", port);
+        sprintf (buf2, "%d", control);
+        sprintf (buf3, "%d", control2);
+        sprintf (buf4, "%d", conclient);
+        sprintf (buf5, "%d", conjava);
+
+        execl (EXE_FILE, "smaug", buf, "copyover", buf2, buf3,
+          buf4, buf5, (char *) NULL);
+
+        /* Failed - sucessful exec will not return */
+
+        perror ("do_copyover: execl");
+        send_to_char ("Reboot FAILED!\n\r",ch);
+
+        /* Here you might want to reopen fpReserve */
+        /* Since I'm a neophyte type guy, I'll assume this is
+           a good idea and cut and past from main()  */
+
+        if ( ( fpReserve = fopen( NULL_FILE, "r" ) ) == NULL )
+         {
+           perror( NULL_FILE );
+           exit( 1 );
+         }
+        if ( ( fpLOG = fopen( NULL_FILE, "r" ) ) == NULL )
+         {
+           perror( NULL_FILE );
+           exit( 1 );
+         }
+
+}
+
+/* Recover from a copyover - load players */
+void copyover_recover ()
+{
+  DESCRIPTOR_DATA *d;
+  FILE *fp;
+  char name [100];
+  char host[MAX_STRING_LENGTH];
+  int desc;
+  bool fOld;
+
+  log_string ("Warmboot recovery initiated");
+
+  fp = fopen (COPYOVER_FILE, "r");
+
+  if (!fp) /* there are some descriptors open which will hang forever then ? */
+        {
+          perror ("copyover_recover:fopen");
+          log_string("Warmboot 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;
+        }
+
+      CREATE(d, DESCRIPTOR_DATA, 1);
+      init_descriptor (d, desc); /* set up various stuff */
+
+      d->host = STRALLOC( host );
+
+      LINK( d, first_descriptor, last_descriptor, next, prev );
+      d->connected = CON_COPYOVER_RECOVER; /* negative so close_socket
+                                              will cut them off */
+
+        /* Now, find the pfile */
+
+      fOld = load_char_obj (d, name, FALSE);
+
+      if (!fOld) /* Player file not found?! */
+       {
+          write_to_descriptor (desc, "\n\rSomehow, your character was lost in the warmboot. Please contact an Immortal.\n\r", 0);
+          close_socket (d, FALSE);
+       }
+      else /* ok! */
+       {
+          write_to_descriptor (desc, "\n\rWarmboot recovery complete.\n\r",0);
+
+           /* This isn't necassary, but _why_
+              do we want to dump someone in limbo? */
+           if (!d->character->in_room)
+                d->character->in_room = get_room_index (ROOM_VNUM_TEMPLE);
+
+           /* Insert in the char_list */
+           LINK( d->character, first_char, last_char, next, prev );
+
+           char_to_room (d->character, d->character->in_room);
+           do_look (d->character, "auto noprog");
+           act (AT_ACTION, "$n materializes!", d->character, NULL, NULL, TO_ROOM);
+           d->connected = CON_PLAYING;
+       }
+
+   }
 }