/***************************************************************************************** * DDDDD A RRRRRRR K K * * D D A A R R K K * * D D A A R R KK K * * D D A A RRRRRRR K K * * D D AAAAAAAAA R R K K * * D D A A R R K K * * DDDDD A A R R K K * * * * * *W WW W A RRRRRRR RRRRRRR IIIIIIII OOOO RRRRRRR SSSSS * * W W W W A A R R R R II O O R R S * * W W W W A A R R R R II O O R R S * * W W W W A A RRRRRRR RRRRRRR II O O RRRRRRR SSSSS * * W W W W AAAAAAAAA R R R R II O O R R S * * W W W W A A R R R R II O O R R S * * W W A A R R R R IIIIIIII OOOO R R SSSSS * * * ***************************************************************************************** * * * Dark Warrior Code additions and changes from the Star Wars Reality code copyright (c) * * 2003 by Michael Ervin, Mark Gottselig, Gavin Mogan * * * * 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. * ***************************************************************************************** * ^ +----- | / ^ ^ | | +-\ * * / \ | | / |\ /| | | | \ * * / \ +--- |< | \ / | | | | | * * /-----\ | | \ | v | | | | / * * / \ | | \ | | +-----+ +-/ * ***************************************************************************************** * * * AFKMud Copyright 1997-2003 by Roger Libiez (Samson), Levi Beckerson (Whir), * * Michael Ward (Tarl), Erik Wolfe (Dwip), Cameron Carroll (Cam), Cyberfox, Karangi, * * Rathian, Raine, and Adjani. All Rights Reserved. * * * * Original SMAUG 1.4a written by Thoric (Derek Snider) with Altrag, Blodkai, Haus, Narn,* * Scryn, Swordbearer, Tricops, Gorog, Rennard, Grishnakh, Fireblade, and Nivek. * * * * Original MERC 2.1 code by Hatchet, Furey, and Kahn. * * * * Original DikuMUD code by: Hans Staerfeldt, Katja Nyboe, Tom Madsen, Michael Seifert, * * and Sebastian Hammer. * ***************************************************************************************** * SWR Hotboot module * ****************************************************************************************/ #include <unistd.h> #include <signal.h> #include <sys/wait.h> #include <dirent.h> #include <string.h> #include <stdio.h> #include <dlfcn.h> #include "mud.h" #include "mccp.h" #define MAX_NEST 100 static OBJ_DATA *rgObjNest[MAX_NEST]; void save_protocol( void ); extern ROOM_INDEX_DATA *room_index_hash[MAX_KEY_HASH]; extern int port; /* Port number to be used */ char *help_fix( char *text ); bool write_to_descriptor args( ( int desc, char *txt, int length ) ); /* * Save the world's ship files */ void write_ship( FILE * fp, SHIP_DATA * ship ) { if( !fp ) return; /* * What other conditions? * How about only ones that landed */ if( ship->shipstate == SHIP_DOCKED ) return; // if( ship->class > SHIP_PLATFORM ) // return; fprintf( fp, "%s", "#SHIP\n" ); fprintf( fp, "Shipfname %s~\n", ship->filename ); if( ship->currspeed != 0 ) fprintf( fp, "Currspeed %d\n", ship->currspeed ); if( ship->chaff != ship->maxchaff ) fprintf( fp, "Chaff %d\n", ship->chaff ); if( ship->shield != ship->maxshield ) fprintf( fp, "Shield %d\n", ship->shield ); if( ship->missiles != ship->maxmissiles ) fprintf( fp, "Missiles %d\n", ship->missiles ); if( ship->torpedos != ship->maxtorpedos ) fprintf( fp, "Torpedos %d\n", ship->torpedos ); if( ship->rockets != ship->maxrockets ) fprintf( fp, "Rockets %d\n", ship->rockets ); fprintf( fp, "Autorecharge %d\n", ship->autorecharge ); fprintf( fp, "Autotrack %d\n", ship->autotrack ); fprintf( fp, "Autospeed %d\n", ship->autospeed ); fprintf( fp, "Autopilot %d\n", ship->autopilot ); fprintf( fp, "VX %d\n", ( int )ship->vx ); fprintf( fp, "VY %d\n", ( int )ship->vy ); fprintf( fp, "VZ %d\n", ( int )ship->vz ); fprintf( fp, "HX %d\n", ( int )ship->hx ); fprintf( fp, "HY %d\n", ( int )ship->hy ); fprintf( fp, "HZ %d\n", ( int )ship->hz ); fprintf( fp, "JX %d\n", ( int )ship->jx ); fprintf( fp, "JY %d\n", ( int )ship->jy ); fprintf( fp, "JZ %d\n", ( int )ship->jz ); if( ship->target0 ) fprintf( fp, "Target0 %s~\n", ship->target0->name ); if( ship->target1 ) fprintf( fp, "Target1 %s~\n", ship->target1->name ); if( ship->target2 ) fprintf( fp, "Target2 %s~\n", ship->target2->name ); fprintf( fp, "Shipstate %d\n", ship->shipstate ); if( ship->dest != NULL && ship->dest[0] != '\0' ) { fprintf( fp, "LandDest %s~\n", ship->dest ); } if( ship->shipstate == SHIP_HYPERSPACE ) { fprintf( fp, "Hyperdistance %d\n", ship->hyperdistance ); fprintf( fp, "Currjump %s~\n", ship->currjump->name ); } if( ship->energy != ship->maxenergy ) fprintf( fp, "Energy %d\n", ship->energy ); if( ship->hull != ship->maxhull ) fprintf( fp, "Hull %d\n", ship->hull ); if( ship->starsystem ) fprintf( fp, "Starsystem %s~\n", ship->starsystem->name ); fprintf( fp, "%s", "EndShip\n\n" ); return; } SHIP_DATA *load_ship( FILE * fp ) { SHIP_DATA *ship = NULL; const char *word; bool fMatch; word = feof( fp ) ? "EndShip" : fread_word( fp ); if( !str_cmp( word, "EndShip" ) ) return NULL; if( !str_cmp( word, "SHIPFNAME" ) ) { char *name = fread_string_nohash( fp ); /* is this right? - Gavin */ SHIP_DATA *temp_ship = NULL; for( temp_ship = first_ship; temp_ship; temp_ship = temp_ship->next ) { if( !str_cmp( name, temp_ship->filename ) ) { ship = temp_ship; break; } } if( ship == NULL ) { bug( "load_ship: No ship data for filename %s", name ); DISPOSE( name ); return NULL; for( ;; ) { word = feof( fp ) ? "EndShip" : fread_word( fp ); if( !str_cmp( word, "EndShip" ) ) break; } } DISPOSE( name ); } else { for( ;; ) { word = feof( fp ) ? "EndShip" : fread_word( fp ); if( !str_cmp( word, "EndShip" ) ) break; } bug( "load_ship: shipfname not found" ); return NULL; } for( ;; ) { word = feof( fp ) ? "EndShip" : fread_word( fp ); fMatch = FALSE; switch ( UPPER( word[0] ) ) { case '*': fMatch = TRUE; fread_to_eol( fp ); break; /* * case '#': * if ( !str_cmp( word, "#TORPEDO" ) ) * { * mob->tempnum = -9999; * fread_obj( mob, fp, OS_CARRY ); * } */ case 'A': KEY( "Autorecharge", ship->autorecharge, ( bool ) fread_number( fp ) ); KEY( "Autotrack", ship->autotrack, ( bool ) fread_number( fp ) ); KEY( "Autospeed", ship->autospeed, ( bool ) fread_number( fp ) ); KEY( "Autopilot", ship->autopilot, ( bool ) fread_number( fp ) ); break; case 'C': KEY( "Currspeed", ship->currspeed, fread_number( fp ) ); if( !str_cmp( word, "Currjump" ) ) { char *temp = fread_string_nohash( fp ); extract_ship( ship ); ship->location = 0; ship->currjump = starsystem_from_name( temp ); DISPOSE( temp ); fMatch = TRUE; break; } KEY( "Chaff", ship->chaff, fread_number( fp ) ); break; case 'E': KEY( "Energy", ship->energy, fread_number( fp ) ); if( !str_cmp( word, "EndShip" ) ) { return ship; } if( !str_cmp( word, "End" ) ) /* End of object, need to ignore this. sometimes they creep in there somehow -- Scion */ fMatch = TRUE; /* Trick the system into thinking it matched something */ break; case 'H': KEY( "Hull", ship->hull, fread_number( fp ) ); KEY( "HX", ship->hx, ( float )fread_number( fp ) ); KEY( "HY", ship->hy, ( float )fread_number( fp ) ); KEY( "HZ", ship->hz, ( float )fread_number( fp ) ); KEY( "Hyperdistance", ship->hyperdistance, fread_number( fp ) ); break; case 'J': KEY( "JX", ship->jx, ( float )fread_number( fp ) ); KEY( "JY", ship->jy, ( float )fread_number( fp ) ); KEY( "JZ", ship->jz, ( float )fread_number( fp ) ); break; case 'L': if( !str_cmp( word, "Landdest" ) ) { if( ship->dest != NULL ) STRFREE( ship->dest ); ship->dest = fread_string( fp ); fMatch = TRUE; break; } break; case 'M': KEY( "Missiles", ship->missiles, fread_number( fp ) ); break; case 'R': KEY( "Rockets", ship->rockets, fread_number( fp ) ); break; case 'S': KEY( "Shield", ship->shield, fread_number( fp ) ); KEY( "Shipstate", ship->shipstate, fread_number( fp ) ); if( !str_cmp( word, "Starsystem" ) ) { char *star_name = fread_string_nohash( fp ); SPACE_DATA *starsystem = starsystem_from_name( star_name ); DISPOSE( star_name ); fMatch = TRUE; extract_ship( ship ); ship->location = 0; if( ship->starsystem ) ship_from_starsystem( ship, starsystem ); ship_to_starsystem( ship, starsystem ); break; } break; case 'T': KEY( "Torpedos", ship->torpedos, fread_number( fp ) ); if( !str_cmp( word, "target0" ) ) { char *temp = fread_string( fp ); SHIP_DATA *target = get_ship( temp ); ship->target0 = target; DISPOSE( temp ); } if( !str_cmp( word, "target1" ) ) { char *temp = fread_string( fp ); SHIP_DATA *target = get_ship( temp ); ship->target1 = target; DISPOSE( temp ); } if( !str_cmp( word, "target2" ) ) { char *temp = fread_string( fp ); SHIP_DATA *target = get_ship( temp ); ship->target2 = target; DISPOSE( temp ); } break; case 'V': KEY( "VX", ship->vx, ( float )fread_number( fp ) ); KEY( "VY", ship->vy, ( float )fread_number( fp ) ); KEY( "VZ", ship->vz, ( float )fread_number( fp ) ); break; } if( !fMatch && str_cmp( word, "End" ) ) bug( "load_mobile: no match: %s", word ); } return NULL; } /* * Save the world's objects and mobs in their current positions -- Scion */ void save_mobile( FILE * fp, CHAR_DATA * mob ) { AFFECT_DATA *paf; SKILLTYPE *skill = NULL; if( !IS_NPC( mob ) || !fp ) return; fprintf( fp, "%s", "#MOBILE\n" ); fprintf( fp, "Vnum %d\n", mob->pIndexData->vnum ); fprintf( fp, "Level %d\n", mob->top_level ); fprintf( fp, "Gold %d\n", mob->gold ); if( mob->in_room ) { if( IS_SET( mob->act, ACT_SENTINEL ) ) { /* * Sentinel mobs get stamped with a "home room" when they are created * by create_mobile(), so we need to save them in their home room regardless * of where they are right now, so they will go to their home room when they * enter the game from a reboot or copyover -- Scion */ fprintf( fp, "Room %d\n", mob->home_vnum ); } else fprintf( fp, "Room %d\n", mob->in_room->vnum ); } else fprintf( fp, "Room %d\n", ROOM_VNUM_LIMBO ); #ifdef OVERLANDCODE fprintf( fp, "Coordinates %d %d %d\n", mob->x, mob->y, mob->map ); #endif if( mob->name && mob->pIndexData->player_name && str_cmp( mob->name, mob->pIndexData->player_name ) ) fprintf( fp, "Name %s~\n", mob->name ); if( mob->short_descr && mob->pIndexData->short_descr && str_cmp( mob->short_descr, mob->pIndexData->short_descr ) ) fprintf( fp, "Short %s~\n", mob->short_descr ); if( mob->long_descr && mob->pIndexData->long_descr && str_cmp( mob->long_descr, mob->pIndexData->long_descr ) ) fprintf( fp, "Long %s~\n", mob->long_descr ); if( mob->description && mob->pIndexData->description && str_cmp( mob->description, mob->pIndexData->description ) ) fprintf( fp, "Description %s~\n", mob->description ); fprintf( fp, "HpManaMove %d %d %d %d %d %d\n", mob->hit, mob->max_hit, mob->mana, mob->max_mana, mob->move, mob->max_move ); fprintf( fp, "Position %d\n", mob->position ); fprintf( fp, "Flags %d\n", mob->act ); fprintf( fp, "AffectedBy %d\n", mob->affected_by ); for( paf = mob->first_affect; paf; paf = paf->next ) { if( paf->type >= 0 && ( skill = get_skilltype( paf->type ) ) == NULL ) continue; if( paf->type >= 0 && paf->type < TYPE_PERSONAL ) fprintf( fp, "AffectData '%s' %3d %3d %3d %d\n", skill->name, paf->duration, paf->modifier, paf->location, paf->bitvector ); else fprintf( fp, "Affect %3d %3d %3d %3d %d\n", paf->type, paf->duration, paf->modifier, paf->location, paf->bitvector ); } de_equip_char( mob ); if( mob->first_carrying ) fwrite_obj( mob, mob->last_carrying, fp, 0, OS_CARRY, TRUE ); re_equip_char( mob ); fprintf( fp, "%s", "EndMobile\n\n" ); return; } void save_world( CHAR_DATA * ch ) { FILE *mobfp; FILE *objfp; FILE *shipfp; int mobfile = 0; int shipfile = 0; char filename[256]; CHAR_DATA *rch; ROOM_INDEX_DATA *pRoomIndex; int iHash; log_string( "Preserving world state...." ); snprintf( filename, 256, "%s%s", SYSTEM_DIR, MOB_FILE ); if( ( mobfp = fopen( filename, "w" ) ) == NULL ) { bug( "%s", "save_world: fopen mob file" ); perror( filename ); } else mobfile++; snprintf( filename, 256, "%s%s", SYSTEM_DIR, SHIP_FILE ); if( ( shipfp = fopen( filename, "w" ) ) == NULL ) { bug( "%s", "save_world: fopen ship file" ); perror( filename ); } else shipfile++; for( iHash = 0; iHash < MAX_KEY_HASH; iHash++ ) { for( pRoomIndex = room_index_hash[iHash]; pRoomIndex; pRoomIndex = pRoomIndex->next ) { if( pRoomIndex ) { if( !pRoomIndex->first_content /* Skip room if nothing in it */ || IS_SET( pRoomIndex->room_flags, ROOM_CLANSTOREROOM ) /* These rooms save on their own */ ) continue; snprintf( filename, 256, "%s%d", COPYOVER_DIR, pRoomIndex->vnum ); if( ( objfp = fopen( filename, "w" ) ) == NULL ) { bug( "save_world: fopen %d", pRoomIndex->vnum ); perror( filename ); continue; } fwrite_obj( NULL, pRoomIndex->last_content, objfp, 0, OS_CARRY, TRUE ); fprintf( objfp, "%s", "#END\n" ); FCLOSE( objfp ); } } } if( mobfile ) { for( rch = first_char; rch; rch = rch->next ) { if( !IS_NPC( rch ) || rch == supermob || IS_SET( rch->act, ACT_PROTOTYPE ) || IS_SET( rch->act, ACT_PET ) ) continue; else save_mobile( mobfp, rch ); } fprintf( mobfp, "%s", "#END\n" ); FCLOSE( mobfp ); } if( shipfile ) { SHIP_DATA *ship = NULL; for( ship = first_ship; ship; ship = ship->next ) { write_ship( shipfp, ship ); } fprintf( shipfp, "%s", "#END\n" ); FCLOSE( shipfp ); } return; } CHAR_DATA *load_mobile( FILE * fp ) { CHAR_DATA *mob = NULL; char *word; bool fMatch; int inroom = 0; ROOM_INDEX_DATA *pRoomIndex = NULL; word = feof( fp ) ? "EndMobile" : fread_word( fp ); if( !str_cmp( word, "Vnum" ) ) { int vnum; vnum = fread_number( fp ); if( get_mob_index( vnum ) == NULL ) { bug( "load_mobile: No index data for vnum %d", vnum ); return NULL; } mob = create_mobile( get_mob_index( vnum ) ); if( !mob ) { for( ;; ) { word = feof( fp ) ? "EndMobile" : fread_word( fp ); /* * So we don't get so many bug messages when something messes up * * --Shaddai */ if( !str_cmp( word, "EndMobile" ) ) break; } bug( "load_mobile: Unable to create mobile for vnum %d", vnum ); return NULL; } } else { for( ;; ) { word = feof( fp ) ? "EndMobile" : fread_word( fp ); /* * So we don't get so many bug messages when something messes up * * --Shaddai */ if( !str_cmp( word, "EndMobile" ) ) break; } extract_char( mob, TRUE ); bug( "%s", "load_mobile: Vnum not found" ); return NULL; } for( ;; ) { word = feof( fp ) ? "EndMobile" : fread_word( fp ); fMatch = FALSE; switch ( UPPER( word[0] ) ) { case '*': fMatch = TRUE; fread_to_eol( fp ); break; case '#': if( !str_cmp( word, "#OBJECT" ) ) { mob->tempnum = -9999; /* Hackish, yes. Works though doesn't it? */ fread_obj( mob, fp, OS_CARRY ); } case 'A': if( !str_cmp( word, "Affect" ) || !str_cmp( word, "AffectData" ) ) { AFFECT_DATA *paf; CREATE( paf, AFFECT_DATA, 1 ); if( !str_cmp( word, "Affect" ) ) { paf->type = fread_number( fp ); } else { int sn; char *sname = fread_word( fp ); if( ( sn = skill_lookup( sname ) ) < 0 ) { if( ( sn = herb_lookup( sname ) ) < 0 ) bug( "%s", "load_mobile: unknown skill." ); else sn += TYPE_HERB; } paf->type = sn; } paf->duration = fread_number( fp ); paf->modifier = fread_number( fp ); paf->location = fread_number( fp ); if( paf->location == APPLY_WEAPONSPELL || paf->location == APPLY_WEARSPELL || paf->location == APPLY_REMOVESPELL || paf->location == APPLY_STRIPSN ) paf->modifier = slot_lookup( paf->modifier ); paf->bitvector = fread_number( fp ); LINK( paf, mob->first_affect, mob->last_affect, next, prev ); fMatch = TRUE; break; } KEY( "AffectedBy", mob->affected_by, fread_number( fp ) ); break; #ifdef OVERLANDCODE case 'C': if( !str_cmp( word, "Coordinates" ) ) { mob->x = fread_number( fp ); mob->y = fread_number( fp ); mob->map = fread_number( fp ); fMatch = TRUE; break; } break; #endif case 'D': KEY( "Description", mob->description, fread_string( fp ) ); break; case 'E': if( !str_cmp( word, "EndMobile" ) ) { if( inroom == 0 ) inroom = ROOM_VNUM_LIMBO; pRoomIndex = get_room_index( inroom ); if( !pRoomIndex ) pRoomIndex = get_room_index( ROOM_VNUM_LIMBO ); char_to_room( mob, pRoomIndex ); mob->tempnum = -9998; /* Yet another hackish fix! */ return mob; } if( !str_cmp( word, "End" ) ) /* End of object, need to ignore this. sometimes they creep in there somehow -- Scion */ fMatch = TRUE; /* Trick the system into thinking it matched something */ break; case 'F': KEY( "Flags", mob->act, fread_number( fp ) ); case 'G': KEY( "Gold", mob->gold, fread_number( fp ) ); break; case 'H': if( !str_cmp( word, "HpManaMove" ) ) { mob->hit = fread_number( fp ); mob->max_hit = fread_number( fp ); mob->mana = fread_number( fp ); mob->max_mana = fread_number( fp ); mob->move = fread_number( fp ); mob->max_move = fread_number( fp ); if( mob->max_move <= 0 ) mob->max_move = 150; fMatch = TRUE; break; } break; case 'L': KEY( "Long", mob->long_descr, fread_string( fp ) ); KEY( "Level", mob->top_level, fread_number( fp ) ); break; case 'M': KEY( "Mobclan", mob->mob_clan, fread_string( fp ) ); break; case 'N': KEY( "Name", mob->name, fread_string( fp ) ); break; case 'P': KEY( "Position", mob->position, fread_number( fp ) ); break; case 'R': KEY( "Room", inroom, fread_number( fp ) ); break; case 'S': KEY( "Short", mob->short_descr, fread_string( fp ) ); break; } if( !fMatch && str_cmp( word, "End" ) ) bug( "load_mobile: no match: %s", word ); } return NULL; } void read_obj_file( char *dirname, char *filename ) { ROOM_INDEX_DATA *room; FILE *fp; char fname[256]; int vnum; vnum = atoi( filename ); if( ( room = get_room_index( vnum ) ) == NULL ) { bug( "read_obj_file: ARGH! Missing room index for %d!", vnum ); return; } snprintf( fname, 256, "%s%s", dirname, filename ); if( ( fp = fopen( fname, "r" ) ) != NULL ) { short iNest; bool found; OBJ_DATA *tobj, *tobj_next; rset_supermob( room ); for( iNest = 0; iNest < MAX_NEST; iNest++ ) rgObjNest[iNest] = NULL; found = TRUE; for( ;; ) { char letter; char *word; letter = fread_letter( fp ); if( letter == '*' ) { fread_to_eol( fp ); continue; } if( letter != '#' ) { bug( "%s", "read_obj_file: # not found." ); break; } word = fread_word( fp ); if( !str_cmp( word, "OBJECT" ) ) /* Objects */ fread_obj( supermob, fp, OS_CARRY ); else if( !str_cmp( word, "END" ) ) /* Done */ break; else { bug( "read_obj_file: bad section: %s", word ); break; } } FCLOSE( fp ); unlink( fname ); for( tobj = supermob->first_carrying; tobj; tobj = tobj_next ) { tobj_next = tobj->next_content; #ifdef OVERLANDCODE if( IS_OBJ_STAT( tobj, ITEM_ONMAP ) ) { SET_ACT_FLAG( supermob, ACT_ONMAP ); supermob->map = tobj->map; supermob->x = tobj->x; supermob->y = tobj->y; } #endif obj_from_char( tobj ); #ifndef OVERLANDCODE obj_to_room( tobj, room ); #else obj_to_room( tobj, room, supermob ); REMOVE_ACT_FLAG( supermob, ACT_ONMAP ); supermob->map = -1; supermob->x = -1; supermob->y = -1; #endif } release_supermob( ); } else log_string( "Cannot open obj file" ); return; } void load_obj_files( void ) { DIR *dp; struct dirent *dentry; char directory_name[100]; log_string( "World state: loading objs" ); snprintf( directory_name, 100, "%s", COPYOVER_DIR ); dp = opendir( directory_name ); dentry = readdir( dp ); while( dentry ) { /* * Added by Tarl 3 Dec 02 because we are now using CVS */ if( !str_cmp( dentry->d_name, "CVS" ) ) { dentry = readdir( dp ); continue; } if( dentry->d_name[0] != '.' ) read_obj_file( directory_name, dentry->d_name ); dentry = readdir( dp ); } closedir( dp ); return; } void load_world( CHAR_DATA * ch ) { FILE *mobfp; FILE *shipfp; char file1[256]; char file2[256]; char *word; int done = 0; bool mobfile = FALSE; bool shipfile = FALSE; snprintf( file1, 256, "%s%s", SYSTEM_DIR, MOB_FILE ); if( ( mobfp = fopen( file1, "r" ) ) == NULL ) { bug( "%s", "load_world: fopen mob file" ); perror( file1 ); } else mobfile = TRUE; snprintf( file2, 256, "%s%s", SYSTEM_DIR, SHIP_FILE ); if( ( shipfp = fopen( file2, "r" ) ) == NULL ) { bug( "%s", "load_world: fopen ship file" ); perror( file1 ); } else shipfile = TRUE; if( mobfile ) { log_string( "World state: loading mobs" ); while( done == 0 ) { if( feof( mobfp ) ) done++; else { word = fread_word( mobfp ); if( str_cmp( word, "#END" ) ) load_mobile( mobfp ); else done++; } } FCLOSE( mobfp ); } load_obj_files( ); if( shipfile ) { done = 0; log_string( "World state: loading ships" ); while( done == 0 ) { if( feof( shipfp ) ) done++; else { word = fread_word( shipfp ); if( str_cmp( word, "#END" ) ) load_ship( shipfp ); else done++; } } FCLOSE( shipfp ); } /* * Once loaded, the data needs to be purged in the event it causes a crash so that it won't try to reload */ unlink( file1 ); unlink( file2 ); return; } /* Warm reboot stuff, gotta make sure to thank Erwin for this :) */ void do_copyover( CHAR_DATA * ch, char *argument ) { FILE *fp; CHAR_DATA *victim = NULL; DESCRIPTOR_DATA *d, *de_next; PLANET_DATA *planet; SHIP_DATA *ship; char buf[100], buf2[100], buf3[100]; extern int control; int count = 0; bool found = FALSE; for( d = first_descriptor; d; d = d->next ) { if( ( d->connected == CON_PLAYING || d->connected == CON_EDITING ) && ( victim = d->character ) != NULL && !IS_NPC( victim ) && victim->in_room && victim->fighting && victim->top_level >= 1 && victim->top_level <= MAX_LEVEL ) { found = TRUE; count++; } } if( found ) { ch_printf( ch, "Cannot Copyover at this time. There are %d combats in progress.\r\n", count ); return; } found = FALSE; for( d = first_descriptor; d; d = d->next ) { if( d->connected == CON_EDITING && d->character ) { found = TRUE; break; } } if( found ) { send_to_char( "Cannot copyover at this time. Someone is using the line editor.\r\n", ch ); return; } sprintf( log_buf, "Copyover initiated by %s.", ch->name ); log_string( log_buf ); fp = fopen( COPYOVER_FILE, "w" ); if( !fp ) { send_to_char( "Copyover file not writeable, aborted.\r\n", ch ); bug( "Could not write to copyover file: %s. Copyover aborted.", COPYOVER_FILE ); perror( "do_copyover:fopen" ); return; } /* * And this one here will save the status of all objects and mobs in the game. * * This really should ONLY ever be used here. The less we do stuff like this the better. */ save_world( ch ); for( ship = first_ship; ship; ship = ship->next ) save_ship( ship ); for( planet = first_planet; planet; planet = planet->next ) save_planet( planet ); #ifdef OLC_SHUTTLE { SHUTTLE_DATA *tshuttle; for( tshuttle = first_shuttle; tshuttle; tshuttle = tshuttle->next ) save_shuttle( tshuttle ); } #endif log_string( "Saving player files and connection states...." ); if( ch && ch->desc ) write_to_descriptor( ch->desc->descriptor, "\033[0m", 0 ); sprintf( buf, "\r\nYou feel a great disturbance in the Force." ); /* * For each playing descriptor, save its state */ for( d = first_descriptor; d; d = de_next ) { CHAR_DATA *och = CH( d ); de_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, "\r\nSorry, we are rebooting. Come back in a few minutes.\r\n", 0 ); close_socket( d, FALSE ); /* throw'em out */ } else { fprintf( fp, "%d %d %d %d %d %s %s\n", d->descriptor, d->can_compress, och->in_room->vnum, d->port, d->idle, och->name, d->host ); /* * One of two places this gets changed */ och->pcdata->hotboot = TRUE; save_char_obj( och ); write_to_descriptor( d->descriptor, buf, 0 ); compressEnd( d ); } } fprintf( fp, "%s", "-1" ); FCLOSE( fp ); #ifdef IMC imc_hotboot( ); #endif /* * added this in case there's a need to debug the contents of the various files */ if( argument && !str_cmp( argument, "debug" ) ) { log_string( "copyover debug - Aborting before execl" ); return; } log_string( "Executing copyover...." ); /* * exec - descriptors are inherited */ snprintf( buf, 100, "%d", port ); snprintf( buf2, 100, "%d", control ); #ifdef IMC if( this_imcmud ) snprintf( buf3, 100, "%d", this_imcmud->desc ); else strncpy( buf3, "-1", 100 ); #else strncpy( buf3, "-1", 100 ); #endif dlclose( sysdata.dlHandle ); execl( EXE_FILE, "swr", buf, "copyover", buf2, buf3, ( char * )NULL ); /* * Failed - sucessful exec will not return */ perror( "do_copyover: execl" ); bug( "%s", "Copyover execution failed!!" ); sysdata.dlHandle = dlopen( NULL, RTLD_LAZY ); if( !sysdata.dlHandle ) { bug( "%s", "FATAL ERROR: Unable to reopen system executable handle!" ); exit( 1 ); } send_to_char( "Copyover FAILED!\r\n", ch ); } /* Recover from a hotboot - load players */ void copyover_recover( void ) { DESCRIPTOR_DATA *d = NULL; FILE *fp; char name[100]; char host[MAX_STRING_LENGTH]; int desc, dcompress, room, dport, idle, maxp = 0; bool fOld; fp = fopen( COPYOVER_FILE, "r" ); if( !fp ) /* there are some descriptors open which will hang forever then ? */ { perror( "copyover_recover: fopen" ); bug( "%s", "Copyover file not found. Exitting." ); exit( 1 ); } unlink( COPYOVER_FILE ); /* In case something crashes - doesn't prevent reading */ for( ;; ) { d = NULL; fscanf( fp, "%d %d %d %d %d %s %s\n", &desc, &dcompress, &room, &dport, &idle, name, host ); if( desc == -1 || feof( fp ) ) break; if( !str_cmp( name, "maxp" ) || !str_cmp( host, "maxp" ) ) { maxp = idle; continue; } /* * Write something, and check if it goes error-free */ if( !dcompress && !write_to_descriptor( desc, "\n\rThe ether swirls in chaos.\n\r", 0 ) ) { close( desc ); /* nope */ continue; } CREATE( d, DESCRIPTOR_DATA, 1 ); d->next = NULL; d->descriptor = desc; d->connected = CON_GET_NAME; d->outsize = 2000; d->idle = 0; d->lines = 0; d->scrlen = 24; d->newstate = 0; d->prevcolor = 0x08; CREATE( d->outbuf, char, d->outsize ); CREATE( d->mccp, MCCP, 1 ); d->can_compress = dcompress; if( d->can_compress ) compressStart( d ); d->host = STRALLOC( host ); d->port = dport; d->idle = idle; 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, TRUE ); if( !fOld ) /* Player file not found?! */ { write_to_descriptor( d->descriptor, "\r\nSomehow, your character was lost during copyover. Contact the immortals ASAP.\r\n", 0 ); close_socket( d, FALSE ); } else /* ok! */ { write_to_descriptor( d->descriptor, "Suddenly, you remember nothing as the Force continues into the Galaxy.\r\n", 0 ); d->character->in_room = get_room_index( room ); 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 ); act( AT_MAGIC, "You appear in a swirl of the Force!", d->character, NULL, NULL, TO_CHAR ); act( AT_MAGIC, "$n appears in a swrrl of the Force!", d->character, NULL, NULL, TO_ROOM ); d->connected = CON_PLAYING; if( ++num_descriptors > sysdata.maxplayers ) sysdata.maxplayers = num_descriptors; #ifdef AUTO_AUTH check_auth_state( d->character ); /* new auth */ #endif } } FCLOSE( fp ); if( maxp > sysdata.maxplayers ) sysdata.maxplayers = maxp; log_string( "copyover recovery complete." ); return; } void emergency_copyover( void ) { FILE *fp; DESCRIPTOR_DATA *d, *d_next; char buf[MSL], buf2[100], buf3[100], buf6[100]; extern int control; log_string( "--- Engaging Emergency Copyover! ---" ); fp = fopen (COPYOVER_FILE, "w"); if (!fp) { log_string ( "Could not write to copyover file!" ); perror ("emergency_copyover:fopen"); return; } snprintf(buf,MSL, "\n\r %s[%sALERT%s]%s: %sEMERGENCY COPYOVER %s- Keep calm, we might pull through!\n\r", ANSI_YELLOW, ANSI_RED, ANSI_YELLOW, ANSI_GREY, ANSI_RED, ANSI_GREY ); save_world( NULL ); save_protocol(); sprintf(buf6, "\n\rYou have an intense feeling of Deja Vu...\n\r"); /* 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 seconds.\n\r", 0); close_socket (d, FALSE); /* throw'em out */ } else { // do_save(d->character, ""); fprintf( fp, "%d %d %d %d %d %s %s\n", d->descriptor, d->can_compress, och->in_room->vnum, d->port, d->idle, och->name, d->host ); save_char_obj (och); write_to_descriptor( d->descriptor, buf, 0); write_to_descriptor( d->descriptor, buf6, 0 ); compressEnd( d ); /* * One of two places this gets changed */ och->pcdata->hotboot = TRUE; } } fprintf (fp, "-1\n"); fclose (fp); /* Close reserve and other always-open files and release other resources */ fclose (fpReserve); fclose (fpLOG); log_string( "Executing Emergency Copyover...." ); /* * exec - descriptors are inherited */ snprintf( buf, 100, "%d", port ); snprintf( buf2, 100, "%d", control ); #ifdef IMC if( this_imcmud ) snprintf( buf3, 100, "%d", this_imcmud->desc ); else strncpy( buf3, "-1", 100 ); #else strncpy( buf3, "-1", 100 ); #endif dlclose( sysdata.dlHandle ); execl( EXE_FILE, "swr", buf, "copyover", buf2, buf3, ( char * )NULL ); perror ("emergency_copyover: failed to copyover in 'execl'"); sysdata.dlHandle = dlopen( NULL, RTLD_LAZY ); if( !sysdata.dlHandle ) { bug( "%s", "FATAL ERROR: Unable to reopen system executable handle!" ); exit(1); } } void ehelpsave( void ) { HELP_DATA *pHelp; FILE *fpout; log_string_plus( "Saving help.are...", LOG_NORMAL, LEVEL_GREATER ); rename( "help.are", "help.are.bak" ); if( ( fpout = fopen( "help.are", "w" ) ) == NULL ) { bug( "hset save: FileOpen", 0 ); perror( "help.are" ); return; } fprintf( fpout, "#HELPS\n\n" ); for( pHelp = first_help; pHelp; pHelp = pHelp->next ) fprintf( fpout, "%d %s~\n%s~\n\n", pHelp->level, pHelp->keyword, help_fix( pHelp->text ) ); fprintf( fpout, "0 $~\n\n\n#$\n" ); fclose( fpout ); return; } void forcesave( void ) { CHAR_DATA *vch; CHAR_DATA *vch_next; for( vch = first_char; vch; vch = vch_next ) { vch_next = vch->next; if( !IS_NPC( vch ) ) { send_to_char( "Emergency...You are forced to save!\n\r", vch ); do_save( vch, "" ); } } return; } void save_protocol( void ) { SHIP_DATA *ship; PLANET_DATA *planet; AREA_DATA *tarea; /* * Save all areas */ for( tarea = first_area; tarea; tarea = tarea->next ) fold_area( tarea, tarea->filename, FALSE ); /* * Save All Helpfiles */ ehelpsave( ); //Save ships for( ship = first_ship; ship; ship = ship->next ) save_ship( ship ); //Save planets for( planet = first_planet; planet; planet = planet->next ) save_planet( planet ); return; }