]>
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); | |
59 | } | |
60 | ||
61 | string_type get(const pointer_type id) { return get(string_type(id)); } | |
62 | void set(const pointer_type id, const pointer_type value) | |
63 | { | |
64 | set(string_type(id), string_type(value)); | |
65 | } | |
66 | void reset(const pointer_type id) { reset(string_type(id)); } | |
67 | ||
68 | string_type get(const string_type & id) | |
69 | { | |
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()); | |
73 | } | |
74 | void set(const string_type & id, const string_type & value) | |
75 | { | |
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); | |
79 | if (res != 0) | |
80 | boost::process::detail::throw_last_error(); | |
81 | } | |
82 | void reset(const string_type & id) | |
83 | { | |
84 | std::string id_c = ::boost::process::detail::convert(id.c_str()); | |
85 | auto res = ::unsetenv(id_c.c_str()); | |
86 | if (res != 0) | |
87 | ::boost::process::detail::throw_last_error(); | |
88 | } | |
89 | ||
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(); | |
96 | ||
f67539c2 | 97 | native_handle_type native_handle() const {return _env_impl;} |
b32b8144 FG |
98 | }; |
99 | ||
100 | template<> | |
101 | class native_environment_impl<char> | |
102 | { | |
103 | public: | |
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 **; | |
108 | ||
109 | void reload() {this->_env_impl = ::environ;} | |
110 | ||
111 | string_type get(const pointer_type id) { return getenv(id); } | |
112 | void set(const pointer_type id, const pointer_type value) | |
113 | { | |
114 | auto res = ::setenv(id, value, 1); | |
115 | if (res != 0) | |
116 | boost::process::detail::throw_last_error(); | |
117 | reload(); | |
118 | } | |
119 | void reset(const pointer_type id) | |
120 | { | |
121 | auto res = ::unsetenv(id); | |
122 | if (res != 0) | |
123 | boost::process::detail::throw_last_error(); | |
124 | reload(); | |
125 | } | |
126 | ||
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());} | |
130 | ||
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; | |
137 | ||
138 | native_handle_type native_handle() const {return ::environ;} | |
139 | }; | |
140 | ||
141 | ||
142 | ||
143 | template<typename Char> | |
144 | struct basic_environment_impl | |
145 | { | |
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)}; | |
149 | public: | |
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**; | |
154 | void reload() | |
155 | { | |
156 | _env_arr = _load_var(_data); | |
157 | _env_impl = _env_arr.data(); | |
158 | } | |
159 | ||
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));} | |
163 | ||
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); | |
167 | ||
168 | basic_environment_impl(const native_environment_impl<Char> & nei); | |
169 | basic_environment_impl() = default; | |
170 | basic_environment_impl(const basic_environment_impl& rhs) | |
171 | : _data(rhs._data) | |
172 | { | |
173 | ||
174 | } | |
175 | basic_environment_impl(basic_environment_impl && ) = default; | |
176 | basic_environment_impl & operator=(const basic_environment_impl& rhs) | |
177 | { | |
178 | _data = rhs._data; | |
179 | _env_arr = _load_var(_data); | |
180 | _env_impl = &*_env_arr.begin(); | |
181 | return *this; | |
182 | } | |
183 | basic_environment_impl & operator=(basic_environment_impl && ) = default; | |
184 | ||
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()) | |
190 | { | |
191 | std::transform(rhs._data.begin(), rhs._data.end(), _data.begin(), | |
192 | [&](const std::basic_string<CharR> & st) | |
193 | { | |
194 | return ::boost::process::detail::convert(st, cv); | |
195 | } | |
196 | ||
197 | ); | |
198 | reload(); | |
199 | } | |
200 | ||
201 | template<typename CharR> | |
202 | basic_environment_impl & operator=(const basic_environment_impl<CharR>& rhs) | |
203 | { | |
204 | _data = ::boost::process::detail::convert(rhs._data); | |
205 | _env_arr = _load_var(&*_data.begin()); | |
206 | _env_impl = &*_env_arr.begin(); | |
207 | return *this; | |
208 | } | |
209 | ||
210 | Char ** _env_impl = &*_env_arr.data(); | |
211 | ||
212 | native_handle_type native_handle() const {return &_data.front();} | |
213 | }; | |
214 | ||
215 | ||
216 | template<typename Char> | |
217 | basic_environment_impl<Char>::basic_environment_impl(const native_environment_impl<Char> & nei) | |
218 | { | |
219 | auto beg = nei.native_handle(); | |
220 | ||
221 | auto end = beg; | |
222 | while (*end != nullptr) | |
223 | end++; | |
224 | this->_data.assign(beg, end); | |
225 | reload(); | |
226 | } | |
227 | ||
228 | ||
229 | template<typename Char> | |
230 | inline auto basic_environment_impl<Char>::get(const string_type &id) -> string_type | |
231 | { | |
232 | auto itr = std::find_if(_data.begin(), _data.end(), | |
20effc67 | 233 | [&](const string_type & st) -> bool |
b32b8144 FG |
234 | { |
235 | if (st.size() <= id.size()) | |
236 | return false; | |
237 | return std::equal(id.begin(), id.end(), st.begin()) && (st[id.size()] == equal_sign<Char>()); | |
238 | } | |
239 | ); | |
240 | ||
241 | if (itr == _data.end()) | |
242 | { | |
243 | return ""; | |
244 | } | |
245 | else return | |
246 | itr->data() + id.size(); //id=Thingy -> +2 points to T | |
247 | } | |
248 | ||
249 | template<typename Char> | |
250 | inline void basic_environment_impl<Char>::set(const string_type &id, const string_type &value) | |
251 | { | |
252 | auto itr = std::find_if(_data.begin(), _data.end(), | |
20effc67 | 253 | [&](const string_type & st) -> bool |
b32b8144 FG |
254 | { |
255 | if (st.size() <= id.size()) | |
256 | return false; | |
257 | return std::equal(id.begin(), id.end(), st.begin()) && (st[id.size()] == equal_sign<Char>()); | |
258 | } | |
259 | ); | |
260 | ||
261 | if (itr != _data.end()) | |
262 | *itr = id + equal_sign<Char>() + value; | |
263 | else | |
264 | _data.push_back(id + equal_sign<Char>() + value); | |
265 | ||
266 | reload(); | |
267 | } | |
268 | ||
269 | template<typename Char> | |
270 | inline void basic_environment_impl<Char>::reset(const string_type &id) | |
271 | { | |
272 | auto itr = std::find_if(_data.begin(), _data.end(), | |
20effc67 | 273 | [&](const string_type & st) -> bool |
b32b8144 FG |
274 | { |
275 | if (st.size() <= id.size()) | |
276 | return false; | |
277 | return std::equal(id.begin(), id.end(), st.begin()) && (st[id.size()] == equal_sign<Char>()); | |
278 | } | |
279 | ); | |
280 | if (itr != _data.end()) | |
281 | { | |
282 | _data.erase(itr);//and remove it | |
283 | } | |
284 | ||
285 | reload(); | |
286 | ||
287 | ||
288 | } | |
289 | ||
290 | template<typename Char> | |
291 | std::vector<Char*> basic_environment_impl<Char>::_load_var(std::vector<std::basic_string<Char>> & data) | |
292 | { | |
293 | std::vector<Char*> ret; | |
294 | ret.reserve(data.size() +1); | |
295 | ||
296 | for (auto & val : data) | |
f67539c2 TL |
297 | { |
298 | if (val.empty()) | |
299 | val.push_back(0); | |
b32b8144 | 300 | ret.push_back(&val.front()); |
f67539c2 | 301 | } |
b32b8144 FG |
302 | |
303 | ret.push_back(nullptr); | |
304 | return ret; | |
305 | } | |
306 | ||
307 | template<typename T> constexpr T env_seperator(); | |
308 | template<> constexpr char env_seperator() {return ':'; } | |
309 | template<> constexpr wchar_t env_seperator() {return L':'; } | |
310 | ||
311 | ||
312 | typedef int native_handle_t; | |
313 | ||
314 | inline int get_id() {return getpid(); } | |
315 | inline int native_handle() {return getpid(); } | |
316 | ||
317 | } | |
318 | ||
319 | } | |
320 | } | |
321 | } | |
322 | ||
323 | ||
324 | ||
325 | ||
326 | #endif /* BOOST_PROCESS_DETAIL_WINDOWS_ENV_STORAGE_HPP_ */ |