File indexing completed on 2025-01-18 09:50:06
0001
0002
0003
0004
0005
0006 #ifndef BOOST_PROCESS_DETAIL_POSIX_ENVIRONMENT_HPP_
0007 #define BOOST_PROCESS_DETAIL_POSIX_ENVIRONMENT_HPP_
0008
0009 #include <string>
0010 #include <vector>
0011 #include <unordered_map>
0012 #include <boost/process/detail/config.hpp>
0013 #include <algorithm>
0014 #include <cstdlib>
0015 #include <boost/process/locale.hpp>
0016
0017
0018 namespace boost { namespace process { namespace detail { namespace posix {
0019
0020 template<typename Char>
0021 class native_environment_impl
0022 {
0023 static std::vector<std::basic_string<Char>> _load()
0024 {
0025 std::vector<std::basic_string<Char>> val;
0026 auto p = environ;
0027 while (*p != nullptr)
0028 {
0029 std::string str = *p;
0030 val.push_back(::boost::process::detail::convert(str));
0031 p++;
0032 }
0033 return val;
0034 }
0035 static std::vector<Char*> _load_var(std::vector<std::basic_string<Char>> & vec)
0036 {
0037 std::vector<Char*> val;
0038 val.resize(vec.size() + 1);
0039 std::transform(vec.begin(), vec.end(), val.begin(),
0040 [](std::basic_string<Char> & str)
0041 {
0042 return &str.front();
0043 });
0044 val.back() = nullptr;
0045 return val;
0046 }
0047 std::vector<std::basic_string<Char>> _buffer = _load();
0048 std::vector<Char*> _impl = _load_var(_buffer);
0049 public:
0050 using char_type = Char;
0051 using pointer_type = const char_type*;
0052 using string_type = std::basic_string<char_type>;
0053 using native_handle_type = char_type **;
0054
0055 void reload()
0056 {
0057 _buffer = _load();
0058 _impl = _load_var(_buffer);
0059 _env_impl = _impl.data();
0060 }
0061
0062 string_type get(const pointer_type id) { return get(string_type(id)); }
0063 void set(const pointer_type id, const pointer_type value)
0064 {
0065 set(string_type(id), string_type(value));
0066 }
0067 void reset(const pointer_type id) { reset(string_type(id)); }
0068
0069 string_type get(const string_type & id)
0070 {
0071 std::string id_c = ::boost::process::detail::convert(id);
0072 std::string g = ::getenv(id_c.c_str());
0073 return ::boost::process::detail::convert(g.c_str());
0074 }
0075 void set(const string_type & id, const string_type & value)
0076 {
0077 std::string id_c = ::boost::process::detail::convert(id.c_str());
0078 std::string value_c = ::boost::process::detail::convert(value.c_str());
0079 auto res = ::setenv(id_c.c_str(), value_c.c_str(), true);
0080 if (res != 0)
0081 boost::process::detail::throw_last_error();
0082 }
0083 void reset(const string_type & id)
0084 {
0085 std::string id_c = ::boost::process::detail::convert(id.c_str());
0086 auto res = ::unsetenv(id_c.c_str());
0087 if (res != 0)
0088 ::boost::process::detail::throw_last_error();
0089 }
0090
0091 native_environment_impl() = default;
0092 native_environment_impl(const native_environment_impl& ) = delete;
0093 native_environment_impl(native_environment_impl && ) = default;
0094 native_environment_impl & operator=(const native_environment_impl& ) = delete;
0095 native_environment_impl & operator=(native_environment_impl && ) = default;
0096 native_handle_type _env_impl = _impl.data();
0097
0098 native_handle_type native_handle() const {return _env_impl;}
0099 };
0100
0101 template<>
0102 class native_environment_impl<char>
0103 {
0104 public:
0105 using char_type = char;
0106 using pointer_type = const char_type*;
0107 using string_type = std::basic_string<char_type>;
0108 using native_handle_type = char_type **;
0109
0110 void reload() {this->_env_impl = ::environ;}
0111
0112 string_type get(const pointer_type id) { return getenv(id); }
0113 void set(const pointer_type id, const pointer_type value)
0114 {
0115 auto res = ::setenv(id, value, 1);
0116 if (res != 0)
0117 boost::process::detail::throw_last_error();
0118 reload();
0119 }
0120 void reset(const pointer_type id)
0121 {
0122 auto res = ::unsetenv(id);
0123 if (res != 0)
0124 boost::process::detail::throw_last_error();
0125 reload();
0126 }
0127
0128 string_type get(const string_type & id) {return get(id.c_str());}
0129 void set(const string_type & id, const string_type & value) {set(id.c_str(), value.c_str()); }
0130 void reset(const string_type & id) {reset(id.c_str());}
0131
0132 native_environment_impl() = default;
0133 native_environment_impl(const native_environment_impl& ) = delete;
0134 native_environment_impl(native_environment_impl && ) = default;
0135 native_environment_impl & operator=(const native_environment_impl& ) = delete;
0136 native_environment_impl & operator=(native_environment_impl && ) = default;
0137 native_handle_type _env_impl = environ;
0138
0139 native_handle_type native_handle() const {return ::environ;}
0140 };
0141
0142
0143
0144 template<typename Char>
0145 struct basic_environment_impl
0146 {
0147 std::vector<std::basic_string<Char>> _data {};
0148 static std::vector<Char*> _load_var(std::vector<std::basic_string<Char>> & data);
0149 std::vector<Char*> _env_arr{_load_var(_data)};
0150 public:
0151 using char_type = Char;
0152 using pointer_type = const char_type*;
0153 using string_type = std::basic_string<char_type>;
0154 using native_handle_type = Char**;
0155 void reload()
0156 {
0157 _env_arr = _load_var(_data);
0158 _env_impl = _env_arr.data();
0159 }
0160
0161 string_type get(const pointer_type id) {return get(string_type(id));}
0162 void set(const pointer_type id, const pointer_type value) {set(string_type(id), value);}
0163 void reset(const pointer_type id) {reset(string_type(id));}
0164
0165 string_type get(const string_type & id);
0166 void set(const string_type & id, const string_type & value);
0167 void reset(const string_type & id);
0168
0169 basic_environment_impl(const native_environment_impl<Char> & nei);
0170 basic_environment_impl() = default;
0171 basic_environment_impl(const basic_environment_impl& rhs)
0172 : _data(rhs._data)
0173 {
0174
0175 }
0176 basic_environment_impl(basic_environment_impl && ) = default;
0177 basic_environment_impl & operator=(const basic_environment_impl& rhs)
0178 {
0179 _data = rhs._data;
0180 _env_arr = _load_var(_data);
0181 _env_impl = &*_env_arr.begin();
0182 return *this;
0183 }
0184 basic_environment_impl & operator=(basic_environment_impl && ) = default;
0185
0186 template<typename CharR>
0187 explicit inline basic_environment_impl(
0188 const basic_environment_impl<CharR>& rhs,
0189 const ::boost::process::codecvt_type & cv = ::boost::process::codecvt())
0190 : _data(rhs._data.size())
0191 {
0192 std::transform(rhs._data.begin(), rhs._data.end(), _data.begin(),
0193 [&](const std::basic_string<CharR> & st)
0194 {
0195 return ::boost::process::detail::convert(st, cv);
0196 }
0197
0198 );
0199 reload();
0200 }
0201
0202 template<typename CharR>
0203 basic_environment_impl & operator=(const basic_environment_impl<CharR>& rhs)
0204 {
0205 _data = ::boost::process::detail::convert(rhs._data);
0206 _env_arr = _load_var(&*_data.begin());
0207 _env_impl = &*_env_arr.begin();
0208 return *this;
0209 }
0210
0211 Char ** _env_impl = &*_env_arr.data();
0212
0213 native_handle_type native_handle() const {return &_data.front();}
0214 };
0215
0216
0217 template<typename Char>
0218 basic_environment_impl<Char>::basic_environment_impl(const native_environment_impl<Char> & nei)
0219 {
0220 auto beg = nei.native_handle();
0221
0222 auto end = beg;
0223 while (*end != nullptr)
0224 end++;
0225 this->_data.assign(beg, end);
0226 reload();
0227 }
0228
0229
0230 template<typename Char>
0231 inline auto basic_environment_impl<Char>::get(const string_type &id) -> string_type
0232 {
0233 auto itr = std::find_if(_data.begin(), _data.end(),
0234 [&](const string_type & st) -> bool
0235 {
0236 if (st.size() <= id.size())
0237 return false;
0238 return std::equal(id.begin(), id.end(), st.begin()) && (st[id.size()] == equal_sign<Char>());
0239 }
0240 );
0241
0242 if (itr == _data.end())
0243 {
0244 return "";
0245 }
0246 else return
0247 itr->data() + id.size();
0248 }
0249
0250 template<typename Char>
0251 inline void basic_environment_impl<Char>::set(const string_type &id, const string_type &value)
0252 {
0253 auto itr = std::find_if(_data.begin(), _data.end(),
0254 [&](const string_type & st) -> bool
0255 {
0256 if (st.size() <= id.size())
0257 return false;
0258 return std::equal(id.begin(), id.end(), st.begin()) && (st[id.size()] == equal_sign<Char>());
0259 }
0260 );
0261
0262 if (itr != _data.end())
0263 *itr = id + equal_sign<Char>() + value;
0264 else
0265 _data.push_back(id + equal_sign<Char>() + value);
0266
0267 reload();
0268 }
0269
0270 template<typename Char>
0271 inline void basic_environment_impl<Char>::reset(const string_type &id)
0272 {
0273 auto itr = std::find_if(_data.begin(), _data.end(),
0274 [&](const string_type & st) -> bool
0275 {
0276 if (st.size() <= id.size())
0277 return false;
0278 return std::equal(id.begin(), id.end(), st.begin()) && (st[id.size()] == equal_sign<Char>());
0279 }
0280 );
0281 if (itr != _data.end())
0282 {
0283 _data.erase(itr);
0284 }
0285
0286 reload();
0287
0288
0289 }
0290
0291 template<typename Char>
0292 std::vector<Char*> basic_environment_impl<Char>::_load_var(std::vector<std::basic_string<Char>> & data)
0293 {
0294 std::vector<Char*> ret;
0295 ret.reserve(data.size() +1);
0296
0297 for (auto & val : data)
0298 {
0299 if (val.empty())
0300 val.push_back(0);
0301 ret.push_back(&val.front());
0302 }
0303
0304 ret.push_back(nullptr);
0305 return ret;
0306 }
0307
0308 template<typename T> constexpr T env_seperator();
0309 template<> constexpr char env_seperator() {return ':'; }
0310 template<> constexpr wchar_t env_seperator() {return L':'; }
0311
0312
0313 typedef int native_handle_t;
0314
0315 inline int get_id() {return getpid(); }
0316 inline int native_handle() {return getpid(); }
0317
0318 }
0319
0320 }
0321 }
0322 }
0323
0324
0325
0326
0327 #endif