Category : Pascal Source Code
Archive   : PASS_ALL.ZIP
Filename : TI229.ASC

 
Output of file : TI229.ASC contained in archive : PASS_ALL.ZIP









PRODUCT : TURBO PASCAL NUMBER : 229
VERSION : ALL
OS : PC-DOS, MS-DOS
DATE : August 1, 1986 PAGE : 1/5
TITLE : EXECUTE SUBPROCESS CALL




The following example routines are public domain programs that
have been uploaded to our Forum on CompuServe. As a courtesy to
our users that do not have immediate access to CompuServe,
Technical Support distributes these routines free of charge.

However, because these routines are public domain programs, not
developed by Borland International, we are unable to provide any
technical support or assistance using these routines. If you need
assistance using these routines, or are experiencing
difficulties, we recommend that you log onto CompuServe and
request assistance from the Forum members that developed these
routines.

{ EXEC.PAS version 1.3

This program contains two functions that allow you to run other
programs from within a Turbo Pascal program. The first function,
SubProcess, actually calls a different program using MS-DOS call
4BH, EXEC. The second function, GetComSpec, returns the path name
of the command interpreter, which is necessary to do certain
operations. There is also a main program that allows you to test
the functions.

}
Program Exec;
Type
Str66=String[66];
Str255=String[255];

Function SubProcess(CommandLine: Str255): Integer;
{ Pass this function a string of the form
'D:\FULL\PATH\NAME\OF\FILE.TYP parameter1 parameter2 ...'

For example,
'C:\SYSTEM\CHKDSK.COM'
'A:\WS.COM DOCUMENT.1'
'C:\DOS\LINK.EXE TEST;'
'C:\COMMAND.COM /C COPY *.* B:\BACKUP >FILESCOP.IED'


The third example shows several things. To do any of the
following, you must invoke the command processor and let it do
the work: redirection; piping; path searching; searching for the














PRODUCT : TURBO PASCAL NUMBER : 229
VERSION : ALL
OS : PC-DOS, MS-DOS
DATE : August 1, 1986 PAGE : 2/5
TITLE : EXECUTE SUBPROCESS CALL




extension of a program (.COM, .EXE, or .BAT); batch files; and
internal DOS commands. The name of the command processor file is
stored in the DOS environment. The function GetComSpec in this
file returns the path name of the command processor. Also note
that you must use the /C parameter or COMMAND will not work
correctly. You can also call COMMAND with no parameters. This
will allow the user to use the DOS prompt to run anything (as
long as there is enough memory). To get back to your program, he
can type the command EXIT.

Actual example:
I:=SubProcess(GetComSpec+' /C COPY *.* B:\BACKUP
>FILESCOP.IED');

The value returned is the result returned by DOS after the EXEC
call. The most common values are:

0: Success
1: Invalid function (should never happen with this routine)
2: File/path not found
8: Not enough memory to load program
10: Bad environment (greater than 32K)
11: Illegal .EXE file format

If you get any other result, consult an MS-DOS Technical
Reference manual.

VERY IMPORTANT NOTE: you MUST use the Options menu of Turbo
Pascal to restrict the amount of free dynamic memory used by your
program. Only the memory that is not used by the heap is
available for use by other programs. }

Const
SSSave: Integer=0;
SPSave: Integer=0;

Var
Regs: Record Case Integer Of
1: (AX,BX,CX,DX,BP,SI,DI,DS,ES,Flags: Integer);
2: (AL,AH,BL,BH,CL,CH,DL,DH: Byte);
End;
FCB1,FCB2: Array [0..36] Of Byte;
PathName: Str66;














PRODUCT : TURBO PASCAL NUMBER : 229
VERSION : ALL
OS : PC-DOS, MS-DOS
DATE : August 1, 1986 PAGE : 3/5
TITLE : EXECUTE SUBPROCESS CALL




CommandTail: Str255;
ParmTable: Record
EnvSeg: Integer;
ComLin: ^Integer;
FCB1Pr: ^Integer;
FCB2Pr: ^Integer;
End;
I,RegsFlags: Integer;

Begin
If Pos(' ',CommandLine)=0 Then
Begin
PathName:=CommandLine+#0;
CommandTail:=^M;
End
Else
Begin
PathName:=Copy(CommandLine,1,Pos(' ',CommandLine)-1)+#0;
CommandTail:=Copy(CommandLine,Pos(' ',CommandLine),255)+^M;
End;
CommandTail[0]:=Pred(CommandTail[0]);
With Regs Do
Begin
FillChar(FCB1,Sizeof(FCB1),0);
AX:=$2901;
DS:=Seg(CommandTail[1]);
SI:=Ofs(CommandTail[1]);
ES:=Seg(FCB1);
DI:=Ofs(FCB1);
MsDos(Regs); { Create FCB 1 }
FillChar(FCB2,Sizeof(FCB2),0);
AX:=$2901;
ES:=Seg(FCB2);
DI:=Ofs(FCB2);
MsDos(Regs); { Create FCB 2 }
ES:=CSeg;
BX:=SSeg-CSeg+MemW[CSeg:MemW[CSeg:$0101]+$112];
AH:=$4A;
MsDos(Regs); { Deallocate unused memory }
With ParmTable Do
Begin
EnvSeg:=MemW[CSeg:$002C];
ComLin:=Addr(CommandTail);














PRODUCT : TURBO PASCAL NUMBER : 229
VERSION : ALL
OS : PC-DOS, MS-DOS
DATE : August 1, 1986 PAGE : 4/5
TITLE : EXECUTE SUBPROCESS CALL




FCB1Pr:=Addr(FCB1);
FCB2Pr:=Addr(FCB2);
End;

InLine($8D/$96/ PathName /$42/ { :=Ofs(PathName[1]); }
$8D/$9E/ ParmTable / { :=Ofs(ParmTable); }
$B8/$00/$4B/ { :=$4B00; }
$1E/$55/ { Save , }
$16/$1F/ { :=Seg(PathName[1]); }
$16/$07/ { :=Seg(ParmTable); }
$2E/$8C/$16/ SSSave / { Save in SSSave }
$2E/$89/$26/ SPSave / { Save in SPSave }
$FA/ { Disable interrupts }
$CD/$21/ { Call MS-DOS }
$FA/ { Disable interrupts }
$2E/$8B/$26/ SPSave / { Restore }
$2E/$8E/$16/ SSSave / { Restore }
$FB/ { Enable interrupts }
$5D/$1F/ { Restore , }
$9C/$8F/$86/ RegsFlags / { Flags:= }
$89/$86/ Regs ); { Regs.AX:=; }

{ The manipulation of SS and SP is necessary because under DOS
2.x, after returning from an EXEC call, ALL registers are
destroyed except CS and IP! }

If (RegsFlags And 1)<>0 Then SubProcess:=AX
Else SubProcess:=0;
End;
End;

Function GetComSpec: Str66;
Type
Env=Array [0..32767] Of Char;
Var
EPtr: ^Env;
EStr: Str255;
Done: Boolean;
I: Integer;

Begin
EPtr:=Ptr(MemW[CSeg:$002C],0);
I:=0;














PRODUCT : TURBO PASCAL NUMBER : 229
VERSION : ALL
OS : PC-DOS, MS-DOS
DATE : August 1, 1986 PAGE : 5/5
TITLE : EXECUTE SUBPROCESS CALL




Done:=False;
EStr:='';
Repeat
If EPtr^[I]=#0 Then
Begin
If EPtr^[I+1]=#0 Then Done:=True;
If Copy(EStr,1,8)='COMSPEC=' Then
Begin
GetComSpec:=Copy(EStr,9,100);
Done:=True;
End;
EStr:='';
End
Else EStr:=EStr+EPtr^[I];
I:=I+1;
Until Done;
End;

{ Example program. Set both mInimum and mAximum free dynamic
memory to 100 and compile this to a .COM file. Delete the next
line to enable: }

Var Command: Str255;
I: Integer;

Begin
Write('Enter a * to quit; put a * before a ');
Writeln('command to use COMMAND.COM.');
Repeat
Write('=->');
ReadLn(Command);
If Command='*' Then Halt;
If Command<>'' Then
Begin
If Command[1]='*' Then
Command:=GetComSpec+' /C '+Copy(Command,2,255);
I:=SubProcess(Command);
If I<>0 Then WriteLn('Error - ',I);
End;
Until False;
End.