[前][次][番号順一覧][スレッド一覧]

ruby-changes:9361

From: yugui <ko1@a...>
Date: Sun, 21 Dec 2008 14:27:39 +0900 (JST)
Subject: [ruby-changes:9361] Ruby:r20899 (ruby_1_9_1): merges r20892 from trunk into ruby_1_9_1.

yugui	2008-12-21 14:27:20 +0900 (Sun, 21 Dec 2008)

  New Revision: 20899

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=20899

  Log:
    merges r20892 from trunk into ruby_1_9_1.
    * 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.

  Modified files:
    branches/ruby_1_9_1/ChangeLog
    branches/ruby_1_9_1/dln.c
    branches/ruby_1_9_1/io.c
    branches/ruby_1_9_1/win32/win32.c

Index: ruby_1_9_1/ChangeLog
===================================================================
--- ruby_1_9_1/ChangeLog	(revision 20898)
+++ ruby_1_9_1/ChangeLog	(revision 20899)
@@ -1,3 +1,18 @@
+Sat Dec 20 18:28:26 2008  Nobuyoshi Nakada  <nobu@r...>
+
+	* 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.
+
 Fri Dec  5 01:37:02 2008  NAKAMURA Usaku  <usa@r...>
 
 	* win32/win32.c (rb_w32_read): ERROR_BROKEN_PIPE is not a real error
Index: ruby_1_9_1/io.c
===================================================================
--- ruby_1_9_1/io.c	(revision 20898)
+++ ruby_1_9_1/io.c	(revision 20899)
@@ -13,6 +13,7 @@
 
 #include "ruby/ruby.h"
 #include "ruby/io.h"
+#include "dln.h"
 #include <ctype.h>
 #include <errno.h>
 
@@ -4446,9 +4447,8 @@
     int status;
     struct popen_arg arg;
 #elif defined(_WIN32)
-    int openmode = rb_io_modestr_oflags(modestr);
-    const char *exename = NULL;
-    volatile VALUE cmdbuf;
+    volatile VALUE argbuf;
+    char **args;
     struct rb_exec_arg sarg;
     int pair[2], write_pair[2];
 #endif
@@ -4557,8 +4557,6 @@
     }
 #elif defined(_WIN32)
     if (argc) {
-	volatile VALUE argbuf;
-	char **args;
 	int i;
 
 	if (argc >= FIXNUM_MAX / sizeof(char *)) {
@@ -4570,10 +4568,6 @@
 	    args[i] = StringValueCStr(argv[i]);
 	}
 	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)) {
       case FMODE_READABLE|FMODE_WRITABLE:
@@ -4610,7 +4604,9 @@
 	rb_exec_arg_fixup(eargp);
 	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 */
 	switch (errno) {
 	  case EAGAIN:
Index: ruby_1_9_1/win32/win32.c
===================================================================
--- ruby_1_9_1/win32/win32.c	(revision 20898)
+++ ruby_1_9_1/win32/win32.c	(revision 20899)
@@ -349,6 +349,17 @@
 			      (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
 init_env(void)
 {
@@ -377,11 +388,7 @@
 	    alloc->lpVtbl->Release(alloc);
 	}
 	if (f) {
-	    char *p = env;
-	    while (*p) {
-		if (*p == '\\') *p = '/';
-		p = CharNext(p);
-	    }
+	    char *p = translate_char(env, '\\', '/');
 	    if (p - env == 2 && env[1] == ':') {
 		*p++ = '/';
 		*p = 0;
@@ -752,143 +759,33 @@
     return cmd;
 }
 
-rb_pid_t
-rb_w32_pipe_exec(const char *cmd, const char *prog, int mode, int *pipe,
-		 int *write_pipe)
-{
-    struct ChildRecord* child;
-    HANDLE hIn, hOut;
-    HANDLE hDupIn, hDupOut;
-    HANDLE hCurProc;
-    SECURITY_ATTRIBUTES sa;
-    BOOL reading, writing;
-    int ret;
+#ifdef HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#else
+# define MAXPATHLEN 512
+#endif
 
-    /* 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;
+#define STRNDUPA(ptr, src, len) \
+    (((char *)memcpy(((ptr) = ALLOCA_N(char, (len) + 1)), (src), (len)))[len] = 0)
 
-    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)
+static int
+check_spawn_mode(int mode)
 {
-    struct ChildRecord *child;
-    DWORD exitcode;
-
     switch (mode) {
       case P_NOWAIT:
       case P_OVERLAY:
-	break;
+	return 0;
       default:
 	errno = EINVAL;
 	return -1;
     }
+}
 
-    child = CreateChild(cmd, prog, NULL, NULL, NULL, NULL);
+static rb_pid_t
+child_result(struct ChildRecord *child, int mode)
+{
+    DWORD exitcode;
+
     if (!child) {
 	return -1;
     }
@@ -906,22 +803,6 @@
     }
 }
 
-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 *
 CreateChild(const char *cmd, const char *prog, SECURITY_ATTRIBUTES *psa,
 	    HANDLE hInput, HANDLE hOutput, HANDLE hError)
@@ -931,10 +812,7 @@
     STARTUPINFO aStartupInfo;
     PROCESS_INFORMATION aProcessInformation;
     SECURITY_ATTRIBUTES sa;
-    const char *shell;
     struct ChildRecord *child;
-    char *p = NULL;
-    char fbuf[MAXPATHLEN];
 
     if (!cmd && !prog) {
 	errno = EFAULT;
@@ -981,6 +859,40 @@
 
     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 (!(p = dln_find_exe_r(prog, NULL, fbuf, sizeof(fbuf)))) {
 	    shell = prog;
@@ -1024,20 +936,17 @@
 		    p = dln_find_exe_r(cmd, NULL, fbuf, sizeof(fbuf));
 		    break;
 		}
-		if (strchr(".:*?\"/\\", *prog)) {
+		if (strchr(":*?\"/\\", *prog)) {
 		    if (cmd[len]) {
-			char *tmp = ALLOCA_N(char, len + 1);
-			memcpy(tmp, cmd, len);
-			tmp[len] = 0;
-			cmd = tmp;
+			STRNDUPA(p, cmd, len);
 		    }
+		    p = dln_find_exe_r(p ? p : cmd, NULL, fbuf, sizeof(fbuf));
+		    cmd += len;
 		    break;
 		}
 		if (ISSPACE(*prog) || strchr("<>|", *prog)) {
 		    len = prog - cmd;
-		    p = ALLOCA_N(char, len + 1);
-		    memcpy(p, cmd, len);
-		    p[len] = 0;
+		    STRNDUPA(p, cmd, len);
 		    p = dln_find_exe_r(p, NULL, fbuf, sizeof(fbuf));
 		    break;
 		}
@@ -1047,36 +956,61 @@
     }
     if (p) {
 	shell = p;
-	while (*p) {
-	    if ((unsigned char)*p == '/')
-		*p = '\\';
-	    p = CharNext(p);
-	}
+	translate_char(p, '/', '\\');
     }
 
-    RUBY_CRITICAL({
-	fRet = CreateProcess(shell, (char *)cmd, psa, psa,
-			     psa->bInheritHandle, dwCreationFlags, NULL, NULL,
-			     &aStartupInfo, &aProcessInformation);
-	errno = map_errno(GetLastError());
-    });
+    return child_result(CreateChild(cmd, shell, NULL, NULL, NULL, NULL), mode);
+}
 
-    if (!fRet) {
-	child->pid = 0;		/* release the slot */
-	return NULL;
-    }
+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];
 
-    CloseHandle(aProcessInformation.hThread);
+    if (check_spawn_mode(mode)) return -1;
 
-    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;
+    if (!prog) prog = argv[0];
+    if ((shell = getenv("COMSPEC")) &&
+	(has_redirection(prog) ||
+	 is_internal_cmd(prog, !is_command_com(shell)))) {
+	prog = shell;
+	c_switch = 1;
+	differ = 1;
     }
-
-    return child;
+    else if ((cmd = dln_find_exe_r(prog, NULL, fbuf, sizeof(fbuf)))) {
+	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 {
@@ -1176,6 +1110,12 @@
 	    ptr++;
 	    break;
 
+	  case '%':
+	    if (*++ptr != '_' && !ISALPHA(*ptr)) break;
+	    while (*++ptr == '_' || ISALNUM(*ptr));
+	    if (*ptr++ == '%') return TRUE;
+	    break;
+
 	  case '\\':
 	    ptr++;
 	  default:
Index: ruby_1_9_1/dln.c
===================================================================
--- ruby_1_9_1/dln.c	(revision 20898)
+++ ruby_1_9_1/dln.c	(revision 20899)
@@ -1518,28 +1518,70 @@
     register const char *ep;
     register char *bp;
     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;
 
     RETURN_IF(!fname);
-    RETURN_IF(fname[0] == '/');
-    RETURN_IF(strncmp("./", fname, 2) == 0 || strncmp("../", fname, 3) == 0);
-    RETURN_IF(exe_flag && strchr(fname, '/'));
 #ifdef DOSISH
-    RETURN_IF(fname[0] == '\\');
+# ifndef CharNext
+# define CharNext(p) ((p)+1)
+# endif
 # ifdef DOSISH_DRIVE_LETTER
-    RETURN_IF(strlen(fname) > 2 && fname[1] == ':');
+    if (((p[0] | 0x20) - 'a') < 26  && p[1] == ':') {
+	p += 2;
+	is_abs = 1;
+    }
 # endif
-    RETURN_IF(strncmp(".\\", fname, 2) == 0 || strncmp("..\\", fname, 3) == 0);
-    RETURN_IF(exe_flag && strchr(fname, '\\'));
+    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(strncmp("./", fname, 2) == 0 || strncmp("../", fname, 3) == 0);
+    RETURN_IF(exe_flag && strchr(fname, '/'));
+
 #undef RETURN_IF
 
     for (dp = path;; dp = ++ep) {
 	register int l;
-	int i;
-	int fspace;
 
 	/* extract a component */
 	ep = strchr(dp, PATH_SEP[0]);
@@ -1602,7 +1644,7 @@
 	memcpy(bp, fname, i + 1);
 
 #if defined(DOSISH)
-	if (exe_flag) {
+	if (exe_flag && !has_ext) {
 	    static const char extension[][5] = {
 #if defined(__EMX__) || defined(_WIN32)
 		".exe", ".com", ".cmd", ".bat",
@@ -1611,6 +1653,7 @@
 	    };
 	    int j;
 
+	  needs_extension:
 	    for (j = 0; j < sizeof(extension) / sizeof(extension[0]); j++) {
 		if (fspace < strlen(extension[j])) {
 		    fprintf(stderr, "openpath: pathname too long (ignored)\n");

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]