void do_GMVisible(CPC *a1, char *a2)
{
    a1->SetVisible();

    CNetMsg v2;

    if(a1->Unk420)
        SayMsg(v2, 6, 0, "", "", "Visible: ON");
    else
        SayMsg(v2, 6, 0, "", "", "Visible: OFF");

    if(a1->Unk768)
        a1->Unk768->WriteToOutput(v2);
}
int EspParseComPort( char c )
{
 int ComPort;

 switch( c )
 {
  case '1':
   ComPort = 1;
   break;

  case '2':
   ComPort = 2;
   break;

  case '3':
   ComPort = 3;
   break;

  case '4':
   ComPort = 4;
   break;

  default:
   SayMsg(ERR_COM_PORT_INVALID);
   break;
 }
 return(ComPort);
}
void do_GMCountNPC(CPC *a1, char *a2)
{
    char dest[100]; // [sp+24h] [bp-64h]@4

    for(int i = 0; i < gserver.Unk452192; ++i)
    {
        if(gserver.Unk452196[i].Unk40 <= 1)
        {
            strcpy(dest, "Zone :");
            IntCat(dest, gserver.Unk452196[i].Unk0, 1);
            strcat(dest, " First :");
            IntCat(dest, gserver.Unk452196[i].Unk36->Unk32.Unk8, 1);
            strcat(dest, " Now :");
            IntCat(dest, gserver.Unk452196[i].Unk36->Unk52, 1);
            strcat(dest, " ShopCount :");
            IntCat(dest, gserver.Unk452196[i].Unk60, 1);

            CNetMsg v2;

            SayMsg(v2, 6, 0, "", "", dest);

            if(a1->Unk768)
                a1->Unk768->WriteToOutput(v2);
        }
    }
}
void do_GMKICK(CPC *a1, char *a2)
{
    CPC *v4; // [sp+34h] [bp-4h]@5

    if(a2)
    {
        if(*a2)
        {
            TrimString(a2);
            if(strcmp(a2, a1->Unk8))
            {
                v4 = gserver.Unk24.Find(a2);
                if(v4)
                {
                    CNetMsg v3;

                    MsgrLogoutReqMsg(v3, -1, gserver.Unk41004, gserver.Unk41008, -1, v4->Unk768->Unk4);

                    if(!gserver.Unk452129 && gserver.Unk12 && !gserver.Unk12->Unk361 && gserver.Unk12)
                        gserver.Unk12->WriteToOutput(v3);

                    strcpy(g_buf, "Sending Kick: ");
                    strcat(g_buf, a2);

                    CNetMsg v2;

                    SayMsg(v2, 6, 0, "", "", g_buf);
                    if(a1->Unk768)
                        a1->Unk768->WriteToOutput(v2);
                }
                else
                {
                    strcpy(g_buf, "Not Found PC: ");
                    strcat(g_buf, a2);

                    CNetMsg v2;

                    SayMsg(v2, 6, 0, "", "", g_buf);
                    if(a1->Unk768)
                        a1->Unk768->WriteToOutput(v2);
                }
            }
        }
    }
}
void do_GMObserve(CPC *a1, char *a2)
{
    CNetMsg v2;

    if(!gserver.Unk41124)
    {
        gserver.Unk41124 = a1->Unk768;
        return;
    }

    if(gserver.Unk41124 != a1->Unk768)
    {
        strcpy(g_buf, "Change Observer: ");

        if(gserver.Unk41124->Unk372)
            strcat(g_buf, gserver.Unk41124->Unk372->Unk8);
        else
            strcat(g_buf, gserver.Unk41124->Unk4);

        strcat(g_buf, " -> ");
        strcat(g_buf, a1->Unk8);

        SayMsg(v2, 6, 0, "", "", g_buf);

        if(gserver.Unk41124)
            gserver.Unk41124->WriteToOutput(v2);

        if(a1->Unk768)
            a1->Unk768->WriteToOutput(v2);

        gserver.Unk41124 = a1->Unk768;
        return;
    }

    SayMsg(v2, 6, 0, "", "", "Observe Reset");

    if(a1->Unk768)
        a1->Unk768->WriteToOutput(v2);

    gserver.Unk41124 = 0;
}
void do_GMBloodPoint(CPC *a1, char *a2)
{
    int v4; // [sp+24h] [bp-4h]@3

    if(a2 && *a2)
    {
        v4 = atoi(a2);
        if(v4 >= 0 && v4 <= 5000)
        {
            a1->Unk752 = v4;
            strcpy(g_buf, "Blood points: ");
            IntCat(g_buf, a1->Unk752, 1);

            CNetMsg v3;

            SayMsg(v3, 6, 0, "", "", g_buf);
            if(a1->Unk768)
                a1->Unk768->WriteToOutput(v3);

            if(a1->Unk752 <= 0)
            {
                a1->Unk752 = 5000;
                a1->SettingItemOption();
            }
        }
    }
    else
    {
        strcpy(g_buf, "Blood points: ");
        IntCat(g_buf, a1->Unk752, 1);

        CNetMsg v3;

        SayMsg(v3, 6, 0, "", "", g_buf);
        if(a1->Unk768)
            a1->Unk768->WriteToOutput(v3);
    }
}
void do_GMWhereAmI(CPC *a1, char *a2)
{
    char dest; // [sp+24h] [bp-64h]@1

    strcpy(&dest, "Server No :");
    IntCat(&dest, gserver.Unk41004, 1);
    strcpy(&dest, "SubServer No :");
    IntCat(&dest, gserver.Unk41008, 1);
    strcpy(&dest, "Zone No :");
    IntCat(&dest, a1->Unk408->Unk0, 1);
    strcat(&dest, " Area No :");
    IntCat(&dest, a1->Unk412->Unk8, 1);

    CNetMsg v2;

    SayMsg(v2, 6, 0, "", "", &dest);
    if(a1->Unk768)
        a1->Unk768->WriteToOutput(v2);
}
void do_HighReform(CPC *ch_, CItem *reformerItem_, CItem *magnifierItem_, CItem *reformItem_, unsigned int count_)
{
	const int needReformerItem = 1;

	{
		CNetMsg::SP rmsg(new CNetMsg);
		useItemFromInventory(ch_, rmsg, reformerItem_, needReformerItem);
		SEND_Q(rmsg, ch_->m_desc);
	}

	{
		CNetMsg::SP rmsg(new CNetMsg);
		useItemFromInventory(ch_, rmsg, magnifierItem_, count_);
		SEND_Q(rmsg, ch_->m_desc);
	}

	reformerItem_ = NULL;
	magnifierItem_ = NULL;

	reformItem_->originReform(count_);

	ch_->m_inventory.sendOneItemInfo(reformItem_);

	GAMELOG << init("ORIGIN ITEM REFORM SUCCESS", ch_) << itemlog(reformItem_) << end;

	if (ch_->m_admin > 0)
	{
		char tmpBuf[1024] = {0,};
		sprintf(tmpBuf, "ITEM REFORM SUCCESS [OPTION IDX : OPTION VARIATION], [%d : %d], [%d : %d], [%d : %d], [%d : %d], [%d : %d], [%d : %d]",
				reformItem_->GetOriginIndex(0), reformItem_->getOriginVar(0),
				reformItem_->GetOriginIndex(1), reformItem_->getOriginVar(1),
				reformItem_->GetOriginIndex(2), reformItem_->getOriginVar(2),
				reformItem_->GetOriginIndex(3), reformItem_->getOriginVar(3),
				reformItem_->GetOriginIndex(4), reformItem_->getOriginVar(4),
				reformItem_->GetOriginIndex(5), reformItem_->getOriginVar(5));
		CNetMsg::SP rmsg(new CNetMsg);
		SayMsg(rmsg, MSG_CHAT_NOTICE, 0, "", "", tmpBuf);
		SEND_Q(rmsg, ch_->m_desc);

		LOG_INFO("%s", tmpBuf);
	}
}
void do_GMGoPC(CPC *a1, char *a2)
{
    CPC *v5; // [sp+20h] [bp-8h]@7

    if(a2 && *a2)
    {
        TrimString(a2);
        if(strcmp(a2, a1->Unk8))
        {
            for(int i = 0; i < gserver.Unk24.Unk32768; ++i)
            {
                v5 = gserver.Unk24.Unk0[i]; // gserver.Unk20[i + 1]
                if(v5 && !strcmp(v5->Unk8, a2))
                {
                    if(v5->Unk408 == a1->Unk408)
                    {
                        GoTo(a1, v5->Unk120.Unk16, v5->Unk120.Unk0, v5->Unk120.Unk4, a1->Unk412->GetHeight(v5->Unk120.Unk16, v5->Unk120.Unk0, v5->Unk120.Unk4), a1->Unk120.Unk12);
                    }
                    else
                    {
                        if(v5->Unk408->Unk0 != 2 && v5->Unk408->Unk0 != 5 && v5->Unk408->Unk0 != 6)
                        {
                            GoZone(a1, v5->Unk408->Unk0, v5->Unk120.Unk16, v5->Unk120.Unk0, v5->Unk120.Unk4);
                        }
                    }

                    return;
                }
            }

            CNetMsg v4;

            SayMsg(v4, 6, 0, "", "", "Not Found the PC");

            if(a1->Unk768)
                a1->Unk768->WriteToOutput(v4);
        }
    }
}
void do_GMImmortal(CPC *a1, char *a2)
{
    char dest[100]; // [sp+24h] [bp-64h]@2

    if(a1->Unk474)
    {
        a1->Unk474 = 0;
        strcpy(dest, "Immortal Set Off");
    }
    else
    {
        a1->Unk474 = 1;
        DelAttackList(a1);
        strcpy(dest, "Immortal Set On");
    }

    CNetMsg v2;

    SayMsg(v2, 6, 0, "", "", dest);

    if(a1->Unk768)
        a1->Unk768->WriteToOutput(v2);
}
void do_GMReboot(CPC *a1, char *a2)
{
    int v4; // [sp+24h] [bp-4h]@4
    char *sa; // [sp+34h] [bp+Ch]@4

    if(a2)
    {
        if(*a2)
        {
            sa = AnyOneArg(a2, g_buf, false);
            v4 = atoi(g_buf);

            TrimString(sa);

            if(gserver.Unk41080 == -1)
            {
                gserver.Unk41080 = 10 * v4;
                if(*sa)
                {
                    CNetMsg v3;

                    SayMsg(v3, 6, 0, "", "", sa);

                    for(int i = 0; i < gserver.Unk24.Unk32768; ++i)
                    {
                        if(gserver.Unk24.Unk0[i])
                        {
                            if(gserver.Unk24.Unk0[i]->Unk768)
                                gserver.Unk24.Unk0[i]->Unk768->WriteToOutput(v3);
                        }
                    }
                }
            }
        }
    }
}
void do_GMGoNPC(CPC *a1, char *a2)
{
    float v10; // [sp+28h] [bp-40h]@31
    CNPC *v11; // [sp+2Ch] [bp-3Ch]@14
    CNPC *v12; // [sp+30h] [bp-38h]@27
    int v14; // [sp+38h] [bp-30h]@14
    float v15; // [sp+3Ch] [bp-2Ch]@14
    int v16; // [sp+40h] [bp-28h]@12
    int v17; // [sp+44h] [bp-24h]@12
    int v18; // [sp+48h] [bp-20h]@12
    int v19; // [sp+4Ch] [bp-1Ch]@12
    CArea *v22; // [sp+58h] [bp-10h]@12
    int v23; // [sp+5Ch] [bp-Ch]@10
    char v24; // [sp+63h] [bp-5h]@5
    char *s; // [sp+64h] [bp-4h]@4

    if(a2)
    {
        if(*a2)
        {
            TrimString(a2);
            s = a2;

            if(strlen(a2))
            {
                v24 = 0;
                while(*s)
                {
                    if(!(*(short *)(_ctype_b + 2 * *s) & 0x800))
                    {
                        v24 = 1;
                        break;
                    }
                    ++s;
                }

                v23 = -1;
                if(!v24)
                    v23 = atoi(a2);

                v22 = a1->Unk412;
                v19 = 0;
                v18 = v22->Unk12 - 1;
                v17 = 0;
                v16 = v22->Unk16 - 1;
                v14 = (v22->Unk16 < v22->Unk12) ? v22->Unk12 : v22->Unk16;
                v15 = v14 * 12.0;
                v11 = 0;

                CNetMsg v9;

                for(int i = v19; i <= v18; ++i)
                {
                    if(i >= 0 && i < v22->Unk12)
                    {
                        for(int j = v17; j <= v16; ++j)
                        {
                            if(j >= 0 && j < v22->Unk16)
                            {
                                for(CCharacter *k = v22->Unk28[i][j].Unk0; k; k = k->Unk404)
                                {
                                    if(k->Unk0 == 1)
                                    {
                                        if((v12 = (CNPC *)k, v23 == -1) && !strcmp(v12->Unk8, a2) || v23 != -1 && v12->Unk468 == v23)
                                        {
                                            v10 = GetDistance(a1, v12);

                                            //UNDEF(v3);
                                            //v4 = v10 < (long double)v15;
                                            //v5 = 0;
                                            //v6 = v10 == v15;

                                            //if((HIBYTE(v3) & 0x45) == 1)
                                            if(v15 > v10)
                                            {
                                                v15 = v10;
                                                v11 = v12;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }

                if(v11)
                {
                    GoTo(a1, v11->Unk120.Unk16, v11->Unk120.Unk0, v11->Unk120.Unk4, a1->Unk412->GetHeight(v11->Unk120.Unk16, v11->Unk120.Unk0, v11->Unk120.Unk4), a1->Unk120.Unk12);
                }
                else
                {
                    SayMsg(v9, 6, 0, "", "", "Not Found the NPC");
                    if(a1->Unk768)
                        a1->Unk768->WriteToOutput(v9);
                }
            }
        }
    }
}
void do_GMChatMonitor(CPC *a1, char *a2)
{
    CPC *v2; // [sp+Ch] [bp-1Ch]@25
    int i; // [sp+24h] [bp-4h]@1
    char *v5; // [sp+34h] [bp+Ch]@24

    for(i = 0; i <= 19; ++i)
    {
        if(gserver.Unk41128[i] == a1->Unk768)
        {
            if(!a2 || !*a2)
            {
                gserver.Unk41128[i] = 0;
                CNetMsg v3;

                SayMsg(v3, 6, 0, "", "", "Monitoring Finished!!!");
                if(a1->Unk768)
                    a1->Unk768->WriteToOutput(v3);

                return;
            }
            break;
        }
    }

    if(i == 20)
    {
        for(i = 0; i <= 19; ++i)
        {
            if(!gserver.Unk41128[i])
            {
                gserver.Unk41128[i] = a1->Unk768;
                break;
            }
        }
    }

    if(i == 20)
    {
        CNetMsg v3;

        SayMsg(v3, 6, 0, "", "", "Cannot More Monitor!!!");
        if(a1->Unk768)
            a1->Unk768->WriteToOutput(v3);
    }

    if(a2)
    {
        if(*a2)
        {
            *g_buf = 0;
            v5 = AnyOneArg(a2, g_buf, 0);
            TrimString(g_buf);

            if(strlen(g_buf))
            {
                v2 = gserver.Unk24.Find(g_buf);
                if(v2)
                {
                    *g_buf = 0;
                    AnyOneArg(v5, g_buf, 1);
                    TrimString(g_buf);

                    v2->Unk475 = 1;
                    v2->Unk475 = (strcmp(g_buf, "off")) ? 1 : 0;

                    CNetMsg v3;

                    strcpy(g_buf, "SET CHAT MONITOR: ");
                    strcat(g_buf, v2->Unk8);
                    SayMsg(v3, 6, 0, "", "", g_buf);

                    if(a1->Unk768)
                        a1->Unk768->WriteToOutput(v3);
                }
                else
                {
                    CNetMsg v3;

                    SayMsg(v3, 6, 0, "", "", "Not Found the PC");
                    if(a1->Unk768)
                        a1->Unk768->WriteToOutput(v3);
                }
            }
        }
    }
}
void ParseOptions( int          argc,
                   char       **argv,
                   ESP_PARMS    *pEspParms,
                   CONNECTION  *pConnection)
{
 char          ParmString[512];
 char          FileSpec[CCHMAXPATH];
 int           i;
 char         *pOption;
 char         *cp;
 char         *cpo;
 int           len;

 /****************************************************************************/
 /* - If user entered no arguments, go to case help.                         */
 /****************************************************************************/
 if( argc == 1 )
   goto casehelp;

 /****************************************************************************/
 /* - set any default options.                                               */
 /****************************************************************************/
 pConnection->DbgOrEsp = _ESP;

 pEspParms->EspFlags.IsParentEsp    = TRUE;

 /****************************************************************************/
 /* - Build a string of tokens delimited by a single blank.                  */
 /****************************************************************************/
 ParmString[0] = '\0';
 for( i=1 ; i<argc; i++)
 {
  strcat(ParmString,argv[i]);
  strcat(ParmString," ");
 }
 strcat(ParmString,"\0");

 /****************************************************************************/
 /* - Scan the parm block and pull off the options and program name.         */
 /****************************************************************************/
 pOption = strtok(ParmString," ");
 do
 {
  switch( *pOption )
  {
   case '/':
    switch( tolower(*(pOption + 1)) )
    {
 casehelp:
     /************************************************************************/
     /* - handle the help options.                                           */
     /************************************************************************/
     case 'h':
     case '?':
      SayMsg(HELP_INVOCATION_ESP);
      break;

     case 'a':
      /***********************************************************************/
      /* - Parse the com port.                                               */
      /***********************************************************************/
      pConnection->ComPort = EspParseComPort( *(pOption+2) );
      break;

     case 'r':
     pConnection->ConnectType = ASYNC;
     {
     /************************************************************************/
     /* - parse off the speed option.                                        */
     /************************************************************************/
      switch( *(pOption + 2) )
      {
       case '0':
        pConnection->BitRate = 300;
        break;

       case '1':
        pConnection->BitRate = 1200;
        break;

       case '2':
        pConnection->BitRate = 2400;
        break;

       case '3':
        pConnection->BitRate = 4800;
        break;

       case '4':
        pConnection->BitRate = 9600;
        break;

       case '5':
        pConnection->BitRate = 19200;
        break;

       case '6':
        pConnection->BitRate = 38400;
        break;

       default:
        /*********************************************************************/
        /* - assume online and already connected.                            */
        /*********************************************************************/
        pConnection->BitRate = 0;
        break;
      }
     }
     break;

caseo:
     case 'o':
      pConnection->modem = TRUE;
      /***********************************************************************/
      /* - Pull off the program name.                                        */
      /***********************************************************************/
      cpo = pOption + 2;
      if( strlen(cpo) != 0 )
      {
       for( cp=FileSpec; (*cpo != ' ') && (*cpo != 0); )
        *cp++ = toupper(*cpo++);
       *cp = '\0';
       pConnection->pModemFile = Talloc(strlen(FileSpec)+1);
       strcpy(pConnection->pModemFile,FileSpec);
      }
      break;

     case '+': /* Joe's private option */
      pEspParms->EspFlags.Verbose = TRUE;
      break;

     case '!':
      pEspParms->EspFlags.UseDebug  = TRUE;
      break;

     case 'n':
      /***********************************************************************/
      /* - connect using netbios.                                            */
      /* - get the logical adapter name.                                     */
      /***********************************************************************/
      pConnection->ConnectType = _NETBIOS;
      len = strlen(pOption+2);
      if( len != 0 )
      {
       if( len > ( MAX_LSN_NAME - LSN_RES_NAME ) )
        len = MAX_LSN_NAME - LSN_RES_NAME;
       cp = Talloc(len + 1);
       strncpy( cp, pOption+2, len );
       pConnection->pLsnName = cp;
      }
      break;

     case 't':
     {
      /***********************************************************************/
      /* - connect using sockets.                                            */
      /***********************************************************************/
      pConnection->ConnectType = SOCKET;
      len = strlen(pOption+2);
      cp  = Talloc(len + 1);

      strncpy( cp, pOption+2, len );

      pConnection->pLsnName = cp;
     }
     break;

     case 'b':
      /***********************************************************************/
      /* - This option tells the probe that child processes are going to     */
      /*   be debugged. It should only show up in the call to parse          */
      /*   invocation options when the "parent" probe is spawned by the      */
      /*   debugger which only happens when debugging child(multiple)        */
      /*   processes on a single machine using local pipes.                  */
      /***********************************************************************/
      pConnection->ConnectType = LOCAL_PIPE;
      break;


     /************************************************************************/
     /* - handle invalid "/" option.                                         */
     /************************************************************************/
     default:
      printf("\n Invalid Option");
       goto casehelp;


    }
    break;

   default:
    printf("\n Invalid Option");
    goto casehelp;
  }
  pOption = strtok(NULL," " );
 }
 while( pOption );
}
int main( int argc, char **argv )
{
 APIRET      rc;
 COMMAND     cmd = {0,0};
 int         n;
 char       *cp;
 char        rc_string[12];
 CONNECTION  Connection;

 EXCEPTIONREGISTRATIONRECORD  reg_rec;

 ESP_QUE_ELEMENT Qelement;


 if( argc == 1 )
  SayMsg(HELP_INVOCATION_ESP);

 /****************************************************************************/
 /*                                                                          */
 /* Parse the invocation options.                                            */
 /*                                                                          */
 /* - If this is a child debugger, then these additional parameters will     */
 /*   precede the invocation parameters inherited from the parent.           */
 /*                                                                          */
 /*   - /child=xxxxx  where child  = child debugger and                      */
 /*                         xxxxx  = child pid (for serial connections only.)*/
 /*                                                                          */
 /*   - /handle=xxxxx where handle = switch for com handle( serial only )    */
 /*                         xxxxx  = parent's com handle - inherited by      */
 /*                                  the child.                              */
 /*                                                                          */
 /****************************************************************************/
 memset( &EspParms,   0, sizeof( ESP_PARMS ) );
 memset( &Connection, 0, sizeof(Connection) );
 if( strstr( argv[1], "/child" ) )
 {
  ParseEspChildOptions( argc, argv, &EspParms, &Connection );
 }
 else
 {
  ParseOptions( argc, argv, &EspParms, &Connection );
 }

 printf("\nESP Version 5.00 \n");fflush(0);

 /****************************************************************************/
 /* - Send connection info to the router.                                    */
 /****************************************************************************/
 SendConnectionToRouter( &Connection );

 /****************************************************************************/
 /* - Make the connection.                                                   */
 /****************************************************************************/
 {
  int RcMoreInfo = 0;

  rc = ConnectInit( &RcMoreInfo );

  if( rc != 0 )
  {
   char  BadConnectMsg[32] = "";
   int   MsgId;

   if( (Connection.ConnectType == _NETBIOS) && (RcMoreInfo != 0) )
   {
    /*************************************************************************/
    /* - handle netbios specific connect errors.                             */
    /*************************************************************************/
    n     = 1;
    MsgId = ERR_NB_INADEQUATE_RESOURCES;

    switch( RcMoreInfo )
    {
     case CANT_LOAD_NETB_DLL:
      n     = 0;
      MsgId = ERR_NB_CANT_LOAD_DLL;
      break;

     case INADEQUATE_SESSIONS:
      strcpy( BadConnectMsg,"sessions");
      break;

     case INADEQUATE_COMMANDS:
      strcpy( BadConnectMsg,"commands");
      break;

     case INADEQUATE_NAMES:
      strcpy( BadConnectMsg,"names");
      break;

     default:
      n = 1;
      MsgId = ERR_BAD_CONNECT;
      sprintf( BadConnectMsg, "NetBios error rc=%d", rc );
      break;
    }
   }
   else if( (Connection.ConnectType == SOCKET) && (RcMoreInfo != 0) )
   {
    /*************************************************************************/
    /* - handle tcpip specific connect errors.                               */
    /*************************************************************************/
    switch( RcMoreInfo )
    {
     case CANT_LOAD_TCPIP_DLL:
      n     = 1;
      MsgId = ERR_TCPIP_CANT_LOAD_DLL;

      sprintf( BadConnectMsg, "%d", rc );
      break;

     case TCPIP_NOT_RUNNING:
      n     = 0;
      MsgId = ERR_TCPIP_NOT_RUNNING;
      break;

     case TCPIP_ERROR:
      n     = 0;
      MsgId = ERR_TCPIP_ERROR;
      break;

     case TCPIP_NO_SERVICES_PORT:
      n     = 0;
      MsgId = ERR_TCPIP_NO_SERVICES_PORT;
      break;

     default:
      n = 1;
      MsgId = ERR_BAD_CONNECT;
      sprintf( BadConnectMsg, "tcpip error rc=%d", rc );
      break;
    }
   }
   else
   {
    /*************************************************************************/
    /* - handle generic connect errors.                                      */
    /*************************************************************************/
    n = 1;
    MsgId = ERR_BAD_CONNECT;
    sprintf( BadConnectMsg, "rc=%d", rc );
   }
   ErrorPrintf( MsgId, n, BadConnectMsg );
  }
 }

 /****************************************************************************/
 /* - register an exception handler for the probe.                           */
 /****************************************************************************/
 reg_rec.ExceptionHandler = Handler;
 DosSetExceptionHandler(&reg_rec);

 /****************************************************************************/
 /* - Add a connect sema4 for serial connections and wait to be posted.      */
 /****************************************************************************/
 if( (SerialParallel() == SERIAL) && ( IsParent() == FALSE ) )
 {
  USHORT   EspPid;
  TIB     *pTib;
  PIB     *pPib;
  ALLPIDS *p;

  SetComHandle( EspParms.handle );

  DosGetInfoBlocks(&pTib,&pPib);
  EspPid = (USHORT)pPib->pib_ulpid;
  CreateConnectSema4( EspPid, _ESP );
  SerialConnect( JUST_WAIT, 0, _ESP, SendMsgToEspQue );
  p = GetEspPid( EspPid );
  p->Connect = CONNECTED;
 }

 /****************************************************************************/
 /* - Each child debugger will have a termination que so we can kill the     */
 /*   child debuggers on quit/restart.                                       */
 /****************************************************************************/
 if( IsParent() == FALSE )
 {
  rc = StartEspTermQue( );
  if( rc != 0 )
  {
   sprintf(rc_string, "%d",rc);
   ErrorPrintf( ERR_CANT_START_QUE, TRUE, 1, rc_string );
  }
 }
 /****************************************************************************/
 /* - Now, start the command processing loop.                                */
 /****************************************************************************/
 for(;;)
 {
  memset(&cmd,0,sizeof(cmd) );
  RmtRecv(DEFAULT_HANDLE, (char*)&cmd, sizeof(cmd));
  if( IsVerbose() ) PrintCmdMessage( cmd.api ) ;
  switch( cmd.api )
  {
   case FINDEXE:
    RxFindExe(cmd);
    break;

   case STARTUSER:
    RxStartUser( cmd );
    break;

   case GOINIT:
    RxGoInit(cmd);
    break;

   case GOENTRY:
    RxGoEntry(cmd);
    break;

   case DEFBRK:
    RxDefBrk(cmd);
    break;

   case UNDBRK:
    RxUndBrk(cmd);
    break;

   case PUTINBRK:
    RxPutInBrk(cmd);
    break;

   case PULLOUTBRK:
    RxPullOutBrk(cmd);
    break;

   case INSERTALLBRK:
    RxInsertAllBrk();
    break;

   case REMOVEALLBRK:
    RxRemoveAllBrk();
    break;

   case SELECT_SESSION:
    /*************************************************************************/
    /* - Only the parent probe can select one of the debuggee sessions, so   */
    /*   we send a message and tell him to do it.                            */
    /*************************************************************************/
    Qelement.ChildPid = GetEspProcessID();
    SendMsgToEspQue( ESP_QMSG_SELECT_SESSION, &Qelement, sizeof(Qelement) );

    memset(&cmd,0,sizeof(cmd) );

    cmd.api = SELECT_SESSION;
    RmtSend( DEFAULT_HANDLE, &cmd, sizeof(cmd) );
    break;

   case GOSTEP:
    RxGoStep(cmd);
    break;

   case GOFAST:
    RxGoFast(cmd);
    break;

   case DOSDEBUG:
    RxDosDebug( cmd );
    break;

   case GETTHREADINFO:
    RxGetThreadInfo( cmd );
    break;

   case FREEZETHREAD:
    RxFreezeThread( cmd );
    break;

   case THAWTHREAD:
    RxThawThread( cmd );
    break;

   case GETCALLSTACK:
    RxGetCallStack(cmd);
    break;

   case GETEXEORDLLENTRY:
    RxGetExeOrDllEntryOrExitPt(cmd);
    break;

   case NORMALQUIT:
    RxNormalQuit(cmd);

    /*************************************************************************/
    /* - The que has to be up until after the normal quit because the        */
    /*   system will need to post an end session message to the queue.       */
    /*************************************************************************/
    if( IsParent() )
    {
     if( SingleMultiple() == MULTIPLE )
     {
      ALLPIDS *p;
      /***********************************************************************/
      /* - Send a message to all of the child probes telling them that       */
      /*   they are going to be killed.                                      */
      /***********************************************************************/
      for( p = GetAllpids(); p ; p = p->next )
      {
       if( (p->PidFlags.IsDebug) == TRUE && (p->pid != GetEspProcessID()) )
       {
        ESP_QUE_ELEMENT Qelement;

        Qelement.ChildPid = p->EspPid;

        SendMsgToEspTermQue(ESP_PROBE_TERM, &Qelement, sizeof(Qelement) );
       }
      }
      /***********************************************************************/
      /* - send a message to the que to kill all the child probes and        */
      /*   then wait until they are all dead.                                */
      /***********************************************************************/
      ResetAllProbesAreDeadFlag( );
      SendMsgToEspQue(ESP_QMSG_PARENT_TERM,NULL,0);
      while( AllProbesAreDead() == FALSE ){ DosSleep(100) ;}
     }
     SendMsgToEspQue(ESP_QMSG_QUE_TERM,NULL,0);
    }

    CloseConnectSema4();

    cmd.api  = NORMALQUIT;
    cmd.len  = sizeof(rc);

    /*************************************************************************/
    /* - Now, tell dbg that we're finished normal quitting.                  */
    /*************************************************************************/
    RmtSend(DEFAULT_HANDLE, &cmd , sizeof(cmd) );
    RmtSend(DEFAULT_HANDLE, &rc, cmd.len );
    break;

   case SETEXECADDR:
    RxSetExecAddr(cmd);
    break;

   case DEFWPS:
    RxDefWps(cmd);
    break;

   case PUTINWPS:
    RxPutInWps(cmd);
    break;

   case PULLOUTWPS:
    RxPullOutWps(cmd);
    break;

   case GETDATABYTES:
    RxGetDataBytes(cmd);
    break;

   case GETMEMBLKS:
    RxGetMemBlocks(cmd);
    break;

   case SETXCPTNOTIFY:
    RxSetExceptions(cmd);
    break;

   case SETEXECTHREAD:
    RxSetExecThread(cmd);
    break;

   case WRITEREGS:
    RxWriteRegs(cmd);
    break;

   case GETCOREGS:
    RxGetCoRegs(cmd);
    break;

   case SETESPRUNOPTS:
    RxSetEspRunOpts(cmd);
    break;

   case TERMINATEESP:
    if( IsParent() == FALSE )
    {
     memset( &Qelement, 0, sizeof(Qelement) );
     Qelement.ChildPid = GetEspProcessID();

     SendMsgToEspQue( ESP_QMSG_CHILD_TERM, &Qelement, sizeof(Qelement) );
    }
    DosUnsetExceptionHandler(&reg_rec);
    RmtSend(DEFAULT_HANDLE, &cmd , sizeof(cmd) );
    ConnectClose( DEFAULT_HANDLE );
    exit(0);
    break;

   case START_QUE_LISTEN:
    SendMsgToEspQue(ESP_QMSG_OPEN_CONNECT,NULL,0);
    break;

   case START_ESP_QUE:
    RxStartEspQue(cmd);
    break;

   case CONNECT_ESP:
    /*************************************************************************/
    /* - Serial connection only.                                             */
    /*************************************************************************/
    {
     USHORT   GoToPid;
     USHORT   YieldPid;
     ALLPIDS *pYield;
     ALLPIDS *pGoTo;
     BOOL     TorF;

     /************************************************************************/
     /* - Receive the pid to be connected and mark it connected.             */
     /* - If this pid has not yet been assigned to a probe, then pGoTo       */
     /*   will be NULL.                                                      */
     /* - There MUST be a probe with a pid==0, so we release that probe.     */
     /*   ( The pid will be stuffed into the structure at goinit() time.)    */
     /* - Post the connect sema4 for the goto pid.                           */
     /************************************************************************/
     RmtRecv( DEFAULT_HANDLE, &GoToPid, cmd.len );
     pGoTo          = GetPid( GoToPid );

     if( pGoTo == NULL )
      pGoTo = GetPid(0);

     pGoTo->Connect = CONNECTED;


     TorF = TRUE;
     if( GoToPid == GetEspProcessID() )
      TorF = FALSE;

     /************************************************************************/
     /* - Send back verification that the connection has been made.          */
     /************************************************************************/
     memset(&cmd,0,sizeof(cmd) );

     cmd.api = SERIAL_POLL;
     RmtSend( DEFAULT_HANDLE, &cmd, sizeof(cmd) );

     PostConnectSema4( &pGoTo->ConnectSema4, TorF );

     /************************************************************************/
     /* - Disconnect/block this probe.                                       */
     /************************************************************************/
     YieldPid        = (USHORT)GetEspProcessID();
     pYield          = GetPid( YieldPid );
     pYield->Connect = DISCONNECTED;

     SerialConnect( SET_WAIT, YieldPid, _ESP, SendMsgToEspQue );
    }
    break;

   case CTRL_BREAK:
    {
     USHORT          ThisPid;
     USHORT          CtrlBreakPid;

     RmtRecv( DEFAULT_HANDLE, &CtrlBreakPid, cmd.len );

     ThisPid = (USHORT)GetEspProcessID();

     Qelement.ChildPid = CtrlBreakPid;
     Qelement.ChildSid = ThisPid;

     SendMsgToEspQue(ESP_QMSG_CTRL_BREAK, &Qelement, sizeof(Qelement));

     SerialConnect( SET_WAIT, ThisPid,  _ESP, SendMsgToEspQue );
    }
    break;

   case SERIAL_POLL:
    ReportMessage();
    break;

   default:
    cp = (char*)&cmd;
    for( n=1; n<=sizeof(cmd); n++,cp++)
     printf("%c",*cp);
    AsyncFlushModem();
    break;
  }
 }
}