home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / sd386v50.zip / sd386src.zip / SD386.C < prev    next >
C/C++ Source or Header  |  1996-08-27  |  70KB  |  1,462 lines

  1. /*****************************************************************************/
  2. /* File:                                             IBM INTERNAL USE ONLY   */
  3. /*   sd386.c                                                                 */
  4. /*                                                                           */
  5. /* Description:                                                              */
  6. /*                                                                           */
  7. /*   Startup program for SD386.                                              */
  8. /*                                                                           */
  9. /* History:                                                                  */
  10. /*                                                                           */
  11. /*   11/12/93 Rewritten.                                                     */
  12. /*                                                                           */
  13. /*****************************************************************************/
  14.  
  15. #include "all.h"
  16.  
  17. extern KEY2FUNC      defk2f[];
  18. extern int           AppTerminated;
  19. extern PtraceBuffer  AppPTB;
  20. extern int           BlowBy;
  21. extern UCHAR        *BoundPtr;
  22. extern UINT          TopLine;
  23. extern UINT          VideoCols;
  24. extern UINT          CurrentMid;
  25. extern UCHAR         Re_Parse_Data;
  26.  
  27. PROCESS_NODE        *pnode;
  28. jmp_buf              RestartContext;
  29.  
  30. static EXCEPTIONREGISTRATIONRECORD  *preg_rec;
  31. static BRK *allbrks = NULL;
  32.  
  33. CmdParms             cmd;
  34.  
  35. ULONG DbgGetProcessID( void ) { return(cmd.ProcessID);   }
  36. ULONG DbgGetSessionID( void ) { return(cmd.SessionID);   }
  37.  
  38. BOOL IsParent       ( void ) { return(cmd.DbgFlags.IsParentDbg)   ;}
  39. BOOL SingleMultiple ( void ) { return(cmd.DbgFlags.SingleMultiple);}
  40. BOOL IsVerbose      ( void ) { return(cmd.DbgFlags.Verbose)       ;}
  41. BOOL DosDebugTrace  ( void ) { return(cmd.DbgFlags.DosDebugTrace );}
  42. BOOL UseExecPgm     ( void ) { return(cmd.DbgFlags.UseExecPgm )   ;}
  43. BOOL IsDbgDebugChild( void ) { return(cmd.DbgFlags.DebugChild)    ;}
  44. BOOL UseDebug       ( void ) { return(cmd.DbgFlags.UseDebug)      ;}
  45. BOOL IsHotKey       ( void ) { return(cmd.DbgFlags.HotKey)        ;}
  46.  
  47. int main( int argc, char **argv )
  48. {
  49.  APIRET        rc;
  50.  DEBFILE      *pdf;
  51.  ULONG         ExeEntryPt;
  52.  ULONG         RunTimeEntryPt;
  53.  ULONG         MainEntryPt;
  54.  char          buffer[CCHMAXPATH];
  55.  char         *ExeFileSpec;
  56.  CONNECTION    Connection;
  57.  ESP_RUN_OPTS *pEspRunOpts = NULL;
  58.  char          BadStartBuffer[CCHMAXPATH];
  59.  ALLPIDS      *p;
  60.  char          rc_string[12];
  61.  USHORT        DbgPid;
  62.  
  63.  EXCEPTIONREGISTRATIONRECORD  reg_rec = {0,&Handler};
  64.  
  65.  if( argc == 1 )
  66.   SayMsg(HELP_INVOCATION_SD386);
  67.  
  68.  /****************************************************************************/
  69.  /*                                                                          */
  70.  /* Parse the invocation options.                                            */
  71.  /*                                                                          */
  72.  /* - If this is a child debugger, then these additional parameters will     */
  73.  /*   precede the invocation parameters inherited from the parent.           */
  74.  /*                                                                          */
  75.  /*   - /child=xxxxx  where child  = child debugger and                      */
  76.  /*                         xxxxx  = child pid (for serial connections only.)*/
  77.  /*                                                                          */
  78.  /*   - /shr=xxxxx    where shr    = switch for shared heap memory handle.   */
  79.  /*                         xxxxx  = shared heap memory handle.              */
  80.  /*                                                                          */
  81.  /*   - /heap=xxxxx   where heap   = switch for shared heap start address.   */
  82.  /*                         xxxxx  = shared heap start address.              */
  83.  /*                                                                          */
  84.  /*   - /handle=xxxxx where handle = switch for com handle( serial only )    */
  85.  /*                         xxxxx  = parent's com handle - inherited by      */
  86.  /*                                  the child.                              */
  87.  /*                                                                          */
  88.  /*   - /qname=xxxxx where  qname  = switch for dbg queue name.              */
  89.  /*                         xxxxx  = dbg queue name.                         */
  90.  /*                                                                          */
  91.  /****************************************************************************/
  92.  memset(&cmd, 0, sizeof(cmd));
  93.  memset(&Connection, 0, sizeof(Connection) );
  94.  if( strstr( argv[1], "/child" ) )
  95.  {
  96.   /***************************************************************************/
  97.   /* - This code is added when were trying to debug a child debugger so      */
  98.   /*   that we can gain access to shared memory.                             */
  99.   /***************************************************************************/
  100. #if 0
  101.   {
  102.    TIB             *pTib;
  103.    PIB             *pPib;
  104.    USHORT           ThisPid;
  105.    USHORT           PidToBeDebugged;
  106.    DBG_QUE_ELEMENT  Qelement;
  107.    char            *pQueName;
  108.  
  109.    PidToBeDebugged = atoi( strchr( argv[1], '=' ) + 1 );
  110.  
  111.  
  112.    DosGetInfoBlocks(&pTib, &pPib);
  113.    ThisPid = (USHORT)pPib->pib_ulpid;
  114.  
  115.    pQueName = strchr( argv[4]+1, '=' ) + 1 ;
  116.  
  117.    printf("\n%s",pQueName);fflush(0);
  118.    SetDbgQueName( pQueName );
  119.  
  120.    Qelement.pid = PidToBeDebugged;
  121.    Qelement.sid = ThisPid;
  122.  
  123.    SendMsgToDbgQue(DBG_QMSG_REQUEST_ACCESS, &Qelement, sizeof(Qelement));
  124.    printf("\nmessage sent to que ");fflush(0);
  125.  
  126.    printf("\nwaiting for shared memory access...");fflush(0);
  127.    DosSleep(10000);
  128.   }
  129. #endif
  130.  
  131.   ParseChildInvocationOptions( argc, argv, &cmd, &Connection );
  132.  }
  133.  else
  134.   ParseInvocationOptions( argc, argv, &cmd, &Connection );
  135.  
  136.  /****************************************************************************/
  137.  /* - handle a null exe for the parent session.                              */
  138.  /****************************************************************************/
  139.  if( (IsParent() == TRUE ) && (cmd.pUserExe == NULL) )
  140.   SayMsg(ERR_NO_EXE);
  141.  
  142.  
  143.  /****************************************************************************/
  144.  /* - If this is a child debugging session, then we set the process id       */
  145.  /*   and session id of the debuggee.                                        */
  146.  /* - The child process id and the child session id were sent over by        */
  147.  /*   the probe along with the new process notification and were added       */
  148.  /*   to the node for this pid prior to spawing the child debugger.          */
  149.  /****************************************************************************/
  150.  if( IsParent() == FALSE )
  151.  {
  152.   p = GetPid( cmd.ProcessID);
  153.   cmd.SessionID   = 0;
  154.   cmd.ProcessType = p->type;
  155.  }
  156.  
  157.  /****************************************************************************/
  158.  /* - If we're debugging child processes and the above parsing did not       */
  159.  /*   specify a connection, then we default to a single machine.  In this    */
  160.  /*   case, the probe is still considered to be remote since we'll be        */
  161.  /*   debugging over a local pipe.                                           */
  162.  /*                                                                          */
  163.  /* - Send the connection details to the router.                             */
  164.  /****************************************************************************/
  165.  if( IsDbgDebugChild() && (Connection.ConnectType == BOUND) )
  166.   Connection.ConnectType = LOCAL_PIPE;
  167.  SendConnectionToRouter( &Connection );
  168.  /****************************************************************************/
  169.  /* - Before making the connection, there needs to a probe that we can       */
  170.  /*   connect to.  If the user has specified the /b invocation option to     */
  171.  /*   debug child processes and we're running in a single machine            */
  172.  /*   configuration, then we need to spawn a parent esp to connect to.       */
  173.  /****************************************************************************/
  174.  if( (ConnectType() == LOCAL_PIPE) && (IsParent() == TRUE) )
  175.  {
  176.   ULONG           ErrorBufLen;
  177.   ESP_SPAWN_FLAGS SpawnFlags;
  178.  
  179.   ErrorBufLen = sizeof(BadStartBuffer);
  180.   memset( BadStartBuffer, 0, ErrorBufLen );
  181.  
  182.   /***************************************************************************/
  183.   /*                                                                         */
  184.   /* - We want to spawn an invisible probe.  Why?  Because the               */
  185.   /*   Session Manager has a restriction that only a parent can              */
  186.   /*   bring a child to the foreground, and since the probe is the           */
  187.   /*   parent of the debuggee, it must be brought to the foreground          */
  188.   /*   before the child's session can be selected.  However, seeing          */
  189.   /*   the probe session pop up in front of your face is annoying so         */
  190.   /*   we make it invisible.                                                 */
  191.   /*                                                                         */
  192.   /* - We always want to start the top level probe using                     */
  193.   /*   DosStartSession() when debugging child process(es) on a               */
  194.   /*   single machine.                                                       */
  195.   /*                                                                         */
  196.   /***************************************************************************/
  197.   SpawnFlags.Visible     = ESP_INVISIBLE;
  198.   SpawnFlags.SpawnMethod = ESP_USE_DOSSTARTSESSION;
  199.   SpawnFlags.SpawnOrigin = ESP_SPAWN_FROM_DBG;
  200.  
  201.   rc = SpawnProbe( &cmd.EspPid,
  202.                    &cmd.EspSid,
  203.                     NULL,
  204.                    ErrorBufLen,
  205.                    BadStartBuffer,
  206.                    SpawnFlags);
  207.  
  208.   if( rc != 0 )
  209.   {
  210.    char rcstring[6];
  211.  
  212.    sprintf(rcstring,"%-d",rc);
  213.    ErrorPrintf( ERR_DOSSTARTSESSION, 2, rcstring, BadStartBuffer );
  214.   }
  215.   /***************************************************************************/
  216.   /* - See the comments above about an invisible probe.                      */
  217.   /***************************************************************************/
  218.   DosSelectSession( cmd.EspSid );
  219.  }
  220.  
  221.  /****************************************************************************/
  222.  /* - if debugging remote( including local pipes then make the               */
  223.  /*   connection.                                                            */
  224.  /****************************************************************************/
  225.  if( IsEspRemote() )
  226.  {
  227.   int   RcMoreInfo = 0;
  228.  
  229.   rc = ConnectInit( &RcMoreInfo );
  230.  
  231.   if( rc != 0 )
  232.   {
  233.    char  BadConnectMsg[32] = "";
  234.    int   MsgId;
  235.    int   n;
  236.  
  237.    if( (Connection.ConnectType == _NETBIOS) && (RcMoreInfo != 0) )
  238.    {
  239.     /*************************************************************************/
  240.     /* - handle netbios specific connect errors.                             */
  241.     /*************************************************************************/
  242.     n     = 1;
  243.     MsgId = ERR_NB_INADEQUATE_RESOURCES;
  244.  
  245.     switch( RcMoreInfo )
  246.     {
  247.      case CANT_LOAD_NETB_DLL:
  248.       n     = 0;
  249.       MsgId = ERR_NB_CANT_LOAD_DLL;
  250.       break;
  251.  
  252.      case INADEQUATE_SESSIONS:
  253.       strcpy( BadConnectMsg,"sessions");
  254.       break;
  255.  
  256.      case INADEQUATE_COMMANDS:
  257.       strcpy( BadConnectMsg,"commands");
  258.       break;
  259.  
  260.      case INADEQUATE_NAMES:
  261.       strcpy( BadConnectMsg,"names");
  262.       break;
  263.  
  264.      default:
  265.       n = 1;
  266.       MsgId = ERR_BAD_CONNECT;
  267.       sprintf( BadConnectMsg, "NetBios error rc=%d", rc );
  268.       break;
  269.     }
  270.    }
  271.    else if( (Connection.ConnectType == SOCKET) && (RcMoreInfo != 0) )
  272.    {
  273.     /*************************************************************************/
  274.     /* - handle tcpip specific connect errors.                               */
  275.     /*************************************************************************/
  276.     switch( RcMoreInfo )
  277.     {
  278.      case CANT_LOAD_TCPIP_DLL:
  279.       n     = 1;
  280.       MsgId = ERR_TCPIP_CANT_LOAD_DLL;
  281.  
  282.       sprintf( BadConnectMsg, "%d", rc );
  283.       break;
  284.  
  285.      case TCPIP_NOT_RUNNING:
  286.       n     = 0;
  287.       MsgId = ERR_TCPIP_NOT_RUNNING;
  288.       break;
  289.  
  290.      case TCPIP_ERROR:
  291.       n     = 0;
  292.       MsgId = ERR_TCPIP_ERROR;
  293.       break;
  294.  
  295.      case TCPIP_NO_SERVICES_PORT:
  296.       n     = 0;
  297.       MsgId = ERR_TCPIP_NO_SERVICES_PORT;
  298.       break;
  299.  
  300.      case TCPIP_NO_HOST_NAME:
  301.       n     = 0;
  302.       MsgId = ERR_TCPIP_NO_HOST_NAME;
  303.       break;
  304.  
  305.      case TCPIP_ESP_NOT_STARTED:
  306.       n     = 0;
  307.       MsgId = ERR_TCPIP_ESP_NOT_STARTED;
  308.       break;
  309.  
  310.      default:
  311.       n = 1;
  312.       MsgId = ERR_BAD_CONNECT;
  313.       sprintf( BadConnectMsg, "tcpip error rc=%d", rc );
  314.       break;
  315.     }
  316.    }
  317.    else
  318.    {
  319.     /*************************************************************************/
  320.     /* - handle generic connect errors.                                      */
  321.     /*************************************************************************/
  322.     n = 1;
  323.     MsgId = ERR_BAD_CONNECT;
  324.     sprintf( BadConnectMsg, "rc=%d", rc );
  325.    }
  326.    ErrorPrintf( MsgId, n, BadConnectMsg );
  327.   }
  328.  }
  329.  
  330.  /****************************************************************************/
  331.  /* - Initialize the screen and display the logo.                            */
  332.  /* - From here on error messages should show up in error boxes.             */
  333.  /****************************************************************************/
  334.  VioInit();
  335.  
  336.  /****************************************************************************/
  337.  /* - Read the user profile if invoked. This must come after VioInit()       */
  338.  /*   because VioInit() defines some arrays that we need.                    */
  339.  /****************************************************************************/
  340.  if( cmd.Profile == TRUE )
  341.   Profile( defk2f );
  342.  
  343.  UpdatePullDownsWithAccelKeys();
  344.  SetDefaultExcepMap();
  345.  SetDefaultColorMap();
  346.  
  347.  
  348.  /****************************************************************************/
  349.  /*                                                                          */
  350.  /* - If this is a child debugger and we're debugging multiple processes     */
  351.  /*   over a serial connection, then                                         */
  352.  /*                                                                          */
  353.  /*    - We need a connect sema4 that will be used for connecting and        */
  354.  /*      disconnecting the the debugger session. It is created in the        */
  355.  /*      set state.                                                          */
  356.  /*                                                                          */
  357.  /*    - We need to tell the router the com handle since it was inherited    */
  358.  /*      from the parent and passed to this debugger through the invocation  */
  359.  /*      paramenters.                                                        */
  360.  /*                                                                          */
  361.  /*    - We need to wait until this debugger gets connected.                 */
  362.  /*                                                                          */
  363.  /****************************************************************************/
  364.  if( (IsParent() == FALSE) && (SerialParallel() == SERIAL) )
  365.  {
  366.   p      = GetPid( cmd.ProcessID );
  367.   DbgPid = p->DbgPid;
  368.   CreateConnectSema4( DbgPid, _DBG );
  369.   OpenSerialMutex();
  370.   SetComHandle( cmd.handle );
  371.   SerialConnect( JUST_WAIT, cmd.ProcessID, _DBG, SendMsgToDbgQue );
  372.  }
  373.  
  374.  /****************************************************************************/
  375.  /* - Each child debugger will have a termination que so we can kill the     */
  376.  /*   child debuggers on quit/restart.                                       */
  377.  /****************************************************************************/
  378.  if( IsParent() == FALSE )
  379.  {
  380.   rc = StartDbgTermQue();
  381.   if( rc != 0 )
  382.   {
  383.    sprintf(rc_string, "%d",rc);
  384.    Error( ERR_CANT_START_QUE, TRUE, 1, rc_string );
  385.   }
  386.  }
  387.  
  388.  /*--------------------------------------------------------------------------*/
  389.  /* - At this point, we are connected to the probe and can start             */
  390.  /*   sending/receiving messages.                                            */
  391.  /*--------------------------------------------------------------------------*/
  392.  
  393.  /****************************************************************************/
  394.  /* - Build runtime options for the probe. The options will be held in       */
  395.  /*   dynamic memory and will be freed after the connection is made and      */
  396.  /*   the options are sent.                                                  */
  397.  /* - The single/multiple flag in DbgFlags is also set at this time by       */
  398.  /*   the call to BuildEspParms().                                           */
  399.  /****************************************************************************/
  400.  if( IsEspRemote() )
  401.  {
  402.   pEspRunOpts = BuildEspParms(&cmd);
  403.   if(pEspRunOpts == NULL )
  404.     Error(ERR_RESPONSE_FILE, TRUE, 1, cmd.pChildProcesses);
  405.  
  406.   /***************************************************************************/
  407.   /* - Add any flags that need to go to the probe.                           */
  408.   /***************************************************************************/
  409.   pEspRunOpts->EspFlags.UseExecPgm     = cmd.DbgFlags.UseExecPgm;
  410.   pEspRunOpts->EspFlags.DebugChild     = cmd.DbgFlags.DebugChild;
  411.   pEspRunOpts->EspFlags.DosDebugTrace  = cmd.DbgFlags.DosDebugTrace;
  412.   pEspRunOpts->EspFlags.SingleMultiple = cmd.DbgFlags.SingleMultiple;
  413.   pEspRunOpts->EspFlags.UseDebug       = cmd.DbgFlags.UseDebug;
  414.  
  415.   if( (SerialParallel() == SERIAL) && (SingleMultiple() == MULTIPLE) )
  416.    RequestSerialMutex();
  417.   xSetEspRunOpts(pEspRunOpts);
  418.   Tfree(pEspRunOpts);
  419.  }
  420.  
  421.  /****************************************************************************/
  422.  /* - Get/Set the fully qualified filespec for the debuggee.                 */
  423.  /****************************************************************************/
  424.  if( IsParent() == TRUE )
  425.  {
  426.   rc = xFindExe(cmd.pUserExe,buffer,sizeof(buffer));
  427.   if( rc != 0 )
  428.    Error(ERR_FILE_CANT_FIND_EXE,TRUE, 1, cmd.pUserExe);
  429.   ExeFileSpec = Talloc(strlen(buffer)+1);
  430.   strcpy(ExeFileSpec,buffer);
  431.   Tfree(cmd.pUserExe);
  432.   cmd.pUserExe = ExeFileSpec;
  433.  
  434.   /***************************************************************************/
  435.   /* - Come here on Restart().                                               */
  436.   /***************************************************************************/
  437.   while( setjmp(RestartContext) )
  438.    RestartInit();
  439.  }
  440.  
  441.  /****************************************************************************/
  442.  /* - register an exception handler for thread 1. We need it for             */
  443.  /*   Ctrl-Break support.                                                    */
  444.  /****************************************************************************/
  445.  DosSetExceptionHandler(®_rec);
  446.  preg_rec = ®_rec;
  447.  
  448.  /****************************************************************************/
  449.  /* - Now, handle the initial startup.                                       */
  450.  /****************************************************************************/
  451.  if( IsParent() == TRUE )
  452.  {
  453.   if( IsEspRemote() )
  454.   {
  455.    /**************************************************************************/
  456.    /* - start up an esp queue.                                               */
  457.    /* - start up a  dbg queue.                                               */
  458.    /**************************************************************************/
  459.    rc = xStartEspQue();
  460.    if( rc != 0 )
  461.    {
  462.     sprintf(rc_string, "%d",rc);
  463.     Error( ERR_CANT_START_QUE, TRUE, 1, rc_string );
  464.    }
  465.  
  466.    rc = StartDbgQue();
  467.    if( rc != 0 )
  468.    {
  469.     sprintf(rc_string, "%d",rc);
  470.     Error( ERR_CANT_START_QUE, TRUE, 1, rc_string );
  471.    }
  472.  
  473.    /**************************************************************************/
  474.    /*                                                                        */
  475.    /* - For parallel connections, the queues are connected with a session    */
  476.    /*   of their own. This session is distinct from the connection that      */
  477.    /*   will be used for api services.                                       */
  478.    /* - The handle for this connection is owned solely by the queue threads. */
  479.    /*                                                                        */
  480.    /**************************************************************************/
  481.    if( SerialParallel() == PARALLEL)
  482.    {
  483.     xStartQueListenThread();
  484.     SendMsgToDbgQue(DBG_QMSG_OPEN_CONNECT,NULL,0);
  485.    }
  486.   }
  487.  
  488.   /***************************************************************************/
  489.   /* - start the debuggee and handle any errors.                             */
  490.   /***************************************************************************/
  491.   memset( BadStartBuffer, 0, sizeof(BadStartBuffer) );
  492.   rc = xStartUser( cmd.pUserExe,
  493.                    cmd.pUserParms,
  494.                    cmd.SessionType,
  495.                   &cmd.SessionID,
  496.                   &cmd.ProcessID,
  497.                   &cmd.ProcessType,
  498.                    sizeof(BadStartBuffer),
  499.                    BadStartBuffer);
  500.  
  501.   if( rc != 0 )
  502.   {
  503.    char rcstring[6];
  504.  
  505.    sprintf(rcstring,"%-d",rc);
  506.    Error( ERR_DOSSTARTSESSION, TRUE, 2, rcstring, BadStartBuffer );
  507.   }
  508.  
  509.   /***************************************************************************/
  510.   /* - Build the pid structure.                                              */
  511.   /***************************************************************************/
  512.   AddPid( cmd.ProcessID,
  513.           cmd.SessionID,
  514.           cmd.EspSid,
  515.           cmd.ProcessType,
  516.           cmd.pUserExe );
  517.  
  518.  }
  519.  
  520.  /*--------------------------------------------------------------------------*/
  521.  /* !!!These comments are out of date and have been left here as a basis     */
  522.  /*    for updating in the future.                                           */
  523.  /*                                                                          */
  524.  /* - At this point, all of the resources have been allocated according      */
  525.  /*   to the following chart.                                                */
  526.  /*                                                                          */
  527.  /*  1. Local -Parent Process - Bound                                        */
  528.  /*  2. Remote-Parent Process - Async                                        */
  529.  /*  3. Remote-Parent Process - Netbios                                      */
  530.  /*                                                                          */
  531.  /*  4. Remote-Single Child Process - Local pipe                             */
  532.  /*  5. Remote-Single Child Process - Async                                  */
  533.  /*  6. Remote-Single Child Process - Netbios                                */
  534.  /*                                                                          */
  535.  /*  7. Remote-Multiple Child Processes - Local pipe                         */
  536.  /*  8. Remote-Multiple Child Processes - Async                              */
  537.  /*  9. Remote-Multiple Child Processes - Netbios                            */
  538.  /*                                                                          */
  539.  /*                                               ------- Parent Dbg only    */
  540.  /*                                              .    .                      */
  541.  /*                                              .    .                      */
  542.  /*                                              .    .         -------Parent*/
  543.  /*                                              .    .        .    .  Esp   */
  544.  /*                                              .    .        .    .  only  */
  545.  /*                                              .    .        .    .        */
  546.  /*                                              .    .        .    .        */
  547.  /*                        | c t | c s | c d t | d | d t | s | e | e t |     */
  548.  /*                        | o y | o e | h i h | b | b h | h | s | s h |     */
  549.  /*                        | n p | n m | e s r | g | g r | r | p | p r |     */
  550.  /*                        | n e | n a | c c e |   |   e | d |   |   e |     */
  551.  /*                        | e   | e 4 | k o a | q | l a |   | q | l a |     */
  552.  /*                        | c   | c   |   n d | u | i d | m | u | i d |     */
  553.  /*                        | t   | t   | f n   | e | s   | e | e | s   |     */
  554.  /*                        |     |     | o e   | u | t   | m | u | t   |     */
  555.  /*  Local/|Connect|Parent/|     |     | r c   | e | e   |   | e | e   |     */
  556.  /*  Remote|Class  |Child  |     |     |   t   |   | n   |   |   | n   |     */
  557.  /*  ------|---------------|-----|---- |-------|---|-----|---|---|-----|     */
  558.  /* 1. L   | BOUND |  P    | B   |  N  |  N    | N |  N  | N | N |  N  |     */
  559.  /* 2. R   | SERIAL|  P    | A   |  N  |  N    | Y |  N  | N | Y |  N  |     */
  560.  /* 3. R   | PRLLEL|  P    | N   |  N  |  N    | Y |  Y  | N | Y |  Y  |     */
  561.  /*        |       |       |     |     |       |   |     |   |   |     |     */
  562.  /* 4. R   | PRLLEL|  C    | LP  |  N  |  N    | Y |  Y  | N | Y |  Y  |     */
  563.  /* 5. R   | SERIAL|  C    | A   |  N  |  N    | Y |  N  | N | Y |  N  |     */
  564.  /* 6. R   | PRLLEL|  C    | N   |  N  |  N    | Y |  Y  | N | Y |  Y  |     */
  565.  /*        |       |       |     |     |       |   |     |   |   |     |     */
  566.  /* 7. R   | PRLLEL|  M    | LP  |  Y  |  N    | Y |  Y  | Y | Y |  Y  |     */
  567.  /* 8. R   | SERIAL|  M    | A   |  Y  |  Y    | Y |  N  | Y | Y |  N  |     */
  568.  /* 9. R   | PRLLEL|  M    | N   |  Y  |  N    | Y |  Y  | Y | Y |  Y  |     */
  569.  /*                                                                          */
  570.  /*                                                                          */
  571.  /*--------------------------------------------------------------------------*/
  572.  if( (Connection.ConnectType==BOUND) || (Connection.ConnectType==LOCAL_PIPE) )
  573.  {
  574.   p = GetPid( cmd.ProcessID );
  575.  
  576.   /***************************************************************************/
  577.   /* - If the user's session is a PM session and SD386 is being started in   */
  578.   /*   a VIO window, then we have a problem and need to give the user a      */
  579.   /*   warning.                                                              */
  580.   /* - If the call to GetProcessType() fails, then proceed. The net result   */
  581.   /*   will be that he will miss the warning message and may proceed to      */
  582.   /*   hang his machine. This is basically what happened in releases prior   */
  583.   /*   to this.                                                              */
  584.   /***************************************************************************/
  585.   if( p->type == SSF_TYPE_PM )
  586.   {
  587.    ULONG    MyType;
  588.  
  589.    if( GetProcessType( &MyType ) == 0 )
  590.    {
  591.     if( MyType == SSF_TYPE_WINDOWABLEVIO )
  592.      Error(ERR_PM_APP_TYPE, FALSE, 0 );
  593.    }
  594.   }
  595.   else
  596.   /***************************************************************************/
  597.   /* - If the user's application is not a PM app and he has turned off       */
  598.   /*   Ctrl-Esc and Alt-Esc access to the desktop, then turn access back on  */
  599.   /* - It it only needs to be turned off when the application is PM.         */
  600.   /***************************************************************************/
  601.   {
  602.    if( IsHotKey() )
  603.    {
  604.     cmd.DbgFlags.HotKey = FALSE;
  605.     SetHotKey();
  606.    }
  607.   }
  608.  }
  609.  
  610.  /****************************************************************************/
  611.  /* -Set the maximum number of low level I/O files open for SD386.           */
  612.  /****************************************************************************/
  613.  DosSetMaxFH(250);
  614.  
  615.  /****************************************************************************/
  616.  /* - Allocate the process node.                                             */
  617.  /****************************************************************************/
  618.  pnode          = (PROCESS_NODE*)Talloc(sizeof(PROCESS_NODE));
  619.  pnode->allbrks = allbrks;              /* need for restart.                 */
  620.  pnode->pid     = cmd.ProcessID;
  621.  pnode->sid     = cmd.SessionID;
  622.  
  623.  /****************************************************************************/
  624.  /* - Do the DosDebug initialization.                                        */
  625.  /****************************************************************************/
  626.  rc  = GoInit( cmd.ProcessID, cmd.SessionID );
  627.  if( rc != 0 )
  628.  {
  629.   char buf[10];
  630.  
  631.   if( rc == 1 )
  632.    Error(ERR_DBG_INIT, TRUE, 1, cmd.pUserExe );
  633.   else
  634.   {
  635.    sprintf(buf,"%d",rc);
  636.    Error(ERR_DOSDEBUG_INIT, TRUE, 1, buf);
  637.   }
  638.  }
  639.  
  640.  /****************************************************************************/
  641.  /* - Get the EXE, the c-runtime, and the main entry points.                 */
  642.  /*   (pdf is a global that will have been set in GoInit()/exeint().         */
  643.  /****************************************************************************/
  644.  pdf = pnode->ExeStruct;
  645.  if( pdf != NULL &&
  646.      pdf->EntryExitPt != 0
  647.    )
  648.   ExeEntryPt = pdf->EntryExitPt;
  649.  else
  650.   Error(ERR_EXE_ENTRY,TRUE,1,cmd.pUserExe);
  651.  
  652.  MainEntryPt = 0;
  653.  RunTimeEntryPt = 0;
  654.  GetRunTimeEntryPt( &RunTimeEntryPt, pdf);
  655.  GetMainEntryPt   ( &MainEntryPt,    pdf);
  656.  
  657.  /****************************************************************************/
  658.  /* - Display the action bar.                                                */
  659.  /****************************************************************************/
  660.  DisplayMenu();
  661.  
  662.  /****************************************************************************/
  663.  /* - Initialize for breakpoint files.                                       */
  664.  /****************************************************************************/
  665.  InitBreakpoints();
  666.  
  667.  /****************************************************************************/
  668.  /* - Add MSH Initialization                                                 */
  669.  /****************************************************************************/
  670. #ifdef MSH
  671.  if( cmd.DbgFlags.UseMsh == TRUE )
  672.   mshInit();
  673. #endif
  674.  
  675. /* commandLine.nparms=0; */
  676.  
  677.  /****************************************************************************/
  678.  /* - Finally...pant...pant...pant, let's go do it.                          */
  679.  /****************************************************************************/
  680.  Run(MainEntryPt,ExeEntryPt);
  681. /* SD386Log(-1,NULL); */ /*Close the logfile.*/
  682.  return(0);
  683. }
  684.  
  685. /*****************************************************************************/
  686. /* GetRunTimeEntryPt()                                                       */
  687. /*                                                                           */
  688. /* Description:                                                              */
  689. /*                                                                           */
  690. /*  Get the location of exe c-runtime entry point.                           */
  691. /*                                                                           */
  692. /* Parameters:                                                               */
  693. /*                                                                           */
  694. /*  fp              FILE * structure of exe/dll file.                        */
  695. /*  pRunTimeEntryPt Where to put the address.                                */
  696. /*  pid             Process id.                                              */
  697. /*  mte             Module table handle of exe/dll.                          */
  698. /*  pdf             debug file structure for exe.                            */
  699. /*                                                                           */
  700. /* Return:                                                                   */
  701. /*                                                                           */
  702. /*  void                                                                     */
  703. /*                                                                           */
  704. /* Assumptions:                                                              */
  705. /*                                                                           */
  706. /*****************************************************************************/
  707.  
  708. #define NUM_OF_RUNTIME_NAMES  2
  709. char *C_RunTimePubName[NUM_OF_RUNTIME_NAMES] =
  710. {
  711.  "__RunExitList",
  712.  "__astart"
  713. };
  714.  
  715. void GetRunTimeEntryPt( ULONG *pRunTimeEntryPt, DEBFILE *pdf )
  716.  
  717. {
  718.  int          i;
  719.  
  720.  *pRunTimeEntryPt = 0;
  721.  for( i = 0; i < NUM_OF_RUNTIME_NAMES ; i++ )
  722.  {
  723.   if( (*pRunTimeEntryPt = DBPub(C_RunTimePubName[i],pdf) ) != NULL )
  724.    return;
  725.  }
  726.  return;
  727. }
  728.  
  729. /*****************************************************************************/
  730. /* GetMainEntryPt()                                                          */
  731. /*                                                                           */
  732. /* Description:                                                              */
  733. /*                                                                           */
  734. /*  Get the location of exe c-runtime entry point.                           */
  735. /*                                                                           */
  736. /* Parameters:                                                               */
  737. /*                                                                           */
  738. /*  fp              FILE * structure of exe/dll file.                        */
  739. /*  pRunTimeEntryPt Where to put the address.                                */
  740. /*  pid             Process id.                                              */
  741. /*  mte             Module table handle of exe/dll.                          */
  742. /*  pdf             debug file structure for exe.                            */
  743. /*                                                                           */
  744. /* Return:                                                                   */
  745. /*                                                                           */
  746. /*  void                                                                     */
  747. /*                                                                           */
  748. /* Assumptions:                                                              */
  749. /*                                                                           */
  750. /*****************************************************************************/
  751.  
  752. #define NUM_OF_MAIN_NAMES  3
  753. char *MainPubName[NUM_OF_MAIN_NAMES] =
  754. {
  755.  "main"    ,
  756.  "_main"   ,
  757.  "winmain"
  758. };
  759.  
  760. void GetMainEntryPt( ULONG *pMainEntryPt, DEBFILE *pdf )
  761. {
  762.  int          i;
  763.  
  764.  *pMainEntryPt = 0;
  765.  for( i = 0; i < NUM_OF_MAIN_NAMES ; i++ )
  766.  {
  767.   if( (*pMainEntryPt = DBPub(MainPubName[i],pdf) ) != NULL )
  768.    return;
  769.  }
  770.  return;
  771. }
  772.  
  773. /*****************************************************************************/
  774. /* RestartInit()                                                             */
  775. /*                                                                           */
  776. /* Description:                                                              */
  777. /*                                                                           */
  778. /*   Initialize for restarting.                                              */
  779. /*                                                                           */
  780. /* Parameters:                                                               */
  781. /*                                                                           */
  782. /* Return:                                                                   */
  783. /*                                                                           */
  784. /* Assumptions:                                                              */
  785. /*                                                                           */
  786. /*****************************************************************************/
  787. void RestartInit( void )
  788. {
  789.  DEBFILE    *pdf;
  790.  DEBFILE    *pdfnext;
  791.  
  792.  FreeThreadList();
  793.  
  794.  for( pdf=pnode->ExeStruct; pdf != NULL; pdf=pdf->next )
  795.   freepdf(pdf);
  796.  
  797.  for( pdf=pnode->ExeStruct; pdf != NULL; )
  798.  {
  799.   pdfnext=pdf->next;
  800.   Tfree((void*)pdf);
  801.   pdf=pdfnext;
  802.  }
  803.  
  804.  
  805.  allbrks = pnode->allbrks;
  806.  
  807.  Tfree(pnode);
  808.  pnode = NULL;
  809.  FreeAllPids();
  810.  
  811.  afilefree();
  812.  dfilefree();Re_Parse_Data = TRUE;
  813.  FreeDisasmViewBuffers();
  814.  
  815.  AppTerminated = FALSE;
  816.  CurrentMid = 0;
  817.  
  818.  /***************************************************************************/
  819.  /* - The BlowBy flag is used to skip the GetFuncsFromEvents call in        */
  820.  /*   showc() and showa so that we can execute functions from the           */
  821.  /*   data window and come back into the data window without stopping       */
  822.  /*   in showc() or showa().                                                */
  823.  /* - To avoid an annoying blink when running functions from the data       */
  824.  /*   window we set the BoundPtr[TopLine] = 0 so that this line could       */
  825.  /*   not be written to. What we have to do here is reset the BoundPtr      */
  826.  /*   back to what it should be.                                            */
  827.  /*                                                                         */
  828.  /***************************************************************************/
  829.  {
  830.   extern UCHAR  Reg_Display;
  831.   BlowBy = NO;
  832.   BoundPtr[TopLine] = VideoCols;
  833.   if(TestBit(Reg_Display,REGS386BIT))
  834.    BoundPtr[TopLine] = VideoCols-REGSWINWIDTH;
  835.   if(TestBit(Reg_Display,REGS387BIT))
  836.    BoundPtr[TopLine] = VideoCols-COREGSWINWIDTH;
  837.  }
  838.  
  839.  /***************************************************************************/
  840.  /* - Free the mte table from a previous run.                               */
  841.  /***************************************************************************/
  842.   FreeMteTable();
  843.  
  844.   FreeMemBlks();
  845.  
  846.  /***************************************************************************/
  847.  /* - Free the SD386 breakpoint environment variable.                       */
  848.  /***************************************************************************/
  849.   FreeSD386Brk();
  850.  
  851. /*_dump_allocated(0);*/
  852. }
  853.  
  854. /*****************************************************************************/
  855. /* Handler()                                                                 */
  856. /*                                                                           */
  857. /* Description:                                                              */
  858. /*                                                                           */
  859. /*  Handler for SD386 exceptions. Currently, we're only interested in        */
  860. /*  C-Break.                                                                 */
  861. /*                                                                           */
  862. /* Parameters:                                                               */
  863. /*                                                                           */
  864. /*   x        See the OS/2 doc.                                              */
  865. /*   y                                                                       */
  866. /*   z                                                                       */
  867. /*   a                                                                       */
  868. /*                                                                           */
  869. /* Return:                                                                   */
  870. /*                                                                           */
  871. /* Assumptions:                                                              */
  872. /*                                                                           */
  873. /*****************************************************************************/
  874. ULONG _System Handler(PEXCEPTIONREPORTRECORD x,
  875.                       PEXCEPTIONREGISTRATIONRECORD y,
  876.                       PCONTEXTRECORD z,
  877.                       PVOID a)
  878. {
  879.  ULONG rc;
  880.  UINT  key;
  881.  
  882.  switch (x->ExceptionNum)
  883.  {
  884.   /***************************************************************************/
  885.   /* - give these non-fatal exceptions back to the os.                       */
  886.   /***************************************************************************/
  887.   case XCPT_GUARD_PAGE_VIOLATION :
  888.   case XCPT_UNABLE_TO_GROW_STACK :
  889.    rc = XCPT_CONTINUE_SEARCH;
  890.    break;
  891.  
  892.   /***************************************************************************/
  893.   /* - these are fatal exceptions that should not happen;however,            */
  894.   /*   in case they do, we get rid of our exception handler and give it      */
  895.   /*   back to the os.                                                       */
  896.   /***************************************************************************/
  897.   default :
  898.    rc = XCPT_CONTINUE_SEARCH;
  899.    break;
  900.  
  901.   case XCPT_ACCESS_VIOLATION :
  902.   case XCPT_INTEGER_DIVIDE_BY_ZERO :
  903.   case XCPT_FLOAT_DIVIDE_BY_ZERO :
  904.   case XCPT_FLOAT_INVALID_OPERATION :
  905.   case XCPT_ILLEGAL_INSTRUCTION :
  906.   case XCPT_PRIVILEGED_INSTRUCTION :
  907.   case XCPT_INTEGER_OVERFLOW :
  908.   case XCPT_FLOAT_OVERFLOW :
  909.   case XCPT_FLOAT_UNDERFLOW :
  910.   case XCPT_FLOAT_DENORMAL_OPERAND :
  911.   case XCPT_FLOAT_INEXACT_RESULT :
  912.   case XCPT_FLOAT_STACK_CHECK :
  913.   case XCPT_DATATYPE_MISALIGNMENT :
  914.    rc = XCPT_CONTINUE_SEARCH;
  915.    DosUnsetExceptionHandler(y);
  916.    break;
  917.  
  918.   /***************************************************************************/
  919.   /* - At this point, we ask the user if he wants to "stop the app" or    917*/
  920.   /*   "kill sd386." If he wants to kill sd386, then we handle it as      917*/
  921.   /*   any other fatal exception like we did above. If he wants to        917*/
  922.   /*   stop the app, then we tell the os that we handled the signal.      917*/
  923.   /*   This will cause DosDebug() to break out of the kernel and this is  917*/
  924.   /*   the effect that we want.                                           917*/
  925.   /***************************************************************************/
  926.   case XCPT_SIGNAL:                                                     /*917*/
  927.    switch (x->ExceptionInfo[0])
  928.    {
  929. caseXCPT_SIGNAL_BREAK:
  930.     case XCPT_SIGNAL_BREAK :
  931.     case XCPT_SIGNAL_INTR :
  932.      /************************************************************************/
  933.      /* - Come here to handle the Ctrl-Break dialog.                         */
  934.      /************************************************************************/
  935.      key = MsgYorN(HELP_CTRL_BREAK);
  936.      if( key == key_1 )
  937.      {
  938.       if( IsEspRemote() && IsExecuteFlag() )
  939.       {
  940.        DBG_QUE_ELEMENT Qelement;
  941.  
  942.        Qelement.pid = DbgGetProcessID();
  943.  
  944.        SendMsgToDbgQue(DBG_QMSG_CTRL_BREAK, &Qelement, sizeof(Qelement));
  945.       }
  946.       rc = XCPT_CONTINUE_EXECUTION;
  947.      }
  948.      else if( key == key_2 )
  949.      {
  950.       rc = XCPT_CONTINUE_SEARCH;
  951.       DosUnsetExceptionHandler(y);
  952.       CloseConnectSema4();
  953.       ConnectClose( DEFAULT_HANDLE );
  954.       CloseSerialMutex();
  955.  
  956.       /***********************************************************************/
  957.       /* - Clean up the screen before we get out of here.                    */
  958.       /***********************************************************************/
  959.       {
  960.        extern UINT VideoRows;
  961.               CSR  DosCsr;
  962.  
  963.        /**********************************************************************/
  964.        /* - Toggle alt-esc and ctrl-esc back on.                             */
  965.        /**********************************************************************/
  966.        if( IsHotKey() ) SetHotKey();
  967.  
  968.        ClrPhyScr( 0, VideoRows-1, vaClear );
  969.        DosCsr.col = 0;
  970.        DosCsr.row = ( uchar )(VideoRows-1);
  971.        PutCsr( &DosCsr );
  972.       }
  973.  
  974.      }
  975.      else
  976.       goto caseXCPT_SIGNAL_BREAK;
  977.      break;
  978.  
  979.     case XCPT_SIGNAL_KILLPROC :
  980.      {
  981.       /***********************************************************************/
  982.       /* - If we fall into this code, then the we've been sent a kill        */
  983.       /*   process signal from an external process.                          */
  984.       /*                                                                     */
  985.       /* - Close the connection sema4 if there is one.                       */
  986.       /* - Take this exception handler out of the chain.                     */
  987.       /* - Close the connection.                                             */
  988.       /* - Tell the que that the child is proceeing to termination.          */
  989.       /* - Tell the operating system that we've handled the signal.          */
  990.       /* - The operating system will interrupt the receive command           */
  991.       /*   at which time, we will terminate the thread and the probe         */
  992.       /*   process...unless we're using an async connection, then            */
  993.       /*   all this bullshit doesn't work so just let the operating          */
  994.       /*   system handle it.                                                 */
  995.       /***********************************************************************/
  996.       DosUnsetExceptionHandler(y);
  997.       CloseConnectSema4();
  998.       ConnectClose( DEFAULT_HANDLE );
  999.       if( IsParent() == FALSE )
  1000.       {
  1001.        DBG_QUE_ELEMENT Qelement;
  1002.  
  1003.        memset( &Qelement, 0, sizeof(Qelement) );
  1004.        Qelement.pid = DbgGetProcessID();
  1005.  
  1006.        SendMsgToDbgQue( DBG_QMSG_CHILD_TERM, &Qelement, sizeof(Qelement) );
  1007.       }
  1008.       rc = XCPT_CONTINUE_SEARCH;
  1009.       /***********************************************************************/
  1010.       /* - Clean up the screen before we get out of here.                    */
  1011.       /***********************************************************************/
  1012.       {
  1013.        extern UINT VideoRows;
  1014.               CSR  DosCsr;
  1015.  
  1016.        /**********************************************************************/
  1017.        /* - Toggle alt-esc and ctrl-esc back on.                             */
  1018.        /**********************************************************************/
  1019.        if( IsHotKey() ) SetHotKey();
  1020.  
  1021.        ClrPhyScr( 0, VideoRows-1, vaClear );
  1022.        DosCsr.col = 0;
  1023.        DosCsr.row = ( uchar )(VideoRows-1);
  1024.        PutCsr( &DosCsr );
  1025.       }
  1026.      }
  1027.      break;
  1028.    }
  1029.    break;
  1030.  }
  1031.  return(rc);
  1032. }
  1033.  
  1034. /*****************************************************************************/
  1035. /* UnRegisterExceptionHandler()                                              */
  1036. /*                                                                           */
  1037. /* Description:                                                              */
  1038. /*                                                                           */
  1039. /*  Remove the exception handler.                                            */
  1040. /*                                                                           */
  1041. /* Parameters:                                                               */
  1042. /*                                                                           */
  1043. /* Return:                                                                   */
  1044. /*                                                                           */
  1045. /* Assumptions:                                                              */
  1046. /*                                                                           */
  1047. /*****************************************************************************/
  1048. void UnRegisterExceptionHandler( void )
  1049. {
  1050.  DosUnsetExceptionHandler(preg_rec);
  1051. }
  1052.  
  1053. /*****************************************************************************/
  1054. /* BuildEspParms()                                                        919*/
  1055. /*                                                                           */
  1056. /* Description:                                                              */
  1057. /*                                                                           */
  1058. /*  Build a block of flags and child process names information to send       */
  1059. /*  to esp.                                                                  */
  1060. /*                                                                           */
  1061. /* Parameters:                                                               */
  1062. /*                                                                           */
  1063. /*  pcmd         ->  to the command/invocation parms structure.              */
  1064. /*                                                                           */
  1065. /* Return:                                                                   */
  1066. /*                                                                           */
  1067. /*  pEspRunOpts  ->  to the dynamic memory block built by this function.     */
  1068. /*  NULL         ==> error.                                                  */
  1069. /*                                                                           */
  1070. /* Assumptions:                                                              */
  1071. /*                                                                           */
  1072. /*  pcmd->pChildProcesses -> to a filespec.                                  */
  1073. /*                                                                           */
  1074. /*  where the filespec is something like:                                    */
  1075. /*                                                                           */
  1076. /*   "@children.lst" specifies a file with a list of child process names.    */
  1077. /*   "child.exe"     specifies only a single child.                          */
  1078. /*                                                                           */
  1079. /*  If pcmd->pChildProcesses==NULL then debugging of all child processes     */
  1080. /*  is assumed.                                                              */
  1081. /*                                                                           */
  1082. /*****************************************************************************/
  1083. ESP_RUN_OPTS *BuildEspParms( CmdParms *pcmd )
  1084. {
  1085.  int    len;
  1086.  char  *cp;
  1087.  char  *pNameBlock;
  1088.  ULONG  NameBlockSize;
  1089.  int    NumOfProcs = 0;
  1090.  
  1091.  ESP_RUN_OPTS *pEspRunOpts = NULL;
  1092.  
  1093.  /****************************************************************************/
  1094.  /* At invocation time, we might have had the following type of invocation   */
  1095.  /* to specify child process debugging:                                      */
  1096.  /*                                                                          */
  1097.  /*   /b[@][filespec]                                                        */
  1098.  /*                                                                          */
  1099.  /* If we did then we have to build a name block so we can tell esp the      */
  1100.  /* names of the child processes to debug.                                   */
  1101.  /*                                                                          */
  1102.  /* We're going to build the following block of flags and names to send      */
  1103.  /* to esp.                                                                  */
  1104.  /*                                                                          */
  1105.  /*      ---  -----------------------                                        */
  1106.  /*       |  | 32 bits of flags      |                                       */
  1107.  /*       |   -----------------------                                        */
  1108.  /*       |  | 32 bit name block size|                                       */
  1109.  /*       |   -----------------------  ---                                   */
  1110.  /*       |  | child1.exe\0          |  |                                    */
  1111.  /*   len |  | child2.exe\0          |  |                                    */
  1112.  /*       |  |     .                 |  |                                    */
  1113.  /*       |  |     .                 |  | NameBlockSize                      */
  1114.  /*       |  |     .                 |  |                                    */
  1115.  /*       |  | childn.exe\0          |  |                                    */
  1116.  /*       |  | \0                    |  |                                    */
  1117.  /*      ---  -----------------------  ---                                   */
  1118.  /*                                                                          */
  1119.  /*   NameBlockSize = 0 ==> debug all child processes.                       */
  1120.  /*                                                                          */
  1121.  /****************************************************************************/
  1122.  
  1123.  cp            = pcmd->pChildProcesses;
  1124.  NameBlockSize = 0;
  1125.  pNameBlock    = NULL;
  1126.  
  1127.  if(cp != NULL)
  1128.  {
  1129.   /***************************************************************************/
  1130.   /* bump len by the length of the name block.                               */
  1131.   /***************************************************************************/
  1132.   if( *cp != '@' )
  1133.   {
  1134.    NameBlockSize = strlen(cp) + 2;
  1135.    pNameBlock    = Talloc(NameBlockSize);
  1136.    strcpy(pNameBlock,cp);
  1137.   }
  1138.   else
  1139.   {
  1140.    if( BuildChildProcessNamesBlock( cp+1,
  1141.                                     &pNameBlock,
  1142.                                     &NameBlockSize,
  1143.                                     &NumOfProcs  )
  1144.      )
  1145.     return(NULL);
  1146.   }
  1147.  }
  1148.  
  1149.  /****************************************************************************/
  1150.  /* - set a flag to indicate single/multiple child process debugging.        */
  1151.  /****************************************************************************/
  1152.  if( NumOfProcs > 1 )
  1153.   pcmd->DbgFlags.SingleMultiple = MULTIPLE;
  1154.  
  1155.  /****************************************************************************/
  1156.  /* now build the block and return a pointer to the caller.                  */
  1157.  /****************************************************************************/
  1158.  len = sizeof(ESP_RUN_OPTS) - 1 + NameBlockSize;
  1159.  
  1160.  pEspRunOpts                 = (ESP_RUN_OPTS*)Talloc(len);
  1161.  pEspRunOpts->NameBlockSize  = NameBlockSize;
  1162.  
  1163.  if( pNameBlock )
  1164.  {
  1165.   memcpy(&(pEspRunOpts->NameBlock),pNameBlock,NameBlockSize);
  1166.   Tfree(pNameBlock);
  1167.  }
  1168.  return(pEspRunOpts);
  1169. }
  1170.  
  1171. /*****************************************************************************/
  1172. /* BuildChildProcessNamesBlock()                                          919*/
  1173. /*                                                                           */
  1174. /* Description:                                                              */
  1175. /*                                                                           */
  1176. /*  Read a user specified response file to get a list of names of            */
  1177. /*  child processes that we want to debug. The names block is                */
  1178. /*  as a string of strings.                                                  */
  1179. /*                                                                           */
  1180. /* Parameters:                                                               */
  1181. /*                                                                           */
  1182. /*  pResponseFileName  -> to file name(s) we're going to read.               */
  1183. /*  pNameBlock         -> to receiver of a pointer to the name block.        */
  1184. /*  pNameBlockSize     -> to receiver of a the name block size.              */
  1185. /*  pNumOfProcs        -> to receiver of a the number of processes.          */
  1186. /*                                                                           */
  1187. /* Return:                                                                   */
  1188. /*                                                                           */
  1189. /*  rc = 0 ==>success.                                                       */
  1190. /*       1 ==>failure.                                                       */
  1191. /*                                                                           */
  1192. /* Assumptions:                                                              */
  1193. /*                                                                           */
  1194. /* - The file is small.                                                      */
  1195. /* - The file is in the current directory or the user has provided an        */
  1196. /*   explicit filespec.                                                      */
  1197. /* - The file is a text file.                                                */
  1198. /* - There is only one exe name per line. EXE extension is not required.     */
  1199. /*                                                                           */
  1200. /*****************************************************************************/
  1201. int BuildChildProcessNamesBlock( char  *pResponseFileName ,
  1202.                                  char **pNameBlock,
  1203.                                  ULONG *pNameBlockSize,
  1204.                                  int   *pNumOfProcs)
  1205. {
  1206.  FILE  *fp;
  1207.  int    len;
  1208.  char   line[CCHMAXPATH];
  1209.  char  *cp;
  1210.  char  *cpp;
  1211.  int    n;
  1212.  
  1213.  /****************************************************************************/
  1214.  /* open the response file and return error if it won't open.                */
  1215.  /****************************************************************************/
  1216.  if( !( fp = fopen(pResponseFileName, "rb" ) ) )
  1217.   return(1);
  1218.  
  1219.  /****************************************************************************/
  1220.  /* - scan the file to get the size of the block needed to hold the names.   */
  1221.  /****************************************************************************/
  1222.  len = 0;
  1223.  for(;;)
  1224.  {
  1225.   char *lp;
  1226.  
  1227.   /***************************************************************************/
  1228.   /* - fgets reads a line from a file.                                       */
  1229.   /***************************************************************************/
  1230.   lp = fgets(line, sizeof(line), fp);
  1231.   if( (lp == NULL) )
  1232.   {
  1233.    /**************************************************************************/
  1234.    /* - A null return indicates an error or an end-of-file condition.  A     */
  1235.    /*   null will be returned for a file that does not have an end-of-file   */
  1236.    /*   character.                                                           */
  1237.    /**************************************************************************/
  1238.    if( feof(fp) != 0 )
  1239.     break;
  1240.    else
  1241.     return(1);
  1242.   }
  1243.   else
  1244.   {
  1245.    /**************************************************************************/
  1246.    /* - lp may be pointing to the end-of-file character. Check for end-of-   */
  1247.    /*   file for a file with an end-of_file mark.                            */
  1248.    /**************************************************************************/
  1249.    if( feof(fp) != 0 )
  1250.     break;
  1251.   }
  1252.  
  1253.   /***************************************************************************/
  1254.   /* - check for a binary file and treat as an error.                        */
  1255.   /***************************************************************************/
  1256.   if( checkline(lp) )
  1257.    return(1);
  1258.  
  1259.   /***************************************************************************/
  1260.   /* - toss blank lines                                                      */
  1261.   /***************************************************************************/
  1262.   cpp=strrchr(line,'\n');if(cpp) *cpp = '\0';
  1263.   cpp=strrchr(line,'\r');if(cpp) *cpp = '\0';
  1264.   n = strlen(line); if( n==0 ) continue;
  1265.   len += n + 1;
  1266.  }
  1267.  len += 1;                              /* add one for the ending '\0'       */
  1268.  
  1269.  /****************************************************************************/
  1270.  /* give the block length and pointer to the caller.                         */
  1271.  /****************************************************************************/
  1272.  *pNameBlockSize = len;
  1273.  *pNameBlock     = cp = Talloc(len);
  1274.  
  1275.  /****************************************************************************/
  1276.  /* now build the following block of names.                                  */
  1277.  /*                                                                          */
  1278.  /*                 -----------------------  ---                             */
  1279.  /*  pNameBlock--->| child1.exe\0          |  |                              */
  1280.  /*                | child2.exe\0          |  |                              */
  1281.  /*                |     .                 |  |                              */
  1282.  /*                |     .                 |  | NameBlockSize                */
  1283.  /*                |     .                 |  |                              */
  1284.  /*                | childn.exe\0          |  |                              */
  1285.  /*                | \0                    |  |                              */
  1286.  /*                 -----------------------  ---                             */
  1287.  /*                                                                          */
  1288.  /* The ending '\0' comes from initializing the allocated block to 0s.       */
  1289.  /* Blank lines will be tossed.                                              */
  1290.  /****************************************************************************/
  1291.  fseek(fp,0L,SEEK_SET);
  1292.  *pNumOfProcs = 0;
  1293.  for(;;)
  1294.  {
  1295.   fgets(line,sizeof(line),fp);
  1296.   if(feof(fp))
  1297.    break;
  1298.   cpp=strrchr(line,'\n');if(cpp) *cpp = '\0';
  1299.   cpp=strrchr(line,'\r');if(cpp) *cpp = '\0';
  1300.   if( strlen(line) == 0 ) continue;
  1301.   strcpy( cp,strupr(line) );
  1302.   cp  += strlen(cp) + 1;
  1303.   *pNumOfProcs += 1;
  1304.  }
  1305.  fclose(fp);
  1306.  return(0);
  1307. }
  1308.  
  1309. /*****************************************************************************/
  1310. /* CheckLine()                                                            919*/
  1311. /*                                                                           */
  1312. /* Description:                                                              */
  1313. /*                                                                           */
  1314. /*  Verify a text line.                                                      */
  1315. /*                                                                           */
  1316. /* Parameters:                                                               */
  1317. /*                                                                           */
  1318. /*  pLine         -> to the line to be verified.                             */
  1319. /*                                                                           */
  1320. /* Return:                                                                   */
  1321. /*                                                                           */
  1322. /*  rc = 0 ==>ok.                                                            */
  1323. /*       1 ==>must be binary.                                                */
  1324. /*                                                                           */
  1325. /* Assumptions:                                                              */
  1326. /*                                                                           */
  1327. /* - Text lines consist of characters >= 0x32 and < 0x80 and may contain     */
  1328. /*   crs and lfs.                                                            */
  1329. /* - The line is null terminated.                                            */
  1330. /*                                                                           */
  1331. /*****************************************************************************/
  1332. int checkline(char *pLine )
  1333. {
  1334.  char *cp = pLine;
  1335.  
  1336.  while(*cp != '\0')
  1337.  {
  1338.   if( ( (0x20 <= *cp)&&(*cp < 0x80) ) ||
  1339.         (*cp == 0x0D)                 ||
  1340.         (*cp == 0x0A)                 ||
  1341.         (*cp == 0x1A)
  1342.     )
  1343.    cp++;
  1344.   else
  1345.    return(1);
  1346.  }
  1347.  return(0);
  1348. }
  1349.  
  1350.  
  1351.  
  1352. void MyExit( void )
  1353. {
  1354.  DBG_QUE_ELEMENT  Qelement;
  1355.  
  1356.  if( IsParent() == FALSE )
  1357.  {
  1358.   Qelement.pid = (ULONG)DbgGetProcessID();
  1359.   SendMsgToDbgQue( DBG_QMSG_SELECT_SESSION, &Qelement, sizeof(Qelement) );
  1360.   DosSleep(15000);
  1361.  }
  1362.  exit(0);
  1363. }
  1364.  
  1365. /*****************************************************************************/
  1366. /* GetProcessType()                                                          */
  1367. /*                                                                           */
  1368. /* Description:                                                              */
  1369. /*                                                                           */
  1370. /*   Get the process type of this debugger.                                  */
  1371. /*                                                                           */
  1372. /* Parameters:                                                               */
  1373. /*                                                                           */
  1374. /*   ptype    -> to the receiver of the type.                                */
  1375. /*                                                                           */
  1376. /* Return:                                                                   */
  1377. /*                                                                           */
  1378. /*   rc                                                                      */
  1379. /*                                                                           */
  1380. /* Assumptions:                                                              */
  1381. /*                                                                           */
  1382. /*   This function uses the undocumented DosQProcStatus() call so be         */
  1383. /*   wary of different behavior for different versions of the operating      */
  1384. /*   system. The documentation that we have at this time is unofficial       */
  1385. /*   but should be pretty close to what eventually gets documented.          */
  1386. /*   (At this time, there are plans to document the call.)                   */
  1387. /*                                                                           */
  1388. /*   We use a stack buffer of 64K as suggested by the DosQProcStatus()       */
  1389. /*   doc.                                                                    */
  1390. /*                                                                           */
  1391. /*****************************************************************************/
  1392. #define BUFFER_SIZE 64*1024-1
  1393. APIRET GetProcessType( ULONG *ptype )
  1394. {
  1395.  void           *pProcStatBuf;
  1396.  ULONG           flags;
  1397.  TIB            *pTib;
  1398.  PIB            *pPib;
  1399.  USHORT          pid;
  1400.  qsPrec_t       *pProcRec;              /* ptr to process record section    */
  1401.  qsS16Headrec_t *p16SemRec;             /* ptr to 16 bit sem section        */
  1402.  
  1403.  /****************************************************************************/
  1404.  /* - First, we have to know the pid.                                        */
  1405.  /****************************************************************************/
  1406.  if( DosGetInfoBlocks(&pTib,&pPib) )
  1407.   return(1);
  1408.  
  1409.  pid = (USHORT)pPib->pib_ulpid;
  1410.  
  1411.  /****************************************************************************/
  1412.  /* - Now get the type.                                                      */
  1413.  /****************************************************************************/
  1414.  pProcRec  = NULL;
  1415.  p16SemRec = NULL;
  1416.  
  1417.  /****************************************************************************/
  1418.  /* - Allocate a 64k buffer. This is the recommended size since a large      */
  1419.  /*   system may generate this much. It's allocated on a 64k boundary        */
  1420.  /*   because DosQprocStatus() is a 16 bit call and we don't want the        */
  1421.  /*   buffer to overlap a 64k boundary.                                      */
  1422.  /****************************************************************************/
  1423.  flags = PAG_COMMIT|PAG_READ|PAG_WRITE|OBJ_TILE;
  1424.  if( DosAllocMem( &pProcStatBuf,BUFFER_SIZE,flags) ||
  1425.      DosQProcStatus( (ULONG*)pProcStatBuf , BUFFER_SIZE )
  1426.    )
  1427.   return(1);
  1428.  
  1429.  /****************************************************************************/
  1430.  /* Define a pointer to the process subsection of information.               */
  1431.  /****************************************************************************/
  1432.  pProcRec   = (qsPrec_t       *)((qsPtrRec_t*)pProcStatBuf)->pProcRec;
  1433.  p16SemRec  = (qsS16Headrec_t *)((qsPtrRec_t*)pProcStatBuf)->p16SemRec;
  1434.  
  1435.  /****************************************************************************/
  1436.  /* - scan to the proc record for the pid.                                   */
  1437.  /****************************************************************************/
  1438.  for( ;pProcRec->pid != pid; )
  1439.  {
  1440.   /***************************************************************************/
  1441.   /* Get a pointer to the next process block and test for past end of block. */
  1442.   /***************************************************************************/
  1443.   pProcRec = (qsPrec_t *)( (char*)(pProcRec->pThrdRec) +
  1444.                                   (pProcRec->cTCB)*sizeof(qsTrec_t));
  1445.  
  1446.   if((void*)pProcRec >= (void*)p16SemRec )
  1447.   {
  1448.    pProcRec = NULL;
  1449.    break;
  1450.   }
  1451.  }
  1452.  
  1453.  if(pProcRec == NULL )
  1454.   return(1);
  1455.  
  1456.  /****************************************************************************/
  1457.  /* - give the type back to the caller.                                      */
  1458.  /****************************************************************************/
  1459.  *ptype = pProcRec->type & 0x7;
  1460.  return(0);
  1461. }
  1462.