]>
Commit | Line | Data |
---|---|---|
b32b8144 FG |
1 | // Copyright (c) 2016 Klemens D. Morgenstern |
2 | // | |
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) | |
5 | ||
6 | #ifndef BOOST_PROCESS_DETAIL_POSIX_ENVIRONMENT_HPP_ | |
7 | #define BOOST_PROCESS_DETAIL_POSIX_ENVIRONMENT_HPP_ | |
8 | ||
9 | #include <string> | |
10 | #include <vector> | |
11 | #include <unordered_map> | |
12 | #include <boost/process/detail/config.hpp> | |
13 | #include <algorithm> | |
14 | #include <cstdlib> | |
15 | #include <boost/process/locale.hpp> | |
16 | ||
17 | ||
18 | namespace boost { namespace process { namespace detail { namespace posix { | |
19 | ||
20 | template<typename Char> | |
21 | class native_environment_impl | |
22 | { | |
23 | static std::vector<std::basic_string<Char>> _load() | |
24 | { | |
25 | std::vector<std::basic_string<Char>> val; | |
26 | auto p = environ; | |
27 | while (*p != nullptr) | |
28 | { | |
29 | std::string str = *p; | |
30 | val.push_back(::boost::process::detail::convert(str)); | |
31 | p++; | |
32 | } | |
33 | return val; | |
34 | } | |
35 | static std::vector<Char*> _load_var(std::vector<std::basic_string<Char>> & vec) | |
36 | { | |
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) | |
41 | { | |
42 | return &str.front(); | |
43 | }); | |
44 | val.back() = nullptr; | |
45 | return val; | |
46 | } | |
47 | std::vector<std::basic_string<Char>> _buffer = _load(); | |
48 | std::vector<Char*> _impl = _load_var(_buffer); | |
49 | public: | |
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 **; | |
54 | ||
55 | void reload() | |
56 | { | |
57 | _buffer = _load(); | |
58 | _impl = _load_var(_buffer); | |
1e59de90 | 59 | _env_impl = _impl.data(); |
b32b8144 FG |
60 | } |
61 | ||
62 | string_type get(const pointer_type id) { return get(string_type(id)); } | |
63 | void set(const pointer_type id, const pointer_type value) | |
64 | { | |
65 | set(string_type(id), string_type(value)); | |
66 | } | |
67 | void reset(const pointer_type id) { reset(string_type(id)); } | |
68 | ||
69 | string_type get(const string_type & id) | |
70 | { | |
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()); | |
74 | } | |
75 | void set(const string_type & id, const string_type & value) | |
76 | { | |
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); | |
80 | if (res != 0) | |
81 | boost::process::detail::throw_last_error(); | |
82 | } | |
83 | void reset(const string_type & id) | |
84 | { | |
85 | std::string id_c = ::boost::process::detail::convert(id.c_str()); | |
86 | auto res = ::unsetenv(id_c.c_str()); | |
87 | if (res != 0) | |
88 | ::boost::process::detail::throw_last_error(); | |
89 | } | |
90 | ||
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(); | |
97 | ||
f67539c2 | 98 | native_handle_type native_handle() const {return _env_impl;} |
b32b8144 FG |
99 | }; |
100 | ||
101 | template<> | |
102 | class native_environment_impl<char> | |
103 | { | |
104 | public: | |
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 **; | |
109 | ||
110 | void reload() {this->_env_impl = ::environ;} | |
111 | ||
112 | string_type get(const pointer_type id) { return getenv(id); } | |
113 | void set(const pointer_type id, const pointer_type value) | |
114 | { | |
115 | auto res = ::setenv(id, value, 1); | |
116 | if (res != 0) | |
117 | boost::process::detail::throw_last_error(); | |
118 | reload(); | |
119 | } | |
120 | void reset(const pointer_type id) | |
121 | { | |
122 | auto res = ::unsetenv(id); | |
123 | if (res != 0) | |
124 | boost::process::detail::throw_last_error(); | |
125 | reload(); | |
126 | } | |
127 | ||
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());} | |
131 | ||
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; | |
138 | ||
139 | native_handle_type native_handle() const {return ::environ;} | |
140 | }; | |
141 | ||
142 | ||
143 | ||
144 | template<typename Char> | |
145 | struct basic_environment_impl | |
146 | { | |
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)}; | |
150 | public: | |
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**; | |
155 | void reload() | |
156 | { | |
157 | _env_arr = _load_var(_data); | |
158 | _env_impl = _env_arr.data(); | |
159 | } | |
160 | ||
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));} | |
164 | ||
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); | |
168 | ||
169 | basic_environment_impl(const native_environment_impl<Char> & nei); | |
170 | basic_environment_impl() = default; | |
171 | basic_environment_impl(const basic_environment_impl& rhs) | |
172 | : _data(rhs._data) | |
173 | { | |
174 | ||
175 | } | |
176 | basic_environment_impl(basic_environment_impl && ) = default; | |
177 | basic_environment_impl & operator=(const basic_environment_impl& rhs) | |
178 | { | |
179 | _data = rhs._data; | |
180 | _env_arr = _load_var(_data); | |
181 | _env_impl = &*_env_arr.begin(); | |
182 | return *this; | |
183 | } | |
184 | basic_environment_impl & operator=(basic_environment_impl && ) = default; | |
185 | ||
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()) | |
191 | { | |
192 | std::transform(rhs._data.begin(), rhs._data.end(), _data.begin(), | |
193 | [&](const std::basic_string<CharR> & st) | |
194 | { | |
195 | return ::boost::process::detail::convert(st, cv); | |
196 | } | |
197 | ||
198 | ); | |
199 | reload(); | |
200 | } | |
201 | ||
202 | template<typename CharR> | |
203 | basic_environment_impl & operator=(const basic_environment_impl<CharR>& rhs) | |
204 | { | |
205 | _data = ::boost::process::detail::convert(rhs._data); | |
206 | _env_arr = _load_var(&*_data.begin()); | |
207 | _env_impl = &*_env_arr.begin(); | |
208 | return *this; | |
209 | } | |
210 | ||
211 | Char ** _env_impl = &*_env_arr.data(); | |
212 | ||
213 | native_handle_type native_handle() const {return &_data.front();} | |
214 | }; | |
215 | ||
216 | ||
217 | template<typename Char> | |
218 | basic_environment_impl<Char>::basic_environment_impl(const native_environment_impl<Char> & nei) | |
219 | { | |
220 | auto beg = nei.native_handle(); | |
221 | ||
222 | auto end = beg; | |
223 | while (*end != nullptr) | |
224 | end++; | |
225 | this->_data.assign(beg, end); | |
226 | reload(); | |
227 | } | |
228 | ||
229 | ||
230 | template<typename Char> | |
231 | inline auto basic_environment_impl<Char>::get(const string_type &id) -> string_type | |
232 | { | |
233 | auto itr = std::find_if(_data.begin(), _data.end(), | |
20effc67 | 234 | [&](const string_type & st) -> bool |
b32b8144 FG |
235 | { |
236 | if (st.size() <= id.size()) | |
237 | return false; | |
238 | return std::equal(id.begin(), id.end(), st.begin()) && (st[id.size()] == equal_sign<Char>()); | |
239 | } | |
240 | ); | |
241 | ||
242 | if (itr == _data.end()) | |
243 | { | |
244 | return ""; | |
245 | } | |
246 | else return | |
247 | itr->data() + id.size(); //id=Thingy -> +2 points to T | |
248 | } | |
249 | ||
250 | template<typename Char> | |
251 | inline void basic_environment_impl<Char>::set(const string_type &id, const string_type &value) | |
252 | { | |
253 | auto itr = std::find_if(_data.begin(), _data.end(), | |
20effc67 | 254 | [&](const string_type & st) -> bool |
b32b8144 FG |
255 | { |
256 | if (st.size() <= id.size()) | |
257 | return false; | |
258 | return std::equal(id.begin(), id.end(), st.begin()) && (st[id.size()] == equal_sign<Char>()); | |
259 | } | |
260 | ); | |
261 | ||
262 | if (itr != _data.end()) | |
263 | *itr = id + equal_sign<Char>() + value; | |
264 | else | |
265 | _data.push_back(id + equal_sign<Char>() + value); | |
266 | ||
267 | reload(); | |
268 | } | |
269 | ||
270 | template<typename Char> | |
271 | inline void basic_environment_impl<Char>::reset(const string_type &id) | |
272 | { | |
273 | auto itr = std::find_if(_data.begin(), _data.end(), | |
20effc67 | 274 | [&](const string_type & st) -> bool |
b32b8144 FG |
275 | { |
276 | if (st.size() <= id.size()) | |
277 | return false; | |
278 | return std::equal(id.begin(), id.end(), st.begin()) && (st[id.size()] == equal_sign<Char>()); | |
279 | } | |
280 | ); | |
281 | if (itr != _data.end()) | |
282 | { | |
283 | _data.erase(itr);//and remove it | |
284 | } | |
285 | ||
286 | reload(); | |
287 | ||
288 | ||
289 | } | |
290 | ||
291 | template<typename Char> | |
292 | std::vector<Char*> basic_environment_impl<Char>::_load_var(std::vector<std::basic_string<Char>> & data) | |
293 | { | |
294 | std::vector<Char*> ret; | |
295 | ret.reserve(data.size() +1); | |
296 | ||
297 | for (auto & val : data) | |
f67539c2 TL |
298 | { |
299 | if (val.empty()) | |
300 | val.push_back(0); | |
b32b8144 | 301 | ret.push_back(&val.front()); |
f67539c2 | 302 | } |
b32b8144 FG |
303 | |
304 | ret.push_back(nullptr); | |
305 | return ret; | |
306 | } | |
307 | ||
308 | template<typename T> constexpr T env_seperator(); | |
309 | template<> constexpr char env_seperator() {return ':'; } | |
310 | template<> constexpr wchar_t env_seperator() {return L':'; } | |
311 | ||
312 | ||
313 | typedef int native_handle_t; | |
314 | ||
315 | inline int get_id() {return getpid(); } | |
316 | inline int native_handle() {return getpid(); } | |
317 | ||
318 | } | |
319 | ||
320 | } | |
321 | } | |
322 | } | |
323 | ||
324 | ||
325 | ||
326 | ||
327 | #endif /* BOOST_PROCESS_DETAIL_WINDOWS_ENV_STORAGE_HPP_ */ |