mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* dln.c (dln_find_1): supplements an extension for executable
files on DOSish platforms. * io.c (pipe_open): use rb_w32_aspawn() for array form. * win32/win32.c (rb_w32_pipe_exec): no longer used. * win32/win32.c (rb_w32_spawn, rb_w32_aspawn): deals with batch files and commands with extensions. [ruby-core:20695] * win32/win32.c (has_redirection): supports environment variables references. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@20892 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
3eb9283504
commit
7ac32d7a16
4 changed files with 200 additions and 206 deletions
15
ChangeLog
15
ChangeLog
|
@ -1,3 +1,18 @@
|
||||||
|
Sat Dec 20 18:28:26 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
|
* dln.c (dln_find_1): supplements an extension for executable
|
||||||
|
files on DOSish platforms.
|
||||||
|
|
||||||
|
* io.c (pipe_open): use rb_w32_aspawn() for array form.
|
||||||
|
|
||||||
|
* win32/win32.c (rb_w32_pipe_exec): no longer used.
|
||||||
|
|
||||||
|
* win32/win32.c (rb_w32_spawn, rb_w32_aspawn): deals with batch
|
||||||
|
files and commands with extensions. [ruby-core:20695]
|
||||||
|
|
||||||
|
* win32/win32.c (has_redirection): supports environment variables
|
||||||
|
references.
|
||||||
|
|
||||||
Sat Dec 20 10:59:16 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
|
Sat Dec 20 10:59:16 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
|
||||||
|
|
||||||
* lib/irb/locale.rb (IRB::Locale#initialize)
|
* lib/irb/locale.rb (IRB::Locale#initialize)
|
||||||
|
|
65
dln.c
65
dln.c
|
@ -1518,28 +1518,70 @@ dln_find_1(const char *fname, const char *path, char *fbuf, int size,
|
||||||
register const char *ep;
|
register const char *ep;
|
||||||
register char *bp;
|
register char *bp;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
int i, fspace;
|
||||||
|
#ifdef DOSISH
|
||||||
|
int is_abs = 0, has_path = 0, has_ext = 0;
|
||||||
|
const char *p = fname;
|
||||||
|
#endif
|
||||||
|
|
||||||
#define RETURN_IF(expr) if (expr) return (char *)fname;
|
#define RETURN_IF(expr) if (expr) return (char *)fname;
|
||||||
|
|
||||||
RETURN_IF(!fname);
|
RETURN_IF(!fname);
|
||||||
|
#ifdef DOSISH
|
||||||
|
# ifndef CharNext
|
||||||
|
# define CharNext(p) ((p)+1)
|
||||||
|
# endif
|
||||||
|
# ifdef DOSISH_DRIVE_LETTER
|
||||||
|
if (((p[0] | 0x20) - 'a') < 26 && p[1] == ':') {
|
||||||
|
p += 2;
|
||||||
|
is_abs = 1;
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
switch (*p) {
|
||||||
|
case '/': case '\\':
|
||||||
|
is_abs = 1;
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
has_path = is_abs;
|
||||||
|
while (*p) {
|
||||||
|
switch (*p) {
|
||||||
|
case '/': case '\\':
|
||||||
|
has_path = 1;
|
||||||
|
has_ext = 0;
|
||||||
|
p++;
|
||||||
|
break;
|
||||||
|
case '.':
|
||||||
|
has_ext = 1;
|
||||||
|
p++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
p = CharNext(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ep = bp = 0;
|
||||||
|
if (!exe_flag) {
|
||||||
|
RETURN_IF(is_abs);
|
||||||
|
}
|
||||||
|
else if (has_path) {
|
||||||
|
RETURN_IF(has_ext);
|
||||||
|
i = p - fname;
|
||||||
|
if (i + 1 > size) goto toolong;
|
||||||
|
fspace = size - i - 1;
|
||||||
|
bp = fbuf;
|
||||||
|
ep = p;
|
||||||
|
memcpy(fbuf, fname, i + 1);
|
||||||
|
goto needs_extension;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
RETURN_IF(fname[0] == '/');
|
RETURN_IF(fname[0] == '/');
|
||||||
RETURN_IF(strncmp("./", fname, 2) == 0 || strncmp("../", fname, 3) == 0);
|
RETURN_IF(strncmp("./", fname, 2) == 0 || strncmp("../", fname, 3) == 0);
|
||||||
RETURN_IF(exe_flag && strchr(fname, '/'));
|
RETURN_IF(exe_flag && strchr(fname, '/'));
|
||||||
#ifdef DOSISH
|
|
||||||
RETURN_IF(fname[0] == '\\');
|
|
||||||
# ifdef DOSISH_DRIVE_LETTER
|
|
||||||
RETURN_IF(strlen(fname) > 2 && fname[1] == ':');
|
|
||||||
# endif
|
|
||||||
RETURN_IF(strncmp(".\\", fname, 2) == 0 || strncmp("..\\", fname, 3) == 0);
|
|
||||||
RETURN_IF(exe_flag && strchr(fname, '\\'));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#undef RETURN_IF
|
#undef RETURN_IF
|
||||||
|
|
||||||
for (dp = path;; dp = ++ep) {
|
for (dp = path;; dp = ++ep) {
|
||||||
register int l;
|
register int l;
|
||||||
int i;
|
|
||||||
int fspace;
|
|
||||||
|
|
||||||
/* extract a component */
|
/* extract a component */
|
||||||
ep = strchr(dp, PATH_SEP[0]);
|
ep = strchr(dp, PATH_SEP[0]);
|
||||||
|
@ -1602,7 +1644,7 @@ dln_find_1(const char *fname, const char *path, char *fbuf, int size,
|
||||||
memcpy(bp, fname, i + 1);
|
memcpy(bp, fname, i + 1);
|
||||||
|
|
||||||
#if defined(DOSISH)
|
#if defined(DOSISH)
|
||||||
if (exe_flag) {
|
if (exe_flag && !has_ext) {
|
||||||
static const char extension[][5] = {
|
static const char extension[][5] = {
|
||||||
#if defined(__EMX__) || defined(_WIN32)
|
#if defined(__EMX__) || defined(_WIN32)
|
||||||
".exe", ".com", ".cmd", ".bat",
|
".exe", ".com", ".cmd", ".bat",
|
||||||
|
@ -1611,6 +1653,7 @@ dln_find_1(const char *fname, const char *path, char *fbuf, int size,
|
||||||
};
|
};
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
|
needs_extension:
|
||||||
for (j = 0; j < sizeof(extension) / sizeof(extension[0]); j++) {
|
for (j = 0; j < sizeof(extension) / sizeof(extension[0]); j++) {
|
||||||
if (fspace < strlen(extension[j])) {
|
if (fspace < strlen(extension[j])) {
|
||||||
fprintf(stderr, "openpath: pathname too long (ignored)\n");
|
fprintf(stderr, "openpath: pathname too long (ignored)\n");
|
||||||
|
|
16
io.c
16
io.c
|
@ -13,6 +13,7 @@
|
||||||
|
|
||||||
#include "ruby/ruby.h"
|
#include "ruby/ruby.h"
|
||||||
#include "ruby/io.h"
|
#include "ruby/io.h"
|
||||||
|
#include "dln.h"
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
|
@ -4446,9 +4447,8 @@ pipe_open(struct rb_exec_arg *eargp, VALUE prog, const char *modestr, int fmode,
|
||||||
int status;
|
int status;
|
||||||
struct popen_arg arg;
|
struct popen_arg arg;
|
||||||
#elif defined(_WIN32)
|
#elif defined(_WIN32)
|
||||||
int openmode = rb_io_modestr_oflags(modestr);
|
volatile VALUE argbuf;
|
||||||
const char *exename = NULL;
|
char **args;
|
||||||
volatile VALUE cmdbuf;
|
|
||||||
struct rb_exec_arg sarg;
|
struct rb_exec_arg sarg;
|
||||||
int pair[2], write_pair[2];
|
int pair[2], write_pair[2];
|
||||||
#endif
|
#endif
|
||||||
|
@ -4557,8 +4557,6 @@ pipe_open(struct rb_exec_arg *eargp, VALUE prog, const char *modestr, int fmode,
|
||||||
}
|
}
|
||||||
#elif defined(_WIN32)
|
#elif defined(_WIN32)
|
||||||
if (argc) {
|
if (argc) {
|
||||||
volatile VALUE argbuf;
|
|
||||||
char **args;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (argc >= FIXNUM_MAX / sizeof(char *)) {
|
if (argc >= FIXNUM_MAX / sizeof(char *)) {
|
||||||
|
@ -4570,10 +4568,6 @@ pipe_open(struct rb_exec_arg *eargp, VALUE prog, const char *modestr, int fmode,
|
||||||
args[i] = StringValueCStr(argv[i]);
|
args[i] = StringValueCStr(argv[i]);
|
||||||
}
|
}
|
||||||
args[i] = NULL;
|
args[i] = NULL;
|
||||||
exename = cmd;
|
|
||||||
cmdbuf = rb_str_tmp_new(rb_w32_argv_size(args));
|
|
||||||
cmd = rb_w32_join_argv(RSTRING_PTR(cmdbuf), args);
|
|
||||||
rb_str_resize(argbuf, 0);
|
|
||||||
}
|
}
|
||||||
switch (fmode & (FMODE_READABLE|FMODE_WRITABLE)) {
|
switch (fmode & (FMODE_READABLE|FMODE_WRITABLE)) {
|
||||||
case FMODE_READABLE|FMODE_WRITABLE:
|
case FMODE_READABLE|FMODE_WRITABLE:
|
||||||
|
@ -4610,7 +4604,9 @@ pipe_open(struct rb_exec_arg *eargp, VALUE prog, const char *modestr, int fmode,
|
||||||
rb_exec_arg_fixup(eargp);
|
rb_exec_arg_fixup(eargp);
|
||||||
rb_run_exec_options(eargp, &sarg);
|
rb_run_exec_options(eargp, &sarg);
|
||||||
}
|
}
|
||||||
while ((pid = rb_w32_spawn(P_NOWAIT, cmd, exename)) == -1) {
|
while ((pid = (args ?
|
||||||
|
rb_w32_aspawn(P_NOWAIT, 0, args) :
|
||||||
|
rb_w32_spawn(P_NOWAIT, cmd, 0))) == -1) {
|
||||||
/* exec failed */
|
/* exec failed */
|
||||||
switch (errno) {
|
switch (errno) {
|
||||||
case EAGAIN:
|
case EAGAIN:
|
||||||
|
|
306
win32/win32.c
306
win32/win32.c
|
@ -349,6 +349,17 @@ flock(int fd, int oper)
|
||||||
(DWORD)-1);
|
(DWORD)-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline char *
|
||||||
|
translate_char(char *p, int from, int to)
|
||||||
|
{
|
||||||
|
while (*p) {
|
||||||
|
if ((unsigned char)*p == from)
|
||||||
|
*p = to;
|
||||||
|
p = CharNext(p);
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
init_env(void)
|
init_env(void)
|
||||||
{
|
{
|
||||||
|
@ -377,11 +388,7 @@ init_env(void)
|
||||||
alloc->lpVtbl->Release(alloc);
|
alloc->lpVtbl->Release(alloc);
|
||||||
}
|
}
|
||||||
if (f) {
|
if (f) {
|
||||||
char *p = env;
|
char *p = translate_char(env, '\\', '/');
|
||||||
while (*p) {
|
|
||||||
if (*p == '\\') *p = '/';
|
|
||||||
p = CharNext(p);
|
|
||||||
}
|
|
||||||
if (p - env == 2 && env[1] == ':') {
|
if (p - env == 2 && env[1] == ':') {
|
||||||
*p++ = '/';
|
*p++ = '/';
|
||||||
*p = 0;
|
*p = 0;
|
||||||
|
@ -752,143 +759,33 @@ rb_w32_join_argv(char *cmd, char *const *argv)
|
||||||
return cmd;
|
return cmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
rb_pid_t
|
#ifdef HAVE_SYS_PARAM_H
|
||||||
rb_w32_pipe_exec(const char *cmd, const char *prog, int mode, int *pipe,
|
# include <sys/param.h>
|
||||||
int *write_pipe)
|
#else
|
||||||
|
# define MAXPATHLEN 512
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define STRNDUPA(ptr, src, len) \
|
||||||
|
(((char *)memcpy(((ptr) = ALLOCA_N(char, (len) + 1)), (src), (len)))[len] = 0)
|
||||||
|
|
||||||
|
static int
|
||||||
|
check_spawn_mode(int mode)
|
||||||
{
|
{
|
||||||
struct ChildRecord* child;
|
|
||||||
HANDLE hIn, hOut;
|
|
||||||
HANDLE hDupIn, hDupOut;
|
|
||||||
HANDLE hCurProc;
|
|
||||||
SECURITY_ATTRIBUTES sa;
|
|
||||||
BOOL reading, writing;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
/* Figure out what we're doing... */
|
|
||||||
if (mode & O_RDWR) {
|
|
||||||
reading = writing = TRUE;
|
|
||||||
}
|
|
||||||
else if (mode & O_WRONLY) {
|
|
||||||
reading = FALSE;
|
|
||||||
writing = TRUE;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
reading = TRUE;
|
|
||||||
writing = FALSE;
|
|
||||||
}
|
|
||||||
mode &= ~(O_RDWR|O_RDONLY|O_WRONLY|O_TEXT);
|
|
||||||
mode |= O_BINARY;
|
|
||||||
|
|
||||||
sa.nLength = sizeof (SECURITY_ATTRIBUTES);
|
|
||||||
sa.lpSecurityDescriptor = NULL;
|
|
||||||
sa.bInheritHandle = TRUE;
|
|
||||||
ret = -1;
|
|
||||||
|
|
||||||
RUBY_CRITICAL(do {
|
|
||||||
/* create pipe */
|
|
||||||
hCurProc = GetCurrentProcess();
|
|
||||||
hIn = hOut = hDupIn = hDupOut = NULL;
|
|
||||||
if (reading) {
|
|
||||||
HANDLE hTmpIn;
|
|
||||||
if (!CreatePipe(&hTmpIn, &hOut, &sa, 2048L)) {
|
|
||||||
errno = map_errno(GetLastError());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!DuplicateHandle(hCurProc, hTmpIn, hCurProc, &hDupIn, 0,
|
|
||||||
FALSE, DUPLICATE_SAME_ACCESS)) {
|
|
||||||
errno = map_errno(GetLastError());
|
|
||||||
CloseHandle(hTmpIn);
|
|
||||||
CloseHandle(hOut);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
CloseHandle(hTmpIn);
|
|
||||||
hTmpIn = NULL;
|
|
||||||
}
|
|
||||||
if (writing) {
|
|
||||||
HANDLE hTmpOut;
|
|
||||||
if (!CreatePipe(&hIn, &hTmpOut, &sa, 2048L)) {
|
|
||||||
errno = map_errno(GetLastError());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!DuplicateHandle(hCurProc, hTmpOut, hCurProc, &hDupOut, 0,
|
|
||||||
FALSE, DUPLICATE_SAME_ACCESS)) {
|
|
||||||
errno = map_errno(GetLastError());
|
|
||||||
CloseHandle(hIn);
|
|
||||||
CloseHandle(hTmpOut);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
CloseHandle(hTmpOut);
|
|
||||||
hTmpOut = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* create child process */
|
|
||||||
child = CreateChild(cmd, prog, &sa, hIn, hOut, NULL);
|
|
||||||
if (!child) {
|
|
||||||
if (hIn)
|
|
||||||
CloseHandle(hIn);
|
|
||||||
if (hOut)
|
|
||||||
CloseHandle(hOut);
|
|
||||||
if (hDupIn)
|
|
||||||
CloseHandle(hDupIn);
|
|
||||||
if (hDupOut)
|
|
||||||
CloseHandle(hDupOut);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* associate handle to file descritor */
|
|
||||||
if (reading) {
|
|
||||||
*pipe = rb_w32_open_osfhandle((intptr_t)hDupIn, O_RDONLY | mode);
|
|
||||||
if (writing)
|
|
||||||
*write_pipe = rb_w32_open_osfhandle((intptr_t)hDupOut,
|
|
||||||
O_WRONLY | mode);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
*pipe = rb_w32_open_osfhandle((intptr_t)hDupOut, O_WRONLY | mode);
|
|
||||||
}
|
|
||||||
if (hIn)
|
|
||||||
CloseHandle(hIn);
|
|
||||||
if (hOut)
|
|
||||||
CloseHandle(hOut);
|
|
||||||
if (reading && writing && *write_pipe == -1) {
|
|
||||||
if (*pipe != -1)
|
|
||||||
rb_w32_close(*pipe);
|
|
||||||
else
|
|
||||||
CloseHandle(hDupIn);
|
|
||||||
CloseHandle(hDupOut);
|
|
||||||
CloseChildHandle(child);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if (*pipe == -1) {
|
|
||||||
if (reading)
|
|
||||||
CloseHandle(hDupIn);
|
|
||||||
else
|
|
||||||
CloseHandle(hDupOut);
|
|
||||||
CloseChildHandle(child);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = child->pid;
|
|
||||||
} while (0));
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
rb_pid_t
|
|
||||||
rb_w32_spawn(int mode, const char *cmd, const char *prog)
|
|
||||||
{
|
|
||||||
struct ChildRecord *child;
|
|
||||||
DWORD exitcode;
|
|
||||||
|
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case P_NOWAIT:
|
case P_NOWAIT:
|
||||||
case P_OVERLAY:
|
case P_OVERLAY:
|
||||||
break;
|
return 0;
|
||||||
default:
|
default:
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static rb_pid_t
|
||||||
|
child_result(struct ChildRecord *child, int mode)
|
||||||
|
{
|
||||||
|
DWORD exitcode;
|
||||||
|
|
||||||
child = CreateChild(cmd, prog, NULL, NULL, NULL, NULL);
|
|
||||||
if (!child) {
|
if (!child) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -906,22 +803,6 @@ rb_w32_spawn(int mode, const char *cmd, const char *prog)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rb_pid_t
|
|
||||||
rb_w32_aspawn(int mode, const char *prog, char *const *argv)
|
|
||||||
{
|
|
||||||
int len = rb_w32_argv_size(argv);
|
|
||||||
char *cmd = ALLOCA_N(char, len);
|
|
||||||
|
|
||||||
if (!prog) prog = argv[0];
|
|
||||||
return rb_w32_spawn(mode, rb_w32_join_argv(cmd, argv), prog);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAVE_SYS_PARAM_H
|
|
||||||
# include <sys/param.h>
|
|
||||||
#else
|
|
||||||
# define MAXPATHLEN 512
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static struct ChildRecord *
|
static struct ChildRecord *
|
||||||
CreateChild(const char *cmd, const char *prog, SECURITY_ATTRIBUTES *psa,
|
CreateChild(const char *cmd, const char *prog, SECURITY_ATTRIBUTES *psa,
|
||||||
HANDLE hInput, HANDLE hOutput, HANDLE hError)
|
HANDLE hInput, HANDLE hOutput, HANDLE hError)
|
||||||
|
@ -931,10 +812,7 @@ CreateChild(const char *cmd, const char *prog, SECURITY_ATTRIBUTES *psa,
|
||||||
STARTUPINFO aStartupInfo;
|
STARTUPINFO aStartupInfo;
|
||||||
PROCESS_INFORMATION aProcessInformation;
|
PROCESS_INFORMATION aProcessInformation;
|
||||||
SECURITY_ATTRIBUTES sa;
|
SECURITY_ATTRIBUTES sa;
|
||||||
const char *shell;
|
|
||||||
struct ChildRecord *child;
|
struct ChildRecord *child;
|
||||||
char *p = NULL;
|
|
||||||
char fbuf[MAXPATHLEN];
|
|
||||||
|
|
||||||
if (!cmd && !prog) {
|
if (!cmd && !prog) {
|
||||||
errno = EFAULT;
|
errno = EFAULT;
|
||||||
|
@ -981,6 +859,40 @@ CreateChild(const char *cmd, const char *prog, SECURITY_ATTRIBUTES *psa,
|
||||||
|
|
||||||
dwCreationFlags = (NORMAL_PRIORITY_CLASS);
|
dwCreationFlags = (NORMAL_PRIORITY_CLASS);
|
||||||
|
|
||||||
|
RUBY_CRITICAL({
|
||||||
|
fRet = CreateProcess(prog, (char *)cmd, psa, psa,
|
||||||
|
psa->bInheritHandle, dwCreationFlags, NULL, NULL,
|
||||||
|
&aStartupInfo, &aProcessInformation);
|
||||||
|
errno = map_errno(GetLastError());
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!fRet) {
|
||||||
|
child->pid = 0; /* release the slot */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseHandle(aProcessInformation.hThread);
|
||||||
|
|
||||||
|
child->hProcess = aProcessInformation.hProcess;
|
||||||
|
child->pid = (rb_pid_t)aProcessInformation.dwProcessId;
|
||||||
|
|
||||||
|
if (!IsWinNT()) {
|
||||||
|
/* On Win9x, make pid positive similarly to cygwin and perl */
|
||||||
|
child->pid = -child->pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
|
||||||
|
rb_pid_t
|
||||||
|
rb_w32_spawn(int mode, const char *cmd, const char *prog)
|
||||||
|
{
|
||||||
|
char fbuf[MAXPATHLEN];
|
||||||
|
char *p = NULL;
|
||||||
|
const char *shell = NULL;
|
||||||
|
|
||||||
|
if (check_spawn_mode(mode)) return -1;
|
||||||
|
|
||||||
if (prog) {
|
if (prog) {
|
||||||
if (!(p = dln_find_exe_r(prog, NULL, fbuf, sizeof(fbuf)))) {
|
if (!(p = dln_find_exe_r(prog, NULL, fbuf, sizeof(fbuf)))) {
|
||||||
shell = prog;
|
shell = prog;
|
||||||
|
@ -1024,20 +936,17 @@ CreateChild(const char *cmd, const char *prog, SECURITY_ATTRIBUTES *psa,
|
||||||
p = dln_find_exe_r(cmd, NULL, fbuf, sizeof(fbuf));
|
p = dln_find_exe_r(cmd, NULL, fbuf, sizeof(fbuf));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (strchr(".:*?\"/\\", *prog)) {
|
if (strchr(":*?\"/\\", *prog)) {
|
||||||
if (cmd[len]) {
|
if (cmd[len]) {
|
||||||
char *tmp = ALLOCA_N(char, len + 1);
|
STRNDUPA(p, cmd, len);
|
||||||
memcpy(tmp, cmd, len);
|
|
||||||
tmp[len] = 0;
|
|
||||||
cmd = tmp;
|
|
||||||
}
|
}
|
||||||
|
p = dln_find_exe_r(p ? p : cmd, NULL, fbuf, sizeof(fbuf));
|
||||||
|
cmd += len;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (ISSPACE(*prog) || strchr("<>|", *prog)) {
|
if (ISSPACE(*prog) || strchr("<>|", *prog)) {
|
||||||
len = prog - cmd;
|
len = prog - cmd;
|
||||||
p = ALLOCA_N(char, len + 1);
|
STRNDUPA(p, cmd, len);
|
||||||
memcpy(p, cmd, len);
|
|
||||||
p[len] = 0;
|
|
||||||
p = dln_find_exe_r(p, NULL, fbuf, sizeof(fbuf));
|
p = dln_find_exe_r(p, NULL, fbuf, sizeof(fbuf));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1047,36 +956,61 @@ CreateChild(const char *cmd, const char *prog, SECURITY_ATTRIBUTES *psa,
|
||||||
}
|
}
|
||||||
if (p) {
|
if (p) {
|
||||||
shell = p;
|
shell = p;
|
||||||
while (*p) {
|
translate_char(p, '/', '\\');
|
||||||
if ((unsigned char)*p == '/')
|
|
||||||
*p = '\\';
|
|
||||||
p = CharNext(p);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RUBY_CRITICAL({
|
return child_result(CreateChild(cmd, shell, NULL, NULL, NULL, NULL), mode);
|
||||||
fRet = CreateProcess(shell, (char *)cmd, psa, psa,
|
|
||||||
psa->bInheritHandle, dwCreationFlags, NULL, NULL,
|
|
||||||
&aStartupInfo, &aProcessInformation);
|
|
||||||
errno = map_errno(GetLastError());
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!fRet) {
|
|
||||||
child->pid = 0; /* release the slot */
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CloseHandle(aProcessInformation.hThread);
|
rb_pid_t
|
||||||
|
rb_w32_aspawn(int mode, const char *prog, char *const *argv)
|
||||||
|
{
|
||||||
|
int len, differ = 0, c_switch =0;
|
||||||
|
const char *shell;
|
||||||
|
char *cmd, fbuf[MAXPATHLEN];
|
||||||
|
|
||||||
child->hProcess = aProcessInformation.hProcess;
|
if (check_spawn_mode(mode)) return -1;
|
||||||
child->pid = (rb_pid_t)aProcessInformation.dwProcessId;
|
|
||||||
|
|
||||||
if (!IsWinNT()) {
|
if (!prog) prog = argv[0];
|
||||||
/* On Win9x, make pid positive similarly to cygwin and perl */
|
if ((shell = getenv("COMSPEC")) &&
|
||||||
child->pid = -child->pid;
|
(has_redirection(prog) ||
|
||||||
|
is_internal_cmd(prog, !is_command_com(shell)))) {
|
||||||
|
prog = shell;
|
||||||
|
c_switch = 1;
|
||||||
|
differ = 1;
|
||||||
}
|
}
|
||||||
|
else if ((cmd = dln_find_exe_r(prog, NULL, fbuf, sizeof(fbuf)))) {
|
||||||
return child;
|
if (cmd == prog) strlcpy(cmd = fbuf, prog, sizeof(fbuf));
|
||||||
|
translate_char(cmd, '/', '\\');
|
||||||
|
prog = cmd;
|
||||||
|
argv++;
|
||||||
|
differ = 1;
|
||||||
|
}
|
||||||
|
else if (strchr(prog, '/')) {
|
||||||
|
strlcpy(fbuf, prog, sizeof(fbuf));
|
||||||
|
translate_char(fbuf, '/', '\\');
|
||||||
|
prog = fbuf;
|
||||||
|
argv++;
|
||||||
|
differ = 1;
|
||||||
|
}
|
||||||
|
if (differ) {
|
||||||
|
char *progs[2];
|
||||||
|
progs[0] = (char *)prog;
|
||||||
|
progs[1] = NULL;
|
||||||
|
len = rb_w32_argv_size(progs);
|
||||||
|
if (c_switch) len += 3;
|
||||||
|
if (argv[0]) len += rb_w32_argv_size(argv);
|
||||||
|
cmd = ALLOCA_N(char, len);
|
||||||
|
rb_w32_join_argv(cmd, progs);
|
||||||
|
if (c_switch) strlcat(cmd, " /c", len);
|
||||||
|
if (argv[0]) rb_w32_join_argv(cmd + strlcat(cmd, " ", len), argv);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
len = rb_w32_argv_size(argv);
|
||||||
|
cmd = ALLOCA_N(char, len);
|
||||||
|
rb_w32_join_argv(cmd, argv);
|
||||||
|
}
|
||||||
|
return child_result(CreateChild(cmd, prog, NULL, NULL, NULL, NULL), mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct _NtCmdLineElement {
|
typedef struct _NtCmdLineElement {
|
||||||
|
@ -1176,6 +1110,12 @@ has_redirection(const char *cmd)
|
||||||
ptr++;
|
ptr++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case '%':
|
||||||
|
if (*++ptr != '_' && !ISALPHA(*ptr)) break;
|
||||||
|
while (*++ptr == '_' || ISALNUM(*ptr));
|
||||||
|
if (*ptr++ == '%') return TRUE;
|
||||||
|
break;
|
||||||
|
|
||||||
case '\\':
|
case '\\':
|
||||||
ptr++;
|
ptr++;
|
||||||
default:
|
default:
|
||||||
|
|
Loading…
Add table
Reference in a new issue