From jgoodwin@expert.cc.purdue.edu Tue Apr 8 22:16:20 1997 Date: Sun, 2 Mar 1997 22:34:14 -0500 (EST) From: Walter Goodwin <jgoodwin@expert.cc.purdue.edu> To: erwin@andreasen.org Subject: Re: Copyover Patch completed for stock 1.02 diff -u dist/src/comm.c tmp/src/comm.c --- dist/src/comm.c Sun Mar 2 20:54:50 1997 +++ tmp/src/comm.c Sun Mar 2 20:41:34 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 */ @@ -111,12 +112,10 @@ 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,18 +198,32 @@ 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); + 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( ); @@ -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.", @@ -2446,7 +2464,19 @@ send_to_pager(buf, ch); } +/* From Erwin */ + +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 ) { @@ -3128,3 +3158,169 @@ } return ret; } + +/* Warm reboot stuff, gotta make sure to thank Erwin for this :) */ + +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 *** COPYOVER 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 != 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, 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 ("Copyover 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 ("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.\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 copyover sorry.\n\r", 0); + close_socket (d, FALSE); + } + else /* ok! */ + { + write_to_descriptor (desc, "\n\rCopyover recovery complete.\n\r",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_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; + } + + } + fclose (fp); +} + diff -u dist/src/db.c tmp/src/db.c --- dist/src/db.c Thu Feb 6 09:22:48 1997 +++ tmp/src/db.c Thu Feb 27 15:06:32 1997 @@ -294,7 +294,7 @@ /* * Big mama top level function. */ -void boot_db( void ) +void boot_db( bool fCopyOver ) { sh_int wear, x; @@ -601,6 +601,11 @@ log_string( "Loading corpses" ); load_corpses( ); MOBtrigger = TRUE; + if (fCopyOver) + { + log_string("Running copyover_recover."); + copyover_recover(); + } } /* init_maps ( ); */ diff -u dist/src/mud.h tmp/src/mud.h --- dist/src/mud.h Thu Feb 6 09:22:50 1997 +++ tmp/src/mud.h Sun Mar 2 20:40:49 1997 @@ -336,15 +336,30 @@ /* * Connected state for a channel. */ -typedef enum -{ - CON_PLAYING, CON_GET_NAME, CON_GET_OLD_PASSWORD, - CON_CONFIRM_NEW_NAME, CON_GET_NEW_PASSWORD, CON_CONFIRM_NEW_PASSWORD, - CON_GET_NEW_SEX, CON_GET_NEW_CLASS, CON_READ_MOTD, - CON_GET_NEW_RACE, CON_GET_EMULATION, CON_EDITING, - CON_GET_WANT_RIPANSI, CON_TITLE, CON_PRESS_ENTER, - CON_WAIT_1, CON_WAIT_2, CON_WAIT_3, - CON_ACCEPTED, CON_GET_PKILL, CON_READ_IMOTD +typedef enum { + CON_GET_NAME = -100, + CON_GET_OLD_PASSWORD, + CON_CONFIRM_NEW_NAME, + CON_GET_NEW_PASSWORD, + CON_CONFIRM_NEW_PASSWORD, + CON_GET_NEW_SEX, + CON_GET_NEW_CLASS, + CON_READ_MOTD, + CON_GET_NEW_RACE, + CON_GET_EMULATION, + CON_GET_WANT_RIPANSI, + CON_TITLE, + CON_PRESS_ENTER, + CON_WAIT_1, + CON_WAIT_2, + CON_WAIT_3, + CON_ACCEPTED, + CON_GET_PKILL, + CON_READ_IMOTD, + CON_COPYOVER_RECOVER, + + CON_PLAYING = 0, + CON_EDITING } connection_types; /* @@ -2451,6 +2466,7 @@ #define SET_BIT(var, bit) ((var) |= (bit)) #define REMOVE_BIT(var, bit) ((var) &= ~(bit)) #define TOGGLE_BIT(var, bit) ((var) ^= (bit)) +#define CH(d) ((d)->original ? (d)->original : (d)->character) /* * Memory allocation macros. @@ -3014,6 +3030,7 @@ DECLARE_DO_FUN( do_compare ); DECLARE_DO_FUN( do_config ); DECLARE_DO_FUN( do_consider ); +DECLARE_DO_FUN( do_copyover ); DECLARE_DO_FUN( do_council_induct); DECLARE_DO_FUN( do_council_outcast); DECLARE_DO_FUN( do_councils ); @@ -3570,8 +3587,11 @@ #define USAGE_FILE SYSTEM_DIR "usage.txt" /* How many people are on every half hour - trying to determine best reboot time */ +#define COPYOVER_FILE SYSTEM_DIR "copyover.dat" /* for warm reboots */ +#define EXE_FILE "../src/smaug" /* executable path */ #define CLASSDIR "../classes/" + /* * Our function prototypes. * One big lump ... this is every function in Merc. @@ -3689,8 +3709,10 @@ void set_pager_color args( ( sh_int AType, CHAR_DATA *ch ) ); void ch_printf args( ( CHAR_DATA *ch, char *fmt, ... ) ); void pager_printf args( (CHAR_DATA *ch, char *fmt, ...) ); +void log_printf args( (char *fmt, ...) ); void act args( ( sh_int AType, const char *format, CHAR_DATA *ch, const void *arg1, const void *arg2, int type ) ); +void copyover_recover args( (void) ); /* reset.c */ RD * make_reset args( ( char letter, int extra, int arg1, int arg2, int arg3 ) ); @@ -3701,7 +3723,7 @@ /* db.c */ void show_file args( ( CHAR_DATA *ch, char *filename ) ); char * str_dup args( ( char const *str ) ); -void boot_db args( ( void ) ); +void boot_db args( ( bool fCopyOver ) ); void area_update args( ( void ) ); void add_char args( ( CHAR_DATA *ch ) ); CD * create_mobile args( ( MOB_INDEX_DATA *pMobIndex ) ); @@ -4398,3 +4420,4 @@ #define GET_ADEPT(ch,sn) ( skill_table[(sn)]->skill_adept[(ch)->class]) + Only in dist/src: smaug diff -u dist/src/tables.c tmp/src/tables.c --- dist/src/tables.c Thu Feb 6 09:22:50 1997 +++ tmp/src/tables.c Thu Feb 27 15:30:48 1997 @@ -211,6 +211,7 @@ if ( !str_cmp( name, "do_council_outcast" )) return do_council_outcast; if ( !str_cmp( name, "do_councils" )) return do_councils; if ( !str_cmp( name, "do_counciltalk" )) return do_counciltalk; + if ( !str_cmp( name, "do_copyover" )) return do_copyover; if ( !str_cmp( name, "do_credits" )) return do_credits; if ( !str_cmp( name, "do_cset" )) return do_cset; break; @@ -730,6 +731,7 @@ if ( skill == do_compare ) return "do_compare"; if ( skill == do_config ) return "do_config"; if ( skill == do_consider ) return "do_consider"; + if ( skill == do_copyover ) return "do_copyover"; if ( skill == do_council_induct ) return "do_council_induct"; if ( skill == do_council_outcast ) return "do_council_outcast"; if ( skill == do_councils ) return "do_councils";