home *** CD-ROM | disk | FTP | other *** search
- {$V-}
- { This procedure allows a Turbo Pascal program to execute any DOS
- command string. COMMAND.COM does the work of looking for command extentions,
- (.COM, .EXE, or .BAT), internal commands, piping, redirection, etc.
-
- Commands can be .BAT files, DOS commands or any other compiled programs,
- but the DOS SET, PROMPT, and PATH commands cannot be used.
-
- Written by:
- Bill Mayne
- 9707 Lawndale Dr.
- Silver Spring, MD 20901
-
- Based on work by:
- Bela Lubkin
- Borland International Technical Support
-
- This version differs from Lubkin's in that:
-
- (1) It always uses COMMAND.COM. Consequently, the code is a bit simpler
- and it is easier to use, though not quite as efficient in some cases.
- It does not allow you to over-ride or by-pass the normal path search.
- (In exceptional cases that might be disadvantage, normally it is what you
- want.) The both the source and object code are somewhat smaller.
-
- (2) The FCBs passed to the subprocess contain blanks for the filename.ext
- rather than the name of the command. (It works anyway. I don't know the
- purpose of these FCBs. It shortens the code some to do it this way.)
-
- (3) The search of the pathname of COMMAND.COM in the environment string is not
- simplified, saving some storage.
-
- (4) It is changed to a procedure instead of a function, but it would be
- easy to change it back if you prefer a function.
-
- The value returned in RC is the value returned by DOS after the DOS call.
- See a DOS technical reference manual for more information on it.
- Suffice it to say that anything nonzero means something went wrong.
-
- 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.
- A very simple program needs about $40 paragraphs (1K bytes). A minimum of
- $100 (4K) is suggested. Some programs may obviously need more. }
-
- type
- ShellStr=string[127];
- { This is the only definition (except the procedure itself) known to
- the outside program, and the only one needed by the procedure.
- This level of independence is desirable for "toolbox" include files
- which may be used in many different programs. }
-
- procedure Shell(CommandLine: ShellStr;var rc:integer);
-
- Type
- Env=Array [0..32767] Of Char;
- Var
- EPtr: ^Env;
- I: Integer;
- 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: String[66];
- CommandTail: String[135];
- ParmTable: Record
- EnvSeg: Integer;
- ComLin: ^Integer;
- FCB1Pr: ^Integer;
- FCB2Pr: ^Integer;
- End;
- Begin
- PathName:=PathName+#0;
-
- With Regs Do
- Begin
- {Create FCBs for EXEC call}
- FillChar(FCB1,Sizeof(FCB1),0);
- FillChar(FCB1[2],11,ord(' ')); {blank filename.ext}
- FillChar(FCB2,Sizeof(FCB2),0);
- FillChar(FCB2[2],11,ord(' ')); {blank filename.ext}
- (* May not need this -
- {Deallocate unused memory}
- ES:=CSeg;
- BX:=SSeg-CSeg+MemW[CSeg:MemW[CSeg:$0101]+$112];
- AH:=$4A;
- MsDos(Regs);
- *)
- {Scan the env and set DS:DX ==> pathname of COMMAND.COM}
- DS:=MemW[CSeg:$002C];
- DX:=0;
- PathName[0]:=chr(8);
- move(Mem[DS:0],PathName[1],8);
- while PathName<>'COMSPEC=' do
- begin
- repeat
- DX:=DX+1;
- until Mem[DS:DX]=0;
- DX:=DX+1;
- move(Mem[DS:DX],Pathname[1],8);
- end;
- DX:=DX+8;
-
- {Now comes the EXEC (DOS function $4B) call}
- CommandTail:=' /C '+CommandLine+^M;
- CommandTail[0]:=Pred(CommandTail[0]);
- With ParmTable Do
- Begin
- EnvSeg:=MemW[CSeg:$002C];
- ComLin:=Addr(CommandTail);
- FCB1Pr:=Addr(FCB1);
- FCB2Pr:=Addr(FCB2);
- End;
- ES:=Seg(ParmTable);
- BX:=Ofs(ParmTable);
- AX:=$4B00;
- MsDos(Regs); { Call subprocess }
-
- {Pass the return code back to the caller}
- If (Flags And 1)<>0 Then rc:=AX
- Else rc:=0;
- End;
- End;