home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / PROG / PASCAL / MISCTI10.ZIP / TI229.ASC < prev    next >
Encoding:
Text File  |  1989-09-18  |  7.2 KB  |  219 lines

  1.   PRODUCT : TURBO PASCAL     NUMBER : 229
  2. VERSION : ALL
  3.      OS : PC-DOS, MS-DOS
  4.    DATE : August 1, 1986
  5.  
  6.   TITLE : EXECUTE SUBPROCESS CALL
  7.  
  8. The  following example routines are public domain  programs  that 
  9. have  been uploaded to our Forum on CompuServe.  As a courtesy to 
  10. our  users  that  do not have  immediate  access  to  CompuServe, 
  11. Technical Support distributes these routines free of charge.
  12.  
  13. However,  because these routines are public domain programs,  not 
  14. developed by Borland International,  we are unable to provide any 
  15. technical support or assistance using these routines. If you need 
  16. assistance   using   these   routines,    or   are   experiencing 
  17. difficulties,  we  recommend  that you log  onto  CompuServe  and 
  18. request  assistance  from the Forum members that developed  these 
  19. routines.
  20.  
  21. This  program contains two functions that allow you to run  other 
  22. programs from within a Turbo Pascal program.  The first function, 
  23. SubProcess,  actually calls a different program using MS-DOS call 
  24. 4BH,  EXEC.   The second function,  GetComSpec,  returns the path 
  25. name of the command interpreter, which is necessary to do certain 
  26. operations.  There is also a main program that allows you to test 
  27. the functions.
  28.  
  29. }
  30. Program Exec;
  31. Type
  32.   Str66=String[66];
  33.   Str255=String[255];
  34.  
  35. Function SubProcess(CommandLine: Str255): Integer;
  36.   { Pass this function a string of the form
  37.       'D:\FULL\PATH\NAME\OF\FILE.TYP parameter1 parameter2 ...'
  38.  
  39.     For example,
  40.       'C:\SYSTEM\CHKDSK.COM'
  41.       'A:\WS.COM DOCUMENT.1'
  42.       'C:\DOS\LINK.EXE TEST;'
  43.       'C:\COMMAND.COM /C COPY *.* B:\BACKUP >FILESCOP.IED'
  44.  
  45. The  third  example  shows several things.   To do  any  of   the 
  46. following,  you  must invoke the command processor and let it  do 
  47. the work:  redirection; piping; path searching; searching for the 
  48. extension of a program (.COM,  .EXE,  or .BAT);  batch files; and 
  49. internal DOS commands.  The name of the command processor file is 
  50. stored in the DOS environment.   The function GetComSpec in  this 
  51. file  returns the path name of the command processor.  Also  note 
  52. that  you  must  use the /C parameter or COMMAND  will  not  work 
  53. correctly.   You can also call COMMAND with no parameters.   This 
  54. will  allow  the user to use the DOS prompt to run  anything  (as 
  55. long  as there is enough memory).    To get back to your program, 
  56. he can type the command EXIT.
  57.  
  58. Actual example:
  59.   I:=SubProcess(GetComSpec+' /C COPY *.* B:\BACKUP
  60. >FILESCOP.IED');
  61.  
  62. The  value returned is the result returned by DOS after the  EXEC 
  63. call.  The most common values are:
  64.  
  65.      0: Success
  66.      1: Invalid function (should never happen with this routine)
  67.      2: File/path not found
  68.      8: Not enough memory to load program
  69.     10: Bad environment (greater than 32K)
  70.     11: Illegal .EXE file format
  71.  
  72. If  you  get  any  other  result,  consult  an  MS-DOS  Technical 
  73. Reference manual.
  74.  
  75. VERY  IMPORTANT  NOTE:  you MUST use the Options  menu  of  Turbo 
  76. Pascal to restrict the amount of free dynamic memory used by your 
  77. program.   Only  the  memory  that  is not used by  the  heap  is 
  78. available for use by other programs. }
  79.  
  80.   Const
  81.     SSSave: Integer=0;
  82.     SPSave: Integer=0;
  83.  
  84.   Var
  85.     Regs: Record Case Integer Of
  86.             1: (AX,BX,CX,DX,BP,SI,DI,DS,ES,Flags: Integer);
  87.             2: (AL,AH,BL,BH,CL,CH,DL,DH: Byte);
  88.           End;
  89.     FCB1,FCB2: Array [0..36] Of Byte;
  90.     PathName: Str66;
  91.     CommandTail: Str255;
  92.  
  93.     ParmTable: Record
  94.                  EnvSeg: Integer;
  95.                  ComLin: ^Integer;
  96.                  FCB1Pr: ^Integer;
  97.                  FCB2Pr: ^Integer;
  98.                End;
  99.     I,RegsFlags: Integer;
  100.  
  101.   Begin
  102.     If Pos(' ',CommandLine)=0 Then
  103.      Begin
  104.       PathName:=CommandLine+#0;
  105.       CommandTail:=^M;
  106.      End
  107.     Else
  108.      Begin
  109.       PathName:=Copy(CommandLine,1,Pos(' ',CommandLine)-1)+#0;
  110.       CommandTail:=Copy(CommandLine,Pos(' ',CommandLine),255)+^M;
  111.      End;
  112.     CommandTail[0]:=Pred(CommandTail[0]);
  113.     With Regs Do
  114.      Begin
  115.       FillChar(FCB1,Sizeof(FCB1),0);
  116.       AX:=$2901;
  117.       DS:=Seg(CommandTail[1]);
  118.       SI:=Ofs(CommandTail[1]);
  119.       ES:=Seg(FCB1);
  120.       DI:=Ofs(FCB1);
  121.       MsDos(Regs); { Create FCB 1 }
  122.       FillChar(FCB2,Sizeof(FCB2),0);
  123.       AX:=$2901;
  124.       ES:=Seg(FCB2);
  125.       DI:=Ofs(FCB2);
  126.       MsDos(Regs); { Create FCB 2 }
  127.       ES:=CSeg;
  128.       BX:=SSeg-CSeg+MemW[CSeg:MemW[CSeg:$0101]+$112];
  129.       AH:=$4A;
  130.       MsDos(Regs); { Deallocate unused memory }
  131.       With ParmTable Do
  132.        Begin
  133.         EnvSeg:=MemW[CSeg:$002C];
  134.         ComLin:=Addr(CommandTail);
  135.         FCB1Pr:=Addr(FCB1);
  136.         FCB2Pr:=Addr(FCB2);
  137.        End;
  138.  
  139.    InLine($8D/$96/ PathName /$42/  { <DX>:=Ofs(PathName[1]); }
  140.           $8D/$9E/ ParmTable /     { <BX>:=Ofs(ParmTable);   }
  141.           $B8/$00/$4B/             { <AX>:=$4B00;            }
  142.           $1E/$55/                 { Save <DS>, <BP>         }
  143.           $16/$1F/                 { <DS>:=Seg(PathName[1]); }
  144.           $16/$07/                 { <ES>:=Seg(ParmTable);   }
  145.           $2E/$8C/$16/ SSSave /    { Save <SS> in SSSave     }
  146.           $2E/$89/$26/ SPSave /    { Save <SP> in SPSave     }
  147.           $FA/                     { Disable interrupts      }
  148.           $CD/$21/                 { Call MS-DOS             }
  149.           $FA/                     { Disable interrupts      }
  150.           $2E/$8B/$26/ SPSave /    { Restore <SP>            }
  151.           $2E/$8E/$16/ SSSave /    { Restore <SS>            }
  152.           $FB/                     { Enable interrupts       }
  153.           $5D/$1F/                 { Restore <BP>,<DS>       }
  154.           $9C/$8F/$86/ RegsFlags / { Flags:=<CPU flags>      }
  155.           $89/$86/ Regs );         { Regs.AX:=<AX>;          }
  156.  
  157.     {  The  manipulation  of  SS  and  SP  is  necessary  because        
  158.        under  DOS 2.x,  after returning from an  EXEC  call,  ALL             
  159.        registers  are  destroyed except CS and IP!   }
  160.  
  161.       If (RegsFlags And 1)<>0 Then SubProcess:=AX
  162.       Else SubProcess:=0;
  163.      End;
  164.   End;
  165.  
  166. Function GetComSpec: Str66;
  167.   Type
  168.     Env=Array [0..32767] Of Char;
  169.   Var
  170.     EPtr: ^Env;
  171.     EStr: Str255;
  172.     Done: Boolean;
  173.     I: Integer;
  174.  
  175.   Begin
  176.     EPtr:=Ptr(MemW[CSeg:$002C],0);
  177.     I:=0;
  178.     Done:=False;
  179.     EStr:='';
  180.     Repeat
  181.       If EPtr^[I]=#0 Then
  182.        Begin
  183.         If EPtr^[I+1]=#0 Then Done:=True;
  184.         If Copy(EStr,1,8)='COMSPEC=' Then
  185.          Begin
  186.           GetComSpec:=Copy(EStr,9,100);
  187.           Done:=True;
  188.          End;
  189.         EStr:='';
  190.        End
  191.       Else EStr:=EStr+EPtr^[I];
  192.       I:=I+1;
  193.     Until Done;
  194.   End;
  195.  
  196. {  Example  program.   Set both mInimum and mAximum free  dynamic 
  197.    memory  to 100 and compile this to a .COM  file.   Delete  the 
  198.    next line to enable: }
  199.  
  200. Var Command: Str255;
  201.     I: Integer;
  202.  
  203. Begin
  204.   Write('Enter a * to quit; put a * before a ');
  205.   Writeln('command to use COMMAND.COM.');
  206.   Repeat
  207.     Write('=->');
  208.     ReadLn(Command);
  209.     If Command='*' Then Halt;
  210.     If Command<>'' Then
  211.      Begin
  212.       If Command[1]='*' Then 
  213.          Command:=GetComSpec+' /C '+Copy(Command,2,255);
  214.       I:=SubProcess(Command);
  215.       If I<>0 Then WriteLn('Error - ',I);
  216.      End;
  217.   Until False;
  218. End.
  219.