Quantcast

[PATCH 1/3] Move the core environment parsing of environ_init into a new win32env_to_cygenv function.

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

[PATCH 1/3] Move the core environment parsing of environ_init into a new win32env_to_cygenv function.

Erik Bray
From: Erik M. Bray <[hidden email]>

win32env_to_cygwenv handles converting wchar to char and some other
minor taks.  Optionally it handles converting any paths in variables to
posix paths.

This will be useful for implementing /proc/<pid>/environ
---
 winsup/cygwin/environ.cc | 84 ++++++++++++++++++++++++++++--------------------
 winsup/cygwin/environ.h  |  2 ++
 2 files changed, 51 insertions(+), 35 deletions(-)

diff --git a/winsup/cygwin/environ.cc b/winsup/cygwin/environ.cc
index 51107c5..667e7c0 100644
--- a/winsup/cygwin/environ.cc
+++ b/winsup/cygwin/environ.cc
@@ -758,18 +758,12 @@ ucenv (char *p, const char *eq)
 void
 environ_init (char **envp, int envc)
 {
-  PWCHAR rawenv, w;
-  int i;
+  PWCHAR rawenv;
   char *p;
-  char *newp;
-  int sawTERM = 0;
   bool envp_passed_in;
-  static char NO_COPY cygterm[] = "TERM=cygwin";
-  tmp_pathbuf tp;
 
   __try
     {
-      char *tmpbuf = tp.t_get ();
       if (!envp)
  envp_passed_in = 0;
       else
@@ -794,9 +788,6 @@ environ_init (char **envp, int envc)
   goto out;
  }
 
-      /* Allocate space for environment + trailing NULL + CYGWIN env. */
-      lastenviron = envp = (char **) malloc ((4 + (envc = 100)) * sizeof (char *));
-
       rawenv = GetEnvironmentStringsW ();
       if (!rawenv)
  {
@@ -805,32 +796,8 @@ environ_init (char **envp, int envc)
  }
       debug_printf ("GetEnvironmentStrings returned %p", rawenv);
 
-      /* Current directory information is recorded as variables of the
- form "=X:=X:\foo\bar; these must be changed into something legal
- (we could just ignore them but maybe an application will
- eventually want to use them).  */
-      for (i = 0, w = rawenv; *w != L'\0'; w = wcschr (w, L'\0') + 1, i++)
- {
-  sys_wcstombs_alloc_no_path (&newp, HEAP_NOTHEAP, w);
-  if (i >= envc)
-    envp = (char **) realloc (envp, (4 + (envc += 100)) * sizeof (char *));
-  envp[i] = newp;
-  if (*newp == '=')
-    *newp = '!';
-  char *eq = strchrnul (newp, '=');
-  ucenv (newp, eq); /* uppercase env vars which need it */
-  if (*newp == 'T' && strncmp (newp, "TERM=", 5) == 0)
-    sawTERM = 1;
-  else if (*newp == 'C' && strncmp (newp, "CYGWIN=", 7) == 0)
-    parse_options (newp + 7);
-  if (*eq)
-    posify_maybe (envp + i, *++eq ? eq : --eq, tmpbuf);
-  debug_printf ("%p: %s", envp[i], envp[i]);
- }
+  lastenviron = envp = win32env_to_cygenv (rawenv, true);
 
-      if (!sawTERM)
- envp[i++] = strdup (cygterm);
-      envp[i] = NULL;
       FreeEnvironmentStringsW (rawenv);
 
     out:
@@ -852,6 +819,53 @@ environ_init (char **envp, int envc)
   __endtry
 }
 
+
+char ** __reg2
+win32env_to_cygenv (PWCHAR rawenv, bool posify)
+{
+  tmp_pathbuf tp;
+  char **envp;
+  int envc;
+  char *newp;
+  int i;
+  int sawTERM = 0;
+  static char NO_COPY cygterm[] = "TERM=cygwin";
+  char *tmpbuf = tp.t_get ();
+  PWCHAR w;
+
+  /* Allocate space for environment + trailing NULL + CYGWIN env. */
+  envp = (char **) malloc ((4 + (envc = 100)) * sizeof (char *));
+
+  /* Current directory information is recorded as variables of the
+     form "=X:=X:\foo\bar; these must be changed into something legal
+     (we could just ignore them but maybe an application will
+     eventually want to use them).  */
+  for (i = 0, w = rawenv; *w != L'\0'; w = wcschr (w, L'\0') + 1, i++)
+    {
+      sys_wcstombs_alloc_no_path (&newp, HEAP_NOTHEAP, w);
+      if (i >= envc)
+        envp = (char **) realloc (envp, (4 + (envc += 100)) * sizeof (char *));
+      envp[i] = newp;
+      if (*newp == '=')
+        *newp = '!';
+      char *eq = strchrnul (newp, '=');
+      ucenv (newp, eq);    /* uppercase env vars which need it */
+      if (*newp == 'T' && strncmp (newp, "TERM=", 5) == 0)
+        sawTERM = 1;
+      else if (*newp == 'C' && strncmp (newp, "CYGWIN=", 7) == 0)
+        parse_options (newp + 7);
+      if (*eq && posify)
+        posify_maybe (envp + i, *++eq ? eq : --eq, tmpbuf);
+      debug_printf ("%p: %s", envp[i], envp[i]);
+    }
+
+  if (!sawTERM)
+    envp[i++] = strdup (cygterm);
+
+  envp[i] = NULL;
+  return envp;
+}
+
 /* Function called by qsort to sort environment strings.  */
 static int
 env_sort (const void *a, const void *b)
diff --git a/winsup/cygwin/environ.h b/winsup/cygwin/environ.h
index 46beb2d..269591a 100644
--- a/winsup/cygwin/environ.h
+++ b/winsup/cygwin/environ.h
@@ -45,4 +45,6 @@ extern "C" char __stdcall **cur_environ ();
 char ** __reg3 build_env (const char * const *envp, PWCHAR &envblock,
   int &envc, bool need_envblock, HANDLE new_token);
 
+char ** __reg2 win32env_to_cygenv (PWCHAR rawenv, bool posify);
+
 #define ENV_CVT -1
--
2.8.3

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

[PATCH 2/3] Add a _pinfo.environ() method analogous to _pinfo.cmdline(), and others.

Erik Bray
From: Erik M. Bray <[hidden email]>

Returns the process's environment concatenated into a single block of
null-terminated strings, along with the length of the environment block.

Adds an associated PICOM_ENVIRON commune_process handler.
---
 winsup/cygwin/pinfo.cc | 83 ++++++++++++++++++++++++++++++++++++++++++++++++--
 winsup/cygwin/pinfo.h  |  4 ++-
 2 files changed, 84 insertions(+), 3 deletions(-)

diff --git a/winsup/cygwin/pinfo.cc b/winsup/cygwin/pinfo.cc
index 1ce6809..fc80efc 100644
--- a/winsup/cygwin/pinfo.cc
+++ b/winsup/cygwin/pinfo.cc
@@ -653,8 +653,26 @@ commune_process (void *arg)
  else if (!WritePipeOverlapped (tothem, path, n, &nr, 1000L))
   sigproc_printf ("WritePipeOverlapped fd failed, %E");
  break;
-      }
-    }
+  }
+ case PICOM_ENVIRON:
+  {
+ sigproc_printf ("processing PICOM_ENVIRON");
+ unsigned n = 0;
+ char **env = cur_environ ();
+ for (char **e = env; *e; e++)
+  n += strlen (*e) + 1;
+ if (!WritePipeOverlapped (tothem, &n, sizeof n, &nr, 1000L))
+  sigproc_printf ("WritePipeOverlapped sizeof argv failed, %E");
+ else
+  for (char **e = env; *e; e++)
+    if (!WritePipeOverlapped (tothem, *e, strlen (*e) + 1, &nr, 1000L))
+      {
+        sigproc_printf ("WritePipeOverlapped arg %d failed, %E", e - env);
+        break;
+      }
+ break;
+  }
+ }
   if (process_sync)
     {
       DWORD res = WaitForSingleObject (process_sync, 5000);
@@ -730,6 +748,7 @@ _pinfo::commune_request (__uint32_t code, ...)
     {
     case PICOM_CMDLINE:
     case PICOM_CWD:
+    case PICOM_ENVIRON:
     case PICOM_ROOT:
     case PICOM_FDS:
     case PICOM_FD:
@@ -993,6 +1012,66 @@ _pinfo::cmdline (size_t& n)
   return s;
 }
 
+
+char *
+_pinfo::environ (size_t& n)
+{
+  char **env = NULL;
+  if (!this || !pid)
+    return NULL;
+  if (ISSTATE (this, PID_NOTCYGWIN))
+    {
+      RTL_USER_PROCESS_PARAMETERS rupp;
+      HANDLE proc = open_commune_proc_parms (dwProcessId, &rupp);
+
+      if (!proc)
+        return NULL;
+
+      MEMORY_BASIC_INFORMATION mbi;
+      SIZE_T envsize;
+      PWCHAR envblock;
+      if (!VirtualQueryEx (proc, rupp.Environment, &mbi, sizeof(mbi)))
+        {
+          NtClose (proc);
+          return NULL;
+        }
+
+      SIZE_T read;
+      envsize = (ptrdiff_t) mbi.RegionSize
+                - ((ptrdiff_t) rupp.Environment - (ptrdiff_t) mbi.BaseAddress);
+      envblock = (PWCHAR) cmalloc_abort (HEAP_COMMUNE, envsize);
+
+      if (ReadProcessMemory (proc, rupp.Environment, envblock, envsize, &read))
+        env = win32env_to_cygenv (envblock, false);
+
+      NtClose (proc);
+    }
+  else if (pid != myself->pid)
+    {
+      commune_result cr = commune_request (PICOM_ENVIRON);
+      n = cr.n;
+      return cr.s;
+    }
+  else
+    env = cur_environ ();
+
+  if (env == NULL)
+      return NULL;
+
+  n = 0;
+  for (char **e = env; *e; e++)
+    n += strlen (*e) + 1;
+
+  char *p, *s;
+  p = s = (char *) cmalloc_abort (HEAP_COMMUNE, n);
+  for (char **e = env; *e; e++)
+    {
+      strcpy (p, *e);
+      p = strchr (p, '\0') + 1;
+    }
+  return s;
+}
+
 /* This is the workhorse which waits for the write end of the pipe
    created during new process creation.  If the pipe is closed or a zero
    is received on the pipe, it is assumed that the cygwin pid has exited.
diff --git a/winsup/cygwin/pinfo.h b/winsup/cygwin/pinfo.h
index fd76c8d..7ad1294 100644
--- a/winsup/cygwin/pinfo.h
+++ b/winsup/cygwin/pinfo.h
@@ -26,7 +26,8 @@ enum picom
   PICOM_ROOT = 3,
   PICOM_FDS = 4,
   PICOM_FD = 5,
-  PICOM_PIPE_FHANDLER = 6
+  PICOM_PIPE_FHANDLER = 6,
+  PICOM_ENVIRON = 7
 };
 
 #define EXITCODE_SET 0x8000000
@@ -106,6 +107,7 @@ public:
   char *root (size_t &);
   char *cwd (size_t &);
   char *cmdline (size_t &);
+  char *environ (size_t &);
   char *win_heap_info (size_t &);
   bool set_ctty (class fhandler_termios *, int);
   bool alert_parent (char);
--
2.8.3

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

[PATCH 3/3] Add a /proc/<pid>/environ proc file handler, analogous to /proc/<pid>/cmdline.

Erik Bray
In reply to this post by Erik Bray
From: Erik M. Bray <[hidden email]>

---
 winsup/cygwin/fhandler_process.cc | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/winsup/cygwin/fhandler_process.cc b/winsup/cygwin/fhandler_process.cc
index 5f530a2..bbb44fa 100644
--- a/winsup/cygwin/fhandler_process.cc
+++ b/winsup/cygwin/fhandler_process.cc
@@ -49,6 +49,7 @@ static off_t format_process_ctty (void *, char *&);
 static off_t format_process_fd (void *, char *&);
 static off_t format_process_mounts (void *, char *&);
 static off_t format_process_mountinfo (void *, char *&);
+static off_t format_process_environ (void *, char *&);
 
 static const virt_tab_t process_tab[] =
 {
@@ -57,6 +58,7 @@ static const virt_tab_t process_tab[] =
   { _VN ("cmdline"),    FH_PROCESS,   virt_file,      format_process_cmdline },
   { _VN ("ctty"),       FH_PROCESS,   virt_file,      format_process_ctty },
   { _VN ("cwd"),        FH_PROCESS,   virt_symlink,   format_process_cwd },
+  { _VN ("environ"),    FH_PROCESS,   virt_file,      format_process_environ },
   { _VN ("exe"),        FH_PROCESS,   virt_symlink,   format_process_exename },
   { _VN ("exename"),    FH_PROCESS,   virt_file,      format_process_exename },
   { _VN ("fd"),         FH_PROCESSFD, virt_directory, format_process_fd },
@@ -570,6 +572,26 @@ format_process_winexename (void *data, char *&destbuf)
   return len;
 }
 
+static off_t
+format_process_environ (void *data, char *&destbuf)
+{
+  _pinfo *p = (_pinfo *) data;
+  size_t fs;
+
+  if (destbuf)
+    {
+      cfree (destbuf);
+      destbuf = NULL;
+    }
+  destbuf = p->environ (fs);
+  if (!destbuf || !*destbuf)
+    {
+      destbuf = cstrdup ("<defunct>");
+      fs = strlen (destbuf) + 1;
+    }
+  return fs;
+}
+
 struct heap_info
 {
   struct heap
--
2.8.3

Loading...