Boost logo

Boost :

Subject: Re: [boost] Environment Variables Library?
From: Bjørn Roald (bjorn_at_[hidden])
Date: 2015-05-21 00:07:29


On 18. mai 2015 11:37, Michael Ainsworth wrote:
> Two primary purposes, two ideas for additional possible uses.
>
> Primary purposes:
>
> 1. To provide cross platform (e.g., POSIX plus Windows) equivalents of setenv, getenv, "unsetenv" and "issetenv".
> 2. To allow iteration over all defined environment variables.
>
> Additional possible uses:
>
> 1. To create a new environment to pass to a new process.
> 2. To provide non "char" based environment variables (e.g., std::wstring).
>

I am interested.

I think at least the primary purposes should be in the standard. So why
not start with a small Boost library that as a minimum provide that, try
out the response on this list then extend services based on demand and
your preferences.

I am surprised of the focus by others on why environment variables are
bad or out of fashion in some environments. While this may be true, I
think it is rather irrelevant. Environment variables are a useful
service provided in the runtime environment of C++ programs and should
be standardized. Posix sadly does not reach all C++ programs, so it
would be useful to have similar facilities inn the C++ standard.

There are valid and sensible use-cases for environment variables, and I
do not see them going away any time soon. Just as with regular C++
variables they may be used in less optimal ways, possibly even insecure
ways. However, note that Posix setenv(...) and Windows
SetEnvironmentVariable(...) does not pollute the global system or user
environment. They do not have global side effects outside the process
or possibly its subsequently created child processes. Thus processes
(C++ programs) provides a sort of scope for environment variables.

Arguments that what we normally need is simple enough with Posix or
Windows APIs just hints that this may be simple to to provide as
standardized facilities so it become trivial to write portable standard
C++ code using environment variables with no #ifdefs or other ugliness.
It may prove to be less simple than we expect, multi-byte characters and
OS size limitations comes to my mind as obstacles, but I think this is
worth trying out.

The facilities for manipulating the environment for child processes may
be a better fit for a separate library, e.g. Boost.Process, but there
may be a case for something simple in the proposed library that can be
managed in the process and passed when creating child processes as
alternative to inheriting the current environment.

One facility that could be nice is portable methods to convert
environment variable values into basic types as well as some more
complex types, in particular file system path and a sequence of file
system paths come to my mind. E.g.:

namespace env = boost::environment;
namespace fs = boost::filesystem;
std::vector<fs::path> paths = env::get_filesystem_paths("PATH");
fs::path home = env::get("HOME");
if(fs::is_directory(home))
{
   paths.push_back(home / "bin";
   env::set_filesystem_paths("PATH", paths);
}

may conveniently get and set the variable correctly using the various
correct path separators depending on operating system conventions.

Beyond the simple generic handling of environment variables above, a
library could provide truly portable accessors to some system wide and
user environment settings. This may deal with variable name variations,
and recommended use of platform API for each runtime environment, see:

http://en.wikipedia.org/wiki/Environment_variable

Such pure access methods, like

fs::path home = env::user_home_directory();

could provide values from $HOME on Unix, %HOMEDIR% on DOS, %USERPROFILE%
Windows or values from whatever environment variable or runtime API is
appropriate for the value in the actual runtime environment. Some other
similar settings that come to my mind as missing pure C++ solutions are
listed below:

// user login data
std::string user_name(); // return login
std::string user_domain(); // return login domain where appropriate

// common storage locations
fs:path user_download_directory();
fs:path user_documents_directory();
fs:path user_pictures_directory();
fs:path user_music_directory();
fs:path user_movies_directory();
fs:path user_desktop_directory();
fs:path temp_directory();

// paths to configuration files
fs:path user_application_data_directory();
fs:path common_application_data_directory();

// executable directory, useful to access installed data
fs:path executable_directory(); // path to running program file

https://msdn.microsoft.com/en-us/library/windows/desktop/bb762181%28v=vs.85%29.aspx
http://doc.qt.io/qt-4.8/qdesktopservices.html
http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html

--
Bjørn

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk