summaryrefslogtreecommitdiff
path: root/win32/win32.c
diff options
context:
space:
mode:
authorJan Dubois <jand@activestate.com>2007-01-04 04:37:48 -0800
committerRafael Garcia-Suarez <rgarciasuarez@gmail.com>2007-01-05 07:49:03 +0000
commitdc0472e9a2aeded945eee8b1bb412d40eff4fe15 (patch)
tree07c3f0b57bb2caed14e7753ca61d4f63c0b7e9cb /win32/win32.c
parentae6198af6119a45e6060c5903f4eddcd7b0f9ade (diff)
downloadperl-dc0472e9a2aeded945eee8b1bb412d40eff4fe15.tar.gz
ANSIfy the PATH environment variable on Windows
Message-ID: <7coqp2pme3r30qaonticuv6c6licieg4cg@4ax.com> p4raw-id: //depot/perl@29690
Diffstat (limited to 'win32/win32.c')
-rw-r--r--win32/win32.c96
1 files changed, 96 insertions, 0 deletions
diff --git a/win32/win32.c b/win32/win32.c
index 4a90d0a02b..562dc0bcd8 100644
--- a/win32/win32.c
+++ b/win32/win32.c
@@ -4781,6 +4781,100 @@ win32_signal(int sig, Sighandler_t subcode)
#ifdef HAVE_INTERP_INTERN
+static void
+ansify_path(void)
+{
+ OSVERSIONINFO osver; /* g_osver may not yet be initialized */
+ size_t len;
+ char *ansi_path;
+ WCHAR *wide_path;
+ WCHAR *wide_dir;
+
+ /* there is no Unicode environment on Windows 9X */
+ osver.dwOSVersionInfoSize = sizeof(osver);
+ GetVersionEx(&osver);
+ if (osver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
+ return;
+
+ /* fetch Unicode version of PATH */
+ len = 2000;
+ wide_path = win32_malloc(len*sizeof(WCHAR));
+ while (wide_path) {
+ size_t newlen = GetEnvironmentVariableW(L"PATH", wide_path, len);
+ if (newlen < len)
+ break;
+ len = newlen;
+ wide_path = win32_realloc(wide_path, len*sizeof(WCHAR));
+ }
+ if (!wide_path)
+ return;
+
+ /* convert to ANSI pathnames */
+ wide_dir = wide_path;
+ ansi_path = NULL;
+ while (wide_dir) {
+ WCHAR *sep = wcschr(wide_dir, ';');
+ char *ansi_dir;
+ size_t ansi_len;
+ size_t wide_len;
+
+ if (sep)
+ *sep++ = '\0';
+
+ /* remove quotes around pathname */
+ if (*wide_dir == '"')
+ ++wide_dir;
+ wide_len = wcslen(wide_dir);
+ if (wide_len && wide_dir[wide_len-1] == '"')
+ wide_dir[wide_len-1] = '\0';
+
+ /* append ansi_dir to ansi_path */
+ ansi_dir = win32_ansipath(wide_dir);
+ ansi_len = strlen(ansi_dir);
+ if (ansi_path) {
+ size_t newlen = len + 1 + ansi_len;
+ ansi_path = win32_realloc(ansi_path, newlen+1);
+ if (!ansi_path)
+ break;
+ ansi_path[len] = ';';
+ memcpy(ansi_path+len+1, ansi_dir, ansi_len+1);
+ len = newlen;
+ }
+ else {
+ len = ansi_len;
+ ansi_path = win32_malloc(5+len+1);
+ if (!ansi_path)
+ break;
+ memcpy(ansi_path, "PATH=", 5);
+ memcpy(ansi_path+5, ansi_dir, len+1);
+ len += 5;
+ }
+ win32_free(ansi_dir);
+ wide_dir = sep;
+ }
+
+ if (ansi_path) {
+ /* Update C RTL environ array. This will only have full effect if
+ * perl_parse() is later called with `environ` as the `env` argument.
+ * Otherwise S_init_postdump_symbols() will overwrite PATH again.
+ *
+ * We do have to ansify() the PATH before Perl has been fully
+ * initialized because S_find_script() uses the PATH when perl
+ * is being invoked with the -S option. This happens before %ENV
+ * is initialized in S_init_postdump_symbols().
+ *
+ * XXX Is this a bug? Should S_find_script() use the environment
+ * XXX passed in the `env` arg to parse_perl()?
+ */
+ putenv(ansi_path);
+ /* Keep system environment in sync because S_init_postdump_symbols()
+ * will not call mg_set() if it initializes %ENV from `environ`.
+ */
+ SetEnvironmentVariableA("PATH", ansi_path+5);
+ win32_free(ansi_path);
+ }
+ win32_free(wide_path);
+}
static void
win32_csighandler(int sig)
@@ -4853,6 +4947,8 @@ Perl_sys_intern_init(pTHX)
/* Push our handler on top */
SetConsoleCtrlHandler(win32_ctrlhandler,TRUE);
}
+
+ ansify_path();
}
void