From ba1a12170b972485ee5271d7d84e2b79382f27a9 Mon Sep 17 00:00:00 2001 From: nobu Date: Fri, 20 Mar 2009 23:17:42 +0000 Subject: [PATCH] * win32/win32.c (rb_w32_spawn, rb_w32_aspawn): omit program name if actual program path is found. [ruby-core:22960] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@23023 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 5 ++ win32/win32.c | 169 +++++++++++++++++++++++++++++++++++--------------- 2 files changed, 123 insertions(+), 51 deletions(-) diff --git a/ChangeLog b/ChangeLog index a1ef9b76a9..bbbf65aba7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Sat Mar 21 08:17:41 2009 Nobuyoshi Nakada + + * win32/win32.c (rb_w32_spawn, rb_w32_aspawn): omit program name + if actual program path is found. [ruby-core:22960] + Sat Mar 21 07:25:56 2009 Nobuyoshi Nakada * io.c (pipe_open): should pass program name even if multiple diff --git a/win32/win32.c b/win32/win32.c index 19b122041d..ddbbe41c8b 100644 --- a/win32/win32.c +++ b/win32/win32.c @@ -845,7 +845,7 @@ join_argv(char *cmd, char *const *argv, BOOL escape) for (t = argv, q = cmd; p = *t; t++) { quote = 0; s = p; - if (!*p || strpbrk(p, " \t\"")) { + if (!*p || strpbrk(p, " \t\"'")) { quote = 1; *q++ = '"'; } @@ -1018,6 +1018,10 @@ rb_w32_spawn(int mode, const char *cmd, const char *prog) if (!(p = dln_find_exe_r(prog, NULL, fbuf, sizeof(fbuf)))) { shell = prog; } + else { + shell = p; + translate_char(p, '/', '\\'); + } } else { int redir = -1; @@ -1038,55 +1042,49 @@ rb_w32_spawn(int mode, const char *cmd, const char *prog) cmd = tmp; } else { - int len = 0; - if (*cmd == '"') { - for (prog = cmd + 1; *prog && *prog != '"'; prog = CharNext(prog)); - len = prog - cmd - 1; - STRNDUPA(p, cmd + 1, len); - p = dln_find_exe_r(p, NULL, fbuf, sizeof(fbuf)); - if (p) goto command_found; - } - for (prog = cmd; *prog; prog = CharNext(prog)) { - if (ISSPACE(*prog)) { - len = prog - cmd; - do ++prog; while (ISSPACE(*prog)); - break; - } - else { - len = 0; - } - } - if (!len) len = strlen(cmd); - + int len = 0, quote = (*cmd == '"') ? '"' : 0; shell = NULL; - prog = cmd; - for (;;) { + for (prog = cmd + !!quote;; prog = CharNext(prog)) { if (!*prog) { - p = dln_find_exe_r(cmd, NULL, fbuf, sizeof(fbuf)); + len = prog - cmd; + shell = cmd; break; } - if (strchr(":*?\"/\\", *prog)) { - if (cmd[len]) { - STRNDUPA(p, cmd, len); - } - p = dln_find_exe_r(p ? p : cmd, NULL, fbuf, sizeof(fbuf)); + if (*prog == quote) { + len = prog++ - cmd - 1; + STRNDUPA(p, cmd + 1, len); + shell = p; + break; + } + if (quote) continue; + if (strchr("*?\"", *prog)) { + len = prog - cmd; + STRNDUPA(p, cmd, len); + shell = p; break; } if (ISSPACE(*prog) || strchr("<>|", *prog)) { len = prog - cmd; STRNDUPA(p, cmd, len); - p = dln_find_exe_r(p, NULL, fbuf, sizeof(fbuf)); + shell = p; break; } - prog++; + } + shell = dln_find_exe_r(shell, NULL, fbuf, sizeof(fbuf)); + if (shell == fbuf) { + len += strlen(prog) + (quote ? 2 : 0) + 1; + cmd = p = ALLOCA_N(char, len); + if (quote) *p++ = '"'; + p += strlcpy(p, fbuf, --len); + if (quote) *p++ = '"'; + p += strlcpy(p, prog, --len); + if (quote) shell = NULL; + } + else { + shell = p; } } } - if (p) { - command_found: - shell = p; - translate_char(p, '/', '\\'); - } return child_result(CreateChild(cmd, shell, NULL, NULL, NULL, NULL), mode); } @@ -1134,6 +1132,7 @@ rb_w32_aspawn(int mode, const char *prog, char *const *argv) join_argv(cmd, progs, ntcmd); if (c_switch) strlcat(cmd, " /c", len); if (argv[0]) join_argv(cmd + strlcat(cmd, " ", len), argv, ntcmd); + prog = 0; } else { len = argv_size(argv, FALSE); @@ -1665,6 +1664,17 @@ move_to_next_entry(DIR *dirp) } } +static char * +win32_conv_from_wstr(const WCHAR *wstr, long *len) +{ + UINT cp = AreFileApisANSI() ? CP_ACP : CP_OEMCP; + char *ptr; + *len = WideCharToMultiByte(cp, 0, wstr, -1, NULL, 0, NULL, NULL) - 1; + if (!(ptr = malloc(*len + 1))) return 0; + WideCharToMultiByte(cp, 0, wstr, -1, ptr, *len + 1, NULL, NULL); + return ptr; +} + // // Readdir just returns the current string pointer and bumps the // string pointer to the next entry. @@ -1672,13 +1682,8 @@ move_to_next_entry(DIR *dirp) static BOOL win32_direct_conv(const WCHAR *file, struct direct *entry, rb_encoding *dummy) { - UINT cp = AreFileApisANSI() ? CP_ACP : CP_OEMCP; - entry->d_namlen = - WideCharToMultiByte(cp, 0, file, -1, NULL, 0, NULL, NULL) - 1; - if (!(entry->d_name = malloc(entry->d_namlen + 1))) + if (!(entry->d_name = win32_conv_from_wstr(file, &entry->d_namlen))) return FALSE; - WideCharToMultiByte(cp, 0, file, -1, entry->d_name, entry->d_namlen + 1, - NULL, NULL); return TRUE; } @@ -1708,19 +1713,25 @@ rb_w32_conv_from_wchar(const WCHAR *wstr, rb_encoding *enc) return rb_str_encode(src, rb_enc_from_encoding(enc), ecflags, ecopts); } +char * +rb_w32_conv_from_wstr(const WCHAR *wstr, long *lenp, rb_encoding *enc) +{ + VALUE str = rb_w32_conv_from_wchar(wstr, enc); + long len; + char *ptr; + + if (NIL_P(str)) return win32_conv_from_wstr(wstr, lenp); + *lenp = len = RSTRING_LEN(str); + memcpy(ptr = malloc(len + 1), RSTRING_PTR(str), len); + ptr[len] = '\0'; + return ptr; +} + static BOOL ruby_direct_conv(const WCHAR *file, struct direct *entry, rb_encoding *enc) { - VALUE dst = rb_w32_conv_from_wchar(file, enc); - - if (NIL_P(dst)) - return win32_direct_conv(file, entry, NULL); - - entry->d_namlen = RSTRING_LEN(dst); - if (!(entry->d_name = malloc(entry->d_namlen + 1))) + if (!(entry->d_name = rb_w32_conv_from_wstr(file, &entry->d_namlen, enc))) return FALSE; - memcpy(entry->d_name, RSTRING_PTR(dst), entry->d_namlen); - entry->d_name[entry->d_namlen] = '\0'; return TRUE; } @@ -5002,3 +5013,59 @@ rb_w32_fsopen(const char *path, const char *mode, int shflags) return f; } #endif + +BOOL +rb_w32_get_special_directory(int n, WCHAR *path) +{ + if (!get_special_folder(n, path)) + return FALSE; + regulate_path(path); + return TRUE; +} + +static VALUE +w32_get_special_directory(VALUE self, VALUE num) +{ + VALUE str; + int n = NUM2INT(num); + WCHAR path[_MAX_PATH]; + + if (!rb_w32_get_special_directory(n, path)) { + rb_sys_fail(0); + } + str = rb_w32_conv_from_wchar(path, rb_filesystem_encoding()); + OBJ_TAINT(str); + return str; +} + +static VALUE +w32_get_system_directory(VALUE self) +{ + VALUE str; + WCHAR path[_MAX_PATH]; + + if (!get_system_directory(path, numberof(path))) { + rb_sys_fail(0); + } + regulate_path(path); + str = rb_w32_conv_from_wchar(path, rb_filesystem_encoding()); + OBJ_TAINT(str); + return str; +} + +void +Init_win32(void) +{ + VALUE mWin32 = rb_define_module("Win32"); + VALUE dir = rb_define_module_under(mWin32, "Dir"); + rb_define_module_function(dir, "special", w32_get_special_directory, 1); + rb_define_module_function(dir, "system", w32_get_system_directory, 0); + rb_define_const(dir, "LOCAL_APPDATA", UINT2NUM(CSIDL_LOCAL_APPDATA)); + rb_define_const(dir, "COMMON_APPDATA", UINT2NUM(CSIDL_COMMON_APPDATA)); + rb_define_const(dir, "WINDOWS", UINT2NUM(CSIDL_WINDOWS)); + rb_define_const(dir, "SYSTEM", UINT2NUM(CSIDL_SYSTEM)); + rb_define_const(dir, "PROFILE", UINT2NUM(CSIDL_PROFILE)); + rb_define_const(dir, "PERSONAL", UINT2NUM(CSIDL_PERSONAL)); + rb_define_const(mWin32, "Version", UINT2NUM(rb_w32_osver())); + rb_ivar_set(rb_mKernel, rb_intern("@__win32__"), mWin32); +}