On 21. mai 2015 12:59, Michael Ainsworth wrote:
On 21 May 2015, at 2:07 pm, Bjørn Roald
wrote: The facilities for manipulating the environment for child processes may be a betterfit 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. 1. You might be right, but my first instinct was that environment variables and processes “fit” together.
agree
2. On the other hand, a process management library (a Boost.Process revision?) that made use of the environment variable library would create a library dependency.
right, it may just be a header only declaration of a few common types that are used in both libraries, or some other way of compatible or shared types for transfeer of data. With some care there is no real dependency either way.
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::vectorfs::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); }
The same arguments we’ve raised regarding the integration of environment-variables/processes would also apply here. That is:
Filesystems are logically independent on environment variables - the only commonality is the use of strings to denote file system locations (e.g., $PATH or %PATH%). Integrating the two creates an (IMO) unnecessary dependency.
Maybe, there certainly is a cost and it may not be worth it, however in 2+ years we will have C++17 with std::filesystem::path so that may make the dependency less concerning. Sure users that do not use the path class should not pay the overhead of a dependency to the filesystem library.
I do like the idea of providing dedicated functions for specific environment variables. For example, “boost::environment::get_path()”.
Regarding the PATH variable (and other “array-like” character-delimited environment variables), I was thinking of implementing this with iterators. For example:
namespace env = boost::environment; environment& current = env::current_environment();
env::variable& path = current.get(“PATH”); for (env::variable::iterator it = path.begin(), end = path.end(); it != end; ++it) { std::cout << *it << std::endl; }
// Possible output: // /bin // /usr/bin // /usr/local/bin // /root/bin
This could be nice, but how does the iterator or environment container determine the colon separator for Unix and the semicolon for Windows. This sort of assumes the iterator only is used for PATH like variables. This may be OK, however the name should reflect it.
path += "/var/lib/pgsql-9.4/bin";
// would you not need platform specific code here? If nothing else for // the colon separator on Posix and semicolon separator on Windows #ifdef POSIX path += ":/var/lib/pgsql-9.4/bin"; #elif Windows path += ";C:\Program Files\pgsql-9.4\bin"; #else #error platform not supported #endif Not all that great, could be a portabe one liner: path,add_path( system_program_dir() / "pgsql-9.4/bin" ); or something like that. -- Bjørn