Apply the following patch to dosexec.c:
*** src/libc/dos/process/dosexec.c~2 Sat Apr 27 21:19:44 1996
--- src/libc/dos/process/dosexec.c Wed Jul 10 21:46:10 1996
***************
*** 13,18 ****
--- 13,19 ----
#include <libc/dosexec.h>
#include <libc/unconst.h>
#include <libc/dosio.h>
+ #include <libc/farptrgs.h>
extern char **environ;
*************** static int direct_exec_tail(const char *
*** 53,61 ****
--- 54,64 ----
const char *progname;
unsigned proglen;
int i;
+ unsigned long fcb1_la, fcb2_la, fname_la;
sync();
+ /* The pathname of the executable to run. */
proglen = strlen(program)+1;
if(_USE_LFN) {
dosmemput(program, proglen, tbuf);
*************** static int direct_exec_tail(const char *
*** 80,111 ****
parm_la = talloc(sizeof(Execp));
dosmemput(progname, proglen, program_la);
!
arg_header[0] = strlen(args);
arg_header[1] = '
';
dosmemput(arg_header, 1, arg_la);
dosmemput(args, strlen(args), arg_la+1);
dosmemput(arg_header+1, 1, arg_la+1+strlen(args));
do {
env_la = talloc(1);
} while (env_la & 15);
talloc(-1);
for (i=0; envp[i]; i++)
{
env_e_la = talloc(strlen(envp[i])+1);
dosmemput(envp[i], strlen(envp[i])+1, env_e_la);
}
arg_header[0] = 0;
! arg_header[1] = 1;
arg_header[2] = 0;
dosmemput(arg_header, 3, talloc(3));
env_e_la = talloc(proglen);
dosmemput(progname, proglen, env_e_la);
! parm.eseg = env_la / 16;
! parm.argseg = arg_la / 16;
! parm.argoff = arg_la & 15;
dosmemput(&parm, sizeof(parm), parm_la);
r.x.ax = 0x4b00;
--- 83,159 ----
parm_la = talloc(sizeof(Execp));
dosmemput(progname, proglen, program_la);
!
! /* The command-line tail. */
arg_header[0] = strlen(args);
arg_header[1] = '
';
dosmemput(arg_header, 1, arg_la);
dosmemput(args, strlen(args), arg_la+1);
dosmemput(arg_header+1, 1, arg_la+1+strlen(args));
+ /* The 2 FCBs. Some programs (like XCOPY from DOS 6.x) need them. */
+ fcb1_la = talloc(16); /* allocate space for 1st FCB */
+ fname_la = arg_la + 1; /* first character of command tail */
+ r.x.ax = 0x2901; /* AL = 1 means skip leading separators */
+ r.x.ds = fname_la / 16; /* pointer to 1st cmd argument */
+ r.x.si = fname_la & 15;
+ r.x.es = fcb1_la / 16; /* pointer to FCB buffer */
+ r.x.di = fcb1_la & 15;
+ __dpmi_int (0x21, &r);
+
+ /* We cannot be sure that Int 21h/AX=2901h parsed the entire
+ first command-line argument (it might not be a filename
+ at all!). We need to get to the next command-line arg
+ before calling 2901 again. 2901 returns the pointer to
+ first unparsed character in DS:SI.
+
+ Note that, in case there is no second command-line argument,
+ the following loop is terminated by the trailing CR which
+ ends the command-line tail. */
+ for (_farsetsel(_dos_ds), fname_la = ((unsigned)r.x.ds) * 16 + r.x.si;
+ !isspace(_farnspeekb(fname_la));
+ fname_la++)
+ ;
+
+ fcb2_la = talloc(16);
+ r.x.ax = 0x2901;
+ r.x.ds = fname_la / 16; /* begin parsing 2nd arg from here */
+ r.x.si = fname_la & 15;
+ r.x.es = fcb2_la / 16;
+ r.x.di = fcb2_la & 15;
+ __dpmi_int (0x21, &r);
+
+ /* The environment must be on a segment boundary, so get
+ to the first location in the transfer buffer whose
+ linear address is divisable by 16. */
do {
env_la = talloc(1);
} while (env_la & 15);
talloc(-1);
+
+ /* The environment, terminated by an extra NULL char. */
for (i=0; envp[i]; i++)
{
env_e_la = talloc(strlen(envp[i])+1);
dosmemput(envp[i], strlen(envp[i])+1, env_e_la);
}
arg_header[0] = 0;
!
! /* The name of the program that owns the environment. */
! arg_header[1] = 1; /* the number of strings (1, little-endian) */
arg_header[2] = 0;
dosmemput(arg_header, 3, talloc(3));
env_e_la = talloc(proglen);
dosmemput(progname, proglen, env_e_la);
! /* Prepare the parameter block and call Int 21h/AX=4B00h. */
! parm.eseg = env_la / 16;
! parm.argseg = arg_la / 16;
! parm.argoff = arg_la & 15;
! parm.fcb1_seg = fcb1_la / 16;
! parm.fcb1_off = fcb1_la & 15;
! parm.fcb2_seg = fcb2_la / 16;
! parm.fcb2_off = fcb2_la & 15;
dosmemput(&parm, sizeof(parm), parm_la);
r.x.ax = 0x4b00;
Actually, if memory serves, most debuggers and other libraries out
there get this wrong. (Turbo Debugger, Turbo C, and Borland Pascal
are known to get it wrong.)
Just calling the parse function twice is not good enough when the
first file name includes a path character, but just calling twice
is exactly what the above products do. Now, try convincing Borland
that any of their products are buggy, ...
One more thing: note that backslash-newlines in the patch were
mangled by the bug tracking system. You should be able to guess
where.