Announcement

Collapse
No announcement yet.

PB/DOS - DosExec-Function

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • PB/DOS - DosExec-Function

    Code:
    '-------------------------------------------------------------------------------
    '
    '        Unit: DOSEXEC1.PBL
    '       Zweck: Laden und Starten eines Programmes über DosExec
    '              (ähnlich SHELL, aber mit Rückgabecode)
    '     Version: 1.30
    '       Stand: 05.08.96
    '     Sprache: PowerBASIC 3
    '       Autor: (C) M.Hoffmann, Friedensallee 105, 22763 Hamburg.
    ' Bemerkungen:
    '  Teilinformationen aus: PBEXEC.BAS von Ethan Winer für MS-BASIC,
    '  konvertiert nach PowerBASIC 3.0 von Gary Blydenburgh. Ist das Carryflag
    '  gesetzt, sind nur die AX-Werte 1,2,3,4,8,10,11 als Fehlercodes zu inter-
    '  pretieren. Diese Information fehlt in ALLEN sonstigen Dokumentationen.
    ' 1.10: Sichern/Restaurieren DTA; wahlweises Umleiten von STDOUT;
    '        (inkompatible Parameterübergabe); ON LOCAL ERROR aktiviert.
    ' 1.20: Abfangen ungültiger Dateinamen-Erweiterungen (nur EXE und COM ok),
    '        Benutzen von VARPTR32 anstalle von FarPtr (100++Bytes kleiner).
    ' 1.30: Methode zur Ausgabeumleitung geändert, da Handle blockiert wurden.
    ' c: dosexec1.pbu      2128   5.08.96  16:03   \pgm\pb3\unit
    '
    
    '---Compiler--------------------------------------------------------------------
    
    $compile  unit
    $cpu      80386
    $debug    map-,pbdebug-,path-,unit-
    $dim      all
    $error    bounds-,numeric-,overflow-,stack-
    $event    off
    $float    emulate
    $lib      all-
    $optimize size
    $static
    
    '---Konstanten------------------------------------------------------------------
    
    %flags = 0
    %ax    = 1
    %bx    = 2
    %dx    = 4
    %ds    = 8
    %es    = 9
    
    '---Definitionen----------------------------------------------------------------
    
    type DosExecParmBlockType
       envSeg   as  word
       cmdPtr   as dword
       fcb1Ptr  as dword
       fcb2Ptr  as dword
    end type
    
    '---Routine---------------------------------------------------------------------
    
    function DosExecPgm (Pgm    as string,_
                         Parms  as string,_
                         Bytes  as long  ,_
                         StdAus as string)_
                         public as integer
    
       '
       ' Eingaben:
       '  Pgm:    Vollständige Spezifikation des auszuführenden Programms
       '  Parms:  Optionale Programmparameter
       '  Bytes:  Benötigter Speicherplatz in Bytes (COMMAND wird auch geladen)
       '          0: sämtlichen verfügbaren Speicher freigeben
       '  StdAus: Standardausgaben des gerufenen Programmes in die angegebene
       '     >>>> Einheit umleiten. ACHTUNG: Verwendet das rufende Programm
       '     >>>> die Einheit "CONS:" für Ausgaben, muß diese zuvor geschlossen
       '     >>>> und anschließend neu geöffnet werden!
       '
       ' Rückgabe:
       '    n                : Returncode des ausgeführten Programms
       '                     :  Highbyte:
       '                     :   0 = Ende via Dos-Funktion 0 oder 4Ch
       '                     :   1 = Abbruch via INT 23h (Ctrl+C/Break)
       '                     :   2 = Abbruch via INT 24h (Critical Error)
       '                     :   3 = Ende via Dos-Funktion 31 (Keep) oder INT 27h
       '                     :  Lowbyte:
       '                     :   Programmendecode
       '   -1 (Dos-Error  1) : nicht unterstützte Funktion
       '   -2 (Dos-Error  2) : Datei nicht gefunden
       '   -3 (Dos-Error  3) : Suchweg nicht gefunden
       '   -4 (Dos-Error  4) : Keine freien Handles
       '   -8 (Dos-Error  8) : Nicht genug Speicherplatz
       '  -10 (Dos-Error 10) : Ungültiges Environment
       '  -11 (Dos-Error 11) : Ungültiger Parameterblock
       '  -16 (PB)           : StdOut kann nicht geöffnet werden
       '  -17 (PB)           : Ungültige Programmspezifikation (<> EXE,COM)
       '
       ' ACHTUNG: Da keine offizielle PB-Funktion, bleiben viele Interrupts
       '          umgebogen (z.B. INT9). Daher mit Vorsicht anwenden.
       '
    
       dim Prog   as local string* 64            ' stellt Maximallänge sicher
       dim CmdL   as local string*128            ' stellt Maximallänge sicher
       dim fcb1   as local string* 16            ' nur Dummy
       dim fcb2   as local string* 16            ' nur Dummy
       dim dummy  as local long                  ' Ergebnis von SETMEM
       dim ToFre  as local long                  ' Freizugebende Bytes
       dim Parm   as local DosExecParmBlockType  ' Übergabeblock für EXEC
       dim Temp   as local string                ' Für Konstruktion der KmdoZeile
       dim DtaOfs as local integer               ' Sicherung DTA-Segment
       dim DtaSeg as local integer               ' Sicherung DTA-Offset
       dim StdHd  as local integer               ' PB Handle für Ausgabeeinheit
       dim DosHd  as local integer               ' DOS-Handle für Ausgabeeinheit
       dim DupHd  as local integer               ' 2. Handle für StdOut zum Retten
    
       if instr(".COM.EXE",ucase$(right$(Pgm,4))) = 0 then
          function = -17
          exit function
       end if
    
       ' DTA sicherstellen (wird von EXEC umgesetzt, aber nicht restauriert!)
       ! mov ah,&h2f
       ! int &h21
       ! mov DtaOfs,bx
       ! mov DtaSeg,es
       ' Erfolg wird NICHT überprüft
    
       if len(StdAus) then
          StdHd = FREEFILE
          on local error resume next
          open StdAus for output as #StdHd
          if errtest<>0 then
             function = -16
             exit function
          end if
          on local error goto 0 ' wieder in allgem. Fehlerroutine zurückschalten
          DosHd = fileattr(StdHd,2)
          ! mov ah,&h45  ; DupHandle
          ! mov bx,1     ; OrgHandle von STDOUT
          ! int &h21     ; keine Fehlerprüfung!
          ! mov DupHd,ax ; Zusätzlicher Handle für STDOUT für Wiederherstellung
          '---------------------------------------------------------------------
          ! mov ah,&h46  ; ForcDup=Umleiten
          ! mov bx,DosHd ; Handle von der übergebenen Datei
          ! mov cx,1     ; Umlenken von STDOUT in DosHd
          ! int &h21     ; Fehler werden ignoriert!
       end if
    
       Prog         = left$(Pgm,63)+chr$(0)
       Temp         = left$(" "+Parms,126)
       CmdL         = chr$(len(Temp))+Temp+chr$(13)
       Parm.envSeg  = 0 ' Benutze Environment des Aufrufers
       Parm.cmdPtr  = varptr32(CmdL)
       Parm.fcb1Ptr = varptr32(fcb1)
       Parm.fcb2Ptr = varptr32(fcb2)
       reg %ax      , &h4B00
       reg %ds      , varseg(Prog)
       reg %dx      , varptr(Prog)
       reg %es      , varseg(Parm)
       reg %bx      , varptr(Parm)
    
       if Bytes = 0 then
          ToFre = fre(-1)
       else
          ToFre = Bytes
       end if
    
       dummy = setmem(-ToFre)
       call interrupt &h21
       dummy = setmem(+ToFre)
    
       if reg(%flags) and 1 then
          select case reg(%ax)
          case 1,2,3,4,8,10,11
             function = -reg(%ax)
             goto DosExecPgmExit
          end select
       end if
       ! mov ah,&h4D
       ! int &h21
       ! mov function,ax
    
    DosExecPgmExit:
    
       ' DTA restaurieren
       ! push ds
       ! mov ah,&h1A
       ! mov dx,DtaOfs
       ! mov ds,DtaSeg
       ! int &h21
       ! pop ds
    
       if len(StdAus) then
          close StdHd    ' Übergebene Datei aus PB-Sicht schließen
          ! mov ah,&h46  ; ForcDup=Umleiten
          ! mov bx,DupHd ; Gedoppelter Handle von STDOUT
          ! mov cx,1     ; Umlenken von STDOUT in gedoppelten Handle, also letzt-
          ! int &h21     ; endlich auf sich selbst. Fehler werden ignoriert!
          ' behebt Problem 'No more filehandles'   ' 1.30
          ! mov ah,&h3e  ; CloseFile (Test)        ' 1.30
          ! mov bx,DupHd ; CloseFile (Test)        ' 1.30
          ! int &h21     ; CloseFile (Test)        ' 1.30
       end if
    
    end function
    ------------------
Working...
X