UNIT PKZExec;

INTERFACE

USES DOS;

{ Purpose :  Execute PKZIP/PKUNZIP on archive files                         }
{ Uses specialized EXEC procedure so main program can use ALL of the memory }
{ Also shows how to take over INT29 to NOT display anything on the CRT      }

CONST
    PKZIP             : PathStr = 'PKZIP.EXE';
    PKUNZIP           : PathStr = 'PKUNZIP.EXE';

VAR ZIPError          : INTEGER;

PROCEDURE CleanUpDir (WorkDir, FileMask : STRING);
                   {Erases files based on a mask }

PROCEDURE DisplayZIPError;
                   { PKZip interface }

PROCEDURE DefaultCleanup (WorkDir : STRING);
                   {Erases files *.BAK, *.MAP, temp*.*}

PROCEDURE ShowEraseStats;
                   {shows count & bytes recovered}

FUNCTION  UnZIPFile (ZIPOpts, ZIPName, DPath, fspec : STRING; qt : BOOLEAN) : BOOLEAN;
                   {Uses PKUnZip to de-archive files }

FUNCTION  ZIPFile (ZIPOpts, ZIPName, fspec  : STRING; qt : BOOLEAN) : BOOLEAN;
                   {Uses PKZip to archive files }

IMPLEMENTATION

VAR  ZIPDefaultZIPOpts : STRING [16];
VAR  ZIPFileName       : STRING [50];
VAR  ZIPDPath          : STRING [50];

VAR  EraseCount        : WORD;        { files erased }
     EraseSizeK        : LONGINT;     { kilobytes released by erasing files }
     ShowOnWrite       : BOOLEAN;
     I29H              : POINTER;

{ EXECUTE STUFF - SHRINK HEAP AND EXECUTE LIKE EXECDOS }

{$F+}
PROCEDURE Int29Handler (AX, BX, CX, DX, SI, DI, DS, ES, BP : WORD); INTERRUPT;
VAR
  Dummy : BYTE;
BEGIN
  Asm
    Sti
  END;
  IF ShowOnWrite THEN WRITE (CHAR (LO (Ax) ) );
  Asm
    Cli
  END;
END;

PROCEDURE ReallocateMemory (P : POINTER); ASSEMBLER;
ASM
  MOV  AX, PrefixSeg
  MOV  ES, AX
  MOV  BX, WORD PTR P + 2
  CMP  WORD PTR P, 0
  JE   @OK
  INC  BX

 @OK :
  SUB  BX, AX
  MOV  AH, 4Ah
  INT  21h
  JC   @X
  LES  DI, P
  MOV  WORD PTR HeapEnd, DI
  MOV  WORD PTR HeapEnd + 2, ES
 @X :
END;

{ ZAP this DEFINE if NOT 386,486}
{..$DEFINE CPU386}

FUNCTION EXECUTE (Name : PathStr ; Tail : STRING) : WORD; ASSEMBLER;
ASM
  {$IFDEF CPU386}
  DB      66h
  PUSH    WORD PTR HeapEnd
  DB      66h
  PUSH    WORD PTR Name
  DB      66h
  PUSH    WORD PTR Tail
  DB      66h
  PUSH    WORD PTR HeapPtr
  {$ELSE}
  PUSH    WORD PTR HeapEnd + 2
  PUSH    WORD PTR HeapEnd
  PUSH    WORD PTR Name + 2
  PUSH    WORD PTR Name
  PUSH    WORD PTR Tail + 2
  PUSH    WORD PTR Tail
  PUSH    WORD PTR HeapPtr + 2
  PUSH    WORD PTR HeapPtr
  {$ENDIF}

  CALL ReallocateMemory
  CALL SwapVectors
  CALL DOS.EXEC
  CALL SwapVectors
  CALL ReallocateMemory
  MOV  AX, DosError
  OR   AX, AX
  JNZ  @OUT
  MOV  AH, 4Dh
  INT  21h
 @OUT :
END;
{$F-}

FUNCTION ExecuteCommand(p,s : STRING; quiet : BOOLEAN) : INTEGER;
BEGIN
ShowOnWrite := NOT quiet;  { turn off INT 29 }
GETINTVEC ($29, I29H);
SETINTVEC ($29, @Int29Handler);         { Install interrupt handler }
Execute(p,s);
SETINTVEC ($29, I29h);
IF DosError = 0 THEN ExecuteCommand := DosExitCode   ELSE ExecuteCommand := DosError;
END;

FUNCTION AddBackSlash (dName : STRING) : STRING;
BEGIN
  IF dName [LENGTH (dName) ] IN ['\', ':', #0] THEN
    AddBackSlash := dName
  ELSE
    AddBackSlash := dName + '\';
END;

FUNCTION EraseFile ( S : PathStr ) : BOOLEAN ;

VAR F : FILE;

BEGIN

EraseFile := FALSE;

ASSIGN (F, S);
RESET (F);

IF IORESULT <> 0 THEN EXIT;

  CLOSE (F);
  ERASE (F);
  EraseFile := (IORESULT = 0);

END;

FUNCTION FileExists ( S : PathStr ) : BOOLEAN ;

VAR F : FILE;

BEGIN

FileExists := FALSE;

ASSIGN (F, S);
RESET (F);

IF IORESULT <> 0 THEN EXIT;

  CLOSE (F);
  FileExists := (IORESULT = 0);

END;

PROCEDURE CleanUpFile (WorkDir : STRING; SR : searchRec);
VAR l    : LONGINT;
    BEGIN
    WITH SR DO
        BEGIN
        l := size DIV 512;
        IF (attr AND 31) = 0 THEN
            BEGIN
            IF l = 0 THEN l := 1;
            EraseSizeK := EraseSizeK + l;
            WRITELN ('         Removing: ', (AddBackSlash (WorkDir) + name),
                    '   ', l DIV 2, 'k');
            EraseFile (AddBackSlash (WorkDir) + name);
            INC (EraseCount);
            END
        ELSE WRITELN (' ??  ', (AddBackSlash (WorkDir) + name), '   ', l DIV 2, 'k',
                     '  attr: ', attr);
        END;
    END;


PROCEDURE CleanUpDir (WorkDir, FileMask : STRING);
VAR Frec : SearchRec;
    s    : STRING [64];
    BEGIN
    s := '';
    FINDFIRST (AddBackSlash (WorkDir) + FileMask, anyfile, Frec);
    WHILE doserror = 0 DO
        BEGIN
        CleanUpFile (WorkDir, Frec);
        FINDNEXT (Frec);
        END;
    END;


PROCEDURE DefaultCleanup (WorkDir : STRING);
    BEGIN
    CleanUpDir (WorkDir, '*.BAK');
    CleanUpDir (WorkDir, '*.MAP');
    CleanUpDir (WorkDir, 'TEMP*.*');
    END;


PROCEDURE DisplayZIPError;
    BEGIN
    CASE ziperror OF
        0       : WRITELN ('no error');
        2,3     : WRITELN (ziperror : 3, ' Error in ZIP file ');
        4..8    : WRITELN (ziperror : 3, ' Insufficient Memory');
        11,12   : WRITELN (ziperror : 3, ' No MORE files ');
        9,13    : WRITELN (ziperror : 3, ' File NOT found ');
        14,50   : WRITELN (ziperror : 3, ' Disk FULL !! ');
        51      : WRITELN (ziperror : 3, ' Unexpected EOF in ZIP file ');
        15      : WRITELN (ziperror : 3, ' Zip file is Read ONLY! ');
        10,16   : WRITELN (ziperror : 3, ' Bad or illegal parameters ');
        17      : WRITELN (ziperror : 3, ' Too many files ');
        18      : WRITELN (ziperror : 3, ' Could NOT open file ');
        1..90   : WRITELN (ziperror : 3, ' Exec DOS error ');
        98      : WRITELN (ziperror : 3, ' requested file not produced ');
        99      : WRITELN (ziperror : 3, ' archive file not found');
        END;
    END;


PROCEDURE PKZIPInit;
     BEGIN
     PKZIP   := FSearch('PKZIP.EXE',GetEnv('PATH'));
     PKUNZIP := FSearch('PKUNZIP.EXE',GetEnv('PATH'));
     ZIPError          := 0;
     ZIPDefaultZIPOpts := '-n';
     ZIPFileName       := '';
     ZIPDPath          := '';
     EraseCount        := 0;
     EraseSizeK        := 0;
     END;


PROCEDURE ShowEraseStats;
    {-Show statistics at the end of run}
    BEGIN
    WRITELN ('Files Erased: ', EraseCount,
            '  bytes used: ', EraseSizeK DIV 2, 'k');
    END;


FUNCTION  UnZIPFile ( ZIPOpts, ZIPName, DPath, fspec : STRING; qt : BOOLEAN) : BOOLEAN;
VAR s, zname     : STRING;
    i, j         : INTEGER;
    BEGIN
    ZIPError       := 0;
    UnZIPFile := TRUE;
    s := '';
    IF ZIPOpts <> '' THEN  s := s + ZIPOpts
    ELSE                   s := s + ZIPDefaultZIPOpts;

    IF ZIPName <> '' THEN  zname := ZIPName
    ELSE                   zname := ZIPFileName;
    IF NOT FileExists (zname) THEN
        BEGIN
        WRITELN ('zname: [', zname, ']');
        UnZIPFile := FALSE;
        ZIPError := 99;
        EXIT;
        END;

    s := s + ' ' + zname;

    IF DPath <> '' THEN s := s + ' ' + DPath
    ELSE                   s := s + ' ' + ZIPDPath;
    s := s + ' ' + fspec;
    ZIPError := ExecuteCommand (PKUNZIP,s,qt);
    IF ZIPError > 0 THEN
         BEGIN
         WRITELN ('PKUNZIP start failed ', ZIPError, ' [', s, ']');
         UnZIPFile := FALSE;
         END
    ELSE BEGIN
         i := POS ('*', fspec);
         j := POS ('?', fspec);
         IF (i = 0) AND (j = 0) THEN
             BEGIN
             IF NOT FileExists (DPath + fspec) THEN
                  BEGIN
                  UnZIPFile := FALSE;
                  ZIPError := 98;
                  END;
             END;
         END;
    END;

FUNCTION  ZIPFile ( ZIPOpts, ZIPName, fspec  : STRING; qt : BOOLEAN) : BOOLEAN;
VAR s, zname     : STRING;
    i, j         : INTEGER;
    BEGIN
    ZIPError       := 0;
    ZIPFile := TRUE;
    s  := '';
    IF ZIPOpts <> '' THEN  s := s + ZIPOpts
    ELSE                   s := s + ZIPDefaultZIPOpts;

    IF ZIPName <> '' THEN  zname := ZIPName
    ELSE                   zname := ZIPFileName;
    s := s + ' ' + zname;
    s := s + ' ' + fspec;
    ZIPError := ExecuteCommand (PKZIP,s,qt);
    IF ZIPError > 0 THEN
         BEGIN
         WRITELN ('PKZIP start failed ', ZIPError, ' [', s, ']');
         ZIPFile := FALSE;
         END
    ELSE BEGIN
         IF NOT FileExists (ZIPname + '.ZIP') THEN
              BEGIN
              ZIPFile := FALSE;
              ZIPError := 98;
              END;
         END;
    END;


     BEGIN
     PKZIPInit;
     END.
