[PATCH 2/3] Add a _pinfo.environ() method analogous to _pinfo.cmdline(), and others.
erik.m.bray@gmail.com
erik.m.bray@gmail.com
Thu Jan 5 17:39:00 GMT 2017
From: "Erik M. Bray" <erik.bray@lri.fr>
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 | 89 ++++++++++++++++++++++++++++++++++++++++++++++++--
winsup/cygwin/pinfo.h | 4 ++-
2 files changed, 90 insertions(+), 3 deletions(-)
diff --git a/winsup/cygwin/pinfo.cc b/winsup/cygwin/pinfo.cc
index 1ce6809..a3e376c 100644
--- a/winsup/cygwin/pinfo.cc
+++ b/winsup/cygwin/pinfo.cc
@@ -653,8 +653,29 @@ 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 +751,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 +1015,69 @@ _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);
+
+ n = 0;
+ 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 = mbi.RegionSize - ((char*) rupp.Environment - (char*) 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;
+
+ 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
More information about the Cygwin-patches
mailing list