home *** CD-ROM | disk | FTP | other *** search
- PRODUCT : TURBO PASCAL NUMBER : 229
- VERSION : ALL
- OS : PC-DOS, MS-DOS
- DATE : August 1, 1986
-
- 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.
-
- 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
- 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;
- 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);
- FCB1Pr:=Addr(FCB1);
- FCB2Pr:=Addr(FCB2);
- End;
-
- InLine($8D/$96/ PathName /$42/ { <DX>:=Ofs(PathName[1]); }
- $8D/$9E/ ParmTable / { <BX>:=Ofs(ParmTable); }
- $B8/$00/$4B/ { <AX>:=$4B00; }
- $1E/$55/ { Save <DS>, <BP> }
- $16/$1F/ { <DS>:=Seg(PathName[1]); }
- $16/$07/ { <ES>:=Seg(ParmTable); }
- $2E/$8C/$16/ SSSave / { Save <SS> in SSSave }
- $2E/$89/$26/ SPSave / { Save <SP> in SPSave }
- $FA/ { Disable interrupts }
- $CD/$21/ { Call MS-DOS }
- $FA/ { Disable interrupts }
- $2E/$8B/$26/ SPSave / { Restore <SP> }
- $2E/$8E/$16/ SSSave / { Restore <SS> }
- $FB/ { Enable interrupts }
- $5D/$1F/ { Restore <BP>,<DS> }
- $9C/$8F/$86/ RegsFlags / { Flags:=<CPU flags> }
- $89/$86/ Regs ); { Regs.AX:=<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;
- 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.
-