environment.hpp 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  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. #ifndef BOOST_PROCESS_DETAIL_POSIX_ENVIRONMENT_HPP_
  6. #define BOOST_PROCESS_DETAIL_POSIX_ENVIRONMENT_HPP_
  7. #include <string>
  8. #include <vector>
  9. #include <unordered_map>
  10. #include <boost/process/v1/detail/config.hpp>
  11. #include <algorithm>
  12. #include <cstdlib>
  13. #include <boost/process/v1/locale.hpp>
  14. namespace boost { namespace process { BOOST_PROCESS_V1_INLINE namespace v1 { namespace detail { namespace posix {
  15. template<typename Char>
  16. class native_environment_impl
  17. {
  18. static std::vector<std::basic_string<Char>> _load()
  19. {
  20. std::vector<std::basic_string<Char>> val;
  21. auto p = environ;
  22. while (*p != nullptr)
  23. {
  24. std::string str = *p;
  25. val.push_back(::boost::process::v1::detail::convert(str));
  26. p++;
  27. }
  28. return val;
  29. }
  30. static std::vector<Char*> _load_var(std::vector<std::basic_string<Char>> & vec)
  31. {
  32. std::vector<Char*> val;
  33. val.resize(vec.size() + 1);
  34. std::transform(vec.begin(), vec.end(), val.begin(),
  35. [](std::basic_string<Char> & str)
  36. {
  37. return &str.front();
  38. });
  39. val.back() = nullptr;
  40. return val;
  41. }
  42. std::vector<std::basic_string<Char>> _buffer = _load();
  43. std::vector<Char*> _impl = _load_var(_buffer);
  44. public:
  45. using char_type = Char;
  46. using pointer_type = const char_type*;
  47. using string_type = std::basic_string<char_type>;
  48. using native_handle_type = char_type **;
  49. void reload()
  50. {
  51. _buffer = _load();
  52. _impl = _load_var(_buffer);
  53. _env_impl = _impl.data();
  54. }
  55. string_type get(const pointer_type id) { return get(string_type(id)); }
  56. void set(const pointer_type id, const pointer_type value)
  57. {
  58. set(string_type(id), string_type(value));
  59. }
  60. void reset(const pointer_type id) { reset(string_type(id)); }
  61. string_type get(const string_type & id)
  62. {
  63. std::string id_c = ::boost::process::v1::detail::convert(id);
  64. std::string g = ::getenv(id_c.c_str());
  65. return ::boost::process::v1::detail::convert(g.c_str());
  66. }
  67. void set(const string_type & id, const string_type & value)
  68. {
  69. std::string id_c = ::boost::process::v1::detail::convert(id.c_str());
  70. std::string value_c = ::boost::process::v1::detail::convert(value.c_str());
  71. auto res = ::setenv(id_c.c_str(), value_c.c_str(), true);
  72. if (res != 0)
  73. boost::process::v1::detail::throw_last_error();
  74. }
  75. void reset(const string_type & id)
  76. {
  77. std::string id_c = ::boost::process::v1::detail::convert(id.c_str());
  78. auto res = ::unsetenv(id_c.c_str());
  79. if (res != 0)
  80. ::boost::process::v1::detail::throw_last_error();
  81. }
  82. native_environment_impl() = default;
  83. native_environment_impl(const native_environment_impl& ) = delete;
  84. native_environment_impl(native_environment_impl && ) = default;
  85. native_environment_impl & operator=(const native_environment_impl& ) = delete;
  86. native_environment_impl & operator=(native_environment_impl && ) = default;
  87. native_handle_type _env_impl = _impl.data();
  88. native_handle_type native_handle() const {return _env_impl;}
  89. };
  90. template<>
  91. class native_environment_impl<char>
  92. {
  93. public:
  94. using char_type = char;
  95. using pointer_type = const char_type*;
  96. using string_type = std::basic_string<char_type>;
  97. using native_handle_type = char_type **;
  98. void reload() {this->_env_impl = ::environ;}
  99. string_type get(const pointer_type id) { return getenv(id); }
  100. void set(const pointer_type id, const pointer_type value)
  101. {
  102. auto res = ::setenv(id, value, 1);
  103. if (res != 0)
  104. boost::process::v1::detail::throw_last_error();
  105. reload();
  106. }
  107. void reset(const pointer_type id)
  108. {
  109. auto res = ::unsetenv(id);
  110. if (res != 0)
  111. boost::process::v1::detail::throw_last_error();
  112. reload();
  113. }
  114. string_type get(const string_type & id) {return get(id.c_str());}
  115. void set(const string_type & id, const string_type & value) {set(id.c_str(), value.c_str()); }
  116. void reset(const string_type & id) {reset(id.c_str());}
  117. native_environment_impl() = default;
  118. native_environment_impl(const native_environment_impl& ) = delete;
  119. native_environment_impl(native_environment_impl && ) = default;
  120. native_environment_impl & operator=(const native_environment_impl& ) = delete;
  121. native_environment_impl & operator=(native_environment_impl && ) = default;
  122. native_handle_type _env_impl = environ;
  123. native_handle_type native_handle() const {return ::environ;}
  124. };
  125. template<typename Char>
  126. struct basic_environment_impl
  127. {
  128. std::vector<std::basic_string<Char>> _data {};
  129. static std::vector<Char*> _load_var(std::vector<std::basic_string<Char>> & data);
  130. std::vector<Char*> _env_arr{_load_var(_data)};
  131. public:
  132. using char_type = Char;
  133. using pointer_type = const char_type*;
  134. using string_type = std::basic_string<char_type>;
  135. using native_handle_type = Char**;
  136. void reload()
  137. {
  138. _env_arr = _load_var(_data);
  139. _env_impl = _env_arr.data();
  140. }
  141. string_type get(const pointer_type id) {return get(string_type(id));}
  142. void set(const pointer_type id, const pointer_type value) {set(string_type(id), value);}
  143. void reset(const pointer_type id) {reset(string_type(id));}
  144. string_type get(const string_type & id);
  145. void set(const string_type & id, const string_type & value);
  146. void reset(const string_type & id);
  147. basic_environment_impl(const native_environment_impl<Char> & nei);
  148. basic_environment_impl() = default;
  149. basic_environment_impl(const basic_environment_impl& rhs)
  150. : _data(rhs._data)
  151. {
  152. }
  153. basic_environment_impl(basic_environment_impl && ) = default;
  154. basic_environment_impl & operator=(const basic_environment_impl& rhs)
  155. {
  156. _data = rhs._data;
  157. _env_arr = _load_var(_data);
  158. _env_impl = &*_env_arr.begin();
  159. return *this;
  160. }
  161. basic_environment_impl & operator=(basic_environment_impl && ) = default;
  162. template<typename CharR>
  163. explicit inline basic_environment_impl(
  164. const basic_environment_impl<CharR>& rhs,
  165. const ::boost::process::v1::codecvt_type & cv = ::boost::process::v1::codecvt())
  166. : _data(rhs._data.size())
  167. {
  168. std::transform(rhs._data.begin(), rhs._data.end(), _data.begin(),
  169. [&](const std::basic_string<CharR> & st)
  170. {
  171. return ::boost::process::v1::detail::convert(st, cv);
  172. }
  173. );
  174. reload();
  175. }
  176. template<typename CharR>
  177. basic_environment_impl & operator=(const basic_environment_impl<CharR>& rhs)
  178. {
  179. _data = ::boost::process::v1::detail::convert(rhs._data);
  180. _env_arr = _load_var(&*_data.begin());
  181. _env_impl = &*_env_arr.begin();
  182. return *this;
  183. }
  184. Char ** _env_impl = &*_env_arr.data();
  185. native_handle_type native_handle() const {return &_data.front();}
  186. };
  187. template<typename Char>
  188. basic_environment_impl<Char>::basic_environment_impl(const native_environment_impl<Char> & nei)
  189. {
  190. auto beg = nei.native_handle();
  191. auto end = beg;
  192. while (*end != nullptr)
  193. end++;
  194. this->_data.assign(beg, end);
  195. reload();
  196. }
  197. template<typename Char>
  198. inline auto basic_environment_impl<Char>::get(const string_type &id) -> string_type
  199. {
  200. auto itr = std::find_if(_data.begin(), _data.end(),
  201. [&](const string_type & st) -> bool
  202. {
  203. if (st.size() <= id.size())
  204. return false;
  205. return std::equal(id.begin(), id.end(), st.begin()) && (st[id.size()] == equal_sign<Char>());
  206. }
  207. );
  208. if (itr == _data.end())
  209. {
  210. return "";
  211. }
  212. else return
  213. itr->data() + id.size(); //id=Thingy -> +2 points to T
  214. }
  215. template<typename Char>
  216. inline void basic_environment_impl<Char>::set(const string_type &id, const string_type &value)
  217. {
  218. auto itr = std::find_if(_data.begin(), _data.end(),
  219. [&](const string_type & st) -> bool
  220. {
  221. if (st.size() <= id.size())
  222. return false;
  223. return std::equal(id.begin(), id.end(), st.begin()) && (st[id.size()] == equal_sign<Char>());
  224. }
  225. );
  226. if (itr != _data.end())
  227. *itr = id + equal_sign<Char>() + value;
  228. else
  229. _data.push_back(id + equal_sign<Char>() + value);
  230. reload();
  231. }
  232. template<typename Char>
  233. inline void basic_environment_impl<Char>::reset(const string_type &id)
  234. {
  235. auto itr = std::find_if(_data.begin(), _data.end(),
  236. [&](const string_type & st) -> bool
  237. {
  238. if (st.size() <= id.size())
  239. return false;
  240. return std::equal(id.begin(), id.end(), st.begin()) && (st[id.size()] == equal_sign<Char>());
  241. }
  242. );
  243. if (itr != _data.end())
  244. {
  245. _data.erase(itr);//and remove it
  246. }
  247. reload();
  248. }
  249. template<typename Char>
  250. std::vector<Char*> basic_environment_impl<Char>::_load_var(std::vector<std::basic_string<Char>> & data)
  251. {
  252. std::vector<Char*> ret;
  253. ret.reserve(data.size() +1);
  254. for (auto & val : data)
  255. {
  256. if (val.empty())
  257. val.push_back(0);
  258. ret.push_back(&val.front());
  259. }
  260. ret.push_back(nullptr);
  261. return ret;
  262. }
  263. template<typename T> constexpr T env_seperator();
  264. template<> constexpr char env_seperator() {return ':'; }
  265. template<> constexpr wchar_t env_seperator() {return L':'; }
  266. typedef int native_handle_t;
  267. inline int get_id() {return getpid(); }
  268. inline int native_handle() {return getpid(); }
  269. }
  270. }
  271. }
  272. }
  273. }
  274. #endif /* BOOST_PROCESS_DETAIL_WINDOWS_ENV_STORAGE_HPP_ */