environment.hpp 9.7 KB

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