home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / sd386v50.zip / sd386src.zip / ESPSTART.C < prev    next >
Text File  |  1995-10-03  |  25KB  |  510 lines

  1. /*****************************************************************************/
  2. /* File:                                             IBM INTERNAL USE ONLY   */
  3. /*   espstart.c                                                              */
  4. /*                                                                           */
  5. /* Description:                                                              */
  6. /*                                                                           */
  7. /*   Start the debuggee.                                                     */
  8. /*                                                                           */
  9. /* History:                                                                  */
  10. /*                                                                           */
  11. /*   06/25/93 Created.                                                       */
  12. /*                                                                           */
  13. /*****************************************************************************/
  14. #include "all.h"
  15.  
  16. #ifdef __ESP__
  17.  
  18.  static HEV Wait4ChildSema4;
  19.  
  20. #endif
  21.  
  22. /*****************************************************************************/
  23. /* - Process id and session id get/set for the parent debuggee.              */
  24. /*****************************************************************************/
  25. static ULONG ParentProcessID;
  26. static ULONG ParentSessionID;
  27.  
  28. static ULONG TerminateSessionID;
  29.  
  30. void  SetParentSessionID( ULONG sid ) { ParentSessionID = sid; }
  31. void  SetParentProcessID( ULONG pid ) { ParentProcessID = pid; }
  32.  
  33. ULONG GetEspParentProcessID() { return(ParentProcessID);   }
  34. ULONG GetEspParentSessionID() { return(ParentSessionID);   }
  35.  
  36. ULONG GetTerminateSessionID() { return(TerminateSessionID);   }
  37.  
  38. /*****************************************************************************/
  39. /* EspStartUser()                                                            */
  40. /*                                                                           */
  41. /* Description:                                                              */
  42. /*                                                                           */
  43. /*   Start the user's application.                                           */
  44. /*                                                                           */
  45. /* Parameters:                                                               */
  46. /*                                                                           */
  47. /*   pUserEXE       -> fully qualified debuggee specification.               */
  48. /*   pUserParms     -> debuggee parms.                                       */
  49. /*   SessionType       user specified session type.                          */
  50. /*   pSessionID        where to put the SessionID.                           */
  51. /*   pProcessID        where to put the ProcessID.                           */
  52. /*   pProcessType      where to put the type( PM, VIO, etc. ) of the process.*/
  53. /*   MsgLen            length of the buffer to receive offending mod if error*/
  54. /*   pMsgBuf        -> buffer to receive offending module name.              */
  55. /*                                                                           */
  56. /* Return:                                                                   */
  57. /*                                                                           */
  58. /*   rc         return code                                                  */
  59. /*                                                                           */
  60. /* Assumptions:                                                              */
  61. /*                                                                           */
  62. /*****************************************************************************/
  63. APIRET EspStartUser(char   *pUserEXE,
  64.                     char   *pUserParms,
  65.                     USHORT  SessionType,
  66.                     ULONG  *pSessionID,
  67.                     ULONG  *pProcessID,
  68.                     ULONG  *pProcessType,
  69.                     ULONG   MsgLen,
  70.                     char   *pMsgBuf )
  71. {
  72.  STARTDATA    sd;
  73.  APIRET       rc;
  74.  char        *cp;
  75.  char         TitleName[35];
  76.  
  77.  /****************************************************************************/
  78.  /* - now start up the parent.                                               */
  79.  /****************************************************************************/
  80.  if( UseExecPgm() )
  81.  {
  82.   char         ExecPgmArgs[512];
  83.   RESULTCODES  result;
  84.   ULONG        ExecFlags;
  85.  
  86.   /***************************************************************************/
  87.   /* - build the program name and program arguments and call DosExecPgm.     */
  88.   /***************************************************************************/
  89.   memset( ExecPgmArgs, 0, sizeof(ExecPgmArgs) );
  90.   strcpy( ExecPgmArgs, pUserEXE);
  91.   if( pUserParms != NULL )
  92.    strcpy( ExecPgmArgs + strlen(pUserEXE) + 1, pUserParms );
  93.  
  94.   ExecFlags = EXEC_TRACE;
  95.  
  96. #ifdef __ESP__
  97. /*---------------------------------------------------------------------------*/
  98.   if( DebugChild() == TRUE )
  99.   {
  100.    ExecFlags = EXEC_ASYNCRESULTDB;
  101.    DosCreateEventSem(NULL,&Wait4ChildSema4,0L,FALSE);
  102.   }
  103. /*---------------------------------------------------------------------------*/
  104. #endif
  105.  
  106.   rc = DosExecPgm( pMsgBuf,
  107.                    MsgLen,
  108.                    ExecFlags,
  109.                    ExecPgmArgs,
  110.                    NULL,
  111.                    &result,
  112.                    ExecPgmArgs);
  113.   if( rc != 0 )
  114.    return(rc);
  115.  
  116.   ParentProcessID = result.codeTerminate;
  117.  }
  118.  else /* Use DosStartSession */
  119.  {
  120.   /***************************************************************************/
  121.   /* - Build the data structure for DosStartSession.                         */
  122.   /* - Note: these are the applicable session types.                         */
  123.   /*     0 = not specified                                                   */
  124.   /*     1 = NOTWINDOWCOMPAT(full scrn)                                      */
  125.   /*     2 = WINDOWCOMPAT                                                    */
  126.   /*     3 = WINDOWAPI ( PM )                                                */
  127.   /***************************************************************************/
  128.    memset( &sd, 0, sizeof(sd) );
  129.    sd.Length        = sizeof(sd);
  130.    sd.Related       = SSF_RELATED_CHILD;
  131.    sd.FgBg          = SSF_FGBG_BACK;
  132.    sd.TraceOpt      = SSF_TRACEOPT_TRACE;
  133.    sd.InheritOpt    = SSF_INHERTOPT_PARENT;
  134.    sd.PgmName       = pUserEXE;
  135.    sd.PgmInputs     = pUserParms;
  136.    sd.SessionType   = SessionType;
  137.    sd.ObjectBuffLen = MsgLen;
  138.    sd.ObjectBuffer  = pMsgBuf;
  139.  
  140. #ifdef __ESP__
  141. /*---------------------------------------------------------------------------*/
  142.    /**************************************************************************/
  143.    /* - if we're debugging child processes then attach the termination       */
  144.    /*   queue and tell DosStartSession() that we want to debug               */
  145.    /*   all descendants.                                                     */
  146.    /* - create a sema4 with an initial state of "set" that will be posted    */
  147.    /*   when the first(or only) child is started.                            */
  148.    /**************************************************************************/
  149.    if( DebugChild() )
  150.    {
  151.     sd.TraceOpt = SSF_TRACEOPT_TRACEALL;
  152.     sd.TermQ    = GetEspQue();
  153.     DosCreateEventSem(NULL,&Wait4ChildSema4,0L,FALSE);
  154.    }
  155. /*---------------------------------------------------------------------------*/
  156. #endif
  157.  
  158.    cp = strrchr( pUserEXE,0x5C );
  159.    sprintf( TitleName , "SD386 App %s" , ++cp );
  160.  
  161.    sd.PgmTitle = TitleName;
  162.  
  163.    rc = DosStartSession( (PSTARTDATA)&sd,
  164.                           &ParentSessionID,
  165.                           &ParentProcessID);
  166.  
  167.    if(rc != 0)
  168.     return(rc);
  169.  }
  170.  
  171.  *pSessionID = TerminateSessionID = ParentSessionID;
  172.  *pProcessID = ParentProcessID;
  173.  
  174.  {
  175.   ULONG type;
  176.  
  177.   /***************************************************************************/
  178.   /* - Get the type of the application.                                      */
  179.   /* - DosQueryAppType puts the app type in bits 0,1,2.                      */
  180.   /***************************************************************************/
  181.   DosQueryAppType( pUserEXE, &type );
  182.   *pProcessType = type & 0x7;
  183.  }
  184.  
  185. #ifdef __ESP__
  186. /*---------------------------------------------------------------------------*/
  187.  {
  188.   ALLPIDS *p;
  189.   TIB     *pTib;
  190.   PIB     *pPib;
  191.  
  192.   /***************************************************************************/
  193.   /* - Add the pid structure for the DosStartSession'd process.              */
  194.   /***************************************************************************/
  195.   AddPid( ParentProcessID, ParentSessionID, 0, 0, NULL );
  196.  
  197.   if( DebugChild() == TRUE )
  198.   {
  199.     /*************************************************************************/
  200.     /* - We need to bring the user's session to the foreground in this       */
  201.     /*   case, else he may not be able to do whatever he needs to do         */
  202.     /*   to give control to the debugger.                                    */
  203.     /*************************************************************************/
  204.     if( ConnectType() == LOCAL_PIPE )
  205.      DosSelectSession(ParentSessionID);
  206.  
  207.    /***************************************************************************/
  208.    /* - Send a message to the queue for the parent process.                   */
  209.    /* - Wait for the child to be started.                                     */
  210.    /* - The queue will update the ParentProcessID and the ParentSessionID.    */
  211.    /***************************************************************************/
  212.    SendNewProcessToQue( ParentProcessID );
  213.    DosWaitEventSem(Wait4ChildSema4,SEM_INDEFINITE_WAIT);
  214.    DosCloseEventSem(Wait4ChildSema4);
  215.  
  216.    *pSessionID = ParentSessionID;
  217.    *pProcessID = ParentProcessID;
  218.   }
  219.  
  220.   /***************************************************************************/
  221.   /* - Put the process id and the session id into the pid structure.         */
  222.   /* - Put the process id of the probe into the pid structure.               */
  223.   /***************************************************************************/
  224.   p      = GetPid( ParentProcessID );
  225.   p->sid = ParentSessionID;
  226.  
  227.   DosGetInfoBlocks(&pTib,&pPib);
  228.  
  229.   p->EspPid = (USHORT)pPib->pib_ulpid;
  230.  
  231.   /***************************************************************************/
  232.   /* - Create the connect sema4 for the parent probe.                        */
  233.   /***************************************************************************/
  234.   if( SerialParallel() == SERIAL )
  235.    CreateConnectSema4( p->EspPid, _ESP );
  236.  }
  237. /*---------------------------------------------------------------------------*/
  238. #endif
  239.  
  240.  return(rc);
  241. }
  242.  
  243. #ifdef __ESP__
  244. /*---------------------------------------------------------------------------*/
  245. /*****************************************************************************/
  246. /* EspSetRunOpts()                                                           */
  247. /*                                                                           */
  248. /* Description:                                                              */
  249. /*                                                                           */
  250. /*   Read a block of esp flags and child/multiple process debugging          */
  251. /*   names. This is only called when the probe is running remote.            */
  252. /*                                                                           */
  253. /* Parameters:                                                               */
  254. /*                                                                           */
  255. /*   pOpts          ->to esp opts.                                           */
  256. /*                                                                           */
  257. /* Return:                                                                   */
  258. /*                                                                           */
  259. /* Assumptions:                                                              */
  260. /*                                                                           */
  261. /*****************************************************************************/
  262. static ESP_RUN_OPTS *pEspRunOpts = NULL;
  263. void EspSetEspRunOpts( ESP_RUN_OPTS *pOpts)
  264. {
  265.  int len;
  266.  ESP_PARMS *pEspParms = GetEspParms();
  267.  
  268.  
  269.  len          = sizeof(ESP_RUN_OPTS) + pOpts->NameBlockSize - 1;
  270.  pEspRunOpts  = (ESP_RUN_OPTS*)Talloc(len);
  271.  
  272.  memcpy(pEspRunOpts,pOpts,len);
  273.  
  274.  /***************************************************************************/
  275.  /* - Add any flags that need to go to the probe.                           */
  276.  /***************************************************************************/
  277.  pEspParms->EspFlags.UseExecPgm     = pEspRunOpts->EspFlags.UseExecPgm;
  278.  pEspParms->EspFlags.DebugChild     = pEspRunOpts->EspFlags.DebugChild;
  279.  pEspParms->EspFlags.DosDebugTrace  = pEspRunOpts->EspFlags.DosDebugTrace;
  280.  pEspParms->EspFlags.SingleMultiple = pEspRunOpts->EspFlags.SingleMultiple;
  281.  
  282. }
  283.  
  284. /*****************************************************************************/
  285. /* - This function posts for the connect sema4.                              */
  286. /*****************************************************************************/
  287. void PostWait4ChildSema4( void )
  288. {
  289.  DosPostEventSem(Wait4ChildSema4);
  290. }
  291.  
  292. /*****************************************************************************/
  293. /* IsDebug()                                                                 */
  294. /*                                                                           */
  295. /* Description:                                                              */
  296. /*                                                                           */
  297. /*   Test a pid to see if this is the name of a process that we want         */
  298. /*   to debug. If it is, then also return the screen group.                  */
  299. /*                                                                           */
  300. /* Parameters:                                                               */
  301. /*                                                                           */
  302. /*   pid         new process pid.                                            */
  303. /*   psid        -> receiver of the screen group.                            */
  304. /*   ptype       -> receiver of the process type.                            */
  305. /*   pmte        -> receiver of the module handle.                           */
  306. /*   pModuleName ->to the exe name for the new process pid.                  */
  307. /*               NULL ==> use DosQprocStatus() to get name from pid.         */
  308. /*                                                                           */
  309. /* Return:                                                                   */
  310. /*                                                                           */
  311. /*   TRUE or FALSE                                                           */
  312. /*                                                                           */
  313. /* Assumptions:                                                              */
  314. /*                                                                           */
  315. /*   This function uses the undocumented DosQProcStatus() call so be         */
  316. /*   wary of different behavior for different versions of the operating      */
  317. /*   system. The documentation that we have at this time is unofficial       */
  318. /*   but should be pretty close to what eventually gets documented.          */
  319. /*   (At this time, there are plans to document the call.)                   */
  320. /*                                                                           */
  321. /*   We use a stack buffer of 64K as suggested by the DosQProcStatus()       */
  322. /*   doc.                                                                    */
  323. /*                                                                           */
  324. /*****************************************************************************/
  325. #define BUFFER_SIZE 64*1024-1
  326. BOOL IsDebug( char *pModuleName,
  327.               USHORT pid,
  328.               ULONG *psid,
  329.               ULONG *ptype,
  330.               USHORT *pmte)
  331. {
  332.  char      ModuleName[CCHMAXPATH];
  333.  char      ExeName[CCHMAXPATH];
  334.  char     *pexe;
  335.  char     *cp;
  336.  void     *pProcStatBuf;
  337.  ULONG     flags;
  338.  
  339.  *psid = 0;
  340.  if( pModuleName == NULL )
  341.  {
  342.   qsPrec_t        *pProcRec  = NULL;     /* ptr to process record section    */
  343.   qsS16Headrec_t  *p16SemRec = NULL;     /* ptr to 16 bit sem section        */
  344.  
  345.   /***************************************************************************/
  346.   /* - Allocate a 64k buffer. This is the recommended size since a large     */
  347.   /*   system may generate this much. It's allocated on a 64k boundary       */
  348.   /*   because DosQprocStatus() is a 16 bit call and we don't want the       */
  349.   /*   buffer to overlap a 64k boundary.                                     */
  350.   /***************************************************************************/
  351.   flags = PAG_COMMIT|PAG_READ|PAG_WRITE|OBJ_TILE;
  352.   if( DosAllocMem( &pProcStatBuf,BUFFER_SIZE,flags) ||
  353.       DosQProcStatus( (ULONG*)pProcStatBuf , BUFFER_SIZE )
  354.     )
  355.    return(FALSE);
  356.  
  357.   /***************************************************************************/
  358.   /* Define a pointer to the process subsection of information.              */
  359.   /***************************************************************************/
  360.   pProcRec   = (qsPrec_t       *)((qsPtrRec_t*)pProcStatBuf)->pProcRec;
  361.   p16SemRec  = (qsS16Headrec_t *)((qsPtrRec_t*)pProcStatBuf)->p16SemRec;
  362.  
  363.   /***************************************************************************/
  364.   /* - scan to the proc record for the pid.                                  */
  365.   /***************************************************************************/
  366.   for( ;pProcRec->pid != pid; )
  367.   {
  368.    /**************************************************************************/
  369.    /* Get a pointer to the next process block and test for past end of block. /
  370.    /**************************************************************************/
  371.    pProcRec = (qsPrec_t *)( (char*)(pProcRec->pThrdRec) +
  372.                                    (pProcRec->cTCB)*sizeof(qsTrec_t));
  373.  
  374.    if((void*)pProcRec >= (void*)p16SemRec )
  375.    {
  376.     pProcRec = NULL;
  377.     break;
  378.    }
  379.   }
  380.  
  381.   if(pProcRec == NULL )
  382.    return(FALSE);
  383.  
  384.   /***************************************************************************/
  385.   /* - give the session id for this process back to the caller.              */
  386.   /* - get the module name associated with this pid.                         */
  387.   /* - scan the block of names checking to see if this is one of             */
  388.   /*   the child processes that we want to debug.                            */
  389.   /* - the names may be in one of the following formats:                     */
  390.   /*                                                                         */
  391.   /*      1. case1                                                           */
  392.   /*      2. case1.exe                                                       */
  393.   /*      3. d:\path1\path2\case1                                            */
  394.   /*      4. d:\path1\path2\case1.exe                                        */
  395.   /*                                                                         */
  396.   /* - copy a name from the name block into a local buffer.                  */
  397.   /* - append a .exe if needed.                                              */
  398.   /* - if the exe name contains a path then perform an explicit compare.     */
  399.   /* - if the exe name does not contain a path, then only compare it to      */
  400.   /*   name part of the module name.                                         */
  401.   /*                                                                         */
  402.   /***************************************************************************/
  403.   *psid  = pProcRec->sgid;
  404.   *ptype = pProcRec->type & 0x7;
  405.   *pmte  = pProcRec->hMte;
  406.   memset(ModuleName,' ',sizeof(ModuleName) );
  407.   if( DosQueryModuleName(pProcRec->hMte,sizeof(ModuleName),ModuleName) )
  408.    return(FALSE);
  409.  }
  410.  else
  411.  {
  412.   strcpy(ModuleName,pModuleName);
  413.  }
  414.  
  415.  /****************************************************************************/
  416.  /* - compare the module name with the response file names.                  */
  417.  /****************************************************************************/
  418.  for( pexe = &pEspRunOpts->NameBlock; *pexe != '\0'; pexe += strlen(pexe)+1 )
  419.  {
  420.   strcpy(ExeName,pexe);
  421.   if( strstr( ExeName , ".EXE") == NULL)
  422.    strcat( ExeName,".EXE");
  423.   if( strrchr(ExeName,'\\') || strrchr(ExeName,'/') )
  424.    cp = ModuleName;
  425.   else
  426.   {
  427.    cp  = strrchr(ModuleName,'\\');
  428.    cp += 1;
  429.   }
  430.   if( stricmp(cp,ExeName) == 0 )
  431.   {
  432.    return(TRUE);
  433.   }
  434.  }
  435.  return(FALSE);
  436. }
  437.  
  438. /*****************************************************************************/
  439. /* GetSessionID()                                                            */
  440. /*                                                                           */
  441. /* Description:                                                              */
  442. /*                                                                           */
  443. /*   Wrapper around IsDebug() function to get a session id.                  */
  444. /*                                                                           */
  445. /* Parameters:                                                               */
  446. /*                                                                           */
  447. /*   pid         process pid.                                                */
  448. /*   psid        receiver of the screen group.                               */
  449. /*                                                                           */
  450. /* Return:                                                                   */
  451. /*                                                                           */
  452. /*   rc = 0==> success                                                       */
  453. /*        1==> failure                                                       */
  454. /*                                                                           */
  455. /* Assumptions:                                                              */
  456. /*                                                                           */
  457. /*****************************************************************************/
  458. APIRET GetSessionID( USHORT pid, ULONG *psid )
  459. {
  460.  ULONG          flags;
  461.  qsPrec_t       *pProcRec  = NULL;       /* ptr to process record section    */
  462.  qsS16Headrec_t *p16SemRec = NULL;       /* ptr to 16 bit sem section        */
  463.  void           *pProcStatBuf;
  464.  
  465.  /***************************************************************************/
  466.  /* - Allocate a 64k buffer. This is the recommended size since a large     */
  467.  /*   system may generate this much. It's allocated on a 64k boundary       */
  468.  /*   because DosQprocStatus() is a 16 bit call and we don't want the       */
  469.  /*   buffer to overlap a 64k boundary.                                     */
  470.  /***************************************************************************/
  471.  flags = PAG_COMMIT|PAG_READ|PAG_WRITE|OBJ_TILE;
  472.  if( DosAllocMem( &pProcStatBuf,BUFFER_SIZE,flags) ||
  473.      DosQProcStatus( (ULONG*)pProcStatBuf , BUFFER_SIZE )
  474.    )
  475.   return(1);
  476.  
  477.  /***************************************************************************/
  478.  /* Define a pointer to the process subsection of information.              */
  479.  /***************************************************************************/
  480.  pProcRec   = (qsPrec_t       *)((qsPtrRec_t*)pProcStatBuf)->pProcRec;
  481.  p16SemRec  = (qsS16Headrec_t *)((qsPtrRec_t*)pProcStatBuf)->p16SemRec;
  482.  
  483.  /***************************************************************************/
  484.  /* - scan to the proc record for the pid.                                  */
  485.  /***************************************************************************/
  486.  for( ;pProcRec->pid != pid; )
  487.  {
  488.   /**************************************************************************/
  489.   /* Get a pointer to the next process block and test for past end of block. /
  490.   /**************************************************************************/
  491.   pProcRec = (qsPrec_t *)( (char*)(pProcRec->pThrdRec) +
  492.                                   (pProcRec->cTCB)*sizeof(qsTrec_t));
  493.  
  494.   if((void*)pProcRec >= (void*)p16SemRec )
  495.   {
  496.    pProcRec = NULL;
  497.    break;
  498.   }
  499.  }
  500.  
  501.  if(pProcRec == NULL )
  502.   return(1);
  503.  
  504.  *psid = pProcRec->sgid;
  505.  return(0);
  506. }
  507. /*---------------------------------------------------------------------------*/
  508. #endif
  509.  
  510.