Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!utgpu!water!watnot!watmath!clyde!rutgers!husc6!bu-cs!bucsb.bu.edu!madd From: madd@bucsb.bu.edu.UUCP Newsgroups: comp.sys.ibm.pc Subject: Re: Turbo source for fork()/exec()? Message-ID: <769@bucsb.bu.edu.UUCP> Date: Tue, 24-Feb-87 19:17:41 EST Article-I.D.: bucsb.769 Posted: Tue Feb 24 19:17:41 1987 Date-Received: Fri, 27-Feb-87 05:44:21 EST References: <3540009@hpfcph.HP.COM> <540@sdiris1.UUCP> Reply-To: madd@bucsb.bu.edu.UUCP (Jim "Jack" Frost) Organization: ODO (Organization for the Disorganization of Organization) Lines: 116 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;