/***************************************************************************
* Star Wars: Storm of Vengeance Alpha 0.1 *
*==========================================================================*
* Sw-Storm Alpha 0.1 Code Changes by Iczer/K.lopes w/ help from Maelfius *
* Additional Code within go to their respective owners. *
*==========================================================================*
* Star Wars Reality Code Additions and changes from the Smaug Code *
* copyright (c) 1997 by Sean Cooper *
*==========================================================================*
* Starwars and Starwars Names copyright(c) Lucas Film Ltd. *
*==========================================================================*
* SMAUG 1.0 (C) 1994, 1995, 1996 by Derek Snider *
* SMAUG code team: Thoric, Altrag, Blodkai, Narn, Haus, *
* Scryn, Rennard, Swordbearer, Gorog, Grishnakh and Tricops *
*==========================================================================*
* Merc 2.1 Diku Mud improvments copyright (C) 1992, 1993 by Michael *
* Chastain, Michael Quan, and Mitchell Tse. *
* Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, *
* Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. *
*==========================================================================*
* Warmboot/Copyover Module *
****************************************************************************/
/* Origional Copyover Code by Erwin S. Andreasen http://www.andreasen.org/ */
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include "mud.h"
#include "os.h"
/* telopt.c */
int start_compress( DESCRIPTOR_DATA *d );
void end_compress( DESCRIPTOR_DATA *d );
/*
* OS-dependent local functions.
*/
SOCKET init_socket( int port );
void new_descriptor( SOCKET new_desc );
bool read_from_descriptor( DESCRIPTOR_DATA * d );
bool write_to_descriptor( DESCRIPTOR_DATA *d, const char *txt, int length );
void init_descriptor( DESCRIPTOR_DATA * dnew, SOCKET desc );
void free_desc( DESCRIPTOR_DATA * d );
/* Warm reboot stuff, gotta make sure to thank Erwin for this :) */
extern int port; /* Port number to be used */
extern SOCKET control; /* Controlling descriptor */
void do_copyover( CHAR_DATA * ch, char *argument )
{
DESCRIPTOR_DATA *d, *d_next;
char buf[100];
FILE *fp = fopen( COPYOVER_FILE, "w" );
#if defined(AMIGA) || defined(__MORPHOS__)
long error_code = 0;
static long sockID = 0;
SOCKET coded_control = 0;
#else
char buf2[100];
#endif
char buf3[100];
if( !fp )
{
send_to_char( "Copyover file not writeable, aborted.\r\n", ch );
log_printf( "Could not write to copyover file: %s", COPYOVER_FILE );
perror( "do_copyover:fopen" );
return;
}
#ifdef AMIGA
coded_control = ReleaseCopyOfSocket( control, UNIQUE_ID );
#elif defined(__MORPHOS__)
coded_control = ReleaseCopyOfSocket( control, ++sockID );
#endif
sprintf( buf, "%s", "\r\nA Blinding Flash of light starts heading towards you, before you can think it engulfs you!\r\n" );
/* For each playing descriptor, save its state */
for( d = first_descriptor; d; d = d_next )
{
CHAR_DATA *och = d->original ? d->original : d->character;
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, "\r\nSorry, we are rebooting."
" Come back in a few minutes.\r\n", 0 );
close_socket( d, FALSE ); /* throw'em out */
}
else
{
#if defined(AMIGA) || defined(__MORPHOS__)
SOCKET cur_desc = INVALID_SOCKET;
#ifdef __MORPHOS__
++sockID;
#else
sockID = UNIQUE_ID;
#endif
cur_desc = ReleaseCopyOfSocket( d->descriptor, sockID );
if( cur_desc == SOCKET_ERROR )
{
fprintf( out_stream, "ReleaseCopyOfSocket() failed.\n" );
fclose( fp );
exit( 1 );
}
#else
SOCKET cur_desc = d->descriptor;
#endif
fprintf( fp, "%d %d %s %s\n", cur_desc, d->mccp ? 1 : 0,
och->name, d->host );
save_char_obj( och );
write_to_descriptor( d, buf, 0 );
end_compress( d );
}
}
fprintf( fp, "-1\n" );
fclose( fp );
#ifdef SWR2_USE_IMC
imc_hotboot();
#endif
#ifdef SWR2_USE_IMC
sprintf( buf3, "%d", imc_getsocket( this_imcmud ) );
#else
sprintf( buf3, "%d", -1 );
#endif
#if defined(AMIGA) || defined(__MORPHOS__)
sprintf( buf, "run >NIL: %s %d copyover %d %s",
sysdata.exe_filename, port, coded_control, buf3 );
error_code = System( (CONST_STRPTR) buf, NULL );
if( error_code == -1 )
{
bug( "Copyover failure, executable could not be run." );
fprintf( out_stream, "Failed to run %s\n", sysdata.exe_filename );
ch_printf( ch, "Copyover FAILED!\r\n" );
}
else
{
exit( 0 );
}
#else
/* exec - descriptors are inherited */
sprintf( buf, "%d", port );
sprintf( buf2, "%d", control );
fclose( out_stream );
out_stream = NULL;
execl( sysdata.exe_filename, sysdata.exe_filename,
buf, "copyover", buf2, buf3, ( char * ) NULL );
/* Failed - sucessful exec will not return */
perror( "do_copyover: execl" );
send_to_char( "Copyover FAILED!\r\n", ch );
#endif
}
/* Recover from a copyover - load players */
void copyover_recover( void )
{
DESCRIPTOR_DATA *d = NULL;
FILE *fp = NULL;
char name[100];
char host[MAX_STRING_LENGTH];
SOCKET desc = 0;
bool fOld = FALSE;
int use_mccp = 0;
log_string( "Copyover 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( "Copyover file not found. Exitting.\r\n" );
exit( 1 );
}
remove( COPYOVER_FILE ); /* In case something crashes
- doesn't prevent reading */
for( ;; )
{
fscanf( fp, "%d %d %s %s\n", &desc, &use_mccp, name, host );
if( desc == -1 || feof( fp ) )
break;
#if defined(AMIGA) || defined(__MORPHOS__)
desc = ObtainSocket( desc, PF_INET, SOCK_STREAM, IPPROTO_TCP );
if( desc == INVALID_SOCKET )
{
bug( "ObtainSocket returned error." );
continue;
}
#endif
CREATE( d, DESCRIPTOR_DATA, 1 );
init_descriptor( d, desc ); /* set up various stuff */
d->host = STRALLOC( host );
/* Make sure we restore the number of descriptors and max players */
num_descriptors++;
/* Write something, and check if it goes error-free */
if( !write_to_descriptor( d, "\r\nThe surge of Light passes leaving you unscathed and your world reshaped anew\r\n", 0 ) )
{
/*closesocket( desc );*/
free_desc(d);
continue;
}
LINK( d, first_descriptor, last_descriptor, next, prev );
d->connected = CON_COPYOVER_RECOVER; /* negative so close_socket will cut them off */
if( use_mccp )
start_compress( d );
/* Now, find the pfile */
fOld = load_char_obj( d, name, FALSE );
if( !fOld ) /* Player file not found?! */
{
write_to_descriptor( d,
"\r\nSomehow, your character was lost in the copyover sorry.\r\n",
0 );
close_socket( d, FALSE );
}
else /* ok! */
{
char argument[MAX_INPUT_LENGTH];
snprintf( argument, MAX_INPUT_LENGTH, "%s", "auto noprog" );
write_to_descriptor( d, "\r\nCopyover recovery complete.\r\n", 0 );
/* Just In Case, Someone said 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_SCHOOL );
/* 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, argument );
load_home( d->character );
act( AT_ACTION, "$n materializes!", d->character, NULL, NULL,
TO_ROOM );
d->connected = CON_PLAYING;
}
}
/* Restore the max players to at least the current number of players */
sysdata.maxplayers = num_descriptors;
fclose( fp );
}