Login
User Name:

Password:



Register
Forgot your password?
Vote for Us!
 parse description bug
Yesterday, 10:08 pm
By Remcon
Couple bugs
Dec 12, 2017, 5:42 pm
By Remcon
Bug in disarm( )
Nov 12, 2017, 6:54 pm
By GatewaySysop
Bug in will_fall( )
Oct 23, 2017, 1:35 am
By GatewaySysop
Bug in do_zap( ), do_brandish( )
Oct 18, 2017, 1:52 pm
By GatewaySysop
LOP 1.45
Author: Remcon
Submitted by: Remcon
LOP Heroes Edition
Author: Vladaar
Submitted by: Vladaar
Heroes sound extras
Author: Vladaar
Submitted by: Vladaar
6Dragons 4.3
Author: Vladaar
Submitted by: Vladaar
Memwatch
Author: Johan Lindh
Submitted by: Vladaar
Users Online
CommonCrawl, Yahoo!, Yandex, DotBot, Bing, Google

Members: 0
Guests: 7
Stats
Files
Topics
Posts
Members
Newest Member
477
3,706
19,240
608
LAntorcha
Today's Birthdays
There are no member birthdays today.
Related Links
» SmaugMuds.org » Bugfix Lists » SWFOTE FUSS Bugfix List » [Bug] mptransfer and transfer...
Forum Rules | Mark all | Recent Posts

[Bug] mptransfer and transfer commands have infinite loop problems
< Newer Topic :: Older Topic >

Pages:<< prev 1 next >>
Post is unread #1 Oct 22, 2005, 11:42 am
Go to the top of the page
Go to the bottom of the page

Samson
Black Hand
GroupAdministrators
Posts3,639
JoinedJan 1, 2002

Bug: mptransfer and transfer commands have infinite loop problems
Danger: Critical - Such loops can paralyze your process
Found by: Qidexan
Fixed by: Samson

---

act_wiz.c, do_transfer

Replace the entire function with the following:

/* This function shared by do_transfer and do_mptransfer
 *
 * Immortals bypass most restrictions on where to transfer victims.
 * NPCs cannot transfer victims who are:
 * 1. Not authorized yet.
 * 2. Outside of the level range for the target room's area.
 * 3. Being sent to private rooms.
 */
void transfer_char( CHAR_DATA *ch, CHAR_DATA *victim, ROOM_INDEX_DATA *location )
{
   if( !victim->in_room )
   {
      bug( "%s: victim in NULL room: %s", __FUNCTION__, victim->name );
      return;
   }

   if( IS_NPC(ch) && room_is_private( victim, location ) )
   {
      progbug( "Mptransfer - Private room", ch );
      return;
   }

   if( !can_see( ch, victim ) )
      return;

   if( IS_NPC(ch) && NOT_AUTHED( victim ) && location->area != victim->in_room->area )
   {
      char buf[MAX_STRING_LENGTH];

      snprintf( buf, MAX_STRING_LENGTH, "Mptransfer - unauthed char (%s)", victim->name );
      progbug( buf, ch );
      return;
   }

   /* If victim not in area's level range, do not transfer */
   if( IS_NPC(ch) && !in_hard_range( victim, location->area ) && !IS_SET( location->room_flags, ROOM_PROTOTYPE ) )
      return;

   if( victim->fighting )
      stop_fighting( victim, TRUE );

   if( !IS_NPC(ch) )
   {
      act( AT_MAGIC, "$n disappears in a cloud of swirling colors.", victim, NULL, NULL, TO_ROOM );
      victim->retran = victim->in_room->vnum;
   }
   char_from_room( victim );
   char_to_room( victim, location );
   if( !IS_NPC(ch) )
   {
      act( AT_MAGIC, "$n arrives from a puff of smoke.", victim, NULL, NULL, TO_ROOM );
      if( ch != victim )
         act( AT_IMMORT, "$n has transferred you.", ch, NULL, victim, TO_VICT );
      do_look( victim, "auto" );
      if( !IS_IMMORTAL( victim ) && !IS_NPC( victim ) && !in_hard_range( victim, location->area ) )
         act( AT_DANGER, "Warning:  this player's level is not within the area's level range.", ch, NULL, NULL, TO_CHAR );
   }
}

void do_transfer( CHAR_DATA * ch, char *argument )
{
   char arg1[MAX_INPUT_LENGTH];
   char arg2[MAX_INPUT_LENGTH];
   ROOM_INDEX_DATA *location;
   DESCRIPTOR_DATA *d;
   CHAR_DATA *victim;

   set_char_color( AT_IMMORT, ch );

   argument = one_argument( argument, arg1 );
   argument = one_argument( argument, arg2 );

   if( arg1[0] == '\0' )
   {
      send_to_char( "Transfer whom (and where)?\n\r", ch );
      return;
   }

   if( arg2[0] != '\0' )
   {
      if( !( location = find_location( ch, arg2 ) ) )
      {
         send_to_char( "That location does not exist.\n\r", ch );
         return;
      }
   }
   else
      location = ch->in_room;

   if( !str_cmp( arg1, "all" ) && get_trust( ch ) >= LEVEL_GREATER )
   {
      for( d = first_descriptor; d; d = d->next )
      {
         if( d->connected == CON_PLAYING && d->character && d->character != ch && d->character->in_room )
            transfer_char( ch, d->character, location );
      }
      return;
   }

   if( !( victim = get_char_world( ch, arg1 ) ) )
   {
      send_to_char( "They aren't here.\n\r", ch );
      return;
   }
   transfer_char( ch, victim, location );
}


mud_comm.c

void transfer_char( CHAR_DATA *ch, CHAR_DATA *victim, ROOM_INDEX_DATA *location );


Find the do_mptransfer function and replace it with the following:
/* lets the mobile transfer people.  the all argument transfers
   everyone in the current room to the specified location 
   the area argument transfers everyone in the current area to the
   specified location */
void do_mptransfer( CHAR_DATA * ch, char *argument )
{
   char arg1[MAX_INPUT_LENGTH], arg2[MAX_INPUT_LENGTH];
   ROOM_INDEX_DATA *location;
   CHAR_DATA *victim, *nextinroom;
   DESCRIPTOR_DATA *d;

   if( !IS_NPC( ch ) || IS_AFFECTED( ch, AFF_CHARM ) )
   {
      send_to_char( "Huh?\n\r", ch );
      return;
   }

   argument = one_argument( argument, arg1 );
   argument = one_argument( argument, arg2 );

   if( arg1[0] == '\0' )
   {
      progbug( "Mptransfer - Bad syntax", ch );
      return;
   }

   if( arg2[0] != '\0' )
   {
      if( !( location = find_location( ch, arg2 ) ) )
      {
         progbug( "Mptransfer - No such location", ch );
         return;
      }
   }
   else
      location = ch->in_room;

   /*
    * Put in the variable nextinroom to make this work right. -Narn 
    */
   if( !str_cmp( arg1, "all" ) )
   {
      for( victim = ch->in_room->first_person; victim; victim = nextinroom )
      {
         nextinroom = victim->next_in_room;

         if( ch == victim )
            continue;

         transfer_char( ch, victim, location );
      }
      return;
   }

   /*
    * This will only transfer PC's in the area not Mobs --Shaddai 
    */
   if( !str_cmp( arg1, "area" ) )
   {
      for( d = first_descriptor; d; d = d->next )
      {
         if( !d->character || ( d->connected != CON_PLAYING &&  d->connected != CON_EDITING )
             || ch->in_room->area != d->character->in_room->area )
            continue;

         if( ch == d->character )
            continue;

         transfer_char( ch, d->character, location );
      }
      return;
   }

   if( !( victim = get_char_world( ch, arg1 ) ) )
   {
      progbug( "Mptransfer - No such person", ch );
      return;
   }
   transfer_char( ch, victim, location );
   return;
}


During testing for a working fix on these functions it was found that the targetting of immortals who are following players who get transferred using the "all" argument had a very high risk of causing an infinite loop in the code which required the process to be killed from the shell to recover. This risk was dependent upon the order in which characters were added and removed from the room lists. The "all" cases have been redone to simply grab everyone in the room except the character who initiated the command and move them all to the new destination. This left the problem of what to do for targetting individual players/mobs for transfer to a new location. Even with fixes that were offered, the end result was that infinite loops were still possible no matter which method was used. This is an unacceptable risk for such a low priority feature. Taking following imms along on the trip is not of such critical importance that this risk can be allowed.
       
Pages:<< prev 1 next >>