1 // Copyright (c) 2016 Klemens D. Morgenstern
3 // Distributed under the Boost Software License, Version 1.0. (See accompanying
4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 #ifndef BOOST_PROCESS_DETAIL_POSIX_ENVIRONMENT_HPP_
7 #define BOOST_PROCESS_DETAIL_POSIX_ENVIRONMENT_HPP_
11 #include <unordered_map>
12 #include <boost/process/detail/config.hpp>
15 #include <boost/process/locale.hpp>
18 namespace boost { namespace process { namespace detail { namespace posix {
20 template<typename Char>
21 class native_environment_impl
23 static std::vector<std::basic_string<Char>> _load()
25 std::vector<std::basic_string<Char>> val;
30 val.push_back(::boost::process::detail::convert(str));
35 static std::vector<Char*> _load_var(std::vector<std::basic_string<Char>> & vec)
37 std::vector<Char*> val;
38 val.resize(vec.size() + 1);
39 std::transform(vec.begin(), vec.end(), val.begin(),
40 [](std::basic_string<Char> & str)
47 std::vector<std::basic_string<Char>> _buffer = _load();
48 std::vector<Char*> _impl = _load_var(_buffer);
50 using char_type = Char;
51 using pointer_type = const char_type*;
52 using string_type = std::basic_string<char_type>;
53 using native_handle_type = char_type **;
58 _impl = _load_var(_buffer);
59 _env_impl = _impl.data();
62 string_type get(const pointer_type id) { return get(string_type(id)); }
63 void set(const pointer_type id, const pointer_type value)
65 set(string_type(id), string_type(value));
67 void reset(const pointer_type id) { reset(string_type(id)); }
69 string_type get(const string_type & id)
71 std::string id_c = ::boost::process::detail::convert(id);
72 std::string g = ::getenv(id_c.c_str());
73 return ::boost::process::detail::convert(g.c_str());
75 void set(const string_type & id, const string_type & value)
77 std::string id_c = ::boost::process::detail::convert(id.c_str());
78 std::string value_c = ::boost::process::detail::convert(value.c_str());
79 auto res = ::setenv(id_c.c_str(), value_c.c_str(), true);
81 boost::process::detail::throw_last_error();
83 void reset(const string_type & id)
85 std::string id_c = ::boost::process::detail::convert(id.c_str());
86 auto res = ::unsetenv(id_c.c_str());
88 ::boost::process::detail::throw_last_error();
91 native_environment_impl() = default;
92 native_environment_impl(const native_environment_impl& ) = delete;
93 native_environment_impl(native_environment_impl && ) = default;
94 native_environment_impl & operator=(const native_environment_impl& ) = delete;
95 native_environment_impl & operator=(native_environment_impl && ) = default;
96 native_handle_type _env_impl = _impl.data();
98 native_handle_type native_handle() const {return _env_impl;}
102 class native_environment_impl<char>
105 using char_type = char;
106 using pointer_type = const char_type*;
107 using string_type = std::basic_string<char_type>;
108 using native_handle_type = char_type **;
110 void reload() {this->_env_impl = ::environ;}
112 string_type get(const pointer_type id) { return getenv(id); }
113 void set(const pointer_type id, const pointer_type value)
115 auto res = ::setenv(id, value, 1);
117 boost::process::detail::throw_last_error();
120 void reset(const pointer_type id)
122 auto res = ::unsetenv(id);
124 boost::process::detail::throw_last_error();
128 string_type get(const string_type & id) {return get(id.c_str());}
129 void set(const string_type & id, const string_type & value) {set(id.c_str(), value.c_str()); }
130 void reset(const string_type & id) {reset(id.c_str());}
132 native_environment_impl() = default;
133 native_environment_impl(const native_environment_impl& ) = delete;
134 native_environment_impl(native_environment_impl && ) = default;
135 native_environment_impl & operator=(const native_environment_impl& ) = delete;
136 native_environment_impl & operator=(native_environment_impl && ) = default;
137 native_handle_type _env_impl = environ;
139 native_handle_type native_handle() const {return ::environ;}
144 template<typename Char>
145 struct basic_environment_impl
147 std::vector<std::basic_string<Char>> _data {};
148 static std::vector<Char*> _load_var(std::vector<std::basic_string<Char>> & data);
149 std::vector<Char*> _env_arr{_load_var(_data)};
151 using char_type = Char;
152 using pointer_type = const char_type*;
153 using string_type = std::basic_string<char_type>;
154 using native_handle_type = Char**;
157 _env_arr = _load_var(_data);
158 _env_impl = _env_arr.data();
161 string_type get(const pointer_type id) {return get(string_type(id));}
162 void set(const pointer_type id, const pointer_type value) {set(string_type(id), value);}
163 void reset(const pointer_type id) {reset(string_type(id));}
165 string_type get(const string_type & id);
166 void set(const string_type & id, const string_type & value);
167 void reset(const string_type & id);
169 basic_environment_impl(const native_environment_impl<Char> & nei);
170 basic_environment_impl() = default;
171 basic_environment_impl(const basic_environment_impl& rhs)
176 basic_environment_impl(basic_environment_impl && ) = default;
177 basic_environment_impl & operator=(const basic_environment_impl& rhs)
180 _env_arr = _load_var(_data);
181 _env_impl = &*_env_arr.begin();
184 basic_environment_impl & operator=(basic_environment_impl && ) = default;
186 template<typename CharR>
187 explicit inline basic_environment_impl(
188 const basic_environment_impl<CharR>& rhs,
189 const ::boost::process::codecvt_type & cv = ::boost::process::codecvt())
190 : _data(rhs._data.size())
192 std::transform(rhs._data.begin(), rhs._data.end(), _data.begin(),
193 [&](const std::basic_string<CharR> & st)
195 return ::boost::process::detail::convert(st, cv);
202 template<typename CharR>
203 basic_environment_impl & operator=(const basic_environment_impl<CharR>& rhs)
205 _data = ::boost::process::detail::convert(rhs._data);
206 _env_arr = _load_var(&*_data.begin());
207 _env_impl = &*_env_arr.begin();
211 Char ** _env_impl = &*_env_arr.data();
213 native_handle_type native_handle() const {return &_data.front();}
217 template<typename Char>
218 basic_environment_impl<Char>::basic_environment_impl(const native_environment_impl<Char> & nei)
220 auto beg = nei.native_handle();
223 while (*end != nullptr)
225 this->_data.assign(beg, end);
230 template<typename Char>
231 inline auto basic_environment_impl<Char>::get(const string_type &id) -> string_type
233 auto itr = std::find_if(_data.begin(), _data.end(),
234 [&](const string_type & st) -> bool
236 if (st.size() <= id.size())
238 return std::equal(id.begin(), id.end(), st.begin()) && (st[id.size()] == equal_sign<Char>());
242 if (itr == _data.end())
247 itr->data() + id.size(); //id=Thingy -> +2 points to T
250 template<typename Char>
251 inline void basic_environment_impl<Char>::set(const string_type &id, const string_type &value)
253 auto itr = std::find_if(_data.begin(), _data.end(),
254 [&](const string_type & st) -> bool
256 if (st.size() <= id.size())
258 return std::equal(id.begin(), id.end(), st.begin()) && (st[id.size()] == equal_sign<Char>());
262 if (itr != _data.end())
263 *itr = id + equal_sign<Char>() + value;
265 _data.push_back(id + equal_sign<Char>() + value);
270 template<typename Char>
271 inline void basic_environment_impl<Char>::reset(const string_type &id)
273 auto itr = std::find_if(_data.begin(), _data.end(),
274 [&](const string_type & st) -> bool
276 if (st.size() <= id.size())
278 return std::equal(id.begin(), id.end(), st.begin()) && (st[id.size()] == equal_sign<Char>());
281 if (itr != _data.end())
283 _data.erase(itr);//and remove it
291 template<typename Char>
292 std::vector<Char*> basic_environment_impl<Char>::_load_var(std::vector<std::basic_string<Char>> & data)
294 std::vector<Char*> ret;
295 ret.reserve(data.size() +1);
297 for (auto & val : data)
301 ret.push_back(&val.front());
304 ret.push_back(nullptr);
308 template<typename T> constexpr T env_seperator();
309 template<> constexpr char env_seperator() {return ':'; }
310 template<> constexpr wchar_t env_seperator() {return L':'; }
313 typedef int native_handle_t;
315 inline int get_id() {return getpid(); }
316 inline int native_handle() {return getpid(); }
327 #endif /* BOOST_PROCESS_DETAIL_WINDOWS_ENV_STORAGE_HPP_ */