123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326 |
- // Copyright (c) 2016 Klemens D. Morgenstern
- //
- // Distributed under the Boost Software License, Version 1.0. (See accompanying
- // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- #ifndef BOOST_PROCESS_DETAIL_POSIX_ENVIRONMENT_HPP_
- #define BOOST_PROCESS_DETAIL_POSIX_ENVIRONMENT_HPP_
- #include <string>
- #include <vector>
- #include <unordered_map>
- #include <boost/process/detail/config.hpp>
- #include <algorithm>
- #include <cstdlib>
- #include <boost/process/locale.hpp>
- namespace boost { namespace process { namespace detail { namespace posix {
- template<typename Char>
- class native_environment_impl
- {
- static std::vector<std::basic_string<Char>> _load()
- {
- std::vector<std::basic_string<Char>> val;
- auto p = environ;
- while (*p != nullptr)
- {
- std::string str = *p;
- val.push_back(::boost::process::detail::convert(str));
- p++;
- }
- return val;
- }
- static std::vector<Char*> _load_var(std::vector<std::basic_string<Char>> & vec)
- {
- std::vector<Char*> val;
- val.resize(vec.size() + 1);
- std::transform(vec.begin(), vec.end(), val.begin(),
- [](std::basic_string<Char> & str)
- {
- return &str.front();
- });
- val.back() = nullptr;
- return val;
- }
- std::vector<std::basic_string<Char>> _buffer = _load();
- std::vector<Char*> _impl = _load_var(_buffer);
- public:
- using char_type = Char;
- using pointer_type = const char_type*;
- using string_type = std::basic_string<char_type>;
- using native_handle_type = char_type **;
- void reload()
- {
- _buffer = _load();
- _impl = _load_var(_buffer);
- }
- string_type get(const pointer_type id) { return get(string_type(id)); }
- void set(const pointer_type id, const pointer_type value)
- {
- set(string_type(id), string_type(value));
- }
- void reset(const pointer_type id) { reset(string_type(id)); }
- string_type get(const string_type & id)
- {
- std::string id_c = ::boost::process::detail::convert(id);
- std::string g = ::getenv(id_c.c_str());
- return ::boost::process::detail::convert(g.c_str());
- }
- void set(const string_type & id, const string_type & value)
- {
- std::string id_c = ::boost::process::detail::convert(id.c_str());
- std::string value_c = ::boost::process::detail::convert(value.c_str());
- auto res = ::setenv(id_c.c_str(), value_c.c_str(), true);
- if (res != 0)
- boost::process::detail::throw_last_error();
- }
- void reset(const string_type & id)
- {
- std::string id_c = ::boost::process::detail::convert(id.c_str());
- auto res = ::unsetenv(id_c.c_str());
- if (res != 0)
- ::boost::process::detail::throw_last_error();
- }
- native_environment_impl() = default;
- native_environment_impl(const native_environment_impl& ) = delete;
- native_environment_impl(native_environment_impl && ) = default;
- native_environment_impl & operator=(const native_environment_impl& ) = delete;
- native_environment_impl & operator=(native_environment_impl && ) = default;
- native_handle_type _env_impl = _impl.data();
- native_handle_type native_handle() const {return _env_impl;}
- };
- template<>
- class native_environment_impl<char>
- {
- public:
- using char_type = char;
- using pointer_type = const char_type*;
- using string_type = std::basic_string<char_type>;
- using native_handle_type = char_type **;
- void reload() {this->_env_impl = ::environ;}
- string_type get(const pointer_type id) { return getenv(id); }
- void set(const pointer_type id, const pointer_type value)
- {
- auto res = ::setenv(id, value, 1);
- if (res != 0)
- boost::process::detail::throw_last_error();
- reload();
- }
- void reset(const pointer_type id)
- {
- auto res = ::unsetenv(id);
- if (res != 0)
- boost::process::detail::throw_last_error();
- reload();
- }
- string_type get(const string_type & id) {return get(id.c_str());}
- void set(const string_type & id, const string_type & value) {set(id.c_str(), value.c_str()); }
- void reset(const string_type & id) {reset(id.c_str());}
- native_environment_impl() = default;
- native_environment_impl(const native_environment_impl& ) = delete;
- native_environment_impl(native_environment_impl && ) = default;
- native_environment_impl & operator=(const native_environment_impl& ) = delete;
- native_environment_impl & operator=(native_environment_impl && ) = default;
- native_handle_type _env_impl = environ;
- native_handle_type native_handle() const {return ::environ;}
- };
- template<typename Char>
- struct basic_environment_impl
- {
- std::vector<std::basic_string<Char>> _data {};
- static std::vector<Char*> _load_var(std::vector<std::basic_string<Char>> & data);
- std::vector<Char*> _env_arr{_load_var(_data)};
- public:
- using char_type = Char;
- using pointer_type = const char_type*;
- using string_type = std::basic_string<char_type>;
- using native_handle_type = Char**;
- void reload()
- {
- _env_arr = _load_var(_data);
- _env_impl = _env_arr.data();
- }
- string_type get(const pointer_type id) {return get(string_type(id));}
- void set(const pointer_type id, const pointer_type value) {set(string_type(id), value);}
- void reset(const pointer_type id) {reset(string_type(id));}
- string_type get(const string_type & id);
- void set(const string_type & id, const string_type & value);
- void reset(const string_type & id);
- basic_environment_impl(const native_environment_impl<Char> & nei);
- basic_environment_impl() = default;
- basic_environment_impl(const basic_environment_impl& rhs)
- : _data(rhs._data)
- {
- }
- basic_environment_impl(basic_environment_impl && ) = default;
- basic_environment_impl & operator=(const basic_environment_impl& rhs)
- {
- _data = rhs._data;
- _env_arr = _load_var(_data);
- _env_impl = &*_env_arr.begin();
- return *this;
- }
- basic_environment_impl & operator=(basic_environment_impl && ) = default;
- template<typename CharR>
- explicit inline basic_environment_impl(
- const basic_environment_impl<CharR>& rhs,
- const ::boost::process::codecvt_type & cv = ::boost::process::codecvt())
- : _data(rhs._data.size())
- {
- std::transform(rhs._data.begin(), rhs._data.end(), _data.begin(),
- [&](const std::basic_string<CharR> & st)
- {
- return ::boost::process::detail::convert(st, cv);
- }
- );
- reload();
- }
- template<typename CharR>
- basic_environment_impl & operator=(const basic_environment_impl<CharR>& rhs)
- {
- _data = ::boost::process::detail::convert(rhs._data);
- _env_arr = _load_var(&*_data.begin());
- _env_impl = &*_env_arr.begin();
- return *this;
- }
- Char ** _env_impl = &*_env_arr.data();
- native_handle_type native_handle() const {return &_data.front();}
- };
- template<typename Char>
- basic_environment_impl<Char>::basic_environment_impl(const native_environment_impl<Char> & nei)
- {
- auto beg = nei.native_handle();
- auto end = beg;
- while (*end != nullptr)
- end++;
- this->_data.assign(beg, end);
- reload();
- }
- template<typename Char>
- inline auto basic_environment_impl<Char>::get(const string_type &id) -> string_type
- {
- auto itr = std::find_if(_data.begin(), _data.end(),
- [&](const string_type & st) -> bool
- {
- if (st.size() <= id.size())
- return false;
- return std::equal(id.begin(), id.end(), st.begin()) && (st[id.size()] == equal_sign<Char>());
- }
- );
- if (itr == _data.end())
- {
- return "";
- }
- else return
- itr->data() + id.size(); //id=Thingy -> +2 points to T
- }
- template<typename Char>
- inline void basic_environment_impl<Char>::set(const string_type &id, const string_type &value)
- {
- auto itr = std::find_if(_data.begin(), _data.end(),
- [&](const string_type & st) -> bool
- {
- if (st.size() <= id.size())
- return false;
- return std::equal(id.begin(), id.end(), st.begin()) && (st[id.size()] == equal_sign<Char>());
- }
- );
- if (itr != _data.end())
- *itr = id + equal_sign<Char>() + value;
- else
- _data.push_back(id + equal_sign<Char>() + value);
- reload();
- }
- template<typename Char>
- inline void basic_environment_impl<Char>::reset(const string_type &id)
- {
- auto itr = std::find_if(_data.begin(), _data.end(),
- [&](const string_type & st) -> bool
- {
- if (st.size() <= id.size())
- return false;
- return std::equal(id.begin(), id.end(), st.begin()) && (st[id.size()] == equal_sign<Char>());
- }
- );
- if (itr != _data.end())
- {
- _data.erase(itr);//and remove it
- }
-
- reload();
- }
- template<typename Char>
- std::vector<Char*> basic_environment_impl<Char>::_load_var(std::vector<std::basic_string<Char>> & data)
- {
- std::vector<Char*> ret;
- ret.reserve(data.size() +1);
- for (auto & val : data)
- {
- if (val.empty())
- val.push_back(0);
- ret.push_back(&val.front());
- }
- ret.push_back(nullptr);
- return ret;
- }
- template<typename T> constexpr T env_seperator();
- template<> constexpr char env_seperator() {return ':'; }
- template<> constexpr wchar_t env_seperator() {return L':'; }
- typedef int native_handle_t;
- inline int get_id() {return getpid(); }
- inline int native_handle() {return getpid(); }
- }
- }
- }
- }
- #endif /* BOOST_PROCESS_DETAIL_WINDOWS_ENV_STORAGE_HPP_ */
|