TIP: Click on subject to list as thread! ANSI
echo: power_bas
to: ALL
from: BRIAN MCLAUGHLIN
date: 1995-10-23 18:14:00
subject: Errorlevel from SHELL 1/2

This code was much too good to let it fade away into obscurity. It is
time to repost it. Kudos to Brent Ashley.
'----------------------------- START CODE ---------------------------
' ErrShell.BAS
'
' - A great example of the power of inline assembler. Returns an errorlevel
'   from a SHELLed program to a PB3 program.
'
' Useage: ErrorLevel? = ErrShell?("PKUNZIP BlahBlah.ZIP")
'
' For EBA library by Brent Ashley
' 8 Nov 1993                   (BMcL NOTE: My birthday. Excellent gift!)
' released to public domain    (BMcL NOTE: Whoopee! Enjoy!)
'
$INCLUDE "CONSTANT.INC"
$OPTION CNTLBREAK OFF
$INCLUDE "LibDecl.INC"
DEFINT A-Z
' exec parameter block for DOS EXEC call
TYPE EPBType
  Envir  AS WORD
  CmdOfs AS WORD
  CmdSeg AS WORD
  FCB1   AS DWORD
  FCB2   AS DWORD
END TYP
FUNCTION ErrShell?( CommandLine$ ) PUBLIC
  '
  ' Uses DOS EXEC function to call command.com
  ' with command string.  Avoids PB's annoying habit
  ' of losing cursor position on SHELL by updating
  ' PB cursor position to BIOS position after called program.
  '
  ' Also returns errorlevel of called program by monitoring
  ' int 12h svc 4ch and returning penultimate value (last
  ' value is returned by command.com itself)
  '
  ' Usage:  ErrorLevel? = ErrShell( CommandLine$ )
  DIM EPB AS EPBType
  ' find command.com
  Comspec$ = ENVIRON$("COMSPEC") + CHR$(0)
  ' set up command line to send to command.com
  Pgm$ = "/c " + CommandLine$ + " " + CHR$(13)
  CmdLen = LEN(Pgm$) - 1
  Pgm$ = CHR$(CmdLen) + Pgm$
  ' get ready to receive errorlevels
  OurCS?? = CODESEG(OurInt21)
  OurInt?? = CODEPTR(OurInt21)
  PenultOfs?? = CODEPTR(PenuErr)
  ' get and save current vector
  ! mov ax, &H3521
  ! int &H21
  ! mov cs:OldIntOfs, bx
  ! mov ax, es
  ! mov cs:OldIntSeg, ax
  ' point vector to our handler
  ! mov dx, OurInt??
  ! push ds
  ! mov ax, OurCS??
  ! mov ds, ax
  ! mov ax, &H2521
  ! int &H21
  ! pop ds
  ' make room for the exec shell
  dummy?? = SETMEM(-700000)
  ' set up exec parameter block
  EPB.Envir = 0
  EPB.FCB1 = 0
  EPB.FCB2 = 0
  EPB.CmdOfs = STRPTR(Pgm$)
  EPB.CmdSeg = STRSEG(Pgm$)
  ' set up registers and call exec function
  REG %DS, STRSEG(Comspec$)
  REG %DX, STRPTR(Comspec$)
  REG %ES, VARSEG(EPB)
  REG %BX, VARPTR(EPB)
  REG %AX, &H4B00
  CALL INTERRUPT(&H21)
  ' get penultimate errorlevel
  SaveSeg?? = pbvDefSeg
  DEF SEG = OurCS??
  ErrShell? = PEEK(PenultOfs??)
  DEF SEG = SaveSeg??
  ' clear data
  ! xor al, al
  ! mov cs:LastErr, al
  ! mov cs:PenuErr, al
  ' uninstall interrupt handler
  ! push ds
  ! mov dx, cs:OldIntOfs
  ! mov ax, cs:OldIntSeg
  ! mov ds, ax
  ! mov ax, &H2521
  ! int &H21
  ! pop ds
  ' fix cursor position
  SaveSeg?? = pbvDefSeg
  DEF SEG = 0
  LOCATE PEEK(&H451) + 1, PEEK(&H450) + 1
  DEF Seg = SaveSeg??
  ' restore far heap
  dummy?? = SETMEM(700000)
  EXIT FUNCTION ' exit here     (my note: what follows are GOSUBs and data??)
  ' our interrupt 21h handler
  OurInt21:
    ! cmp ah, &H4C
    ! je Svc4C
    ! jmp GotoOldInt
  ' if it's svc 4ch, save last 2 errorlevels
  Svc4C:
    ! push ax
    ! mov ah, cs:LastErr
    ! mov cs:PenuErr, ah
    ! mov cs:LastErr, al
    ! pop ax
  GotoOldInt:
    ! jmp dword ptr cs:OldIntPtr
>>> Continued to next message
 * SLMR 2.1a * MAXLIB For PB v1.2 - Access arrays and files in EMS/XMS!
--- WILDMAIL!/WC v4.12 
---------------
* Origin: NWCS Online (1:105/362.0)

SOURCE: echomail via exec-pc

Email questions or comments to sysop@ipingthereforeiam.com
All parts of this website painstakingly hand-crafted in the U.S.A.!
IPTIA BBS/MUD/Terminal/Game Server List, © 2025 IPTIA Consulting™.