diff --git a/winsup/cygwin/pinfo.cc b/winsup/cygwin/pinfo.cc index 9b74442d0..a88b6d06c 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 fd76c8d6b..7ad12941c 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);