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);
61 string_type get(const pointer_type id) { return get(string_type(id)); }
62 void set(const pointer_type id, const pointer_type value)
64 set(string_type(id), string_type(value));
66 void reset(const pointer_type id) { reset(string_type(id)); }
68 string_type get(const string_type & id)
70 std::string id_c = ::boost::process::detail::convert(id);
71 std::string g = ::getenv(id_c.c_str());
72 return ::boost::process::detail::convert(g.c_str());
74 void set(const string_type & id, const string_type & value)
76 std::string id_c = ::boost::process::detail::convert(id.c_str());
77 std::string value_c = ::boost::process::detail::convert(value.c_str());
78 auto res = ::setenv(id_c.c_str(), value_c.c_str(), true);
80 boost::process::detail::throw_last_error();
82 void reset(const string_type & id)
84 std::string id_c = ::boost::process::detail::convert(id.c_str());
85 auto res = ::unsetenv(id_c.c_str());
87 ::boost::process::detail::throw_last_error();
90 native_environment_impl() = default;
91 native_environment_impl(const native_environment_impl& ) = delete;
92 native_environment_impl(native_environment_impl && ) = default;
93 native_environment_impl & operator=(const native_environment_impl& ) = delete;
94 native_environment_impl & operator=(native_environment_impl && ) = default;
95 native_handle_type _env_impl = _impl.data();
97 native_handle_type native_handle() const {return _env_impl;}
101 class native_environment_impl<char>
104 using char_type = char;
105 using pointer_type = const char_type*;
106 using string_type = std::basic_string<char_type>;
107 using native_handle_type = char_type **;
109 void reload() {this->_env_impl = ::environ;}
111 string_type get(const pointer_type id) { return getenv(id); }
112 void set(const pointer_type id, const pointer_type value)
114 auto res = ::setenv(id, value, 1);
116 boost::process::detail::throw_last_error();
119 void reset(const pointer_type id)
121 auto res = ::unsetenv(id);
123 boost::process::detail::throw_last_error();
127 string_type get(const string_type & id) {return get(id.c_str());}
128 void set(const string_type & id, const string_type & value) {set(id.c_str(), value.c_str()); }
129 void reset(const string_type & id) {reset(id.c_str());}
131 native_environment_impl() = default;
132 native_environment_impl(const native_environment_impl& ) = delete;
133 native_environment_impl(native_environment_impl && ) = default;
134 native_environment_impl & operator=(const native_environment_impl& ) = delete;
135 native_environment_impl & operator=(native_environment_impl && ) = default;
136 native_handle_type _env_impl = environ;
138 native_handle_type native_handle() const {return ::environ;}
143 template<typename Char>
144 struct basic_environment_impl
146 std::vector<std::basic_string<Char>> _data {};
147 static std::vector<Char*> _load_var(std::vector<std::basic_string<Char>> & data);
148 std::vector<Char*> _env_arr{_load_var(_data)};
150 using char_type = Char;
151 using pointer_type = const char_type*;
152 using string_type = std::basic_string<char_type>;
153 using native_handle_type = Char**;
156 _env_arr = _load_var(_data);
157 _env_impl = _env_arr.data();
160 string_type get(const pointer_type id) {return get(string_type(id));}
161 void set(const pointer_type id, const pointer_type value) {set(string_type(id), value);}
162 void reset(const pointer_type id) {reset(string_type(id));}
164 string_type get(const string_type & id);
165 void set(const string_type & id, const string_type & value);
166 void reset(const string_type & id);
168 basic_environment_impl(const native_environment_impl<Char> & nei);
169 basic_environment_impl() = default;
170 basic_environment_impl(const basic_environment_impl& rhs)
175 basic_environment_impl(basic_environment_impl && ) = default;
176 basic_environment_impl & operator=(const basic_environment_impl& rhs)
179 _env_arr = _load_var(_data);
180 _env_impl = &*_env_arr.begin();
183 basic_environment_impl & operator=(basic_environment_impl && ) = default;
185 template<typename CharR>
186 explicit inline basic_environment_impl(
187 const basic_environment_impl<CharR>& rhs,
188 const ::boost::process::codecvt_type & cv = ::boost::process::codecvt())
189 : _data(rhs._data.size())
191 std::transform(rhs._data.begin(), rhs._data.end(), _data.begin(),
192 [&](const std::basic_string<CharR> & st)
194 return ::boost::process::detail::convert(st, cv);
201 template<typename CharR>
202 basic_environment_impl & operator=(const basic_environment_impl<CharR>& rhs)
204 _data = ::boost::process::detail::convert(rhs._data);
205 _env_arr = _load_var(&*_data.begin());
206 _env_impl = &*_env_arr.begin();
210 Char ** _env_impl = &*_env_arr.data();
212 native_handle_type native_handle() const {return &_data.front();}
216 template<typename Char>
217 basic_environment_impl<Char>::basic_environment_impl(const native_environment_impl<Char> & nei)
219 auto beg = nei.native_handle();
222 while (*end != nullptr)
224 this->_data.assign(beg, end);
229 template<typename Char>
230 inline auto basic_environment_impl<Char>::get(const string_type &id) -> string_type
232 auto itr = std::find_if(_data.begin(), _data.end(),
233 [&](const string_type & st)
235 if (st.size() <= id.size())
237 return std::equal(id.begin(), id.end(), st.begin()) && (st[id.size()] == equal_sign<Char>());
241 if (itr == _data.end())
246 itr->data() + id.size(); //id=Thingy -> +2 points to T
249 template<typename Char>
250 inline void basic_environment_impl<Char>::set(const string_type &id, const string_type &value)
252 auto itr = std::find_if(_data.begin(), _data.end(),
253 [&](const string_type & st)
255 if (st.size() <= id.size())
257 return std::equal(id.begin(), id.end(), st.begin()) && (st[id.size()] == equal_sign<Char>());
261 if (itr != _data.end())
262 *itr = id + equal_sign<Char>() + value;
264 _data.push_back(id + equal_sign<Char>() + value);
269 template<typename Char>
270 inline void basic_environment_impl<Char>::reset(const string_type &id)
272 auto itr = std::find_if(_data.begin(), _data.end(),
273 [&](const string_type & st)
275 if (st.size() <= id.size())
277 return std::equal(id.begin(), id.end(), st.begin()) && (st[id.size()] == equal_sign<Char>());
280 if (itr != _data.end())
282 _data.erase(itr);//and remove it
290 template<typename Char>
291 std::vector<Char*> basic_environment_impl<Char>::_load_var(std::vector<std::basic_string<Char>> & data)
293 std::vector<Char*> ret;
294 ret.reserve(data.size() +1);
296 for (auto & val : data)
300 ret.push_back(&val.front());
303 ret.push_back(nullptr);
307 template<typename T> constexpr T env_seperator();
308 template<> constexpr char env_seperator() {return ':'; }
309 template<> constexpr wchar_t env_seperator() {return L':'; }
312 typedef int native_handle_t;
314 inline int get_id() {return getpid(); }
315 inline int native_handle() {return getpid(); }
326 #endif /* BOOST_PROCESS_DETAIL_WINDOWS_ENV_STORAGE_HPP_ */