Mail Archives: djgpp-workers/2001/07/06/14:23:48
Changes in this revision:
* Eli's suggestions.
* I also increased the buffer size for rpath to prevent a buffer overflow
when the path is FILENAME_MAX - 1 characters long and an extension is added.
* process.h says that P_NOWAIT always fails with an error, but where is that
error set? A grep of the djgpp cvs find no references to P_NOWAIT except in
include/process.h. So I added a check for it to __djgpp_spawn.
* Set defaults when no flags or environment were passed.
I'll leave out the find_* functions since they haven't changed and the obvious changes
to the spawn* functions.
/* for libc/dosexec.h */
#define SPAWN_FLAG_EXTENSION_SEARCH 1
#define SPAWN_FLAG_INTERP_ONLY_SEARCH 2
#define SPAWN_SEARCH_FLAGS \
(SPAWN_FLAG_EXTENSION_SEARCH | SPAWN_FLAG_INTERP_ONLY_SEARCH)
int __djgpp_spawn(int mode, const char *path, char *const argv[],
char *const envp[], unsigned long flags);
int spawnve(int mode, const char *path, char *const argv[], char *const envp[])
{
return __djgpp_spawn(mode, path, argv, envp, SPAWN_FLAG_EXTENSION_SEARCH);
}
int __djgpp_spawn(int mode, const char *path, char *const argv[],
char *const envp[], unsigned long flags)
{
/* This is the one that does the work! */
union { char *const *x; char **p; } u;
const int no_interp_found = -1;
int i = no_interp_found;
char **argvp;
char **envpp;
char rpath[FILENAME_MAX + 4], *rp, *rd = 0;
int e = errno;
int ret_code;
if (path == 0 || argv[0] == 0)
{
errno = EINVAL;
return -1;
}
if (mode == P_NOWAIT)
{
errno = ENOSYS;
return -1;
}
if (strlen(path) > FILENAME_MAX - 1)
{
errno = ENAMETOOLONG;
return -1;
}
u.x = argv; argvp = u.p;
u.x = envp; envpp = u.p;
/* Set defaults for the environment and search method. */
if (envpp == NULL)
envpp = environ;
if ((flags & SPAWN_SEARCH_FLAGS) == 0)
flags |= SPAWN_FLAG_EXTENSION_SEARCH;
/* Copy the path to rpath and also mark where the extension is. */
fflush(stdout); /* just in case */
for (rp=rpath; *path; *rp++ = *path++)
{
if (*path == '.')
rd = rp;
if (*path == '\\' || *path == '/')
rd = 0;
}
*rp = 0;
/* Perform an extension search when the flag SPAWN_INTERP_SEARCH is not
present. If LFN is supported on the volume where rpath resides, we
might have something like foo.bar.exe or even foo.exe.com.
If so, look for RPATH.ext before even trying RPATH itself.
Otherwise, try to add an extension to a file without one. */
if (flags & SPAWN_FLAG_EXTENSION_SEARCH)
{
if (_use_lfn(path) || !rd)
{
i = find_extension(rpath, rp);
/* When LFN is supported and an extension search fails, the go32_exec
interpreter will be selected instead of none. In this case,
set the interpreter to none so the interpreter will be selected
from the existing extension. */
if ((i != no_interp_found) && rd && *rp == 0)
i = no_interp_found;
}
}
/* If no interpreter has already been detected, find one based on the
extension in rpath. */
if (i == no_interp_found)
i = find_interpreter(rpath, rd ? rd : rp);
/* The file does not exist. Return with errno set either by find_extension
or find_interpreter to indicate the error. */
if (i == no_interp_found)
return -1;
errno = e;
ret_code = interpreters[i].interp(rpath, argvp, envpp);
if (mode == P_OVERLAY)
exit(ret_code);
return ret_code;
}
- Raw text -