Contributor: SWAG SUPPORT TEAM        

(* This unit lets you execute any child program and redirect the
   child program output to NUL / PRN / CON or file.
   It's very simple to use (look at the EXAMPLE.PAS).
   This source is completlly freeware but make sure to remove
   this remark if any changes are made I don't want anyone to
   spread his bugs with my source.
   Of course any suggestions are welcome as well as questions
   about the source.

   Written by Schwartz Gabriel.   20/03/1993.
   Anyone who has any question can leave me a message at 
   CompuServe to EliaShim address 100320,36
*)

{$A+,B-,D-,E-,F+,G-,I-,L-,N-,O-,P-,Q-,R-,S-,T-,V-,X+,Y+}

Unit Redir;

Interface

Var
  IOStatus      : Integer;
  RedirError    : Integer;
  ExecuteResult : Word;

{------------------------------------------------------------------------------}
procedure Execute (ProgName, ComLine, Redir: String);
{------------------------------------------------------------------------------}

Implementation

Uses DOS;

Type
  PMCB = ^TMCB;
  TMCB = record
           Typ   : Char;
           Owner : Word;
           Size  : Word;
         end;

  PtrRec = record
             Ofs, Seg : Word;
           end;

  THeader = record
              Signature : Word;
              PartPag   : Word;
              PageCnt   : Word;
              ReloCnt   : Word;
              HdrSize   : Word;
              MinMem    : Word;
              MaxMem    : Word;
              ReloSS    : Word;
              ExeSP     : Word;
              ChkSum    : Word;
              ExeIP     : Word;
              ReloCS    : Word;
              TablOff   : Word;
              OverNo    : Word;
            end;

Var
  PrefSeg      : Word;
  MinBlockSize : Word;
  MCB          : PMCB;
  FName        : PathStr;
  F            : File;
  MyBlockSize  : Word;
  Header       : THeader;

{------------------------------------------------------------------------------}

procedure Execute (ProgName, ComLine, Redir: String);

type
  PHandles = ^THandles;
  THandles = Array [Byte] of Byte;

  PWord = ^Word;

var
  RedirChanged : Boolean;
  Handles      : PHandles;
  OldHandle    : Byte;

  {............................................................................}

  function ChangeRedir : Boolean;

  begin
    ChangeRedir:=False;
    If Redir = '' then Exit;
    Assign (F, Redir);
    Rewrite (F);
    RedirError:=IOResult;
    If IOStatus <> 0 then Exit;
    Handles:=Ptr (PrefixSeg, PWord (Ptr (PrefixSeg, $34))^);
    OldHandle:=Handles^[1];
    Handles^[1]:=Handles^[FileRec (F).Handle];
    ChangeRedir:=True;
  end;

  {............................................................................}

  procedure CompactHeap;

  var
    Regs : Registers;

  begin
    Regs.AH:=$4A;
    Regs.ES:=PrefSeg;
    Regs.BX:=MinBlockSize + (PtrRec (HeapPtr).Seg - PtrRec (HeapOrg).Seg);
    MsDos (Regs);
  end;

  {............................................................................}

  procedure DosExecute;

  Begin
    SwapVectors;
    Exec (ProgName, ComLine);
    IOStatus:=DosError;
    ExecuteResult:=DosExitCode;
    SwapVectors;
  End;

  {............................................................................}

  procedure ExpandHeap;

  var
    Regs : Registers;

  begin
    Regs.AH:=$4A;
    Regs.ES:=PrefSeg;
    Regs.BX:=MyBlockSize;
    MsDos (Regs);
  end;

  {............................................................................}

  procedure RestoreRedir;

  begin
    If not RedirChanged then Exit;
    Handles^[1]:=OldHandle;
    Close (F);
  end;

  {............................................................................}

Begin
  RedirError:=0;
  RedirChanged:=ChangeRedir;
  CompactHeap;
  DosExecute;
  Expandheap;
  RestoreRedir;
End;

{------------------------------------------------------------------------------}

Begin
  SetCBreak (False);
  FName:=ParamStr (0);
  Assign (F, FName);
  Reset (F, 1);
  IOStatus:=IOResult;
  If IOStatus = 0 then
    begin
      BlockRead (F, Header, SizeOf (Header));
      IOStatus:=IOResult;
      If IOStatus = 0 then MinBlockSize:=Header.PageCnt * 32 + Header.MinMem + 1
      Else MinBlockSize:=$8000;
      Close (F);
    end
  Else MinBlockSize:=$8000;
  PtrRec (MCB).Seg:=PrefixSeg - 1;
  PtrRec (MCB).Ofs:=$0000;
  MyBlockSize:=MCB^.Size;
  PrefSeg:=PrefixSeg;
End.