[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: path separator (was: target triplet)

From: Brian Dessent
Subject: Re: path separator (was: target triplet)
Date: Tue, 23 Jan 2007 12:28:48 -0800

Matthew Woehlke wrote:

> ...and I should clarify, *only* $PATH (and I think $PWD and/or one or
> two others, but nothing else) is translated. So your statement is
> actually correct except you forgot the exception. :-)
> I forget exactly what "others" is/are, but it's something that basically
> /has/ to be translated, because both POSIX (Cygwin) and Windows need it
> to be meaningful values in their 'language'. I.e. if Cygwin doesn't
> break, assume all variables that will be used by a native Windows
> program (like, e.g. LIB, INCLUDE) should be given in DOS style.

What Cygwin does for the environment is actually rather complicated --
it maintains two completely separate copies of it.

The 'real' environment is the one that Windows knows about: the one that
you can access with the Win32 API functions
{Get,Set}EnvironmentVariable, the one that is passed to child processes
with CreateProcess, the one you see if you inspect the process with's Process Explorer, and so on.  This is also what will
be seen by any "native" (non-Cygwin) binary created as a child process.

The 'fake' environment is maintained entirely internal to Cygwin.  It is
what is accessed by all POSIX functions {get,set,put}env, etc. as well
as any other standard C pointers such as the third main argument.  It is
also passed on to Cygwin child processes, but indirectly through the
special Cygwin parent-child communication, not via the usual
CreateProcess inheritance.  This also means any size limitations imposed
by Windows do not exist, so the max PATH length and total environment
size are virtually unlimited, which is a nice side effect.  (I will
refer to this environment as the POSIX environment from here on.)

So the 'real' environment contains variables in native form, e.g.
"PATH=C:\WINDOWS;C:\WINDOWS\SYSTEM", and the POSIX environment contains
all variables in POSIX form, e.g.

Now, it would be really inefficient if it had to keep a copy of every
environment variable in both environments, and handle keeping them in
sync every time one changes.  Thus when a Cygwin binary first launches
(and it's not inheriting a POSIX environ from a parent) it takes its
'real' environment, POSIX-ifies certain members[1], and copies the rest
verbatim into the POSIX environment.  It then empties the 'real'
environment entirely except for a handful[2] of required variables that
must remain for certain Win32 API calls to succeed.

Hence the normal state of existance for a Cygwin process is to have an
almost empty 'real' environment with the actual meat being the POSIX
environment.  This works because Cygwin binaries all use the POSIX
access methods to get/set values, all of which go through Cygwin and
thus can modify this POSIX environment.

This works all well and fine until it's time to create a child process. 
Here, when launching a Cygwin process there's no need to even sync the
POSIX environment back to the 'real' one, since the child will get a
copy of the POSIX one anyway.  But for other cases, it is necessary to
first sync in the reverse direction and populate the 'real' environment,
so that native apps work as expected.

This gets us to the current behavior: Cygwin binaries see POSIX style
values, native apps see native style values, and child inheritance both
directions works as expected with appropriate path style conversion. 
And of course Cygwin binaries still have a skeletal 'real' environment
for the sake of Win32 API calls.

There is only one remaining wrinkle, and that is when a Cygwin binary
tries to access its environment using native/Win32 API methods, or if a
Cygwin binary wants to call CreateProcess directly.  Normally this kind
of "API leaking" is a bad thing -- Cygwin binaries should use POSIX
methods for everything.  But it still comes up occasionally.  In this
case there is a hook call[3] that can be used to force Cygwin to do the
POSIX to 'real' sync.

So back to the original question... Simply put, any Cygwin binary should
always use POSIX paths, colons for path separators, and
{get,set,put}env.  The rest should be taken care of automatically.


[3] cygwin_internal(CW_SYNC_WINENV)

reply via email to

[Prev in Thread] Current Thread [Next in Thread]