Add a _pinfo.environ() method analogous to _pinfo.cmdline(), and others.

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.
This commit is contained in:
Erik M. Bray 2017-01-10 16:03:09 +01:00 committed by Corinna Vinschen
parent 7fd70a9706
commit 578bbc3a29
2 changed files with 84 additions and 3 deletions

View File

@ -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.

View File

@ -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);