[comp.sys.ibm.pc] Turbo source for fork

dalem@hpfcph.UUCP (02/12/87)

Does anyone have a Turbo Pascal procedure/function that will execute an
arbitrary MSDOS command (chkdsk, format, command, or any executable file)?
If it's small, perhaps you could post it.  If not, please email me.  Thanks.

						Dale McCluskey

						{hplabs,ihnp4}!hpfcla!dalem

jjc@sdiris1.UUCP (02/15/87)

In article <3540009@hpfcph.HP.COM>, dalem@hpfcph.HP.COM ( Dale McCluskey) writes:
> Does anyone have a Turbo Pascal procedure/function that will execute an
> arbitrary MSDOS command (chkdsk, format, command, or any executable file)?
> If it's small, perhaps you could post it.  If not, please email me.  Thanks.

Please Post, I would like a copy too.

-----------------------------------------------------------------------
UUCP: ...!sdcsvax!jack!man!sdiris1!jim |  Jim Carter 
Work : +1 619 450 6516                 |  Control Data Corporation (CIM)
Home : +1 619 455 0607                 |  4455 Eastgate Mall, 
                                       |  San Diego, CA  92121

dragheb@isis.UUCP (02/16/87)

In article <540@sdiris1.UUCP> jjc@sdiris1.UUCP (Jim Carter) writes:
>In article <3540009@hpfcph.HP.COM>, dalem@hpfcph.HP.COM ( Dale McCluskey) writes:
>> Does anyone have a Turbo Pascal procedure/function that will execute an
>> arbitrary MSDOS command (chkdsk, format, command, or any executable file)?
>> If it's small, perhaps you could post it.  If not, please email me.  Thanks.
>

I know that Blaise Power Tools (a set of C-like tools for Turbo Pascal)
have two types of spawns: one for loading COMMAND.COM with the /C option
and one just to exec another program.  These tools sell for around $95.00
and for the exec include a special assembly file.  The best
way to do this is to write one's own assembly procedure....I am
working on this and am having trouble linking it into
Turbo,....if I get it figured out, I will post it (it almost works
100% of the time on its own, but Turbo is sort of wierd :-)




-- 
Do it in C.  If you can't do it in C, do it in Assembly. 
If you can't  do it in Assembly, it is not worth doing!!

Darius Ragheb    isis!dragheb  |  dragheb@isis.cs.du.edu

madd@bucsb.bu.edu.UUCP (02/25/87)

In article <3540009@hpfcph.HP.COM>, dalem@hpfcph.HP.COM ( Dale McCluskey) writes:
> Does anyone have a Turbo Pascal procedure/function that will execute an
> arbitrary MSDOS command (chkdsk, format, command, or any executable file)?
> If it's small, perhaps you could post it.  If not, please email me.  Thanks.

Following this posting is a quick exec() that I wrote.  I am not sure if
it will work as is, because I don't have a Turbo compiler over here, and
I rewrote this online.  If it doesn't work, it'll probably be something
really simple (like missing ';' or something).  I think that the basic
structure is all right.  I basically created it from the DOS Tech Ref
manual's description of the function call.  Note the "note" within the
program.  I could not determine from the description in the book whether
DOS wants a string-length byte or an ASCIIZ string for the parameters
string, so I gave code for both.  I am pretty sure it's the one that
is outside of the comments, however.

Make sure you pay attention to the "things to remember".  I had a few
problems getting the first one of these that I made to run, so you should
profit from my experiences so you won't spend all night tearing your hair
out.

Happy hacking!

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
                   - Jim Frost * The Madd Hacker -
UUCP:  ..!harvard!bu-cs!bucsb!madd | ARPANET: madd@bucsb.bu.edu
CSNET: madd%bucsb@bu-cs            | BITNET:  cscc71c@bostonu
-------------------------------+---+------------------------------------
"Oh beer, oh beer." -- Me      |      [=(BEER) <- Bud the Beer (cheers!)

-- slice here --

{ exec.inc:

  This function allows a Turbo Pascal program to execute another
  program from within it.  Call it as follows:

    errcode:= exec(prgname,parameters);

  Things to remember:
    * you MUST set the Turbo Pascal compile option mAximum memory to
      some smaller value, in order to allow DOS to use some memory to
      execute programs.  Otherwise, you need to use the DOS setblock
      command to free up memory blocks, which is a pain and very
      delicate.
    * you MUST provide the complete pathname AND EXTENSION of the program
      to invoke.
    * Some possible return codes:
        0 = executed ok
        1 = invalid function (this function blew up)
        2 = file not found (couldn't find program to load -- maybe forgot
            extension [.COM or .EXE] or had an incorrect/missing path)
        3 = path not found
        8 = insufficient memory (program too big, or you forgot to compile
            with mAx memory set to some smaller value than the default)
        10 = invalid environment (environ pointer screwed up)
      Other return codes are possible, but I think these are the one's
      you might have problems with.  Usually I use a case statement like
      follows:
          case exec("myprog.com","parm1 parm2 ...") of
            0 : ; { no error }
              ...
          end;

  Function written by Jim Frost.
}

type str255 = string[255];

function exec(prgname, prgparms : str255) : integer;
type registers = record
                  ax,bx,cx,dx,bp,si,di,ds,es,flags : integer
                end;
     parmblock = record
                   envseg, { environment segment }
                   prgseg, { pointer to command line }
                   prgofs,
                   fcb1seg, { pointers to default fcb blocks }
                   fcb1ofs,
                   fcb2seg,
                   fcb2seg : integer
                 end;
var r : register;  { registers to pass to DOS }
    p : parmblock; { parameter block needed }
begin
  prgname:= prgname+chr(0);      { add a NULL to program name (ASCIIZ string) }
  p.envseg:= memw[cseg : $002c]; { use parent's environment }

(* note: I can't remember whether it wants a ASCIIZ string or a string w/
   length.  The Tech Ref manual says that the PSP pointer uses a length-
   of-string byte, so I think you use the default one.  If the line I set
   up doesn't seem to work right, use this:

     prgparms:= prgparms+chr(0);  { make ASCIIZ string }
     p.prgseg:= seg(prgparms[1]); { get pointer to command line parameters }
     p.prgofs:= ofs(prgparms[1]);
*)
  p.prgseg:= seg(prgparms);      { pointer to the command line parameters }
  p.prgofs:= ofs(prgparms);
(* end of note *)

  p.fcb1seg:= cseg;              { just pass the parent's fcb's }
  p.fcb1ofs:= $5c;
  p.fcb2seg:= cseg;
  p.fcb2seg:= $6c;
  r.ax:= $4b00;                  { AH= 4BH, AL= 00H; load and execute }
  r.ds:= seg(prgname[1]);        { pointer to program name }
  r.dx:= ofs(prgname[1]);
  r.es:= seg(p);                 { pointer to parameter block }
  r.bx:= ofs(p);
  msdos(r);
  if (r.flags and 1)=1 then { carry bit set on return }
    exec:= lo(r.ax)         { set error code for return }
  else
    exec:= 0                { no error }
end;