This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[RFC] Add support for locally modified environment variables for windows-nat.c
- From: "Pierre Muller" <pierre dot muller at ics-cnrs dot unistra dot fr>
- To: <gdb-patches at sourceware dot org>
- Cc: "'Sebastián Puebla Castro'" <spuebla at hotmail dot com>
- Date: Wed, 20 Apr 2011 12:26:25 +0200
- Subject: [RFC] Add support for locally modified environment variables for windows-nat.c
A while ago
Sebastian Puebla submitted a patch for
support of locally modified environment variables.
http://sourceware.org/ml/gdb-patches/2010-05/msg00317.html
http://sourceware.org/ml/gdb-patches/2010-08/msg00026.html
http://sourceware.org/ml/gdb-patches/2010-11/msg00128.html
Nevertheless, I suspect that his patch would not have worked for Cygwin,
because Cygwin converts several environment variables
from windows style to POSIX style.
Here is a patch that does support also Cygwin special variables.
This patch applies on top of my previously submitted patch
to separate out Cygwin/mingw and ANSI/Unicode specific code.
http://sourceware.org/ml/gdb-patches/2011-04/msg00328.html
The patch allows to propagate locally modified
environment variables to inferior for both Cygwin and mingw
compilation hosts.
There list of cygwin converted variables was
extracted from from winsup/cygwin/environ.cc source,
from January 2011.
Comments welcome,
Pierre Muller
2011-04-20 Pierre Muller <muller@ics.u-strasbg.fr>
Add support for locally modifed environment variables in windows
native hosts.
(win_env): New type.
(conv_envvars): New array of type win_env.
(cygwin_convert_envs, cywin_restore_envs): New functions using
CONV_ENVVARS array to convert Cygwin environment variables
back and forth to Windows style.
(windows_create_inferior): Add support for setting 7th parameter
of CreateProcess call containing possibly locally modified
environment variables.
diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c
index 9b49e6e..90e52af 100644
--- a/gdb/windows-nat.c
+++ b/gdb/windows-nat.c
@@ -1967,6 +1967,95 @@ windows_set_console_info (STARTUPINFO *si, DWORD
*flags)
*flags |= CREATE_NEW_CONSOLE;
}
+#ifdef __CYGWIN__
+/* List of names which are converted from dos to unix on the way in
+ and back again on the way out.
+ PATH needs to be here because CreateProcess uses it and gdb uses
+ CreateProcess. HOME is here because most shells use it and would be
+ confused by Windows style path names. */
+typedef struct struct_win_env {
+ char *name;
+ int in_index;
+ void *in_orig_val;
+ int is_list;
+} win_env;
+
+/* This list is extracted from cygwin/environ.cc source,
+ list from January 2011. */
+static win_env conv_envvars[] =
+ {
+ {"PATH=", -1, NULL, 1},
+ {"HOME=", -1, NULL, 0},
+ {"LD_LIBRARY_PATH=", -1, NULL, 1},
+ {"TMPDIR=", -1, NULL, 0},
+ {"TMP=", -1, NULL, 0},
+ {"TEMP=", -1, NULL, 0},
+ {NULL, -1, NULL, 0}
+ };
+
+/* cgwin_convert_envs function uses conv_envvars array above to
+ convert Cygwin environment variables back to win32 format. */
+
+static void
+cygwin_convert_envs (char **in_env)
+{
+ int i, j;
+
+ for (i = 0; in_env[i]; i++)
+ {
+ for (j = 0; conv_envvars[j].name; j++)
+ {
+ char *name = conv_envvars[j].name;
+ int nlen = strlen(name);
+
+ if (strncmp (in_env[i], name, nlen) == 0)
+ {
+ char *conv;
+ int len;
+
+ /* We found this environment variable that we need to convert.
*/
+ conv_envvars[j].in_index = i;
+ conv_envvars[j].in_orig_val = in_env[i];
+ if (conv_envvars[j].is_list)
+ {
+ len = cygwin_conv_path_list (CCP_POSIX_TO_WIN_A,
+ &in_env[i][nlen], NULL, 0);
+ conv = (char *) alloca (len + nlen + 1);
+ strcpy (conv, name);
+ cygwin_conv_path_list (CCP_POSIX_TO_WIN_A,
+ &in_env[i][nlen], &conv[nlen],
len);
+ }
+ else
+ {
+ conv = (char *) alloca (__PMAX + nlen);
+ strcpy (conv, name);
+ cygwin_conv_path (CCP_POSIX_TO_WIN_A,
+ &in_env[i][nlen], &conv[nlen], __PMAX);
+ }
+ in_env[i] = xstrdup (conv);
+ }
+ }
+ }
+}
+
+/* cygwin_restore_envs function restores in_env elements to their
+ original value. */
+
+static void
+cygwin_restore_envs (char **in_env)
+{
+ int i, j;
+
+ for (j = 0; conv_envvars[j].name; j++)
+ if (conv_envvars[j].in_index != -1)
+ {
+ xfree (in_env[conv_envvars[j].in_index]);
+ in_env[conv_envvars[j].in_index] = conv_envvars[j].in_orig_val;
+ }
+}
+
+#endif
+
/* Start an inferior windows child process and sets inferior_ptid to its
pid.
EXEC_FILE is the file to run.
ALLARGS is a string containing the arguments to the program.
@@ -1983,6 +2072,9 @@ windows_create_inferior (struct target_ops *ops, char
*exec_file,
win_buf_t *toexec;
win_buf_t *cygallargs;
win_buf_t *args;
+ size_t env_size;
+ int i;
+ win_buf_t *out_env;
#ifdef __USEWIDE
size_t len;
#endif
@@ -2010,6 +2102,7 @@ windows_create_inferior (struct target_ops *ops, char
*exec_file,
windows_set_console_info (&si, &flags);
#ifdef __CYGWIN__
+ cygwin_convert_envs (in_env);
if (!useshell)
#endif
{
@@ -2071,15 +2164,43 @@ windows_create_inferior (struct target_ops *ops,
char *exec_file,
wcscpy (args, toexec);
wcscat (args, L" ");
wcscat (args, cygallargs);
+ env_size = 1;
+ for (i = 0; in_env[i]; i++)
+ {
+ env_size += mbstowcs (NULL, in_env[i], 0) + 1;
+ }
+ out_env = (win_buf_t *) alloca (env_size * sizeof (win_buf_t *));
+ env_size = 0;
+ for (i = 0; in_env[i]; i++)
+ {
+ int len = mbstowcs (NULL, in_env[i], 0) + 1;
+ mbstowcs (&out_env[env_size], in_env[i], len);
+ env_size += len;
+ }
+ out_env[env_size] = L'\0';
+ flags |= CREATE_UNICODE_ENVIRONMENT;
#else
args = (win_buf_t *) alloca (strlen (toexec) + strlen (cygallargs) + 2);
strcpy (args, toexec);
strcat (args, " ");
strcat (args, cygallargs);
+ env_size = 1;
+ for (i = 0; in_env[i]; i++)
+ {
+ env_size += strlen(in_env[i]) + 1;
+ }
+ out_env = (win_buf_t *) alloca (env_size * sizeof (win_buf_t *));
+ env_size = 0;
+ for (i = 0; in_env[i]; i++)
+ {
+ int len = strlen(in_env[i]) + 1;
+ strcpy (&out_env[env_size], in_env[i]);
+ env_size += len;
+ }
+ out_env[env_size] = '\0';
#endif
#ifdef __CYGWIN__
- /* Prepare the environment vars for CreateProcess. */
cygwin_internal (CW_SYNC_WINENV);
if (!inferior_io_terminal)
@@ -2137,11 +2258,13 @@ windows_create_inferior (struct target_ops *ops,
char *exec_file,
NULL, /* thread */
TRUE, /* inherit handles */
flags, /* start flags */
- NULL, /* environment */
+ out_env, /* environment */
NULL, /* current directory */
&si,
&pi);
#ifdef __CYGWIN__
+ cygwin_restore_envs (in_env);
+
if (tty >= 0)
{
close (tty);