* spawn.cc (spawn_guts): Reorganize slightly so that 16 bit check is done prior

to check for command.com/cmd.com.  Don't bother setting CREATE_SUSPENDED flag
for a MS-DOS process since it doesn't work anyway.  Avoid calling remember()
when the child process has already exited.
(av::fixup): Explicitly set cygexec flag to falseon a 16 bit process.
This commit is contained in:
Christopher Faylor 2006-01-10 02:39:22 +00:00
parent e93a726084
commit 5da5f949d8
2 changed files with 94 additions and 80 deletions

View File

@ -1,3 +1,12 @@
2006-01-09 Christopher Faylor <cgf@timesys.com>
* spawn.cc (spawn_guts): Reorganize slightly so that 16 bit check is
done prior to check for command.com/cmd.com. Don't bother setting
CREATE_SUSPENDED flag for a MS-DOS process since it doesn't work
anyway. Avoid calling remember() when the child process has already
exited.
(av::fixup): Explicitly set cygexec flag to falseon a 16 bit process.
2006-01-09 Corinna Vinschen <corinna@vinschen.de> 2006-01-09 Corinna Vinschen <corinna@vinschen.de>
* include/getopt.h (getopt_long_only): Declare. * include/getopt.h (getopt_long_only): Declare.

View File

@ -426,6 +426,7 @@ spawn_guts (const char * prog_arg, const char *const *argv,
linebuf one_line; linebuf one_line;
child_info_spawn ch; child_info_spawn ch;
char *envblock;
path_conv real_path; path_conv real_path;
bool reset_sendsig = false; bool reset_sendsig = false;
@ -461,6 +462,21 @@ spawn_guts (const char * prog_arg, const char *const *argv,
newargv.set (ac, argv); newargv.set (ac, argv);
int err;
const char *ext;
if ((ext = perhaps_suffix (prog_arg, real_path, err)) == NULL)
{
set_errno (err);
res = -1;
goto out;
}
bool wascygexec = real_path.iscygexec ();
res = newargv.fixup (chtype, prog_arg, real_path, ext);
if (res)
goto out;
if (ac == 3 && argv[1][0] == '/' && argv[1][1] == 'c' && if (ac == 3 && argv[1][0] == '/' && argv[1][1] == 'c' &&
(iscmd (argv[0], "command.com") || iscmd (argv[0], "cmd.exe"))) (iscmd (argv[0], "command.com") || iscmd (argv[0], "cmd.exe")))
{ {
@ -477,98 +493,83 @@ spawn_guts (const char * prog_arg, const char *const *argv,
one_line.add (argv[2]); one_line.add (argv[2]);
strcpy (real_path, argv[0]); strcpy (real_path, argv[0]);
null_app_name = true; null_app_name = true;
goto skip_arg_parsing;
} }
int err;
const char *ext;
if ((ext = perhaps_suffix (prog_arg, real_path, err)) == NULL)
{
set_errno (err);
res = -1;
goto out;
}
bool wascygexec = real_path.iscygexec ();
res = newargv.fixup (chtype, prog_arg, real_path, ext);
if (res)
goto out;
if (wascygexec)
newargv.dup_all ();
else else
{ {
for (int i = 0; i < newargv.argc; i++) if (wascygexec)
newargv.dup_all ();
else
{ {
char *p = NULL; for (int i = 0; i < newargv.argc; i++)
const char *a;
newargv.dup_maybe (i);
a = i ? newargv[i] : (char *) real_path;
int len = strlen (a);
if (len != 0 && !strpbrk (a, " \t\n\r\""))
one_line.add (a, len);
else
{ {
one_line.add ("\"", 1); char *p = NULL;
/* Handle embedded special characters " and \. const char *a;
A " is always preceded by a \.
A \ is not special unless it precedes a ". If it does, newargv.dup_maybe (i);
then all preceding \'s must be doubled to avoid having a = i ? newargv[i] : (char *) real_path;
the Windows command line parser interpret the \ as quoting int len = strlen (a);
the ". This rule applies to a string of \'s before the end if (len != 0 && !strpbrk (a, " \t\n\r\""))
of the string, since cygwin/windows uses a " to delimit the one_line.add (a, len);
argument. */ else
for (; (p = strpbrk (a, "\"\\")); a = ++p)
{ {
one_line.add (a, p - a); one_line.add ("\"", 1);
/* Find length of string of backslashes */ /* Handle embedded special characters " and \.
int n = strspn (p, "\\"); A " is always preceded by a \.
if (!n) A \ is not special unless it precedes a ". If it does,
one_line.add ("\\\"", 2); /* No backslashes, so it must be a ". then all preceding \'s must be doubled to avoid having
The " has to be protected with a backslash. */ the Windows command line parser interpret the \ as quoting
else the ". This rule applies to a string of \'s before the end
of the string, since cygwin/windows uses a " to delimit the
argument. */
for (; (p = strpbrk (a, "\"\\")); a = ++p)
{ {
one_line.add (p, n); /* Add the run of backslashes */ one_line.add (a, p - a);
/* Need to double up all of the preceding /* Find length of string of backslashes */
backslashes if they precede a quote or EOS. */ int n = strspn (p, "\\");
if (!p[n] || p[n] == '"') if (!n)
one_line.add (p, n); one_line.add ("\\\"", 2); /* No backslashes, so it must be a ".
p += n - 1; /* Point to last backslash */ The " has to be protected with a backslash. */
else
{
one_line.add (p, n); /* Add the run of backslashes */
/* Need to double up all of the preceding
backslashes if they precede a quote or EOS. */
if (!p[n] || p[n] == '"')
one_line.add (p, n);
p += n - 1; /* Point to last backslash */
}
} }
if (*a)
one_line.add (a);
one_line.add ("\"", 1);
} }
if (*a) one_line.add (" ", 1);
one_line.add (a); }
one_line.add ("\"", 1);
one_line.finish (real_path.iscygexec ());
if (one_line.ix >= MAXWINCMDLEN)
{
debug_printf ("Command line too long (>32K), return E2BIG");
set_errno (E2BIG);
res = -1;
goto out;
} }
one_line.add (" ", 1);
} }
one_line.finish (real_path.iscygexec ()); newargv.all_calloced ();
moreinfo->argc = newargv.argc;
moreinfo->argv = newargv;
if (one_line.ix >= MAXWINCMDLEN) if (mode != _P_OVERLAY ||
{ !DuplicateHandle (hMainProc, myself.shared_handle (), hMainProc,
debug_printf ("Command line too long (>32K), return E2BIG"); &moreinfo->myself_pinfo, 0,
set_errno (E2BIG); TRUE, DUPLICATE_SAME_ACCESS))
res = -1; moreinfo->myself_pinfo = NULL;
goto out; else
} VerifyHandle (moreinfo->myself_pinfo);
} }
char *envblock;
newargv.all_calloced ();
moreinfo->argc = newargv.argc;
moreinfo->argv = newargv;
if (mode != _P_OVERLAY ||
!DuplicateHandle (hMainProc, myself.shared_handle (), hMainProc,
&moreinfo->myself_pinfo, 0,
TRUE, DUPLICATE_SAME_ACCESS))
moreinfo->myself_pinfo = NULL;
else
VerifyHandle (moreinfo->myself_pinfo);
skip_arg_parsing:
PROCESS_INFORMATION pi; PROCESS_INFORMATION pi;
pi.hProcess = pi.hThread = NULL; pi.hProcess = pi.hThread = NULL;
pi.dwProcessId = pi.dwThreadId = 0; pi.dwProcessId = pi.dwThreadId = 0;
@ -624,8 +625,9 @@ spawn_guts (const char * prog_arg, const char *const *argv,
after CreateProcess and before copying the datastructures to the child. after CreateProcess and before copying the datastructures to the child.
So we have to start the child in suspend state, unfortunately, to avoid So we have to start the child in suspend state, unfortunately, to avoid
a race condition. */ a race condition. */
if (wincap.start_proc_suspended () || mode != _P_OVERLAY if (!newargv.win16_exe
|| cygheap->fdtab.need_fixup_before ()) && (wincap.start_proc_suspended () || mode != _P_OVERLAY
|| cygheap->fdtab.need_fixup_before ()))
flags |= CREATE_SUSPENDED; flags |= CREATE_SUSPENDED;
const char *runpath = null_app_name ? NULL : (const char *) real_path; const char *runpath = null_app_name ? NULL : (const char *) real_path;
@ -836,7 +838,8 @@ spawn_guts (const char * prog_arg, const char *const *argv,
{ {
case _P_OVERLAY: case _P_OVERLAY:
myself.hProcess = pi.hProcess; myself.hProcess = pi.hProcess;
if (synced && !myself->wr_proc_pipe) if (synced && WaitForSingleObject (pi.hProcess, 0) == WAIT_TIMEOUT
&& !myself->wr_proc_pipe)
{ {
extern bool is_toplevel_proc; extern bool is_toplevel_proc;
is_toplevel_proc = true; is_toplevel_proc = true;
@ -1078,6 +1081,8 @@ av::fixup (child_info_types chtype, const char *prog_arg, path_conv& real_path,
win16_exe = off < sizeof (IMAGE_DOS_HEADER); win16_exe = off < sizeof (IMAGE_DOS_HEADER);
if (!win16_exe) if (!win16_exe)
real_path.set_cygexec (!!hook_or_detect_cygwin (buf, NULL, subsys)); real_path.set_cygexec (!!hook_or_detect_cygwin (buf, NULL, subsys));
else
real_path.set_cygexec (false);
UnmapViewOfFile (buf); UnmapViewOfFile (buf);
iscui = subsys == IMAGE_SUBSYSTEM_WINDOWS_CUI; iscui = subsys == IMAGE_SUBSYSTEM_WINDOWS_CUI;
break; break;