'===========================================================================
' Subject: CHECK IF IN A SHELL                Date: 09-06-92 (18:09)       
'  Author: Tony Elliott                       Code: QB, PDS                
'  Origin: QB TidBits                       Packet: DOS.ABC
'===========================================================================
' >Is it possible for a spawned program (via SHELL or more importantly via
' >QBSWAP) to know the name of the program which spawned it? (or even to know
' >that it is a shelled program and not a "top-level" program?)  How?

'There is a way to determine if a program is a child process. However,
'I haven't been able to determine the name of the parent process. This
'EXE filename is normally store just above the apps copy of the
'environment. Apparently this info is destroyed when the parent app
'shells.

'Here's some code to determine if the app is being executed from a
'shell:

'$INCLUDE: 'QB.BI'

DEFINT A-Z
DECLARE FUNCTION ImInAShell% ()
DECLARE FUNCTION BPeek% (Segment&, Offset%)
DECLARE FUNCTION WPeek% (Segment&, Offset%)
DECLARE FUNCTION ExeName$ (Psp%)

IF ImInAShell% THEN
    PRINT "I'm in a shell!"
ELSE
    PRINT "I'm not in a shell."
END IF
 

FUNCTION BPeek% (Segment&, Offset%)

    'Peeks a byte (two bytes) and returns it as a result of the function

    DEF SEG = Segment&                  'Point to data segment
    Temp% = PEEK(Offset%)               'Peek byte into temp variable
    DEF SEG                             'Point back to DGroup
    BPeek% = Temp%                      'Return it

END FUNCTION

FUNCTION ImInAShell%

  DIM Reg AS RegTypeX
	
  IntNo = &H21                        'Get Current PSP
  Reg.ax = &H5100
  GOSUB DoDosCall
  CurrentPSP = Reg.bx

  Reg.ax = &H5200                     'Get DOS "List of Lists"
  GOSUB DoDosCall
  Offset = Reg.bx
	
  'Get pointer to first memory control block (MCB) ES:BX-2
  MemBlock& = WPeek(CLNG(Reg.es), Offset - 2)

  DO
    Id = BPeek(MemBlock&, 0)
    SELECT CASE Id
	  CASE &H4D                   'Part of MCB chain
	    OwnerPSP = WPeek(MemBlock&, 1)
	    BlockSize& = WPeek(MemBlock&, 3)
	    IF OwnerPSP <> 0 AND OwnerPSP <> 8 AND LastPSP <> OwnerPSP THEN
		  'Valid block
		  LastPSP = OwnerPSP
		  ParentPSP = WPeek(CLNG(OwnerPSP), &H16)
		  IF ParentPSP = OwnerPSP THEN
			IF FirstCommandCom = 0 THEN
			   FirstCommandCom = ParentPSP
			ELSE
			   ImInAShell = -1
			   EXIT DO
			END IF
		  END IF
	    ELSEIF OwnerPSP = CurrentPSP THEN
		  EXIT DO                         'Stop when we get to our
	    END IF                             'own PSP.
				 
	CASE &H5A                               'Last block in chain
	    EXIT DO

	CASE ELSE                               'Error - MCB's Destroyed!!
	    EXIT DO

	END SELECT
	MemBlock& = MemBlock& + BlockSize& + 1      'Next block in chain
 LOOP
 EXIT FUNCTION

DoDosCall:
	CALL INTERRUPTX(IntNo, Reg, Reg)
RETURN
END FUNCTION

FUNCTION WPeek% (Segment&, Offset%)

    'Peeks a word (two bytes) and returns it as a result of the function

    DEF SEG = Segment&
    TempL% = PEEK(Offset%)
    TempH% = PEEK(Offset% + 1)
    DEF SEG
    POKE VARPTR(Result%), TempL%
    POKE VARPTR(Result%) + 1, TempH%
    WPeek% = Result%

END FUNCTION

