update boost
This commit is contained in:
240
linx64/include/boost/process/v2/bind_launcher.hpp
Normal file
240
linx64/include/boost/process/v2/bind_launcher.hpp
Normal file
@@ -0,0 +1,240 @@
|
||||
//
|
||||
// boost/process/v2/bind_launcher.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2022 Klemens D. Morgenstern (klemens dot morgenstern at gmx dot net)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BOOST_PROCESS_V2_BIND_LAUNCHER_HPP
|
||||
#define BOOST_PROCESS_V2_BIND_LAUNCHER_HPP
|
||||
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
#include <boost/process/v2/default_launcher.hpp>
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template<std::size_t ... Idx>
|
||||
struct index_sequence { };
|
||||
|
||||
template<std::size_t Size, typename T>
|
||||
struct make_index_sequence_impl;
|
||||
|
||||
template<std::size_t Size, std::size_t ... Idx>
|
||||
struct make_index_sequence_impl<Size, index_sequence<Idx...>>
|
||||
{
|
||||
constexpr make_index_sequence_impl() {}
|
||||
using type = typename make_index_sequence_impl<Size - 1u, index_sequence<Size - 1u, Idx...>>::type;
|
||||
};
|
||||
|
||||
template<std::size_t ... Idx>
|
||||
struct make_index_sequence_impl<0u, index_sequence<Idx...>>
|
||||
{
|
||||
constexpr make_index_sequence_impl() {}
|
||||
using type = index_sequence<Idx...>;
|
||||
};
|
||||
|
||||
|
||||
template<std::size_t Cnt>
|
||||
struct make_index_sequence
|
||||
{
|
||||
using type = typename make_index_sequence_impl<Cnt, index_sequence<>>::type;
|
||||
};
|
||||
|
||||
template<std::size_t Cnt>
|
||||
using make_index_sequence_t = typename make_index_sequence<Cnt>::type;
|
||||
|
||||
}
|
||||
|
||||
/** @brief Utility class to bind initializers to a launcher
|
||||
* @tparam Launcher The inner launcher to be used
|
||||
* @tparam ...Init The initializers to be prepended.
|
||||
*
|
||||
* This can be used when multiple processes shared some settings,
|
||||
* e.g.
|
||||
*
|
||||
*/
|
||||
template<typename Launcher, typename ... Init>
|
||||
struct bound_launcher
|
||||
{
|
||||
template<typename Launcher_, typename ... Init_>
|
||||
bound_launcher(Launcher_ && l, Init_ && ... init) :
|
||||
launcher_(std::forward<Launcher_>(l)), init_(std::forward<Init_>(init)...)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename ExecutionContext, typename Args, typename ... Inits>
|
||||
auto operator()(ExecutionContext & context,
|
||||
const typename std::enable_if<std::is_convertible<
|
||||
ExecutionContext&, BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context&>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits) -> basic_process<typename ExecutionContext::executor_type>
|
||||
{
|
||||
return invoke(detail::make_index_sequence_t<sizeof...(Init)>{},
|
||||
context,
|
||||
executable,
|
||||
std::forward<Args>(args),
|
||||
std::forward<Inits>(inits)...);
|
||||
}
|
||||
|
||||
|
||||
template<typename ExecutionContext, typename Args, typename ... Inits>
|
||||
auto operator()(ExecutionContext & context,
|
||||
error_code & ec,
|
||||
const typename std::enable_if<std::is_convertible<
|
||||
ExecutionContext&, BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context&>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<typename ExecutionContext::executor_type>
|
||||
{
|
||||
return invoke(detail::make_index_sequence_t<sizeof...(Init)>{},
|
||||
context, ec,
|
||||
executable,
|
||||
std::forward<Args>(args),
|
||||
std::forward<Inits>(inits)...);
|
||||
}
|
||||
|
||||
template<typename Executor, typename Args, typename ... Inits>
|
||||
auto operator()(Executor exec,
|
||||
const typename std::enable_if<
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::execution::is_executor<Executor>::value ||
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::is_executor<Executor>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<Executor>
|
||||
{
|
||||
return invoke(detail::make_index_sequence_t<sizeof...(Init)>{},
|
||||
std::move(exec),
|
||||
executable,
|
||||
std::forward<Args>(args),
|
||||
std::forward<Inits>(inits)...);
|
||||
}
|
||||
|
||||
template<typename Executor, typename Args, typename ... Inits>
|
||||
auto operator()(Executor exec,
|
||||
error_code & ec,
|
||||
const typename std::enable_if<
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::execution::is_executor<Executor>::value ||
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::is_executor<Executor>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<Executor>
|
||||
{
|
||||
return invoke(detail::make_index_sequence_t<sizeof...(Init)>{},
|
||||
std::move(exec), ec,
|
||||
executable,
|
||||
std::forward<Args>(args),
|
||||
std::forward<Inits>(inits)...);
|
||||
}
|
||||
|
||||
private:
|
||||
template<std::size_t ... Idx, typename ExecutionContext, typename Args, typename ... Inits>
|
||||
auto invoke(detail::index_sequence<Idx...>,
|
||||
ExecutionContext & context,
|
||||
const typename std::enable_if<std::is_convertible<
|
||||
ExecutionContext&, BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context&>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits) -> basic_process<typename ExecutionContext::executor_type>
|
||||
{
|
||||
return launcher_(context,
|
||||
executable,
|
||||
std::forward<Args>(args),
|
||||
std::get<Idx>(init_)...,
|
||||
std::forward<Inits>(inits)...);
|
||||
}
|
||||
|
||||
|
||||
template<std::size_t ... Idx, typename ExecutionContext, typename Args, typename ... Inits>
|
||||
auto invoke(detail::index_sequence<Idx...>,
|
||||
ExecutionContext & context,
|
||||
error_code & ec,
|
||||
const typename std::enable_if<std::is_convertible<
|
||||
ExecutionContext&, BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context&>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<typename ExecutionContext::executor_type>
|
||||
{
|
||||
return launcher_(context, ec,
|
||||
executable,
|
||||
std::forward<Args>(args),
|
||||
std::get<Idx>(init_)...,
|
||||
std::forward<Inits>(inits)...);
|
||||
}
|
||||
|
||||
template<std::size_t ... Idx, typename Executor, typename Args, typename ... Inits>
|
||||
auto invoke(detail::index_sequence<Idx...>,
|
||||
Executor exec,
|
||||
const typename std::enable_if<
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::execution::is_executor<Executor>::value ||
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::is_executor<Executor>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<Executor>
|
||||
{
|
||||
return launcher_(std::move(exec),
|
||||
executable,
|
||||
std::forward<Args>(args),
|
||||
std::get<Idx>(init_)...,
|
||||
std::forward<Inits>(inits)...);
|
||||
}
|
||||
|
||||
template<std::size_t ... Idx, typename Executor, typename Args, typename ... Inits>
|
||||
auto invoke(detail::index_sequence<Idx...>,
|
||||
Executor exec,
|
||||
error_code & ec,
|
||||
const typename std::enable_if<
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::execution::is_executor<Executor>::value ||
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::is_executor<Executor>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<Executor>
|
||||
{
|
||||
return launcher_(std::move(exec), ec,
|
||||
executable,
|
||||
std::forward<Args>(args),
|
||||
std::get<Idx>(init_)...,
|
||||
std::forward<Inits>(inits)...);
|
||||
}
|
||||
|
||||
Launcher launcher_;
|
||||
std::tuple<Init...> init_;
|
||||
};
|
||||
|
||||
|
||||
template<typename Launcher, typename ... Init>
|
||||
auto bind_launcher(Launcher && launcher, Init && ... init)
|
||||
-> bound_launcher<typename std::decay<Launcher>::type,
|
||||
typename std::decay<Init>::type...>
|
||||
{
|
||||
return bound_launcher<typename std::decay<Launcher>::type,
|
||||
typename std::decay<Init>::type...>(
|
||||
std::forward<Launcher>(launcher),
|
||||
std::forward<Init>(init)...);
|
||||
}
|
||||
|
||||
/// @brief @overload bind_launcher(Launcher && launcher, Init && init)
|
||||
/// @tparam ...Init The initializer types to bind to the default_launcher.
|
||||
/// @param ...init The initializers types to bind to the default_launcher.
|
||||
/// @return The new default_launcher.
|
||||
template<typename ... Init>
|
||||
auto bind_default_launcher(Init && ... init)
|
||||
-> bound_launcher<default_process_launcher,
|
||||
typename std::decay<Init>::type...>
|
||||
{
|
||||
return bound_launcher<default_process_launcher,
|
||||
typename std::decay<Init>::type...>(
|
||||
default_process_launcher(),
|
||||
std::forward<Init>(init)...);
|
||||
}
|
||||
|
||||
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#endif // BOOST_PROCESS_V2_BIND_LAUNCHER_HPP
|
||||
232
linx64/include/boost/process/v2/cstring_ref.hpp
Normal file
232
linx64/include/boost/process/v2/cstring_ref.hpp
Normal file
@@ -0,0 +1,232 @@
|
||||
// Copyright (c) 2022 Klemens D. Morgenstern
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_PROCESS_V2_CSTRING_REF_HPP
|
||||
#define BOOST_PROCESS_V2_CSTRING_REF_HPP
|
||||
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_STANDALONE)
|
||||
#include <string_view>
|
||||
#else
|
||||
#include <boost/utility/string_view.hpp>
|
||||
#endif
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
BOOST_CONSTEXPR static const char* null_char_(char) {return "";}
|
||||
BOOST_CONSTEXPR static const wchar_t* null_char_(wchar_t) {return L"";}
|
||||
BOOST_CONSTEXPR static const char16_t* null_char_(char16_t) {return u"";}
|
||||
BOOST_CONSTEXPR static const char32_t* null_char_(char32_t) {return U"";}
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_HAS_CHAR8_T)
|
||||
BOOST_CONSTEXPR static const char8_t* null_char_(char8_t) {return u8"";}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_STANDALONE)
|
||||
using std::basic_string_view;
|
||||
using std:: string_view;
|
||||
using std:: wstring_view;
|
||||
#else
|
||||
using boost::basic_string_view;
|
||||
using boost:: string_view;
|
||||
using boost:: wstring_view;
|
||||
#endif
|
||||
|
||||
|
||||
/// Small wrapper for a null-terminated string that can be directly passed to C APIS
|
||||
/** This ref can only be modified by moving the front pointer. It does not store the
|
||||
* size, but can detect values that can directly be passed to system APIs.
|
||||
*
|
||||
* It can be constructed from a `char*` pointer or any class that has a `c_str()`
|
||||
* member function, e.g. std::string or boost::static_string.
|
||||
*
|
||||
*/
|
||||
template<typename CharT, typename Traits = std::char_traits<CharT>>
|
||||
struct basic_cstring_ref
|
||||
{
|
||||
using value_type = CharT;
|
||||
using traits_type = Traits;
|
||||
|
||||
BOOST_CONSTEXPR basic_cstring_ref() noexcept : view_(detail::null_char_(value_type{})) {}
|
||||
BOOST_CONSTEXPR basic_cstring_ref(std::nullptr_t) = delete;
|
||||
|
||||
BOOST_CONSTEXPR basic_cstring_ref( const value_type* s ) : view_(s) {}
|
||||
|
||||
template<typename Source,
|
||||
typename =
|
||||
typename std::enable_if<
|
||||
std::is_same<const value_type,
|
||||
typename std::remove_pointer<decltype(std::declval<Source>().c_str())>::type
|
||||
>::value>::type>
|
||||
BOOST_CONSTEXPR basic_cstring_ref(Source && src) : view_(src.c_str()) {}
|
||||
|
||||
BOOST_CONSTEXPR typename basic_string_view<value_type, Traits>::const_pointer c_str() const BOOST_NOEXCEPT
|
||||
{
|
||||
return this->data();
|
||||
}
|
||||
|
||||
using string_view_type = basic_string_view<value_type, Traits>;
|
||||
constexpr operator string_view_type() const {return view_;}
|
||||
|
||||
using pointer = CharT *;
|
||||
using const_pointer = const CharT *;
|
||||
using reference = CharT &;
|
||||
using const_reference = const CharT &;
|
||||
using const_iterator = const_pointer;
|
||||
using iterator = const_iterator;
|
||||
using const_reverse_iterator = typename std::reverse_iterator<const_iterator>;
|
||||
using reverse_iterator = typename std::reverse_iterator<iterator>;
|
||||
using size_type = std::size_t;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
|
||||
static BOOST_CONSTEXPR size_type npos = -1;
|
||||
|
||||
BOOST_CONSTEXPR const_iterator begin() const BOOST_NOEXCEPT {return view_;};
|
||||
BOOST_CONSTEXPR const_iterator end() const BOOST_NOEXCEPT {return view_ + length();};
|
||||
BOOST_CONSTEXPR const_iterator cbegin() const BOOST_NOEXCEPT {return view_;};
|
||||
BOOST_CONSTEXPR const_iterator cend() const BOOST_NOEXCEPT {return view_ + length();};
|
||||
BOOST_CONSTEXPR const_reverse_iterator rbegin() const BOOST_NOEXCEPT {return reverse_iterator(view_ + length());};
|
||||
BOOST_CONSTEXPR const_reverse_iterator rend() const BOOST_NOEXCEPT {return reverse_iterator(view_);};
|
||||
BOOST_CONSTEXPR const_reverse_iterator crbegin() const BOOST_NOEXCEPT {return reverse_iterator(view_ + length());};
|
||||
BOOST_CONSTEXPR const_reverse_iterator crend() const BOOST_NOEXCEPT {return reverse_iterator(view_);};
|
||||
|
||||
BOOST_CONSTEXPR size_type size() const BOOST_NOEXCEPT {return length(); }
|
||||
BOOST_CONSTEXPR size_type length() const BOOST_NOEXCEPT {return traits_type::length(view_); }
|
||||
BOOST_CONSTEXPR size_type max_size() const BOOST_NOEXCEPT {return (std::numeric_limits<std::size_t>::max)() / sizeof(CharT); }
|
||||
BOOST_ATTRIBUTE_NODISCARD BOOST_CONSTEXPR bool empty() const BOOST_NOEXCEPT {return *view_ == *detail::null_char_(CharT{}); }
|
||||
|
||||
BOOST_CONSTEXPR const_reference operator[](size_type pos) const {return view_[pos] ;}
|
||||
BOOST_CXX14_CONSTEXPR const_reference at(size_type pos) const
|
||||
{
|
||||
if (pos >= size())
|
||||
throw_exception(std::out_of_range("cstring-view out of range"));
|
||||
return view_[pos];
|
||||
}
|
||||
BOOST_CONSTEXPR const_reference front() const {return *view_;}
|
||||
BOOST_CONSTEXPR const_reference back() const {return view_[length() - 1];}
|
||||
BOOST_CONSTEXPR const_pointer data() const BOOST_NOEXCEPT {return view_;}
|
||||
BOOST_CXX14_CONSTEXPR void remove_prefix(size_type n) {view_ = view_ + n;}
|
||||
void swap(basic_cstring_ref& s) BOOST_NOEXCEPT {std::swap(view_, s.view_);}
|
||||
|
||||
size_type copy(value_type* s, size_type n, size_type pos = 0) const
|
||||
{
|
||||
return traits_type::copy(s, view_ + pos, n) - view_;
|
||||
}
|
||||
BOOST_CONSTEXPR basic_cstring_ref substr(size_type pos = 0) const
|
||||
{
|
||||
return basic_cstring_ref(view_ + pos);
|
||||
}
|
||||
|
||||
BOOST_CONSTEXPR string_view_type substr(size_type pos, size_type length) const
|
||||
{
|
||||
return string_view_type(view_).substr(pos, length);
|
||||
}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR int compare(basic_cstring_ref x) const BOOST_NOEXCEPT
|
||||
{
|
||||
auto idx = 0u;
|
||||
for (; view_[idx] != null_char_()[0] && x[idx] != null_char_()[0]; idx++)
|
||||
if (!traits_type::eq(view_[idx], x[idx]))
|
||||
return traits_type::lt(view_[idx], x[idx]) ? -1 : 1;
|
||||
|
||||
return traits_type::to_int_type(view_[idx]) -
|
||||
traits_type::to_int_type(x[idx]); // will compare to null char of either.
|
||||
}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR bool starts_with(string_view_type x) const BOOST_NOEXCEPT
|
||||
{
|
||||
if (x.empty())
|
||||
return true;
|
||||
|
||||
auto idx = 0u;
|
||||
for (; view_[idx] != null_char_()[0] && idx < x.size(); idx++)
|
||||
if (!traits_type::eq(view_[idx], x[idx]))
|
||||
return false;
|
||||
|
||||
return idx == x.size() || view_[idx] != null_char_()[0];
|
||||
}
|
||||
BOOST_CONSTEXPR bool starts_with(value_type x) const BOOST_NOEXCEPT
|
||||
{
|
||||
return traits_type::eq(view_[0], x);
|
||||
}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR size_type find( CharT ch, size_type pos = 0 ) const BOOST_NOEXCEPT
|
||||
{
|
||||
for (auto p = view_ + pos; *p != *null_char_(); p++)
|
||||
if (traits_type::eq(*p, ch))
|
||||
return p - view_;
|
||||
return npos;
|
||||
}
|
||||
|
||||
|
||||
friend BOOST_CXX14_CONSTEXPR bool operator==(basic_cstring_ref x, basic_cstring_ref y) BOOST_NOEXCEPT
|
||||
{
|
||||
std::size_t idx = 0u;
|
||||
for (idx = 0u; x[idx] != null_char_()[0] && y[idx] != null_char_()[0]; idx++)
|
||||
if (!traits_type::eq(x[idx], y[idx]))
|
||||
return false;
|
||||
return x[idx] == y[idx];
|
||||
}
|
||||
friend BOOST_CXX14_CONSTEXPR bool operator!=(basic_cstring_ref x, basic_cstring_ref y) BOOST_NOEXCEPT
|
||||
{
|
||||
std::size_t idx = 0u;
|
||||
for (idx = 0u; x[idx] != null_char_()[0] &&
|
||||
y[idx] != null_char_()[0]; idx++)
|
||||
if (!traits_type::eq(x[idx], y[idx]))
|
||||
return true;
|
||||
return x[idx] != y[idx];
|
||||
}
|
||||
friend BOOST_CXX14_CONSTEXPR bool operator< (basic_cstring_ref x, basic_cstring_ref y) BOOST_NOEXCEPT {return x.compare(y) < 0;}
|
||||
friend BOOST_CXX14_CONSTEXPR bool operator> (basic_cstring_ref x, basic_cstring_ref y) BOOST_NOEXCEPT {return x.compare(y) > 0;}
|
||||
friend BOOST_CXX14_CONSTEXPR bool operator<=(basic_cstring_ref x, basic_cstring_ref y) BOOST_NOEXCEPT {return x.compare(y) <= 0;}
|
||||
friend BOOST_CXX14_CONSTEXPR bool operator>=(basic_cstring_ref x, basic_cstring_ref y) BOOST_NOEXCEPT {return x.compare(y) >= 0;}
|
||||
|
||||
// modifiers
|
||||
void clear() BOOST_NOEXCEPT { view_ = null_char_(); } // Boost extension
|
||||
|
||||
std::basic_string<value_type, traits_type> to_string() const {
|
||||
return std::basic_string<CharT, Traits>(begin(), end());
|
||||
}
|
||||
|
||||
template<typename Allocator>
|
||||
std::basic_string<value_type, traits_type, Allocator> to_string(const Allocator& a) const {
|
||||
return std::basic_string<value_type, traits_type, Allocator>(begin(), end(), a);
|
||||
}
|
||||
|
||||
private:
|
||||
BOOST_CONSTEXPR static const_pointer null_char_() {return detail::null_char_(CharT{});}
|
||||
const_pointer view_;
|
||||
};
|
||||
|
||||
template<class charT, class traits>
|
||||
inline std::basic_ostream<charT, traits>&
|
||||
operator<<(std::basic_ostream<charT, traits>& os,
|
||||
const basic_cstring_ref<charT,traits>& str)
|
||||
{
|
||||
return os << static_cast<basic_string_view<charT, traits>>(str);
|
||||
}
|
||||
|
||||
template <class charT, class traits>
|
||||
std::size_t hash_value(basic_string_view<charT, traits> s) {
|
||||
return boost::hash_range(s.begin(), s.end());
|
||||
}
|
||||
|
||||
using cstring_ref = basic_cstring_ref<char>;
|
||||
using wcstring_ref = basic_cstring_ref<wchar_t>;
|
||||
using u16cstring_ref = basic_cstring_ref<char16_t>;
|
||||
using u32cstring_ref = basic_cstring_ref<char32_t>;
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_HAS_CHAR8_T)
|
||||
using u8cstring_ref = basic_cstring_ref<char8_t>;
|
||||
#endif
|
||||
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#endif //BOOST_PROCESS_V2_CSTRING_REF_HPP
|
||||
66
linx64/include/boost/process/v2/default_launcher.hpp
Normal file
66
linx64/include/boost/process/v2/default_launcher.hpp
Normal file
@@ -0,0 +1,66 @@
|
||||
//
|
||||
// boost/process/v2/default_launcher.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2022 Klemens D. Morgenstern (klemens dot morgenstern at gmx dot net)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BOOST_PROCESS_V2_DEFAULT_LAUNCHER_HPP
|
||||
#define BOOST_PROCESS_V2_DEFAULT_LAUNCHER_HPP
|
||||
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
#include <boost/process/v2/windows/default_launcher.hpp>
|
||||
#else
|
||||
#if defined(BOOST_PROCESS_V2_PDFORK)
|
||||
#include <boost/process/v2/posix/pdfork_launcher.hpp>
|
||||
#else
|
||||
#include <boost/process/v2/posix/default_launcher.hpp>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
|
||||
#if defined(GENERATING_DOCUMENTATION)
|
||||
|
||||
/// The default launcher for processes.
|
||||
/** This launcher will be used by process if a
|
||||
* process is launched through the constructor:
|
||||
*
|
||||
* @code {.cpp}
|
||||
* process proc("test", {});
|
||||
* // equivalent to
|
||||
* process prod = default_launcher()("test", {});
|
||||
* @endcode
|
||||
*
|
||||
*/
|
||||
|
||||
typedef implementation_defined default_process_launcher;
|
||||
|
||||
#else
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
typedef windows::default_launcher default_process_launcher;
|
||||
#else
|
||||
#if defined(BOOST_PROCESS_V2_PDFORK)
|
||||
typedef posix::pdfork_launcher default_process_launcher;
|
||||
#else
|
||||
typedef posix::default_launcher default_process_launcher;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_HEADER_ONLY)
|
||||
#include <boost/process/v2/impl/default_launcher.ipp>
|
||||
#endif
|
||||
|
||||
#endif //BOOST_PROCESS_V2_DEFAULT_LAUNCHER_HPP
|
||||
180
linx64/include/boost/process/v2/detail/config.hpp
Normal file
180
linx64/include/boost/process/v2/detail/config.hpp
Normal file
@@ -0,0 +1,180 @@
|
||||
// Copyright (c) 2022 Klemens D. Morgenstern
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_PROCESS_V2_DETAIL_CONFIG_HPP
|
||||
#define BOOST_PROCESS_V2_DETAIL_CONFIG_HPP
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_STANDALONE)
|
||||
|
||||
#define BOOST_PROCESS_V2_ASIO_NAMESPACE asio
|
||||
#define BOOST_PROCESS_V2_COMPLETION_TOKEN_FOR(Sig) ASIO_COMPLETION_TOKEN_FOR(Sig)
|
||||
#define BOOST_PROCESS_V2_DEFAULT_COMPLETION_TOKEN_TYPE(Executor) ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)
|
||||
#define BOOST_PROCESS_V2_INITFN_AUTO_RESULT_TYPE(Token, Signature) ASIO_INITFN_AUTO_RESULT_TYPE(Token, Signature)
|
||||
#define BOOST_PROCESS_V2_DEFAULT_COMPLETION_TOKEN(Executor) ASIO_DEFAULT_COMPLETION_TOKEN(Executor)
|
||||
#define BOOST_PROCESS_V2_INITFN_DEDUCED_RESULT_TYPE(x,y,z) ASIO_INITFN_DEDUCED_RESULT_TYPE(x,y,z)
|
||||
|
||||
#include <asio/detail/config.hpp>
|
||||
#include <system_error>
|
||||
#include <filesystem>
|
||||
#include <string_view>
|
||||
#include <iomanip>
|
||||
#include <optional>
|
||||
|
||||
#if defined(ASIO_WINDOWS)
|
||||
#define BOOST_PROCESS_V2_WINDOWS 1
|
||||
|
||||
// Windows: suppress definition of "min" and "max" macros.
|
||||
#if !defined(NOMINMAX)
|
||||
# define NOMINMAX 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(ASIO_HAS_UNISTD_H)
|
||||
#define BOOST_PROCESS_V2_POSIX 1
|
||||
#endif
|
||||
|
||||
#define BOOST_PROCESS_V2_BEGIN_NAMESPACE namespace process_v2 {
|
||||
#define BOOST_PROCESS_V2_END_NAMESPACE }
|
||||
#define BOOST_PROCESS_V2_NAMESPACE process_v2
|
||||
|
||||
#else
|
||||
|
||||
#define BOOST_PROCESS_V2_ASIO_NAMESPACE boost::asio
|
||||
#define BOOST_PROCESS_V2_COMPLETION_TOKEN_FOR(Sig) BOOST_ASIO_COMPLETION_TOKEN_FOR(Sig)
|
||||
#define BOOST_PROCESS_V2_DEFAULT_COMPLETION_TOKEN_TYPE(Executor) BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)
|
||||
#define BOOST_PROCESS_V2_INITFN_AUTO_RESULT_TYPE(Token, Signature) BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(Token, Signature)
|
||||
#define BOOST_PROCESS_V2_DEFAULT_COMPLETION_TOKEN(Executor) BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(Executor)
|
||||
#define BOOST_PROCESS_V2_INITFN_DEDUCED_RESULT_TYPE(x,y,z) BOOST_ASIO_INITFN_DEDUCED_RESULT_TYPE(x,y,z)
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/io/quoted.hpp>
|
||||
#include <boost/system/error_code.hpp>
|
||||
#include <boost/system/system_category.hpp>
|
||||
#include <boost/system/system_error.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#if defined(BOOST_WINDOWS_API)
|
||||
#define BOOST_PROCESS_V2_WINDOWS 1
|
||||
|
||||
// Windows: suppress definition of "min" and "max" macros.
|
||||
#if !defined(NOMINMAX)
|
||||
# define NOMINMAX 1
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_POSIX_API)
|
||||
#define BOOST_PROCESS_V2_POSIX 1
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_PROCESS_V2_WINDOWS) && !defined(BOOST_POSIX_API)
|
||||
#error Unsupported operating system
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_PROCESS_USE_STD_FS)
|
||||
#include <filesystem>
|
||||
#else
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/filesystem/operations.hpp>
|
||||
#endif
|
||||
|
||||
#define BOOST_PROCESS_V2_BEGIN_NAMESPACE namespace boost { namespace process { namespace v2 {
|
||||
#define BOOST_PROCESS_V2_END_NAMESPACE } } }
|
||||
#define BOOST_PROCESS_V2_NAMESPACE boost::process::v2
|
||||
|
||||
#endif
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
|
||||
#if defined(BOOST_PROCESS_STANDALONE)
|
||||
|
||||
using std::error_code ;
|
||||
using std::error_category ;
|
||||
using std::system_category ;
|
||||
using std::system_error ;
|
||||
namespace filesystem = std::filesystem;
|
||||
using std::quoted;
|
||||
using std::optional;
|
||||
|
||||
#define BOOST_PROCESS_V2_RETURN_EC(ev) \
|
||||
return ::BOOST_PROCESS_V2_NAMESPACE::error_code(ev, ::BOOST_PROCESS_V2_NAMESPACE::system_category()); \
|
||||
|
||||
#define BOOST_PROCESS_V2_ASSIGN_EC(ec, ...) ec.assign(__VA_ARGS__);
|
||||
#define BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) \
|
||||
ec.assign(::BOOST_PROCESS_V2_NAMESPACE::detail::get_last_error()); \
|
||||
|
||||
|
||||
#else
|
||||
|
||||
using boost::system::error_code ;
|
||||
using boost::system::error_category ;
|
||||
using boost::system::system_category ;
|
||||
using boost::system::system_error ;
|
||||
using boost::io::quoted;
|
||||
using boost::optional;
|
||||
|
||||
#ifdef BOOST_PROCESS_USE_STD_FS
|
||||
namespace filesystem = std::filesystem;
|
||||
#else
|
||||
namespace filesystem = boost::filesystem;
|
||||
#endif
|
||||
|
||||
#define BOOST_PROCESS_V2_RETURN_EC(ev) \
|
||||
{ \
|
||||
static constexpr auto loc##__LINE__((BOOST_CURRENT_LOCATION)); \
|
||||
return ::BOOST_PROCESS_V2_NAMESPACE::error_code(ev, ::BOOST_PROCESS_V2_NAMESPACE::system_category(), &loc##__LINE__); \
|
||||
}
|
||||
|
||||
#define BOOST_PROCESS_V2_ASSIGN_EC(ec, ...) \
|
||||
{ \
|
||||
static constexpr auto loc##__LINE__((BOOST_CURRENT_LOCATION)); \
|
||||
ec.assign(__VA_ARGS__, &loc##__LINE__); \
|
||||
}
|
||||
|
||||
#define BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) \
|
||||
{ \
|
||||
static constexpr auto loc##__LINE__((BOOST_CURRENT_LOCATION)); \
|
||||
ec.assign(::BOOST_PROCESS_V2_NAMESPACE::detail::get_last_error(), &loc##__LINE__); \
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#ifndef BOOST_PROCESS_V2_HEADER_ONLY
|
||||
# ifndef BOOST_PROCESS_V2_SEPARATE_COMPILATION
|
||||
# define BOOST_PROCESS_V2_HEADER_ONLY 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if BOOST_PROCESS_V2_DOXYGEN
|
||||
# define BOOST_PROCESS_V2_DECL
|
||||
#elif defined(BOOST_PROCESS_V2_HEADER_ONLY)
|
||||
# define BOOST_PROCESS_V2_DECL inline
|
||||
#else
|
||||
# define BOOST_PROCESS_V2_DECL
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_POSIX)
|
||||
|
||||
#if defined(__linux__) && !defined(BOOST_PROCESS_V2_DISABLE_PIDFD_OPEN)
|
||||
|
||||
#include <sys/syscall.h>
|
||||
|
||||
#if defined(SYS_pidfd_open)
|
||||
#define BOOST_PROCESS_V2_PIDFD_OPEN 1
|
||||
#define BOOST_PROCESS_V2_HAS_PROCESS_HANDLE 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__FreeBSD__) && defined(BOOST_PROCESS_V2_ENABLE_PDFORK)
|
||||
#define BOOST_PROCESS_V2_PDFORK 1
|
||||
#define BOOST_PROCESS_V2_HAS_PROCESS_HANDLE 1
|
||||
#endif
|
||||
#else
|
||||
#define BOOST_PROCESS_V2_HAS_PROCESS_HANDLE 1
|
||||
#endif
|
||||
|
||||
#endif //BOOST_PROCESS_V2_DETAIL_CONFIG_HPP
|
||||
80
linx64/include/boost/process/v2/detail/environment_posix.hpp
Normal file
80
linx64/include/boost/process/v2/detail/environment_posix.hpp
Normal file
@@ -0,0 +1,80 @@
|
||||
//
|
||||
// process/environment/detail/environment_posix.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2021 Klemens D. Morgenstern (klemens dot morgenstern at gmx dot net)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BOOST_PROCESS_V2_DETAIL_ENVIRONMENT_POSIX_HPP
|
||||
#define BOOST_PROCESS_V2_DETAIL_ENVIRONMENT_POSIX_HPP
|
||||
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
#include <boost/process/v2/cstring_ref.hpp>
|
||||
|
||||
#if defined(__APPLE__) || defined(__MACH__) || defined(__FreeBSD__) || defined(__DragonFly__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__sun)
|
||||
extern "C" { extern char **environ; }
|
||||
#endif
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
|
||||
namespace environment
|
||||
{
|
||||
|
||||
using char_type = char;
|
||||
|
||||
template<typename Char>
|
||||
using key_char_traits = std::char_traits<Char>;
|
||||
|
||||
template<typename Char>
|
||||
using value_char_traits = std::char_traits<Char>;
|
||||
|
||||
|
||||
constexpr char_type equality_sign = '=';
|
||||
constexpr char_type delimiter = ':';
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
BOOST_PROCESS_V2_DECL
|
||||
basic_cstring_ref<char_type, value_char_traits<char>>
|
||||
get(basic_cstring_ref<char_type, key_char_traits<char_type>> key, error_code & ec);
|
||||
|
||||
BOOST_PROCESS_V2_DECL
|
||||
void set(basic_cstring_ref<char_type, key_char_traits<char_type>> key,
|
||||
basic_cstring_ref<char_type, value_char_traits<char_type>> value,
|
||||
error_code & ec);
|
||||
|
||||
BOOST_PROCESS_V2_DECL
|
||||
void unset(basic_cstring_ref<char_type, key_char_traits<char_type>> key,
|
||||
error_code & ec);
|
||||
}
|
||||
|
||||
|
||||
using native_handle_type = const char * const *;
|
||||
using native_iterator = native_handle_type;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
BOOST_PROCESS_V2_DECL native_handle_type load_native_handle();
|
||||
struct native_handle_deleter
|
||||
{
|
||||
void operator()(native_handle_type) const {}
|
||||
};
|
||||
|
||||
BOOST_PROCESS_V2_DECL native_iterator next(native_handle_type nh);
|
||||
BOOST_PROCESS_V2_DECL native_iterator find_end(native_handle_type nh);
|
||||
inline const char_type * dereference(native_iterator iterator) {return *iterator;}
|
||||
|
||||
BOOST_PROCESS_V2_DECL bool is_executable(const filesystem::path & pth, error_code & ec);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#endif
|
||||
212
linx64/include/boost/process/v2/detail/environment_win.hpp
Normal file
212
linx64/include/boost/process/v2/detail/environment_win.hpp
Normal file
@@ -0,0 +1,212 @@
|
||||
//
|
||||
// process/environment/detail/environment_win.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2021 Klemens D. Morgenstern (klemens dot morgenstern at gmx dot net)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BOOST_PROCESS_V2_DETAIL_ENVIRONMENT_WIN_HPP
|
||||
#define BOOST_PROCESS_V2_DETAIL_ENVIRONMENT_WIN_HPP
|
||||
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
#include <boost/process/v2/cstring_ref.hpp>
|
||||
|
||||
#include <cwctype>
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
|
||||
namespace environment
|
||||
{
|
||||
|
||||
using char_type = wchar_t;
|
||||
|
||||
template<typename Char>
|
||||
struct key_char_traits
|
||||
{
|
||||
typedef Char char_type;
|
||||
typedef typename std::char_traits<char_type>::int_type int_type;
|
||||
typedef typename std::char_traits<char_type>::off_type off_type;
|
||||
typedef typename std::char_traits<char_type>::pos_type pos_type;
|
||||
typedef typename std::char_traits<char_type>::state_type state_type;
|
||||
|
||||
BOOST_CONSTEXPR static char to_lower(char c) {return std::tolower(to_int_type(c));}
|
||||
BOOST_CONSTEXPR static wchar_t to_lower(wchar_t c) {return std::towlower(to_int_type(c));}
|
||||
|
||||
BOOST_CONSTEXPR static int_type to_lower(int_type i, char ) {return std::tolower(i);}
|
||||
BOOST_CONSTEXPR static int_type to_lower(int_type i, wchar_t) {return std::towlower(i);}
|
||||
|
||||
|
||||
BOOST_CONSTEXPR static
|
||||
void assign(char_type& c1, const char_type& c2) BOOST_NOEXCEPT
|
||||
{
|
||||
c1 = c2;
|
||||
}
|
||||
|
||||
BOOST_CONSTEXPR static
|
||||
bool eq(char_type c1, char_type c2) BOOST_NOEXCEPT
|
||||
{
|
||||
return to_lower(c1) == to_lower(c2);
|
||||
}
|
||||
|
||||
BOOST_CONSTEXPR static
|
||||
bool lt(char_type c1, char_type c2) BOOST_NOEXCEPT
|
||||
{
|
||||
return to_lower(c1) < to_lower(c2);
|
||||
}
|
||||
|
||||
BOOST_CONSTEXPR static
|
||||
int compare(const char_type* s1, const char_type* s2, size_t n) BOOST_NOEXCEPT
|
||||
{
|
||||
auto itrs = std::mismatch(s1, s1 + n, s2, &eq);
|
||||
if (itrs.first == (s1 + n))
|
||||
return 0;
|
||||
auto c1 = to_lower(*itrs.first);
|
||||
auto c2 = to_lower(*itrs.second);
|
||||
|
||||
return (c1 < c2 ) ? -1 : 1;
|
||||
}
|
||||
|
||||
BOOST_CONSTEXPR static size_t length(const char* s) BOOST_NOEXCEPT { return std::strlen(s); }
|
||||
BOOST_CONSTEXPR static size_t length(const wchar_t* s) BOOST_NOEXCEPT { return std::wcslen(s); }
|
||||
|
||||
BOOST_CONSTEXPR static
|
||||
const char_type* find(const char_type* s, size_t n, const char_type& a) BOOST_NOEXCEPT
|
||||
{
|
||||
const char_type u = to_lower(a);
|
||||
return std::find_if(s, s + n, [u](char_type c){return to_lower(c) == u;});
|
||||
}
|
||||
|
||||
BOOST_CONSTEXPR static
|
||||
char_type* move(char_type* s1, const char_type* s2, size_t n) BOOST_NOEXCEPT
|
||||
{
|
||||
if (s1 < s2)
|
||||
return std::move(s2, s2 + n, s1);
|
||||
else
|
||||
return std::move_backward(s2, s2 + n, s1);
|
||||
}
|
||||
|
||||
BOOST_CONSTEXPR static
|
||||
char_type* copy(char_type* s1, const char_type* s2, size_t n) BOOST_NOEXCEPT
|
||||
{
|
||||
return std::copy(s2, s2 + n, s1);
|
||||
}
|
||||
|
||||
BOOST_CONSTEXPR static
|
||||
char_type* assign(char_type* s, size_t n, char_type a) BOOST_NOEXCEPT
|
||||
{
|
||||
std::fill(s, s + n, a);
|
||||
return s +n;
|
||||
}
|
||||
|
||||
BOOST_CONSTEXPR static
|
||||
int_type not_eof(int_type c) BOOST_NOEXCEPT
|
||||
{
|
||||
return eq_int_type(c, eof()) ? ~eof() : c;
|
||||
}
|
||||
|
||||
BOOST_CONSTEXPR static
|
||||
char_type to_char_type(int_type c) BOOST_NOEXCEPT
|
||||
{
|
||||
return char_type(c);
|
||||
}
|
||||
|
||||
BOOST_CONSTEXPR static
|
||||
int_type to_int_type(char c) BOOST_NOEXCEPT
|
||||
{
|
||||
return int_type((unsigned char)c);
|
||||
}
|
||||
|
||||
BOOST_CONSTEXPR static
|
||||
int_type to_int_type(wchar_t c) BOOST_NOEXCEPT
|
||||
{
|
||||
return int_type((wchar_t)c);
|
||||
}
|
||||
|
||||
BOOST_CONSTEXPR static
|
||||
bool eq_int_type(int_type c1, int_type c2) BOOST_NOEXCEPT
|
||||
{
|
||||
return to_lower(c1, char_type()) == to_lower(c2, char_type());
|
||||
}
|
||||
|
||||
BOOST_CONSTEXPR static inline int_type eof() BOOST_NOEXCEPT
|
||||
{
|
||||
return int_type(EOF);
|
||||
}
|
||||
};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
|
||||
template<typename Char>
|
||||
std::size_t hash_step(std::size_t prev, Char c, key_char_traits<Char>)
|
||||
{
|
||||
return prev ^ (key_char_traits<Char>::to_lower(c) << 1);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
template<typename Char>
|
||||
using value_char_traits = std::char_traits<Char>;
|
||||
|
||||
BOOST_CONSTEXPR static char_type equality_sign = L'=';
|
||||
BOOST_CONSTEXPR static char_type delimiter = L';';
|
||||
|
||||
using native_handle_type = wchar_t*;
|
||||
using native_iterator = const wchar_t*;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
BOOST_PROCESS_V2_DECL
|
||||
std::basic_string<wchar_t, value_char_traits<wchar_t>> get(
|
||||
basic_cstring_ref<wchar_t, key_char_traits<wchar_t>> key,
|
||||
error_code & ec);
|
||||
|
||||
BOOST_PROCESS_V2_DECL
|
||||
void set(basic_cstring_ref<wchar_t, key_char_traits<wchar_t>> key,
|
||||
basic_cstring_ref<wchar_t, value_char_traits<wchar_t>> value,
|
||||
error_code & ec);
|
||||
|
||||
BOOST_PROCESS_V2_DECL
|
||||
void unset(basic_cstring_ref<wchar_t, key_char_traits<wchar_t>> key,
|
||||
error_code & ec);
|
||||
|
||||
|
||||
BOOST_PROCESS_V2_DECL
|
||||
std::basic_string<char, value_char_traits<char>> get(
|
||||
basic_cstring_ref<char, key_char_traits<char>> key,
|
||||
error_code & ec);
|
||||
|
||||
BOOST_PROCESS_V2_DECL
|
||||
void set(basic_cstring_ref<char, key_char_traits<char>> key,
|
||||
basic_cstring_ref<char, value_char_traits<char>> value,
|
||||
error_code & ec);
|
||||
|
||||
BOOST_PROCESS_V2_DECL
|
||||
void unset(basic_cstring_ref<char, key_char_traits<char>> key,
|
||||
error_code & ec);
|
||||
|
||||
BOOST_PROCESS_V2_DECL native_handle_type load_native_handle();
|
||||
struct native_handle_deleter
|
||||
{
|
||||
native_handle_deleter() = default;
|
||||
native_handle_deleter(const native_handle_deleter& ) = default;
|
||||
BOOST_PROCESS_V2_DECL void operator()(native_handle_type nh) const;
|
||||
|
||||
};
|
||||
|
||||
inline const char_type * dereference(native_iterator iterator) {return iterator;}
|
||||
BOOST_PROCESS_V2_DECL native_iterator next(native_iterator nh);
|
||||
BOOST_PROCESS_V2_DECL native_iterator find_end(native_handle_type nh);
|
||||
BOOST_PROCESS_V2_DECL bool is_executable(const filesystem::path & pth, error_code & ec);
|
||||
}
|
||||
|
||||
}
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#endif //BOOST_PROCESS_V2_DETAIL_ENVIRONMENT_WIN_HPP
|
||||
18
linx64/include/boost/process/v2/detail/impl/environment.ipp
Normal file
18
linx64/include/boost/process/v2/detail/impl/environment.ipp
Normal file
@@ -0,0 +1,18 @@
|
||||
// Copyright (c) 2022 Klemens D. Morgenstern
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_PROCESS_V2_DETAIL_IMPL_ENVIRONMENT_IPP
|
||||
#define BOOST_PROCESS_V2_DETAIL_IMPL_ENVIRONMENT_IPP
|
||||
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
#include <boost/process/v2/detail/impl/environment_win.ipp>
|
||||
#elif defined(BOOST_PROCESS_V2_POSIX)
|
||||
#include <boost/process/v2/detail/impl/environment_posix.ipp>
|
||||
#else
|
||||
#error Operating System not supported.
|
||||
#endif
|
||||
|
||||
#endif //BOOST_PROCESS_V2_DETAIL_IMPL_ENVIRONMENT_IPP
|
||||
@@ -0,0 +1,81 @@
|
||||
//
|
||||
// process/this_process/detail/environment_posix.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2021 Klemens D. Morgenstern (klemens dot morgenstern at gmx dot net)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BOOST_PROCESS_V2_DETAIL_ENVIRONMENT_WIN_HPP
|
||||
#define BOOST_PROCESS_V2_DETAIL_ENVIRONMENT_WIN_HPP
|
||||
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
#include <boost/process/v2/detail/last_error.hpp>
|
||||
#include <boost/process/v2/environment.hpp>
|
||||
#include <boost/process/v2/cstring_ref.hpp>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <cstring>
|
||||
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
|
||||
namespace environment
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
basic_cstring_ref<char_type, value_char_traits<char>> get(
|
||||
basic_cstring_ref<char_type, key_char_traits<char_type>> key,
|
||||
error_code & ec)
|
||||
{
|
||||
auto res = ::getenv(key.c_str());
|
||||
if (res == nullptr)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, ENOENT, system_category())
|
||||
return {};
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void set(basic_cstring_ref<char_type, key_char_traits<char_type>> key,
|
||||
basic_cstring_ref<char_type, value_char_traits<char_type>> value,
|
||||
error_code & ec)
|
||||
{
|
||||
if (::setenv(key.c_str(), value.c_str(), true))
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
}
|
||||
|
||||
void unset(basic_cstring_ref<char_type, key_char_traits<char_type>> key, error_code & ec)
|
||||
{
|
||||
if (::unsetenv(key.c_str()))
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
}
|
||||
|
||||
|
||||
native_handle_type load_native_handle() { return ::environ; }
|
||||
|
||||
|
||||
native_iterator next(native_iterator nh)
|
||||
{
|
||||
return nh + 1;
|
||||
}
|
||||
|
||||
native_iterator find_end(native_handle_type nh)
|
||||
{
|
||||
while (*nh != nullptr)
|
||||
nh++;
|
||||
return nh;
|
||||
}
|
||||
bool is_executable(const filesystem::path & p, error_code & ec)
|
||||
{
|
||||
return filesystem::is_regular_file(p, ec) && (::access(p.c_str(), X_OK) == 0);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#endif //BOOST_PROCESS_V2_DETAIL_ENVIRONMENT_WIN_HPP
|
||||
142
linx64/include/boost/process/v2/detail/impl/environment_win.ipp
Normal file
142
linx64/include/boost/process/v2/detail/impl/environment_win.ipp
Normal file
@@ -0,0 +1,142 @@
|
||||
//
|
||||
// process/this_process/detail/environment_win.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2021 Klemens D. Morgenstern (klemens dot morgenstern at gmx dot net)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BOOST_PROCESS_V2_DETAIL_IMPL_ENVIRONMENT_WIN_IPP
|
||||
#define BOOST_PROCESS_V2_DETAIL_IMPL_ENVIRONMENT_WIN_IPP
|
||||
|
||||
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
#include <boost/process/v2/detail/environment_win.hpp>
|
||||
#include <boost/process/v2/detail/impl/environment.ipp>
|
||||
#include <boost/process/v2/detail/last_error.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cwctype>
|
||||
#include <cstring>
|
||||
|
||||
#include <shellapi.h>
|
||||
|
||||
#include <boost/process/v2/cstring_ref.hpp>
|
||||
#include <boost/process/v2/error.hpp>
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
|
||||
namespace environment
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
std::basic_string<char_type, value_char_traits<char_type>> get(
|
||||
basic_cstring_ref<char_type, key_char_traits<char_type>> key,
|
||||
error_code & ec)
|
||||
{
|
||||
std::basic_string<char_type, value_char_traits<char_type>> buf;
|
||||
|
||||
std::size_t size = 0u;
|
||||
do
|
||||
{
|
||||
buf.resize(buf.size() + 4096);
|
||||
size = ::GetEnvironmentVariableW(key.c_str(), &buf.front(), static_cast<DWORD>(buf.size()));
|
||||
}
|
||||
while (size == buf.size());
|
||||
|
||||
buf.resize(size);
|
||||
|
||||
if (buf.size() == 0)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
void set(basic_cstring_ref<char_type, key_char_traits<char_type>> key,
|
||||
basic_cstring_ref<char_type, value_char_traits<char_type>> value,
|
||||
error_code & ec)
|
||||
{
|
||||
if (!::SetEnvironmentVariableW(key.c_str(), value.c_str()))
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
}
|
||||
|
||||
void unset(basic_cstring_ref<char_type, key_char_traits<char_type>> key,
|
||||
error_code & ec)
|
||||
{
|
||||
if (!::SetEnvironmentVariableW(key.c_str(), nullptr))
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
}
|
||||
|
||||
|
||||
std::basic_string<char, value_char_traits<char>> get(
|
||||
basic_cstring_ref<char, key_char_traits<char>> key,
|
||||
error_code & ec)
|
||||
{
|
||||
std::basic_string<char, value_char_traits<char>> buf;
|
||||
|
||||
std::size_t size = 0u;
|
||||
do
|
||||
{
|
||||
buf.resize(buf.size() + 4096);
|
||||
size = ::GetEnvironmentVariableA(key.c_str(), &buf.front(), static_cast<DWORD>(buf.size()));
|
||||
}
|
||||
while (size == buf.size());
|
||||
|
||||
buf.resize(size);
|
||||
|
||||
if (buf.size() == 0)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
void set(basic_cstring_ref<char, key_char_traits<char>> key,
|
||||
basic_cstring_ref<char, value_char_traits<char>> value,
|
||||
error_code & ec)
|
||||
{
|
||||
if (!::SetEnvironmentVariableA(key.c_str(), value.c_str()))
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
}
|
||||
|
||||
void unset(basic_cstring_ref<char, key_char_traits<char>> key,
|
||||
error_code & ec)
|
||||
{
|
||||
if (!::SetEnvironmentVariableA(key.c_str(), nullptr))
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
}
|
||||
|
||||
|
||||
native_handle_type load_native_handle() { return ::GetEnvironmentStringsW(); }
|
||||
void native_handle_deleter::operator()(native_handle_type nh) const
|
||||
{
|
||||
::FreeEnvironmentStringsW(nh);
|
||||
}
|
||||
|
||||
native_iterator next(native_iterator nh)
|
||||
{
|
||||
while (*nh != L'\0')
|
||||
nh++;
|
||||
return ++nh;
|
||||
}
|
||||
|
||||
|
||||
native_iterator find_end(native_handle_type nh)
|
||||
{
|
||||
while ((*nh != L'\0') || (*std::next(nh) != L'\0'))
|
||||
nh++;
|
||||
return ++nh;
|
||||
}
|
||||
|
||||
bool is_executable(const filesystem::path & pth, error_code & ec)
|
||||
{
|
||||
return filesystem::is_regular_file(pth, ec) && SHGetFileInfoW(pth.native().c_str(), 0,0,0, SHGFI_EXETYPE);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#endif //BOOST_PROCESS_V2_DETAIL_IMPL_ENVIRONMENT_WIN_IPP
|
||||
34
linx64/include/boost/process/v2/detail/impl/last_error.ipp
Normal file
34
linx64/include/boost/process/v2/detail/impl/last_error.ipp
Normal file
@@ -0,0 +1,34 @@
|
||||
// Copyright (c) 2022 Klemens D. Morgenstern
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_PROCESS_V2_DETAIL_IMPL_LAST_ERROR_IPP
|
||||
#define BOOST_PROCESS_V2_DETAIL_IMPL_LAST_ERROR_IPP
|
||||
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
#include <boost/process/v2/detail/last_error.hpp>
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <cerrno>
|
||||
#endif
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
namespace detail
|
||||
{
|
||||
|
||||
error_code get_last_error()
|
||||
{
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
return error_code(::GetLastError(), system_category());
|
||||
#else
|
||||
return error_code(errno, system_category());
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#endif //BOOST_PROCESS_V2_DETAIL_IMPL_LAST_ERROR_IPP
|
||||
@@ -0,0 +1,169 @@
|
||||
// Copyright (c) 2022 Klemens D. Morgenstern
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_PROCESS_V2_DETAIL_IMPL_PROCESS_HANDLE_WINDOWS_IPP
|
||||
#define BOOST_PROCESS_V2_DETAIL_IMPL_PROCESS_HANDLE_WINDOWS_IPP
|
||||
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
#include <boost/process/v2/detail/last_error.hpp>
|
||||
#include <boost/process/v2/detail/throw_error.hpp>
|
||||
#include <boost/process/v2/detail/process_handle_windows.hpp>
|
||||
#include <boost/process/v2/ext/detail/proc_info.hpp>
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#if !defined(BOOST_PROCESS_V2_DISABLE_UNDOCUMENTED_API)
|
||||
extern "C"
|
||||
{
|
||||
|
||||
LONG WINAPI NtResumeProcess(HANDLE ProcessHandle);
|
||||
LONG WINAPI NtSuspendProcess(HANDLE ProcessHandle);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
void get_exit_code_(
|
||||
HANDLE handle,
|
||||
native_exit_code_type & exit_code,
|
||||
error_code & ec)
|
||||
{
|
||||
if (!::GetExitCodeProcess(handle, &exit_code))
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
}
|
||||
|
||||
|
||||
HANDLE open_process_(DWORD pid)
|
||||
{
|
||||
auto proc = OpenProcess(PROCESS_TERMINATE | SYNCHRONIZE, FALSE, pid);
|
||||
if (proc == nullptr)
|
||||
{
|
||||
error_code ec;
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
throw system_error(ec, "open_process()");
|
||||
}
|
||||
|
||||
return proc;
|
||||
}
|
||||
|
||||
|
||||
void terminate_if_running_(HANDLE handle)
|
||||
{
|
||||
DWORD exit_code = 0u;
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
return ;
|
||||
if (::GetExitCodeProcess(handle, &exit_code))
|
||||
if (exit_code == STILL_ACTIVE)
|
||||
::TerminateProcess(handle, 260);
|
||||
}
|
||||
|
||||
bool check_handle_(HANDLE handle, error_code & ec)
|
||||
{
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, ERROR_INVALID_HANDLE_STATE, system_category())
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool check_pid_(pid_type pid_, error_code & ec)
|
||||
{
|
||||
if (pid_ == 0)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, ERROR_INVALID_HANDLE_STATE, system_category())
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
struct enum_windows_data_t
|
||||
{
|
||||
error_code &ec;
|
||||
pid_type pid;
|
||||
};
|
||||
|
||||
static BOOL CALLBACK enum_window(HWND hwnd, LPARAM param)
|
||||
{
|
||||
auto data = reinterpret_cast<enum_windows_data_t*>(param);
|
||||
DWORD pid{0u};
|
||||
GetWindowThreadProcessId(hwnd, &pid);
|
||||
if (pid != data->pid)
|
||||
return TRUE;
|
||||
|
||||
LRESULT res = ::SendMessageW(hwnd, WM_CLOSE, 0, 0);
|
||||
|
||||
if (res)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(data->ec)
|
||||
return res == 0;
|
||||
}
|
||||
|
||||
void request_exit_(pid_type pid_, error_code & ec)
|
||||
{
|
||||
enum_windows_data_t data{ec, pid_};
|
||||
|
||||
if (!::EnumWindows(enum_window, reinterpret_cast<LONG_PTR>(&data)))
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
}
|
||||
|
||||
void interrupt_(pid_type pid_, error_code & ec)
|
||||
{
|
||||
if (!::GenerateConsoleCtrlEvent(CTRL_C_EVENT, pid_))
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
}
|
||||
|
||||
void terminate_(HANDLE handle, error_code & ec, DWORD & exit_status)
|
||||
{
|
||||
if (!::TerminateProcess(handle, 260))
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
}
|
||||
|
||||
void check_running_(HANDLE handle, error_code & ec, DWORD & exit_status)
|
||||
{
|
||||
if (!::GetExitCodeProcess(handle, &exit_status))
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
}
|
||||
|
||||
#if !defined(BOOST_PROCESS_V2_DISABLE_UNDOCUMENTED_API)
|
||||
void suspend_(HANDLE handle, error_code & ec)
|
||||
{
|
||||
auto nt_err = NtSuspendProcess(handle);
|
||||
ULONG dos_err = RtlNtStatusToDosError(nt_err);
|
||||
if (dos_err)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
}
|
||||
|
||||
void resume_(HANDLE handle, error_code & ec)
|
||||
{
|
||||
auto nt_err = NtResumeProcess(handle);
|
||||
ULONG dos_err = RtlNtStatusToDosError(nt_err);
|
||||
if (dos_err)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
}
|
||||
#else
|
||||
void suspend_(HANDLE, error_code & ec)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, ERROR_CALL_NOT_IMPLEMENTED, system_category())
|
||||
}
|
||||
|
||||
void resume_(HANDLE handle, error_code & ec)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, ERROR_CALL_NOT_IMPLEMENTED, system_category())
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_PROCESS_V2_HEADER_ONLY)
|
||||
template struct basic_process_handle_win<>;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#endif //BOOST_PROCESS_V2_DETAIL_IMPL_PROCESS_HANDLE_WINDOWS_IPP
|
||||
31
linx64/include/boost/process/v2/detail/impl/throw_error.ipp
Normal file
31
linx64/include/boost/process/v2/detail/impl/throw_error.ipp
Normal file
@@ -0,0 +1,31 @@
|
||||
// Copyright (c) 2022 Klemens D. Morgenstern
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_PROCESS_V2_DETAIL_IMPL_THROW_ERROR_IPP
|
||||
#define BOOST_PROCESS_V2_DETAIL_IMPL_THROW_ERROR_IPP
|
||||
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
#include <boost/process/v2/detail/throw_error.hpp>
|
||||
#include <boost/process/v2/detail/throw_exception.hpp>
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
namespace detail
|
||||
{
|
||||
|
||||
void do_throw_error(const error_code& err)
|
||||
{
|
||||
system_error e(err);
|
||||
throw_exception(e);
|
||||
}
|
||||
|
||||
void do_throw_error(const error_code& err, const char* location)
|
||||
{
|
||||
system_error e(err, location);
|
||||
throw_exception(e);
|
||||
}
|
||||
|
||||
}
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#endif //BOOST_PROCESS_V2_DETAIL_IMPL_THROW_ERROR_IPP
|
||||
379
linx64/include/boost/process/v2/detail/impl/utf8.ipp
Normal file
379
linx64/include/boost/process/v2/detail/impl/utf8.ipp
Normal file
@@ -0,0 +1,379 @@
|
||||
// Copyright (c) 2022 Klemens D. Morgenstern
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_PROCESS_V2_DETAIL_IMPL_UTF8_HPP
|
||||
#define BOOST_PROCESS_V2_DETAIL_IMPL_UTF8_HPP
|
||||
|
||||
#include <boost/process/v2/detail/utf8.hpp>
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
#include <boost/process/v2/detail/last_error.hpp>
|
||||
#include <boost/process/v2/error.hpp>
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
|
||||
inline void handle_error(error_code & ec)
|
||||
{
|
||||
const auto err = ::GetLastError();
|
||||
switch (err)
|
||||
{
|
||||
case ERROR_INSUFFICIENT_BUFFER:
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, error::insufficient_buffer, error::utf8_category)
|
||||
break;
|
||||
case ERROR_NO_UNICODE_TRANSLATION:
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, error::invalid_character, error::utf8_category)
|
||||
break;
|
||||
default:
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, err, system_category())
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t size_as_utf8(const wchar_t * in, std::size_t size, error_code & ec)
|
||||
{
|
||||
auto res = WideCharToMultiByte(
|
||||
CP_UTF8, // CodePage,
|
||||
0, // dwFlags,
|
||||
in, // lpWideCharStr,
|
||||
static_cast<int>(size), // cchWideChar,
|
||||
nullptr, // lpMultiByteStr,
|
||||
0, // cbMultiByte,
|
||||
nullptr, // lpDefaultChar,
|
||||
FALSE); // lpUsedDefaultChar
|
||||
|
||||
if (res == 0u)
|
||||
handle_error(ec);
|
||||
return static_cast<std::size_t>(res);
|
||||
}
|
||||
|
||||
std::size_t size_as_wide(const char * in, std::size_t size, error_code & ec)
|
||||
{
|
||||
auto res = ::MultiByteToWideChar(
|
||||
CP_UTF8, // CodePage
|
||||
0, // dwFlags
|
||||
in, // lpMultiByteStr
|
||||
static_cast<int>(size), // cbMultiByte
|
||||
nullptr, // lpWideCharStr
|
||||
0); // cchWideChar
|
||||
if (res == 0u)
|
||||
handle_error(ec);
|
||||
|
||||
return static_cast<std::size_t>(res);
|
||||
}
|
||||
|
||||
std::size_t convert_to_utf8(const wchar_t *in, std::size_t size, char * out,
|
||||
std::size_t max_size, error_code & ec)
|
||||
{
|
||||
auto res = ::WideCharToMultiByte(
|
||||
CP_UTF8, // CodePage
|
||||
0, // dwFlags
|
||||
in, // lpWideCharStr
|
||||
static_cast<int>(size), // cchWideChar
|
||||
out, // lpMultiByteStr
|
||||
static_cast<int>(max_size), // cbMultiByte
|
||||
nullptr, // lpDefaultChar
|
||||
FALSE); // lpUsedDefaultChar
|
||||
if (res == 0u)
|
||||
handle_error(ec);
|
||||
|
||||
return static_cast<std::size_t>(res);
|
||||
}
|
||||
|
||||
std::size_t convert_to_wide(const char *in, std::size_t size, wchar_t * out,
|
||||
std::size_t max_size, error_code & ec)
|
||||
{
|
||||
auto res = ::MultiByteToWideChar(
|
||||
CP_UTF8, // CodePage
|
||||
0, // dwFlags
|
||||
in, // lpMultiByteStr
|
||||
static_cast<int>(size), // cbMultiByte
|
||||
out, // lpWideCharStr
|
||||
static_cast<int>(max_size)); // cchWideChar
|
||||
if (res == 0u)
|
||||
handle_error(ec);
|
||||
|
||||
return static_cast<std::size_t>(res);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
|
||||
template<std::size_t s>
|
||||
inline int get_cont_octet_out_count_impl(wchar_t word) {
|
||||
if (word < 0x80) {
|
||||
return 0;
|
||||
}
|
||||
if (word < 0x800) {
|
||||
return 1;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline int get_cont_octet_out_count_impl<4>(wchar_t word) {
|
||||
if (word < 0x80) {
|
||||
return 0;
|
||||
}
|
||||
if (word < 0x800) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Note that the following code will generate warnings on some platforms
|
||||
// where wchar_t is defined as UCS2. The warnings are superfluous as the
|
||||
// specialization is never instantiated with such compilers, but this
|
||||
// can cause problems if warnings are being treated as errors, so we guard
|
||||
// against that. Including <boost/detail/utf8_codecvt_facet.hpp> as we do
|
||||
// should be enough to get WCHAR_MAX defined.
|
||||
#if !defined(WCHAR_MAX)
|
||||
# error WCHAR_MAX not defined!
|
||||
#endif
|
||||
// cope with VC++ 7.1 or earlier having invalid WCHAR_MAX
|
||||
#if defined(_MSC_VER) && _MSC_VER <= 1310 // 7.1 or earlier
|
||||
return 2;
|
||||
#elif WCHAR_MAX > 0x10000
|
||||
|
||||
if (word < 0x10000) {
|
||||
return 2;
|
||||
}
|
||||
if (word < 0x200000) {
|
||||
return 3;
|
||||
}
|
||||
if (word < 0x4000000) {
|
||||
return 4;
|
||||
}
|
||||
return 5;
|
||||
|
||||
#else
|
||||
return 2;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline int get_cont_octet_out_count(wchar_t word)
|
||||
{
|
||||
return detail::get_cont_octet_out_count_impl<sizeof(wchar_t)>(word);
|
||||
}
|
||||
|
||||
// copied from boost/detail/utf8_codecvt_facet.ipp
|
||||
// Copyright (c) 2001 Ronald Garcia, Indiana University (garcia@osl.iu.edu)
|
||||
// Andrew Lumsdaine, Indiana University (lums@osl.iu.edu).
|
||||
|
||||
inline unsigned int get_octet_count(unsigned char lead_octet)
|
||||
{
|
||||
// if the 0-bit (MSB) is 0, then 1 character
|
||||
if (lead_octet <= 0x7f) return 1;
|
||||
|
||||
// Otherwise the count number of consecutive 1 bits starting at MSB
|
||||
// assert(0xc0 <= lead_octet && lead_octet <= 0xfd);
|
||||
|
||||
if (0xc0 <= lead_octet && lead_octet <= 0xdf) return 2;
|
||||
else if (0xe0 <= lead_octet && lead_octet <= 0xef) return 3;
|
||||
else if (0xf0 <= lead_octet && lead_octet <= 0xf7) return 4;
|
||||
else if (0xf8 <= lead_octet && lead_octet <= 0xfb) return 5;
|
||||
else return 6;
|
||||
}
|
||||
|
||||
inline bool invalid_continuing_octet(unsigned char octet_1) {
|
||||
return (octet_1 < 0x80|| 0xbf< octet_1);
|
||||
}
|
||||
|
||||
inline unsigned int get_cont_octet_count(unsigned char lead_octet)
|
||||
{
|
||||
return get_octet_count(lead_octet) - 1;
|
||||
}
|
||||
|
||||
inline const wchar_t * get_octet1_modifier_table() noexcept
|
||||
{
|
||||
static const wchar_t octet1_modifier_table[] = {
|
||||
0x00, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc
|
||||
};
|
||||
return octet1_modifier_table;
|
||||
}
|
||||
|
||||
|
||||
std::size_t size_as_utf8(const wchar_t * in, std::size_t size, error_code & ec)
|
||||
{
|
||||
std::size_t res = 0u;
|
||||
const auto from_end = in + size;
|
||||
for (auto from = in; from != from_end; from++)
|
||||
res += get_cont_octet_out_count(*from) + 1;
|
||||
return res;
|
||||
}
|
||||
|
||||
std::size_t size_as_wide(const char * in, std::size_t size, error_code & ec)
|
||||
{
|
||||
const auto from = in;
|
||||
const auto from_end = from + size;
|
||||
const char * from_next = from;
|
||||
for (std::size_t char_count = 0u; from_next < from_end; ++char_count) {
|
||||
unsigned int octet_count = get_octet_count(*from_next);
|
||||
// The buffer may represent incomplete characters, so terminate early if one is found
|
||||
if (octet_count > static_cast<std::size_t>(from_end - from_next))
|
||||
break;
|
||||
from_next += octet_count;
|
||||
}
|
||||
|
||||
return from_next - from;
|
||||
}
|
||||
|
||||
std::size_t convert_to_utf8(const wchar_t * in, std::size_t size,
|
||||
char * out, std::size_t max_size, error_code & ec)
|
||||
{
|
||||
|
||||
const wchar_t * from = in;
|
||||
const wchar_t * from_end = from + size;
|
||||
const wchar_t * & from_next = from;
|
||||
char * to = out;
|
||||
char * to_end = out + max_size;
|
||||
char * & to_next = to;
|
||||
|
||||
const wchar_t * const octet1_modifier_table = get_octet1_modifier_table();
|
||||
wchar_t max_wchar = (std::numeric_limits<wchar_t>::max)();
|
||||
while (from != from_end && to != to_end) {
|
||||
|
||||
// Check for invalid UCS-4 character
|
||||
if (*from > max_wchar) {
|
||||
from_next = from;
|
||||
to_next = to;
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, error::invalid_character, error::get_utf8_category())
|
||||
return 0u;
|
||||
}
|
||||
|
||||
int cont_octet_count = get_cont_octet_out_count(*from);
|
||||
|
||||
// RG - comment this formula better
|
||||
int shift_exponent = cont_octet_count * 6;
|
||||
|
||||
// Process the first character
|
||||
*to++ = static_cast<char>(octet1_modifier_table[cont_octet_count] +
|
||||
(unsigned char)(*from / (1 << shift_exponent)));
|
||||
|
||||
// Process the continuation characters
|
||||
// Invariants: At the start of the loop:
|
||||
// 1) 'i' continuing octets have been generated
|
||||
// 2) '*to' points to the next location to place an octet
|
||||
// 3) shift_exponent is 6 more than needed for the next octet
|
||||
int i = 0;
|
||||
while (i != cont_octet_count && to != to_end) {
|
||||
shift_exponent -= 6;
|
||||
*to++ = static_cast<char>(0x80 + ((*from / (1 << shift_exponent)) % (1 << 6)));
|
||||
++i;
|
||||
}
|
||||
// If we filled up the out buffer before encoding the character
|
||||
if (to == to_end && i != cont_octet_count) {
|
||||
from_next = from;
|
||||
to_next = to - (i + 1);
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, error::insufficient_buffer, error::get_utf8_category())
|
||||
return 0u;
|
||||
}
|
||||
++from;
|
||||
}
|
||||
from_next = from;
|
||||
to_next = to;
|
||||
|
||||
// Were we done or did we run out of destination space
|
||||
if (from != from_end)
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, error::insufficient_buffer, error::get_utf8_category())
|
||||
|
||||
return to_next - out;
|
||||
}
|
||||
|
||||
inline bool invalid_leading_octet(unsigned char octet_1) {
|
||||
return (0x7f < octet_1 && octet_1 < 0xc0) ||
|
||||
(octet_1 > 0xfd);
|
||||
}
|
||||
|
||||
std::size_t convert_to_wide(const char * in, std::size_t size,
|
||||
wchar_t * out, std::size_t max_size, error_code & ec)
|
||||
{
|
||||
const char * from = in;
|
||||
const char * from_end = from + size;
|
||||
const char * & from_next = from;
|
||||
wchar_t * to = out;
|
||||
wchar_t * to_end = out + max_size;
|
||||
wchar_t * & to_next = to;
|
||||
|
||||
// Basic algorithm: The first octet determines how many
|
||||
// octets total make up the UCS-4 character. The remaining
|
||||
// "continuing octets" all begin with "10". To convert, subtract
|
||||
// the amount that specifies the number of octets from the first
|
||||
// octet. Subtract 0x80 (1000 0000) from each continuing octet,
|
||||
// then mash the whole lot together. Note that each continuing
|
||||
// octet only uses 6 bits as unique values, so only shift by
|
||||
// multiples of 6 to combine.
|
||||
const wchar_t * const octet1_modifier_table = detail::get_octet1_modifier_table();
|
||||
while (from != from_end && to != to_end) {
|
||||
|
||||
// Error checking on the first octet
|
||||
if (invalid_leading_octet(*from)) {
|
||||
from_next = from;
|
||||
to_next = to;
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, error::invalid_character, error::get_utf8_category())
|
||||
return 0u;
|
||||
}
|
||||
|
||||
// The first octet is adjusted by a value dependent upon
|
||||
// the number of "continuing octets" encoding the character
|
||||
const int cont_octet_count = get_cont_octet_count(*from);
|
||||
|
||||
// The unsigned char conversion is necessary in case char is
|
||||
// signed (I learned this the hard way)
|
||||
wchar_t ucs_result =
|
||||
(unsigned char)(*from++) - octet1_modifier_table[cont_octet_count];
|
||||
|
||||
// Invariants:
|
||||
// 1) At the start of the loop, 'i' continuing characters have been
|
||||
// processed
|
||||
// 2) *from points to the next continuing character to be processed.
|
||||
int i = 0;
|
||||
while (i != cont_octet_count && from != from_end) {
|
||||
|
||||
// Error checking on continuing characters
|
||||
if (invalid_continuing_octet(*from)) {
|
||||
from_next = from;
|
||||
to_next = to;
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, error::invalid_character, error::get_utf8_category())
|
||||
return 0u;
|
||||
}
|
||||
|
||||
ucs_result *= (1 << 6);
|
||||
|
||||
// each continuing character has an extra (10xxxxxx)b attached to
|
||||
// it that must be removed.
|
||||
ucs_result += (unsigned char)(*from++) - 0x80;
|
||||
++i;
|
||||
}
|
||||
|
||||
// If the buffer ends with an incomplete unicode character...
|
||||
if (from == from_end && i != cont_octet_count) {
|
||||
// rewind "from" to before the current character translation
|
||||
from_next = from - (i + 1);
|
||||
to_next = to;
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, error::insufficient_buffer, error::get_utf8_category())
|
||||
return 0u;
|
||||
}
|
||||
*to++ = ucs_result;
|
||||
}
|
||||
from_next = from;
|
||||
to_next = to;
|
||||
|
||||
if (from != from_end)
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, error::insufficient_buffer, error::get_utf8_category())
|
||||
|
||||
return to_next - out;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#endif //BOOST_PROCESS_V2_DETAIL_IMPL_UTF8_HPP
|
||||
28
linx64/include/boost/process/v2/detail/last_error.hpp
Normal file
28
linx64/include/boost/process/v2/detail/last_error.hpp
Normal file
@@ -0,0 +1,28 @@
|
||||
// Copyright (c) 2022 Klemens D. Morgenstern
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_PROCESS_V2_DETAIL_LAST_ERROR_HPP
|
||||
#define BOOST_PROCESS_V2_DETAIL_LAST_ERROR_HPP
|
||||
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
BOOST_PROCESS_V2_DECL error_code get_last_error();
|
||||
|
||||
}
|
||||
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_HEADER_ONLY)
|
||||
|
||||
#include <boost/process/v2/detail/impl/last_error.ipp>
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif //BOOST_PROCESS_V2_DETAIL_LAST_ERROR_HPP
|
||||
355
linx64/include/boost/process/v2/detail/process_handle_fd.hpp
Normal file
355
linx64/include/boost/process/v2/detail/process_handle_fd.hpp
Normal file
@@ -0,0 +1,355 @@
|
||||
|
||||
// Copyright (c) 2022 Klemens D. Morgenstern
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_PROCESS_V2_DETAIL_PROCESS_HANDLE_FD_HPP
|
||||
#define BOOST_PROCESS_V2_DETAIL_PROCESS_HANDLE_FD_HPP
|
||||
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/syscall.h>
|
||||
|
||||
#include <boost/process/v2/detail/last_error.hpp>
|
||||
#include <boost/process/v2/detail/throw_error.hpp>
|
||||
#include <boost/process/v2/exit_code.hpp>
|
||||
#include <boost/process/v2/pid.hpp>
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_STANDALONE)
|
||||
#include <asio/any_io_executor.hpp>
|
||||
#include <asio/compose.hpp>
|
||||
#include <asio/posix/basic_stream_descriptor.hpp>
|
||||
#include <asio/post.hpp>
|
||||
#else
|
||||
#include <boost/asio/any_io_executor.hpp>
|
||||
#include <boost/asio/compose.hpp>
|
||||
#include <boost/asio/posix/basic_stream_descriptor.hpp>
|
||||
#include <boost/asio/post.hpp>
|
||||
#endif
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template<typename Executor = BOOST_PROCESS_V2_ASIO_NAMESPACE::any_io_executor>
|
||||
struct basic_process_handle_fd
|
||||
{
|
||||
using native_handle_type = int;
|
||||
|
||||
typedef Executor executor_type;
|
||||
|
||||
executor_type get_executor()
|
||||
{ return descriptor_.get_executor(); }
|
||||
|
||||
/// Rebinds the process_handle to another executor.
|
||||
template<typename Executor1>
|
||||
struct rebind_executor
|
||||
{
|
||||
/// The socket type when rebound to the specified executor.
|
||||
typedef basic_process_handle_fd<Executor1> other;
|
||||
};
|
||||
|
||||
template<typename ExecutionContext>
|
||||
basic_process_handle_fd(ExecutionContext &context,
|
||||
typename std::enable_if<
|
||||
std::is_convertible<ExecutionContext &,
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context &>::value>::type * = nullptr)
|
||||
: pid_(-1), descriptor_(context)
|
||||
{
|
||||
}
|
||||
|
||||
basic_process_handle_fd(executor_type executor)
|
||||
: pid_(-1), descriptor_(executor)
|
||||
{
|
||||
}
|
||||
|
||||
basic_process_handle_fd(executor_type executor, pid_type pid)
|
||||
: pid_(pid), descriptor_(executor, syscall(SYS_pidfd_open, pid, 0))
|
||||
{
|
||||
}
|
||||
|
||||
basic_process_handle_fd(executor_type executor, pid_type pid, native_handle_type process_handle)
|
||||
: pid_(pid), descriptor_(executor, process_handle)
|
||||
{
|
||||
}
|
||||
|
||||
basic_process_handle_fd(basic_process_handle_fd &&handle)
|
||||
: pid_(handle.pid_), descriptor_(std::move(handle.descriptor_))
|
||||
{
|
||||
handle.pid_ = -1;
|
||||
}
|
||||
|
||||
template<typename Executor1>
|
||||
basic_process_handle_fd(basic_process_handle_fd<Executor1> &&handle)
|
||||
: pid_(handle.pid_), descriptor_(std::move(handle.descriptor_))
|
||||
{
|
||||
handle.pid_ = -1;
|
||||
}
|
||||
|
||||
|
||||
basic_process_handle_fd& operator=(basic_process_handle_fd &&handle)
|
||||
{
|
||||
pid_ = handle.pid_;
|
||||
descriptor_ = std::move(handle.descriptor_);
|
||||
handle.pid_ = -1;
|
||||
return *this;
|
||||
}
|
||||
|
||||
pid_type id() const
|
||||
{ return pid_; }
|
||||
|
||||
native_handle_type native_handle() {return pid_;}
|
||||
|
||||
void terminate_if_running(error_code &)
|
||||
{
|
||||
if (pid_ <= 0)
|
||||
return;
|
||||
if (::waitpid(pid_, nullptr, WNOHANG) == 0)
|
||||
{
|
||||
::kill(pid_, SIGKILL);
|
||||
::waitpid(pid_, nullptr, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void terminate_if_running()
|
||||
{
|
||||
if (pid_ <= 0)
|
||||
return;
|
||||
if (::waitpid(pid_, nullptr, WNOHANG) == 0)
|
||||
{
|
||||
::kill(pid_, SIGKILL);
|
||||
::waitpid(pid_, nullptr, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void wait(native_exit_code_type &exit_status, error_code &ec)
|
||||
{
|
||||
if (pid_ <= 0)
|
||||
return;
|
||||
while (::waitpid(pid_, &exit_status, 0) < 0)
|
||||
{
|
||||
if (errno != EINTR)
|
||||
{
|
||||
ec = get_last_error();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void wait(native_exit_code_type &exit_status)
|
||||
{
|
||||
if (pid_ <= 0)
|
||||
return;
|
||||
error_code ec;
|
||||
wait(exit_status, ec);
|
||||
if (ec)
|
||||
detail::throw_error(ec, "wait(pid)");
|
||||
}
|
||||
|
||||
void interrupt(error_code &ec)
|
||||
{
|
||||
if (pid_ <= 0)
|
||||
return;
|
||||
if (::kill(pid_, SIGINT) == -1)
|
||||
ec = get_last_error();
|
||||
}
|
||||
|
||||
void interrupt()
|
||||
{
|
||||
if (pid_ <= 0)
|
||||
return;
|
||||
error_code ec;
|
||||
interrupt(ec);
|
||||
if (ec)
|
||||
detail::throw_error(ec, "interrupt");
|
||||
}
|
||||
|
||||
void request_exit(error_code &ec)
|
||||
{
|
||||
if (pid_ <= 0)
|
||||
return;
|
||||
if (::kill(pid_, SIGTERM) == -1)
|
||||
ec = get_last_error();
|
||||
}
|
||||
|
||||
void request_exit()
|
||||
{
|
||||
if (pid_ <= 0)
|
||||
return;
|
||||
error_code ec;
|
||||
request_exit(ec);
|
||||
if (ec)
|
||||
detail::throw_error(ec, "request_exit");
|
||||
}
|
||||
|
||||
void suspend()
|
||||
{
|
||||
if (pid_ <= 0)
|
||||
return ;
|
||||
error_code ec;
|
||||
suspend(ec);
|
||||
if (ec)
|
||||
detail::throw_error(ec, "suspend");
|
||||
}
|
||||
|
||||
void suspend(error_code &ec)
|
||||
{
|
||||
if (pid_ <= 0)
|
||||
return ;
|
||||
if (::kill(pid_, SIGSTOP) == -1)
|
||||
ec = get_last_error();
|
||||
}
|
||||
|
||||
void resume()
|
||||
{
|
||||
if (pid_ <= 0)
|
||||
return ;
|
||||
error_code ec;
|
||||
resume(ec);
|
||||
if (ec)
|
||||
detail::throw_error(ec, "resume");
|
||||
}
|
||||
|
||||
void resume(error_code &ec)
|
||||
{
|
||||
if (pid_ <= 0)
|
||||
return ;
|
||||
if (::kill(pid_, SIGCONT) == -1)
|
||||
ec = get_last_error();
|
||||
}
|
||||
void terminate(native_exit_code_type &exit_status, error_code &ec)
|
||||
{
|
||||
if (pid_ <= 0)
|
||||
return;
|
||||
if (::kill(pid_, SIGKILL) == -1)
|
||||
ec = get_last_error();
|
||||
}
|
||||
|
||||
void terminate(native_exit_code_type &exit_status)
|
||||
{
|
||||
if (pid_ <= 0)
|
||||
return;
|
||||
error_code ec;
|
||||
terminate(exit_status, ec);
|
||||
if (ec)
|
||||
detail::throw_error(ec, "terminate");
|
||||
}
|
||||
|
||||
bool running(native_exit_code_type &exit_code, error_code & ec)
|
||||
{
|
||||
if (pid_ <= 0)
|
||||
return false;
|
||||
int code = 0;
|
||||
int res = ::waitpid(pid_, &code, WNOHANG);
|
||||
if (res == -1)
|
||||
ec = get_last_error();
|
||||
else if (res == 0)
|
||||
return true;
|
||||
else
|
||||
ec.clear();
|
||||
|
||||
if (res == 0)
|
||||
return true;
|
||||
else
|
||||
{
|
||||
exit_code = code;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool running(native_exit_code_type &exit_code)
|
||||
{
|
||||
if (pid_ <= 0)
|
||||
return false;
|
||||
|
||||
error_code ec;
|
||||
bool res = running(exit_code, ec);
|
||||
if (ec)
|
||||
detail::throw_error(ec, "is_running");
|
||||
return res;
|
||||
}
|
||||
|
||||
bool is_open() const
|
||||
{
|
||||
return pid_ != -1;
|
||||
}
|
||||
|
||||
template<BOOST_PROCESS_V2_COMPLETION_TOKEN_FOR(void(error_code, native_exit_code_type))
|
||||
WaitHandler BOOST_PROCESS_V2_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
|
||||
BOOST_PROCESS_V2_INITFN_AUTO_RESULT_TYPE(WaitHandler, void (error_code, native_exit_code_type))
|
||||
async_wait(WaitHandler &&handler BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
|
||||
{
|
||||
return BOOST_PROCESS_V2_ASIO_NAMESPACE::async_compose<WaitHandler, void(error_code, native_exit_code_type)>(
|
||||
async_wait_op_{descriptor_, pid_}, handler, descriptor_);
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename>
|
||||
friend
|
||||
struct basic_process_handle_fd;
|
||||
pid_type pid_ = -1;
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::posix::basic_stream_descriptor<Executor> descriptor_;
|
||||
|
||||
struct async_wait_op_
|
||||
{
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::posix::basic_descriptor<Executor> &descriptor;
|
||||
pid_type pid_;
|
||||
|
||||
template<typename Self>
|
||||
void operator()(Self &&self)
|
||||
{
|
||||
error_code ec;
|
||||
native_exit_code_type exit_code{};
|
||||
int wait_res = -1;
|
||||
if (pid_ <= 0) // error, complete early
|
||||
ec = BOOST_PROCESS_V2_ASIO_NAMESPACE::error::bad_descriptor;
|
||||
else
|
||||
{
|
||||
wait_res = ::waitpid(pid_, &exit_code, WNOHANG);
|
||||
if (wait_res == -1)
|
||||
ec = get_last_error();
|
||||
}
|
||||
|
||||
|
||||
if (!ec && (wait_res == 0))
|
||||
{
|
||||
descriptor.async_wait(
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::posix::descriptor_base::wait_read, std::move(self));
|
||||
return;
|
||||
}
|
||||
|
||||
struct completer
|
||||
{
|
||||
error_code ec;
|
||||
native_exit_code_type code;
|
||||
typename std::decay<Self>::type self;
|
||||
|
||||
void operator()()
|
||||
{
|
||||
self.complete(ec, code);
|
||||
}
|
||||
};
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::post(descriptor.get_executor(),
|
||||
completer{ec, exit_code, std::move(self)});
|
||||
|
||||
}
|
||||
|
||||
template<typename Self>
|
||||
void operator()(Self &&self, error_code ec, int = 0)
|
||||
{
|
||||
native_exit_code_type exit_code{};
|
||||
if (!ec)
|
||||
if (::waitpid(pid_, &exit_code, 0) == -1)
|
||||
ec = get_last_error();
|
||||
std::move(self).complete(ec, exit_code);
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#endif //BOOST_PROCESS_HANDLE_FD_OR_SIGNAL_HPP
|
||||
@@ -0,0 +1,383 @@
|
||||
|
||||
// Copyright (c) 2022 Klemens D. Morgenstern
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_PROCESS_V2_DETAIL_PROCESS_HANDLE_FD_OR_SIGNAL_HPP
|
||||
#define BOOST_PROCESS_V2_DETAIL_PROCESS_HANDLE_FD_OR_SIGNAL_HPP
|
||||
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <boost/process/v2/detail/last_error.hpp>
|
||||
#include <boost/process/v2/detail/throw_error.hpp>
|
||||
#include <boost/process/v2/exit_code.hpp>
|
||||
#include <boost/process/v2/pid.hpp>
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_STANDALONE)
|
||||
#include <asio/any_io_executor.hpp>
|
||||
#include <asio/compose.hpp>
|
||||
#include <asio/dispatch.hpp>
|
||||
#include <asio/posix/basic_stream_descriptor.hpp>
|
||||
#include <asio/post.hpp>
|
||||
#include <asio/windows/signal_set.hpp>
|
||||
#else
|
||||
#include <boost/asio/any_io_executor.hpp>
|
||||
#include <boost/asio/compose.hpp>
|
||||
#include <boost/asio/dispatch.hpp>
|
||||
#include <boost/asio/posix/basic_stream_descriptor.hpp>
|
||||
#include <boost/asio/post.hpp>
|
||||
#include <boost/asio/signal_set.hpp>
|
||||
#endif
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template<typename Executor = BOOST_PROCESS_V2_ASIO_NAMESPACE::any_io_executor>
|
||||
struct basic_process_handle_fd_or_signal
|
||||
{
|
||||
using native_handle_type = int;
|
||||
|
||||
typedef Executor executor_type;
|
||||
|
||||
executor_type get_executor()
|
||||
{ return signal_set_.get_executor(); }
|
||||
|
||||
/// Rebinds the process_handle to another executor.
|
||||
template<typename Executor1>
|
||||
struct rebind_executor
|
||||
{
|
||||
/// The socket type when rebound to the specified executor.
|
||||
typedef basic_process_handle_fd_or_signal<Executor1> other;
|
||||
};
|
||||
|
||||
template<typename ExecutionContext>
|
||||
basic_process_handle_fd_or_signal(ExecutionContext &context,
|
||||
typename std::enable_if<
|
||||
std::is_convertible<ExecutionContext &,
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context &>::value
|
||||
>::type * = nullptr)
|
||||
: pid_(-1), descriptor_(context)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename ExecutionContext>
|
||||
basic_process_handle_fd_or_signal(ExecutionContext &context,
|
||||
pid_type pid,
|
||||
typename std::enable_if<
|
||||
std::is_convertible<ExecutionContext &,
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context &>::value
|
||||
>::type * = nullptr)
|
||||
: pid_(pid), descriptor_(context)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename ExecutionContext>
|
||||
basic_process_handle_fd_or_signal(ExecutionContext &context,
|
||||
pid_type pid, native_handle_type process_handle,
|
||||
typename std::enable_if<
|
||||
std::is_convertible<ExecutionContext &,
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context &>::value
|
||||
>::type * = nullptr)
|
||||
: pid_(pid), descriptor_(context, process_handle)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
basic_process_handle_fd_or_signal(Executor executor)
|
||||
: pid_(-1), descriptor_(executor)
|
||||
{
|
||||
}
|
||||
|
||||
basic_process_handle_fd_or_signal(Executor executor, pid_type pid)
|
||||
: pid_(pid), descriptor_(executor)
|
||||
{
|
||||
}
|
||||
|
||||
basic_process_handle_fd_or_signal(Executor executor, pid_type pid, native_handle_type process_handle)
|
||||
: pid_(pid), descriptor_(executor, process_handle)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
basic_process_handle_fd_or_signal(basic_process_handle_fd_or_signal &&handle)
|
||||
: pid_(handle.pid_), descriptor_(std::move(handle.descriptor_))
|
||||
{
|
||||
handle.pid_ = -1;
|
||||
}
|
||||
// Warn: does not change the executor of the signal-set.
|
||||
basic_process_handle_fd_or_signal& operator=(basic_process_handle_fd_or_signal &&handle)
|
||||
{
|
||||
pid_ = handle.pid_;
|
||||
descriptor_ = std::move(handle.descriptor_);
|
||||
handle.pid_ = -1;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
template<typename Executor1>
|
||||
basic_process_handle_fd_or_signal(basic_process_handle_fd_or_signal<Executor1> &&handle)
|
||||
: pid_(handle.pid_), descriptor_(std::move(handle.descriptor_))
|
||||
{
|
||||
handle.pid_ = -1;
|
||||
}
|
||||
|
||||
pid_type id() const
|
||||
{ return pid_; }
|
||||
native_handle_type native_handle() {return pid_;}
|
||||
|
||||
void terminate_if_running(error_code &)
|
||||
{
|
||||
if (pid_ <= 0)
|
||||
return;
|
||||
if (::waitpid(pid_, nullptr, WNOHANG) == 0)
|
||||
{
|
||||
::kill(pid_, SIGKILL);
|
||||
::waitpid(pid_, nullptr, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void terminate_if_running()
|
||||
{
|
||||
if (pid_ <= 0)
|
||||
return;
|
||||
if (::waitpid(pid_, nullptr, WNOHANG) == 0)
|
||||
{
|
||||
::kill(pid_, SIGKILL);
|
||||
::waitpid(pid_, nullptr, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void wait(native_exit_code_type &exit_status, error_code &ec)
|
||||
{
|
||||
if (pid_ <= 0)
|
||||
return;
|
||||
while (::waitpid(pid_, &exit_status, 0) < 0)
|
||||
{
|
||||
if (errno != EINTR)
|
||||
{
|
||||
ec = get_last_error();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void wait(native_exit_code_type &exit_status)
|
||||
{
|
||||
if (pid_ <= 0)
|
||||
return;
|
||||
error_code ec;
|
||||
wait(exit_status, ec);
|
||||
if (ec)
|
||||
detail::throw_error(ec, "wait(pid)");
|
||||
}
|
||||
|
||||
void interrupt(error_code &ec)
|
||||
{
|
||||
if (pid_ <= 0)
|
||||
return;
|
||||
if (::kill(pid_, SIGINT) == -1)
|
||||
ec = get_last_error();
|
||||
}
|
||||
|
||||
void interrupt()
|
||||
{
|
||||
if (pid_ <= 0)
|
||||
return;
|
||||
error_code ec;
|
||||
interrupt(ec);
|
||||
if (ec)
|
||||
detail::throw_error(ec, "interrupt");
|
||||
}
|
||||
|
||||
void request_exit(error_code &ec)
|
||||
{
|
||||
if (pid_ <= 0)
|
||||
return;
|
||||
if (::kill(pid_, SIGTERM) == -1)
|
||||
ec = get_last_error();
|
||||
}
|
||||
|
||||
void request_exit()
|
||||
{
|
||||
if (pid_ <= 0)
|
||||
return;
|
||||
error_code ec;
|
||||
request_exit(ec);
|
||||
if (ec)
|
||||
detail::throw_error(ec, "request_exit");
|
||||
}
|
||||
|
||||
void suspend()
|
||||
{
|
||||
if (pid_ <= 0)
|
||||
return ;
|
||||
error_code ec;
|
||||
suspend(ec);
|
||||
if (ec)
|
||||
detail::throw_error(ec, "suspend");
|
||||
}
|
||||
|
||||
void suspend(error_code &ec)
|
||||
{
|
||||
if (pid_ <= 0)
|
||||
return ;
|
||||
if (::kill(pid_, SIGSTOP) == -1)
|
||||
ec = get_last_error();
|
||||
}
|
||||
|
||||
void resume()
|
||||
{
|
||||
if (pid_ <= 0)
|
||||
return ;
|
||||
error_code ec;
|
||||
resume(ec);
|
||||
if (ec)
|
||||
detail::throw_error(ec, "resume");
|
||||
}
|
||||
|
||||
void resume(error_code &ec)
|
||||
{
|
||||
if (pid_ <= 0)
|
||||
return ;
|
||||
if (::kill(pid_, SIGCONT) == -1)
|
||||
ec = get_last_error();
|
||||
}
|
||||
|
||||
void terminate(native_exit_code_type &exit_status, error_code &ec)
|
||||
{
|
||||
if (pid_ <= 0)
|
||||
return;
|
||||
if (::kill(pid_, SIGKILL) == -1)
|
||||
ec = get_last_error();
|
||||
}
|
||||
|
||||
void terminate(native_exit_code_type &exit_status)
|
||||
{
|
||||
if (pid_ <= 0)
|
||||
return;
|
||||
error_code ec;
|
||||
terminate(exit_status, ec);
|
||||
if (ec)
|
||||
detail::throw_error(ec, "terminate");
|
||||
}
|
||||
|
||||
bool running(native_exit_code_type &exit_code, error_code & ec)
|
||||
{
|
||||
if (pid_ <= 0)
|
||||
return false;
|
||||
int code = 0;
|
||||
int res = ::waitpid(pid_, &code, WNOHANG);
|
||||
if (res == -1)
|
||||
ec = get_last_error();
|
||||
else
|
||||
ec.clear();
|
||||
|
||||
if (process_is_running(res))
|
||||
return true;
|
||||
else
|
||||
{
|
||||
exit_code = code;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool running(native_exit_code_type &exit_code)
|
||||
{
|
||||
if (pid_ <= 0)
|
||||
return false;
|
||||
|
||||
error_code ec;
|
||||
bool res = running(exit_code, ec);
|
||||
if (ec)
|
||||
detail::throw_error(ec, "is_running");
|
||||
return res;
|
||||
}
|
||||
|
||||
bool is_open() const
|
||||
{
|
||||
return pid_ != -1;
|
||||
}
|
||||
|
||||
template<BOOST_PROCESS_V2_COMPLETION_TOKEN_FOR(void(error_code, int))
|
||||
WaitHandler BOOST_PROCESS_V2_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
|
||||
BOOST_PROCESS_V2_INITFN_AUTO_RESULT_TYPE(WaitHandler, void (error_code, native_exit_code_type))
|
||||
async_wait(WaitHandler &&handler BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
|
||||
{
|
||||
return BOOST_PROCESS_V2_ASIO_NAMESPACE::async_compose<WaitHandler, void(error_code, native_exit_code_type)>(
|
||||
async_wait_op_{descriptor_, signal_set_, pid_}, handler, descriptor_);
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename>
|
||||
friend
|
||||
struct basic_process_handle_fd_or_signal;
|
||||
pid_type pid_ = -1;
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::posix::basic_stream_descriptor<Executor> descriptor_;
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::basic_signal_set<Executor> signal_set_{descriptor_.get_executor(), SIGCHLD};
|
||||
|
||||
struct async_wait_op_
|
||||
{
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::posix::basic_descriptor<Executor> &descriptor;
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::basic_signal_set<Executor> &handle;
|
||||
pid_type pid_;
|
||||
bool needs_post = true;
|
||||
|
||||
template<typename Self>
|
||||
void operator()(Self &&self, error_code ec = {}, int = 0)
|
||||
{
|
||||
native_exit_code_type exit_code{};
|
||||
int wait_res = -1;
|
||||
if (pid_ <= 0) // error, complete early
|
||||
ec = BOOST_PROCESS_V2_ASIO_NAMESPACE::error::bad_descriptor;
|
||||
else
|
||||
{
|
||||
wait_res = ::waitpid(pid_, &exit_code, WNOHANG);
|
||||
if (wait_res == -1)
|
||||
ec = get_last_error();
|
||||
}
|
||||
|
||||
if (!ec && (wait_res == 0))
|
||||
{
|
||||
needs_post = false;
|
||||
if (descriptor.is_open())
|
||||
descriptor.async_wait(
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::posix::descriptor_base::wait_read,
|
||||
std::move(self));
|
||||
else
|
||||
handle.async_wait(std::move(self));
|
||||
return;
|
||||
}
|
||||
|
||||
struct completer
|
||||
{
|
||||
error_code ec;
|
||||
native_exit_code_type code;
|
||||
typename std::decay<Self>::type self;
|
||||
|
||||
void operator()()
|
||||
{
|
||||
self.complete(ec, code);
|
||||
}
|
||||
};
|
||||
|
||||
const auto exec = self.get_executor();
|
||||
completer cpl{ec, exit_code, std::move(self)};
|
||||
if (needs_post)
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::post(exec, std::move(cpl));
|
||||
else
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::dispatch(exec, std::move(cpl));
|
||||
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#endif //BOOST_PROCESS_HANDLE_FD_OR_SIGNAL_HPP
|
||||
350
linx64/include/boost/process/v2/detail/process_handle_signal.hpp
Normal file
350
linx64/include/boost/process/v2/detail/process_handle_signal.hpp
Normal file
@@ -0,0 +1,350 @@
|
||||
// Copyright (c) 2022 Klemens D. Morgenstern
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_PROCESS_V2_DETAIL_PROCESS_HANDLE_SIGNAL_HPP
|
||||
#define BOOST_PROCESS_V2_DETAIL_PROCESS_HANDLE_SIGNAL_HPP
|
||||
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <boost/process/v2/detail/last_error.hpp>
|
||||
#include <boost/process/v2/detail/throw_error.hpp>
|
||||
#include <boost/process/v2/exit_code.hpp>
|
||||
#include <boost/process/v2/pid.hpp>
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_STANDALONE)
|
||||
#include <asio/any_io_executor.hpp>
|
||||
#include <asio/compose.hpp>
|
||||
#include <asio/dispatch.hpp>
|
||||
#include <asio/post.hpp>
|
||||
#include <asio/signal_set.hpp>
|
||||
#else
|
||||
#include <boost/asio/any_io_executor.hpp>
|
||||
#include <boost/asio/compose.hpp>
|
||||
#include <boost/asio/dispatch.hpp>
|
||||
#include <boost/asio/post.hpp>
|
||||
#include <boost/asio/signal_set.hpp>
|
||||
#endif
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template<typename Executor = BOOST_PROCESS_V2_ASIO_NAMESPACE::any_io_executor>
|
||||
struct basic_process_handle_signal
|
||||
{
|
||||
struct native_handle_type
|
||||
{
|
||||
native_handle_type() = delete;
|
||||
native_handle_type(const native_handle_type & ) = delete;
|
||||
~native_handle_type() = default;
|
||||
};
|
||||
|
||||
typedef Executor executor_type;
|
||||
|
||||
executor_type get_executor()
|
||||
{ return signal_set_.get_executor(); }
|
||||
|
||||
/// Rebinds the process_handle to another executor.
|
||||
template<typename Executor1>
|
||||
struct rebind_executor
|
||||
{
|
||||
/// The socket type when rebound to the specified executor.
|
||||
typedef basic_process_handle_signal<Executor1> other;
|
||||
};
|
||||
|
||||
template<typename ExecutionContext>
|
||||
basic_process_handle_signal(ExecutionContext &context,
|
||||
typename std::enable_if<
|
||||
std::is_convertible<ExecutionContext &,
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context &>::value
|
||||
>::type * = nullptr)
|
||||
: pid_(-1), signal_set_(context, SIGCHLD)
|
||||
{
|
||||
}
|
||||
|
||||
basic_process_handle_signal(Executor executor)
|
||||
: pid_(-1), signal_set_(executor, SIGCHLD)
|
||||
{
|
||||
}
|
||||
|
||||
basic_process_handle_signal(Executor executor, pid_type pid)
|
||||
: pid_(pid), signal_set_(executor, SIGCHLD)
|
||||
{
|
||||
}
|
||||
|
||||
basic_process_handle_signal(basic_process_handle_signal && handle)
|
||||
: pid_(handle.pid_), signal_set_(handle.signal_set_.get_executor(), SIGCHLD)
|
||||
{
|
||||
handle.pid_ = -1;
|
||||
}
|
||||
|
||||
basic_process_handle_signal& operator=(basic_process_handle_signal && handle)
|
||||
{
|
||||
pid_ = handle.id();
|
||||
signal_set_.~basic_signal_set();
|
||||
using ss = BOOST_PROCESS_V2_ASIO_NAMESPACE::basic_signal_set<Executor>;
|
||||
new (&signal_set_) ss(handle.get_executor(), SIGCHLD);
|
||||
handle.pid_ = -1;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
template<typename Executor1>
|
||||
basic_process_handle_signal(basic_process_handle_signal<Executor1> && handle)
|
||||
: pid_(handle.pid_), signal_set_(Executor1(handle.signal_set_.get_executor()), SIGCHLD)
|
||||
{
|
||||
handle.pid_ = -1;
|
||||
}
|
||||
|
||||
pid_type id() const { return pid_; }
|
||||
native_handle_type native_handle() {return {};}
|
||||
|
||||
void terminate_if_running(error_code &)
|
||||
{
|
||||
terminate_if_running();
|
||||
}
|
||||
|
||||
void terminate_if_running()
|
||||
{
|
||||
if (pid_ <= 0)
|
||||
return;
|
||||
if (::waitpid(pid_, nullptr, WNOHANG) == 0)
|
||||
{
|
||||
::kill(pid_, SIGKILL);
|
||||
::waitpid(pid_, nullptr, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void wait(native_exit_code_type &exit_status, error_code &ec)
|
||||
{
|
||||
if (pid_ <= 0)
|
||||
return;
|
||||
while (::waitpid(pid_, &exit_status, 0) < 0)
|
||||
{
|
||||
if (errno != EINTR)
|
||||
{
|
||||
ec = get_last_error();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void wait(native_exit_code_type &exit_status)
|
||||
{
|
||||
if (pid_ <= 0)
|
||||
return;
|
||||
error_code ec;
|
||||
wait(exit_status, ec);
|
||||
if (ec)
|
||||
detail::throw_error(ec, "wait(pid)");
|
||||
}
|
||||
|
||||
void interrupt(error_code &ec)
|
||||
{
|
||||
if (pid_ <= 0)
|
||||
return;
|
||||
if (::kill(pid_, SIGTERM) == -1)
|
||||
ec = get_last_error();
|
||||
}
|
||||
|
||||
void interrupt()
|
||||
{
|
||||
if (pid_ <= 0)
|
||||
return;
|
||||
error_code ec;
|
||||
interrupt(ec);
|
||||
if (ec)
|
||||
detail::throw_error(ec, "interrupt");
|
||||
}
|
||||
|
||||
void request_exit(error_code &ec)
|
||||
{
|
||||
if (pid_ <= 0)
|
||||
return;
|
||||
if (::kill(pid_, SIGTERM) == -1)
|
||||
ec = get_last_error();
|
||||
}
|
||||
|
||||
void request_exit()
|
||||
{
|
||||
if (pid_ <= 0)
|
||||
return;
|
||||
error_code ec;
|
||||
request_exit(ec);
|
||||
if (ec)
|
||||
detail::throw_error(ec, "request_exit");
|
||||
}
|
||||
|
||||
void suspend()
|
||||
{
|
||||
if (pid_ <= 0)
|
||||
return;
|
||||
error_code ec;
|
||||
suspend(ec);
|
||||
if (ec)
|
||||
detail::throw_error(ec, "suspend");
|
||||
}
|
||||
|
||||
void suspend(error_code &ec)
|
||||
{
|
||||
if (pid_ <= 0)
|
||||
return;
|
||||
if (::kill(pid_, SIGCONT) == -1)
|
||||
ec = get_last_error();
|
||||
}
|
||||
|
||||
void resume()
|
||||
{
|
||||
if (pid_ <= 0)
|
||||
return;
|
||||
error_code ec;
|
||||
resume(ec);
|
||||
if (ec)
|
||||
detail::throw_error(ec, "resume");
|
||||
}
|
||||
|
||||
void resume(error_code &ec)
|
||||
{
|
||||
if (pid_ <= 0)
|
||||
return;
|
||||
if (::kill(pid_, SIGTERM) == -1)
|
||||
ec = get_last_error();
|
||||
}
|
||||
|
||||
void terminate(native_exit_code_type &exit_status, error_code &ec)
|
||||
{
|
||||
if (pid_ <= 0)
|
||||
return;
|
||||
if (::kill(pid_, SIGKILL) == -1)
|
||||
ec = get_last_error();
|
||||
}
|
||||
|
||||
void terminate(native_exit_code_type &exit_status)
|
||||
{
|
||||
if (pid_ <= 0)
|
||||
return;
|
||||
error_code ec;
|
||||
terminate(exit_status, ec);
|
||||
if (ec)
|
||||
detail::throw_error(ec, "terminate");
|
||||
}
|
||||
|
||||
bool running(native_exit_code_type &exit_code, error_code & ec)
|
||||
{
|
||||
if (pid_ <= 0)
|
||||
return false;
|
||||
int code = 0;
|
||||
int res = ::waitpid(pid_, &code, WNOHANG);
|
||||
if (res == -1)
|
||||
ec = get_last_error();
|
||||
|
||||
if (res == 0)
|
||||
return true;
|
||||
else
|
||||
{
|
||||
exit_code = code;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool running(native_exit_code_type &exit_code)
|
||||
{
|
||||
if (pid_ <= 0)
|
||||
return false;
|
||||
|
||||
error_code ec;
|
||||
bool res = running(exit_code, ec);
|
||||
if (ec)
|
||||
detail::throw_error(ec, "is_running");
|
||||
return res;
|
||||
}
|
||||
|
||||
bool is_open() const
|
||||
{
|
||||
return pid_ != -1;
|
||||
}
|
||||
|
||||
template<BOOST_PROCESS_V2_COMPLETION_TOKEN_FOR(void(error_code, int))
|
||||
WaitHandler BOOST_PROCESS_V2_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
|
||||
BOOST_PROCESS_V2_INITFN_AUTO_RESULT_TYPE(WaitHandler, void (error_code, native_exit_code_type))
|
||||
async_wait(WaitHandler &&handler BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
|
||||
{
|
||||
return BOOST_PROCESS_V2_ASIO_NAMESPACE::async_compose<WaitHandler, void(error_code, native_exit_code_type)>(
|
||||
async_wait_op_{signal_set_, pid_}, handler, signal_set_);
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename>
|
||||
friend struct basic_process_handle_signal;
|
||||
pid_type pid_ = -1;
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::basic_signal_set<Executor> signal_set_;
|
||||
|
||||
struct async_wait_op_
|
||||
{
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::basic_signal_set<Executor> &handle;
|
||||
pid_type pid_;
|
||||
|
||||
template<typename Self>
|
||||
void operator()(Self &&self)
|
||||
{
|
||||
handle.async_wait(std::move(self));
|
||||
handle.cancel();
|
||||
// we cancel so we end up on the signal-sets executor
|
||||
}
|
||||
|
||||
template<typename Self>
|
||||
void operator()(Self &&self, error_code ec, int sig)
|
||||
{
|
||||
if (ec == BOOST_PROCESS_V2_ASIO_NAMESPACE::error::operation_aborted &&
|
||||
self.get_cancellation_state().cancelled()
|
||||
== BOOST_PROCESS_V2_ASIO_NAMESPACE::cancellation_type::none)
|
||||
ec.clear();
|
||||
|
||||
native_exit_code_type exit_code = -1;
|
||||
int wait_res = -1;
|
||||
|
||||
if (pid_ <= 0) // error, complete early
|
||||
ec = BOOST_PROCESS_V2_ASIO_NAMESPACE::error::bad_descriptor;
|
||||
else if (!ec)
|
||||
{
|
||||
wait_res = ::waitpid(pid_, &exit_code, WNOHANG);
|
||||
if (wait_res == -1)
|
||||
ec = get_last_error();
|
||||
}
|
||||
|
||||
if (!ec && (wait_res == 0))
|
||||
{
|
||||
handle.async_wait(std::move(self));
|
||||
return;
|
||||
}
|
||||
|
||||
struct completer
|
||||
{
|
||||
error_code ec;
|
||||
native_exit_code_type code;
|
||||
typename std::decay<Self>::type self;
|
||||
|
||||
void operator()()
|
||||
{
|
||||
self.complete(ec, code);
|
||||
}
|
||||
};
|
||||
|
||||
const auto exec = self.get_executor();
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::dispatch(exec, completer{ec, exit_code, std::move(self)});
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
|
||||
#endif //BOOST_PROCESS_V2_DETAIL_PROCESS_HANDLE_SIGNAL_HPP
|
||||
@@ -0,0 +1,305 @@
|
||||
// Copyright (c) 2022 Klemens D. Morgenstern
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_PROCESS_V2_DETAIL_PROCESS_HANDLE_WINDOWS_HPP
|
||||
#define BOOST_PROCESS_V2_DETAIL_PROCESS_HANDLE_WINDOWS_HPP
|
||||
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
|
||||
#include <boost/process/v2/exit_code.hpp>
|
||||
#include <boost/process/v2/pid.hpp>
|
||||
#include <boost/process/v2/detail/throw_error.hpp>
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_STANDALONE)
|
||||
#include <asio/any_io_executor.hpp>
|
||||
#include <asio/compose.hpp>
|
||||
#include <asio/windows/basic_object_handle.hpp>
|
||||
#else
|
||||
#include <boost/asio/any_io_executor.hpp>
|
||||
#include <boost/asio/compose.hpp>
|
||||
#include <boost/asio/windows/basic_object_handle.hpp>
|
||||
#endif
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
BOOST_PROCESS_V2_DECL void get_exit_code_( void * handle, native_exit_code_type & exit_code, error_code & ec);
|
||||
BOOST_PROCESS_V2_DECL void * open_process_(pid_type pid);
|
||||
BOOST_PROCESS_V2_DECL void terminate_if_running_(void * handle);
|
||||
BOOST_PROCESS_V2_DECL bool check_handle_(void* handle, error_code & ec);
|
||||
BOOST_PROCESS_V2_DECL bool check_pid_(pid_type pid_, error_code & ec);
|
||||
BOOST_PROCESS_V2_DECL void interrupt_(pid_type pid_, error_code & ec);
|
||||
BOOST_PROCESS_V2_DECL void suspend_(void * handle, error_code & ec);
|
||||
BOOST_PROCESS_V2_DECL void resume_(void * handle, error_code & ec);
|
||||
BOOST_PROCESS_V2_DECL void terminate_(void * handle, error_code & ec, native_exit_code_type & exit_code);
|
||||
BOOST_PROCESS_V2_DECL void request_exit_(pid_type pid_, error_code & ec);
|
||||
BOOST_PROCESS_V2_DECL void check_running_(void* handle, error_code & ec, native_exit_code_type & exit_status);
|
||||
|
||||
template<typename Executor = BOOST_PROCESS_V2_ASIO_NAMESPACE::any_io_executor>
|
||||
struct basic_process_handle_win
|
||||
{
|
||||
typedef BOOST_PROCESS_V2_ASIO_NAMESPACE::windows::basic_object_handle<Executor> handle_type;
|
||||
typedef typename handle_type::native_handle_type native_handle_type;
|
||||
|
||||
typedef Executor executor_type;
|
||||
|
||||
executor_type get_executor()
|
||||
{ return handle_.get_executor(); }
|
||||
|
||||
/// Rebinds the process_handle to another executor.
|
||||
template<typename Executor1>
|
||||
struct rebind_executor
|
||||
{
|
||||
/// The socket type when rebound to the specified executor.
|
||||
typedef basic_process_handle_win<Executor1> other;
|
||||
};
|
||||
|
||||
template<typename ExecutionContext>
|
||||
basic_process_handle_win(ExecutionContext &context,
|
||||
typename std::enable_if<
|
||||
std::is_convertible<ExecutionContext &,
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context &>::value
|
||||
>::type = 0)
|
||||
: pid_(0), handle_(context)
|
||||
{
|
||||
}
|
||||
|
||||
basic_process_handle_win(Executor executor)
|
||||
: pid_(0), handle_(executor)
|
||||
{
|
||||
}
|
||||
|
||||
basic_process_handle_win(Executor executor, pid_type pid)
|
||||
: pid_(pid), handle_(executor, detail::open_process_(pid))
|
||||
{
|
||||
}
|
||||
|
||||
basic_process_handle_win(Executor executor, pid_type pid, native_handle_type process_handle)
|
||||
: pid_(pid), handle_(executor, process_handle)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
template<typename Executor1>
|
||||
basic_process_handle_win(basic_process_handle_win<Executor1> && handle)
|
||||
: pid_(handle.pid_), handle_(handle.handle_.get_executor())
|
||||
{
|
||||
}
|
||||
|
||||
basic_process_handle_win(basic_process_handle_win && handle)
|
||||
: pid_(handle.id()), handle_(std::move(handle.handle_))
|
||||
{
|
||||
handle.pid_ = static_cast<DWORD>(-1);
|
||||
}
|
||||
|
||||
basic_process_handle_win& operator=(basic_process_handle_win && handle)
|
||||
{
|
||||
pid_ = handle.pid_;
|
||||
handle_ = std::move(handle.handle_);
|
||||
handle.pid_ = static_cast<DWORD>(-1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
~basic_process_handle_win()
|
||||
{
|
||||
if (handle_.is_open())
|
||||
{
|
||||
error_code ec;
|
||||
handle_.close(ec);
|
||||
}
|
||||
}
|
||||
|
||||
native_handle_type native_handle()
|
||||
{ return handle_.native_handle(); }
|
||||
|
||||
pid_type id() const
|
||||
{ return pid_; }
|
||||
|
||||
void terminate_if_running(error_code &)
|
||||
{
|
||||
detail::terminate_if_running_(handle_.native_handle());
|
||||
}
|
||||
|
||||
void terminate_if_running()
|
||||
{
|
||||
detail::terminate_if_running_(handle_.native_handle());
|
||||
}
|
||||
|
||||
void wait(native_exit_code_type &exit_status, error_code &ec)
|
||||
{
|
||||
if (!detail::check_handle_(handle_.native_handle(), ec))
|
||||
return;
|
||||
|
||||
handle_.wait(ec);
|
||||
if (!ec)
|
||||
detail::get_exit_code_(handle_.native_handle(), exit_status, ec);
|
||||
}
|
||||
|
||||
|
||||
void wait(native_exit_code_type &exit_status)
|
||||
{
|
||||
error_code ec;
|
||||
wait(exit_status, ec);
|
||||
if (ec)
|
||||
detail::throw_error(ec, "wait(pid)");
|
||||
}
|
||||
|
||||
void interrupt(error_code &ec)
|
||||
{
|
||||
if (!detail::check_pid_(pid_, ec))
|
||||
return;
|
||||
|
||||
detail::interrupt_(pid_, ec);
|
||||
}
|
||||
|
||||
void interrupt()
|
||||
{
|
||||
error_code ec;
|
||||
interrupt(ec);
|
||||
if (ec)
|
||||
detail::throw_error(ec, "interrupt");
|
||||
}
|
||||
|
||||
void request_exit(error_code &ec)
|
||||
{
|
||||
if (!detail::check_pid_(pid_, ec))
|
||||
return;
|
||||
detail::request_exit_(pid_, ec);
|
||||
}
|
||||
|
||||
void request_exit()
|
||||
{
|
||||
error_code ec;
|
||||
request_exit(ec);
|
||||
if (ec)
|
||||
detail::throw_error(ec, "request_exit");
|
||||
}
|
||||
|
||||
void suspend(error_code &ec)
|
||||
{
|
||||
detail::suspend_(handle_.native_handle(), ec);
|
||||
}
|
||||
|
||||
void suspend()
|
||||
{
|
||||
error_code ec;
|
||||
suspend(ec);
|
||||
if (ec)
|
||||
detail::throw_error(ec, "suspend");
|
||||
}
|
||||
|
||||
void resume(error_code &ec)
|
||||
{
|
||||
detail::resume_(handle_.native_handle(), ec);
|
||||
}
|
||||
|
||||
void resume()
|
||||
{
|
||||
error_code ec;
|
||||
suspend(ec);
|
||||
if (ec)
|
||||
detail::throw_error(ec, "resume");
|
||||
}
|
||||
|
||||
void terminate(native_exit_code_type &exit_status, error_code &ec)
|
||||
{
|
||||
if (!detail::check_handle_(handle_.native_handle(), ec))
|
||||
return;
|
||||
|
||||
detail::terminate_(handle_.native_handle(), ec, exit_status);
|
||||
if (!ec)
|
||||
wait(exit_status, ec);
|
||||
|
||||
}
|
||||
|
||||
void terminate(native_exit_code_type &exit_status)
|
||||
{
|
||||
error_code ec;
|
||||
terminate(exit_status, ec);
|
||||
if (ec)
|
||||
detail::throw_error(ec, "terminate");
|
||||
}
|
||||
|
||||
bool running(native_exit_code_type &exit_code, error_code & ec)
|
||||
{
|
||||
if (!detail::check_handle_(handle_.native_handle(), ec))
|
||||
return false;
|
||||
|
||||
native_exit_code_type code;
|
||||
//single value, not needed in the winapi.
|
||||
detail::check_running_(handle_.native_handle(), ec, code);
|
||||
if (ec)
|
||||
return false;
|
||||
|
||||
if (process_is_running(code))
|
||||
return true;
|
||||
else
|
||||
{
|
||||
exit_code = code;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool running(native_exit_code_type &exit_code)
|
||||
{
|
||||
error_code ec;
|
||||
bool res = running(exit_code, ec);
|
||||
if (ec)
|
||||
detail::throw_error(ec, "is_running");
|
||||
return res;
|
||||
}
|
||||
|
||||
bool is_open() const
|
||||
{
|
||||
return handle_.is_open();
|
||||
}
|
||||
|
||||
template<BOOST_PROCESS_V2_COMPLETION_TOKEN_FOR(void(error_code, native_exit_code_type))
|
||||
WaitHandler BOOST_PROCESS_V2_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
|
||||
BOOST_PROCESS_V2_INITFN_AUTO_RESULT_TYPE(WaitHandler, void (error_code, native_exit_code_type))
|
||||
async_wait(WaitHandler &&handler BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
|
||||
{
|
||||
return BOOST_PROCESS_V2_ASIO_NAMESPACE::async_compose<WaitHandler, void(error_code, native_exit_code_type)>(
|
||||
async_wait_op_{handle_}, handler, handle_
|
||||
);
|
||||
}
|
||||
template<typename>
|
||||
friend struct basic_process_handle_win;
|
||||
private:
|
||||
pid_type pid_;
|
||||
handle_type handle_;
|
||||
|
||||
struct async_wait_op_
|
||||
{
|
||||
handle_type &handle;
|
||||
|
||||
template<typename Self>
|
||||
void operator()(Self &&self)
|
||||
{
|
||||
handle.async_wait(std::move(self));
|
||||
}
|
||||
|
||||
template<typename Self>
|
||||
void operator()(Self &&self, error_code ec)
|
||||
{
|
||||
native_exit_code_type exit_code{};
|
||||
if (!ec)
|
||||
detail::get_exit_code_(handle.native_handle(), exit_code, ec);
|
||||
std::move(self).complete(ec, exit_code);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
#if !defined(BOOST_PROCESS_V2_HEADER_ONLY)
|
||||
extern template struct basic_process_handle_win<>;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
|
||||
#endif //BOOST_PROCESS_V2_DETAIL_PROCESS_HANDLE_WINDOWS_HPP
|
||||
38
linx64/include/boost/process/v2/detail/throw_error.hpp
Normal file
38
linx64/include/boost/process/v2/detail/throw_error.hpp
Normal file
@@ -0,0 +1,38 @@
|
||||
// Copyright (c) 2022 Klemens D. Morgenstern
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_PROCESS_V2_DETAIL_THROW_ERROR_HPP
|
||||
#define BOOST_PROCESS_V2_DETAIL_THROW_ERROR_HPP
|
||||
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
namespace detail
|
||||
{
|
||||
|
||||
BOOST_PROCESS_V2_DECL void do_throw_error(const error_code& err);
|
||||
BOOST_PROCESS_V2_DECL void do_throw_error(const error_code& err, const char* location);
|
||||
|
||||
inline void throw_error(const error_code& err)
|
||||
{
|
||||
if (err)
|
||||
do_throw_error(err);
|
||||
}
|
||||
|
||||
inline void throw_error(const error_code& err, const char* location)
|
||||
{
|
||||
if (err)
|
||||
do_throw_error(err, location);
|
||||
}
|
||||
|
||||
}
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_HEADER_ONLY)
|
||||
|
||||
#include <boost/process/v2/detail/impl/throw_error.ipp>
|
||||
|
||||
#endif
|
||||
|
||||
#endif //BOOST_PROCESS_V2_DETAIL_THROW_ERROR_HPP
|
||||
39
linx64/include/boost/process/v2/detail/throw_exception.hpp
Normal file
39
linx64/include/boost/process/v2/detail/throw_exception.hpp
Normal file
@@ -0,0 +1,39 @@
|
||||
// Copyright (c) 2022 Klemens D. Morgenstern
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_PROCESS_V2_DETAIL_THROW_EXCEPTION_HPP
|
||||
#define BOOST_PROCESS_V2_DETAIL_THROW_EXCEPTION_HPP
|
||||
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
|
||||
#if !defined(BOOST_PROCESS_V2_STANDALONE)
|
||||
|
||||
#include <boost/throw_exception.hpp>
|
||||
|
||||
#endif
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_STANDALONE)
|
||||
|
||||
template <typename Exception>
|
||||
inline void throw_exception(const Exception& e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
using boost::throw_exception;
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#endif //BOOST_PROCESS_V2_DETAIL_THROW_EXCEPTION_HPP
|
||||
95
linx64/include/boost/process/v2/detail/utf8.hpp
Normal file
95
linx64/include/boost/process/v2/detail/utf8.hpp
Normal file
@@ -0,0 +1,95 @@
|
||||
// Copyright (c) 2022 Klemens D. Morgenstern
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_PROCESS_V2_DETAIL_UTF8_HPP
|
||||
#define BOOST_PROCESS_V2_DETAIL_UTF8_HPP
|
||||
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
#include <boost/process/v2/detail/throw_error.hpp>
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
BOOST_PROCESS_V2_DECL std::size_t size_as_utf8(const wchar_t * in, std::size_t size, error_code & ec);
|
||||
BOOST_PROCESS_V2_DECL std::size_t size_as_wide(const char * in, std::size_t size, error_code & ec);
|
||||
|
||||
BOOST_PROCESS_V2_DECL std::size_t convert_to_utf8(const wchar_t * in, std::size_t size,
|
||||
char * out, std::size_t max_size, error_code & ec);
|
||||
BOOST_PROCESS_V2_DECL std::size_t convert_to_wide(const char * in, std::size_t size,
|
||||
wchar_t * out, std::size_t max_size, error_code & ec);
|
||||
|
||||
template<typename CharOut, typename Traits = std::char_traits<CharOut>,
|
||||
typename Allocator = std::allocator<CharOut>, typename CharIn,
|
||||
typename = typename std::enable_if<std::is_same<CharOut, CharIn>::value>::type>
|
||||
BOOST_PROCESS_V2_DECL
|
||||
std::basic_string<CharOut, Traits, Allocator> conv_string(
|
||||
const CharIn * data, std::size_t size,
|
||||
const Allocator allocator = Allocator{})
|
||||
{
|
||||
return std::basic_string<CharOut, Traits, Allocator>(data, size, allocator);
|
||||
}
|
||||
|
||||
|
||||
template<typename CharOut, typename Traits = std::char_traits<CharOut>,
|
||||
typename Allocator = std::allocator<CharOut>,
|
||||
typename = typename std::enable_if<std::is_same<CharOut, char>::value>::type>
|
||||
BOOST_PROCESS_V2_DECL
|
||||
std::basic_string<CharOut, Traits, Allocator> conv_string(
|
||||
const wchar_t * data, std::size_t size,
|
||||
const Allocator allocator = Allocator{})
|
||||
{
|
||||
error_code ec;
|
||||
const auto req_size = size_as_utf8(data, size, ec);
|
||||
if (ec)
|
||||
detail::throw_error(ec, "size_as_utf8");
|
||||
|
||||
std::basic_string<CharOut, Traits, Allocator> res(allocator);
|
||||
res.resize(req_size);
|
||||
|
||||
auto res_size = convert_to_utf8(data, size, &res.front(), req_size, ec);
|
||||
if (ec)
|
||||
detail::throw_error(ec, "convert_to_utf8");
|
||||
|
||||
res.resize(res_size);
|
||||
return res;
|
||||
}
|
||||
|
||||
template<typename CharOut, typename Traits = std::char_traits<CharOut>,
|
||||
typename Allocator = std::allocator<CharOut>,
|
||||
typename = typename std::enable_if<std::is_same<CharOut, wchar_t>::value>::type>
|
||||
BOOST_PROCESS_V2_DECL
|
||||
std::basic_string<CharOut, Traits, Allocator> conv_string(
|
||||
const char * data, std::size_t size,
|
||||
const Allocator allocator = Allocator{})
|
||||
{
|
||||
error_code ec;
|
||||
const auto req_size = size_as_wide(data, size, ec);
|
||||
if (ec)
|
||||
detail::throw_error(ec, "size_as_wide");
|
||||
|
||||
std::basic_string<CharOut, Traits, Allocator> res(allocator);
|
||||
res.resize(req_size);
|
||||
|
||||
auto res_size = convert_to_wide(data, size, &res.front(), req_size, ec);
|
||||
if (ec)
|
||||
detail::throw_error(ec, "convert_to_wide");
|
||||
|
||||
res.resize(res_size);
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_HEADER_ONLY)
|
||||
|
||||
#include <boost/process/v2/detail/impl/utf8.ipp>
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif //BOOST_PROCESS_V2_DETAIL_UTF8_HPP
|
||||
1893
linx64/include/boost/process/v2/environment.hpp
Normal file
1893
linx64/include/boost/process/v2/environment.hpp
Normal file
File diff suppressed because it is too large
Load Diff
50
linx64/include/boost/process/v2/error.hpp
Normal file
50
linx64/include/boost/process/v2/error.hpp
Normal file
@@ -0,0 +1,50 @@
|
||||
// Copyright (c) 2021 Klemens D. Morgenstern
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_PROCESS_V2_ERROR_HPP
|
||||
#define BOOST_PROCESS_V2_ERROR_HPP
|
||||
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
|
||||
namespace error
|
||||
{
|
||||
|
||||
/// Errors used for utf8 <-> UCS-2 conversions.
|
||||
enum utf8_conv_error
|
||||
{
|
||||
insufficient_buffer = 1,
|
||||
invalid_character,
|
||||
};
|
||||
|
||||
extern BOOST_PROCESS_V2_DECL const error_category& get_utf8_category();
|
||||
static const error_category& utf8_category = get_utf8_category();
|
||||
|
||||
extern BOOST_PROCESS_V2_DECL const error_category& get_exit_code_category();
|
||||
|
||||
/// An error category that can be used to interpret exit codes of subprocesses.
|
||||
/** Currently not used by boost.process, but it might be in the future.
|
||||
*
|
||||
* void run_my_process(filesystem::path pt, error_code & ec)
|
||||
* {
|
||||
* process proc(pt, {});
|
||||
* proc.wait();
|
||||
* ec.assign(proc.native_exit_code(), error::get_exit_code_category());
|
||||
* }
|
||||
*
|
||||
* */
|
||||
static const error_category& exit_code_category = get_exit_code_category();
|
||||
|
||||
}
|
||||
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_HEADER_ONLY)
|
||||
|
||||
#include <boost/process/v2/impl/error.ipp>
|
||||
|
||||
#endif
|
||||
|
||||
#endif //BOOST_PROCESS_V2_ERROR_HPP
|
||||
120
linx64/include/boost/process/v2/execute.hpp
Normal file
120
linx64/include/boost/process/v2/execute.hpp
Normal file
@@ -0,0 +1,120 @@
|
||||
// Copyright (c) 2022 Klemens D. Morgenstern
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_PROCESS_V2_EXECUTE_HPP
|
||||
#define BOOST_PROCESS_V2_EXECUTE_HPP
|
||||
|
||||
#include <boost/process/v2/process.hpp>
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_STANDALONE)
|
||||
#include <asio/bind_cancellation_slot.hpp>
|
||||
#else
|
||||
#include <boost/asio/bind_cancellation_slot.hpp>
|
||||
#endif
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
|
||||
|
||||
/**
|
||||
* @brief Run a process and wait for it to complete.
|
||||
*
|
||||
* @tparam Executor The asio executor of the process handle
|
||||
* @param proc The process to be run.
|
||||
* @return int The exit code of the process
|
||||
* @exception system_error An error that might have occurred during the wait.
|
||||
*/
|
||||
template<typename Executor>
|
||||
inline int execute(basic_process<Executor> proc)
|
||||
{
|
||||
return proc.wait();
|
||||
}
|
||||
|
||||
/** \overload int execute(const basic_process<Executor> proc) */
|
||||
template<typename Executor>
|
||||
inline int execute(basic_process<Executor> proc, error_code & ec)
|
||||
{
|
||||
return proc.wait(ec);
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template<typename Executor>
|
||||
struct execute_op
|
||||
{
|
||||
std::unique_ptr<basic_process<Executor>> proc;
|
||||
|
||||
struct cancel
|
||||
{
|
||||
using cancellation_type = BOOST_PROCESS_V2_ASIO_NAMESPACE::cancellation_type;
|
||||
basic_process<Executor> * proc;
|
||||
cancel(basic_process<Executor> * proc) : proc(proc) {}
|
||||
|
||||
void operator()(cancellation_type tp)
|
||||
{
|
||||
error_code ign;
|
||||
if ((tp & cancellation_type::total) != cancellation_type::none)
|
||||
proc->interrupt(ign);
|
||||
else if ((tp & cancellation_type::partial) != cancellation_type::none)
|
||||
proc->request_exit(ign);
|
||||
else if ((tp & cancellation_type::terminal) != cancellation_type::none)
|
||||
proc->terminate(ign);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Self>
|
||||
void operator()(Self && self)
|
||||
{
|
||||
self.reset_cancellation_state();
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::cancellation_slot s = self.get_cancellation_state().slot();
|
||||
if (s.is_connected())
|
||||
s.emplace<cancel>(proc.get());
|
||||
|
||||
auto pro_ = proc.get();
|
||||
pro_->async_wait(
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::bind_cancellation_slot(
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::cancellation_slot(),
|
||||
std::move(self)));
|
||||
}
|
||||
|
||||
template<typename Self>
|
||||
void operator()(Self && self, error_code ec, int res)
|
||||
{
|
||||
self.get_cancellation_state().slot().clear();
|
||||
self.complete(ec, res);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/// Execute a process asynchronously
|
||||
/** This function asynchronously for a process to complete.
|
||||
*
|
||||
* Cancelling the execution will signal the child process to exit
|
||||
* with the following interpretations:
|
||||
*
|
||||
* - cancellation_type::total -> interrupt
|
||||
* - cancellation_type::partial -> request_exit
|
||||
* - cancellation_type::terminal -> terminate
|
||||
*
|
||||
* It is to note that `async_execute` will us the lowest selected cancellation
|
||||
* type. A subprocess might ignore anything not terminal.
|
||||
*/
|
||||
template<typename Executor = BOOST_PROCESS_V2_ASIO_NAMESPACE::any_io_executor,
|
||||
BOOST_PROCESS_V2_COMPLETION_TOKEN_FOR(void (error_code, int))
|
||||
WaitHandler BOOST_PROCESS_V2_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)>
|
||||
inline
|
||||
BOOST_PROCESS_V2_INITFN_AUTO_RESULT_TYPE(WaitHandler, void (error_code, int))
|
||||
async_execute(basic_process<Executor> proc,
|
||||
WaitHandler && handler BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(Executor))
|
||||
{
|
||||
std::unique_ptr<basic_process<Executor>> pro_(new basic_process<Executor>(std::move(proc)));
|
||||
auto exec = proc.get_executor();
|
||||
return BOOST_PROCESS_V2_ASIO_NAMESPACE::async_compose<WaitHandler, void(error_code, int)>(
|
||||
detail::execute_op<Executor>{std::move(pro_)}, handler, exec);
|
||||
}
|
||||
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#endif //BOOST_PROCESS_V2_EXECUTE_HPP
|
||||
132
linx64/include/boost/process/v2/exit_code.hpp
Normal file
132
linx64/include/boost/process/v2/exit_code.hpp
Normal file
@@ -0,0 +1,132 @@
|
||||
//
|
||||
// process/exit_code.hpp
|
||||
// ~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2022 Klemens D. Morgenstern (klemens dot morgenstern at gmx dot net)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BOOST_PROCESS_V2_EXIT_CODE_HPP
|
||||
#define BOOST_PROCESS_V2_EXIT_CODE_HPP
|
||||
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
#include <boost/process/v2/error.hpp>
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_STANDALONE)
|
||||
#include <asio/associator.hpp>
|
||||
#include <asio/async_result.hpp>
|
||||
#else
|
||||
#include <boost/asio/associator.hpp>
|
||||
#include <boost/asio/async_result.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_POSIX)
|
||||
#include <sys/wait.h>
|
||||
#endif
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
|
||||
#if defined(GENERATING_DOCUMENTATION)
|
||||
|
||||
/// The native exit-code type, usually an integral value
|
||||
/** The OS may have a value different from `int` to represent
|
||||
* the exit codes of subprocesses. It might also
|
||||
* contain additional information.
|
||||
*/
|
||||
typedef implementation_defined native_exit_code_type;
|
||||
|
||||
|
||||
/// Check if the native exit code indicates the process is still running
|
||||
bool process_is_running(native_exit_code_type code);
|
||||
|
||||
/// Obtain the portable part of the exit code, i.e. what the subprocess has returned from main.
|
||||
int evaluate_exit_code(native_exit_code_type code);
|
||||
|
||||
|
||||
#else
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
|
||||
typedef unsigned long native_exit_code_type;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
constexpr native_exit_code_type still_active = 259u;
|
||||
}
|
||||
|
||||
inline bool process_is_running(native_exit_code_type code)
|
||||
{
|
||||
return code == detail::still_active;
|
||||
}
|
||||
|
||||
inline int evaluate_exit_code(native_exit_code_type code)
|
||||
{
|
||||
return static_cast<int>(code);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
typedef int native_exit_code_type;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
constexpr native_exit_code_type still_active = 0x7f;
|
||||
}
|
||||
|
||||
inline bool process_is_running(int code)
|
||||
{
|
||||
return !WIFEXITED(code) && !WIFSIGNALED(code);
|
||||
}
|
||||
|
||||
inline int evaluate_exit_code(int code)
|
||||
{
|
||||
if (WIFEXITED(code))
|
||||
return WEXITSTATUS(code);
|
||||
else if (WIFSIGNALED(code))
|
||||
return WTERMSIG(code);
|
||||
else
|
||||
return code;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/// @{
|
||||
/** Helper to subsume an exit-code into an error_code if there's no actual error isn't set.
|
||||
* @code {.cpp}
|
||||
* process proc{ctx, "exit", {"1"}};
|
||||
*
|
||||
* proc.async_wait(
|
||||
* asio::deferred(
|
||||
* [&proc](error_code ec, int)
|
||||
* {
|
||||
* return asio::deferred.values(
|
||||
* check_exit_code(ec, proc.native_exit_code())
|
||||
* );
|
||||
*
|
||||
* [](error_code ec)
|
||||
* {
|
||||
* assert(ec.value() == 10);
|
||||
* assert(ec.category() == error::get_exit_code_category());
|
||||
* }));
|
||||
*
|
||||
* @endcode
|
||||
*/
|
||||
|
||||
inline error_code check_exit_code(
|
||||
error_code &ec, native_exit_code_type native_code,
|
||||
const error_category & category = error::get_exit_code_category())
|
||||
{
|
||||
if (!ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, native_code, category);
|
||||
return ec;
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#endif //BOOST_PROCESS_V2_EXIT_CODE_HPP
|
||||
16
linx64/include/boost/process/v2/ext.hpp
Normal file
16
linx64/include/boost/process/v2/ext.hpp
Normal file
@@ -0,0 +1,16 @@
|
||||
//
|
||||
// Copyright (c) 2023 Klemens Morgenstern (klemens.morgenstern@gmx.net)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BOOST_PROCESS_V2_EXT_HPP
|
||||
#define BOOST_PROCESS_V2_EXT_HPP
|
||||
|
||||
#include <boost/process/v2/ext/cmd.hpp>
|
||||
#include <boost/process/v2/ext/cwd.hpp>
|
||||
#include <boost/process/v2/ext/env.hpp>
|
||||
#include <boost/process/v2/ext/exe.hpp>
|
||||
|
||||
#endif //BOOST_PROCESS_V2_EXT_HPP
|
||||
71
linx64/include/boost/process/v2/ext/cmd.hpp
Normal file
71
linx64/include/boost/process/v2/ext/cmd.hpp
Normal file
@@ -0,0 +1,71 @@
|
||||
// Copyright (c) 2022 Klemens D. Morgenstern
|
||||
// Copyright (c) 2022 Samuel Venable
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_PROCESS_V2_CMD_HPP
|
||||
#define BOOST_PROCESS_V2_CMD_HPP
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
#include <boost/process/v2/detail/throw_error.hpp>
|
||||
#include <boost/process/v2/process_handle.hpp>
|
||||
#include <boost/process/v2/pid.hpp>
|
||||
|
||||
#include <boost/process/v2/shell.hpp>
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
|
||||
namespace ext {
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
BOOST_PROCESS_V2_DECL shell cmd(HANDLE handle, error_code & ec);
|
||||
BOOST_PROCESS_V2_DECL shell cmd(HANDLE handle);
|
||||
#endif
|
||||
|
||||
/// @{
|
||||
/// Get the argument vector of another process
|
||||
BOOST_PROCESS_V2_DECL shell cmd(pid_type pid, error_code & ec);
|
||||
BOOST_PROCESS_V2_DECL shell cmd(pid_type pid);
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
BOOST_PROCESS_V2_DECL shell cmd(HANDLE handle, error_code & ec);
|
||||
BOOST_PROCESS_V2_DECL shell cmd(HANDLE handle);
|
||||
#endif
|
||||
|
||||
template<typename Executor>
|
||||
BOOST_PROCESS_V2_DECL shell cmd(basic_process_handle<Executor> & handle, error_code & ec)
|
||||
{
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
return cmd(handle.native_handle(), ec);
|
||||
#else
|
||||
return cmd(handle.id(), ec);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename Executor>
|
||||
BOOST_PROCESS_V2_DECL shell cmd(basic_process_handle<Executor> & handle)
|
||||
{
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
return cmd(handle.native_handle());
|
||||
#else
|
||||
return cmd(handle.id());
|
||||
#endif
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
} // namespace ext
|
||||
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_HEADER_ONLY)
|
||||
|
||||
#include <boost/process/v2/ext/impl/cmd.ipp>
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif // BOOST_PROCESS_V2_CMD_HPP
|
||||
58
linx64/include/boost/process/v2/ext/cwd.hpp
Normal file
58
linx64/include/boost/process/v2/ext/cwd.hpp
Normal file
@@ -0,0 +1,58 @@
|
||||
// Copyright (c) 2022 Klemens D. Morgenstern
|
||||
// Copyright (c) 2022 Samuel Venable
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_PROCESS_V2_CWD_HPP
|
||||
#define BOOST_PROCESS_V2_CWD_HPP
|
||||
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
#include <boost/process/v2/detail/throw_error.hpp>
|
||||
|
||||
#include <boost/process/v2/pid.hpp>
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
|
||||
namespace ext {
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
BOOST_PROCESS_V2_DECL filesystem::path cwd(HANDLE handle, error_code & ec);
|
||||
BOOST_PROCESS_V2_DECL filesystem::path cwd(HANDLE handle);
|
||||
#endif
|
||||
|
||||
/// @{
|
||||
/// Obtain the current path of another process
|
||||
BOOST_PROCESS_V2_DECL filesystem::path cwd(pid_type pid, error_code & ec);
|
||||
BOOST_PROCESS_V2_DECL filesystem::path cwd(pid_type pid);
|
||||
|
||||
template<typename Executor>
|
||||
BOOST_PROCESS_V2_DECL filesystem::path cwd(basic_process_handle<Executor> & handle, error_code & ec)
|
||||
{
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
return cwd(handle.native_handle(), ec);
|
||||
#else
|
||||
return cwd(handle.id(), ec);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename Executor>
|
||||
BOOST_PROCESS_V2_DECL filesystem::path cwd(basic_process_handle<Executor> & handle)
|
||||
{
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
return cwd(handle.native_handle());
|
||||
#else
|
||||
return cwd(handle.id());
|
||||
#endif
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
} // namespace ext
|
||||
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_HEADER_ONLY)
|
||||
#include <boost/process/v2/ext/impl/cwd.ipp>
|
||||
#endif
|
||||
|
||||
#endif // BOOST_PROCESS_V2_CWD_HPP
|
||||
127
linx64/include/boost/process/v2/ext/detail/impl/proc_info.ipp
Normal file
127
linx64/include/boost/process/v2/ext/detail/impl/proc_info.ipp
Normal file
@@ -0,0 +1,127 @@
|
||||
// Copyright (c) 2022 Klemens D. Morgenstern
|
||||
// Copyright (c) 2022 Samuel Venable
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_PROCESS_V2_IMPL_DETAIL_PROC_INFO_IPP
|
||||
#define BOOST_PROCESS_V2_IMPL_DETAIL_PROC_INFO_IPP
|
||||
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
#include <boost/process/v2/detail/last_error.hpp>
|
||||
#include <boost/process/v2/detail/throw_error.hpp>
|
||||
#include <boost/process/v2/ext/detail/proc_info.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
#if (defined(__APPLE__) && defined(__MACH__))
|
||||
#include <cstdlib>
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/proc_info.h>
|
||||
#include <libproc.h>
|
||||
#endif
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
namespace ext
|
||||
{
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
// type of process memory to read?
|
||||
enum MEMTYP {MEMCMD, MEMCWD};
|
||||
std::wstring cwd_cmd_from_proc(HANDLE proc, int type, boost::system::error_code & ec)
|
||||
{
|
||||
std::wstring buffer;
|
||||
PEB peb;
|
||||
SIZE_T nRead = 0;
|
||||
ULONG len = 0;
|
||||
PROCESS_BASIC_INFORMATION pbi;
|
||||
RTL_USER_PROCESS_PARAMETERS_EXTENDED upp;
|
||||
|
||||
NTSTATUS status = 0;
|
||||
PVOID buf = nullptr;
|
||||
status = NtQueryInformationProcess(proc, ProcessBasicInformation, &pbi, sizeof(pbi), &len);
|
||||
ULONG error = RtlNtStatusToDosError(status);
|
||||
|
||||
if (error)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, error, boost::system::system_category())
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!ReadProcessMemory(proc, pbi.PebBaseAddress, &peb, sizeof(peb), &nRead))
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!ReadProcessMemory(proc, peb.ProcessParameters, &upp, sizeof(upp), &nRead))
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return {};
|
||||
}
|
||||
|
||||
if (type == MEMCWD)
|
||||
{
|
||||
buf = upp.CurrentDirectory.DosPath.Buffer;
|
||||
len = upp.CurrentDirectory.DosPath.Length;
|
||||
}
|
||||
else if (type == MEMCMD)
|
||||
{
|
||||
buf = upp.CommandLine.Buffer;
|
||||
len = upp.CommandLine.Length;
|
||||
}
|
||||
|
||||
buffer.resize(len / 2 + 1);
|
||||
|
||||
if (!ReadProcessMemory(proc, buf, &buffer[0], len, &nRead))
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return {};
|
||||
}
|
||||
|
||||
buffer.pop_back();
|
||||
return buffer;
|
||||
}
|
||||
|
||||
// with debug_privilege enabled allows reading info from more processes
|
||||
// this includes stuff such as exe path, cwd path, cmdline, and environ
|
||||
HANDLE open_process_with_debug_privilege(boost::process::v2::pid_type pid, boost::system::error_code & ec)
|
||||
{
|
||||
HANDLE proc = nullptr;
|
||||
HANDLE hToken = nullptr;
|
||||
LUID luid;
|
||||
TOKEN_PRIVILEGES tkp;
|
||||
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
|
||||
{
|
||||
if (LookupPrivilegeValue(nullptr, SE_DEBUG_NAME, &luid))
|
||||
{
|
||||
tkp.PrivilegeCount = 1;
|
||||
tkp.Privileges[0].Luid = luid;
|
||||
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
||||
if (AdjustTokenPrivileges(hToken, false, &tkp, sizeof(tkp), nullptr, nullptr))
|
||||
{
|
||||
proc = OpenProcess(PROCESS_ALL_ACCESS, false, pid);
|
||||
}
|
||||
}
|
||||
CloseHandle(hToken);
|
||||
}
|
||||
if (!proc)
|
||||
proc = OpenProcess(PROCESS_ALL_ACCESS, false, pid);
|
||||
if (!proc)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return proc;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace ext
|
||||
|
||||
} // namespace detail
|
||||
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#endif // BOOST_PROCESS_V2_IMPL_DETAIL_PROC_INFO_IPP
|
||||
|
||||
125
linx64/include/boost/process/v2/ext/detail/proc_info.hpp
Normal file
125
linx64/include/boost/process/v2/ext/detail/proc_info.hpp
Normal file
@@ -0,0 +1,125 @@
|
||||
// Copyright (c) 2022 Klemens D. Morgenstern
|
||||
// Copyright (c) 2022 Samuel Venable
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_PROCESS_V2_DETAIL_PROC_INFO_HPP
|
||||
#define BOOST_PROCESS_V2_DETAIL_PROC_INFO_HPP
|
||||
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
#include <boost/process/v2/detail/throw_error.hpp>
|
||||
#include <boost/process/v2/pid.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
#include <iterator>
|
||||
#include <algorithm>
|
||||
#include <windows.h>
|
||||
#include <winternl.h>
|
||||
extern "C" ULONG NTAPI RtlNtStatusToDosError(NTSTATUS Status);
|
||||
#endif
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
namespace ext
|
||||
{
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
#if !defined(_MSC_VER)
|
||||
#pragma pack(push, 8)
|
||||
#else
|
||||
#include <pshpack8.h>
|
||||
#endif
|
||||
|
||||
/* CURDIR struct from:
|
||||
https://github.com/processhacker/phnt/
|
||||
CC BY 4.0 licence */
|
||||
|
||||
typedef struct {
|
||||
UNICODE_STRING DosPath;
|
||||
HANDLE Handle;
|
||||
} CURDIR;
|
||||
|
||||
/* RTL_DRIVE_LETTER_CURDIR struct from:
|
||||
https://github.com/processhacker/phnt/
|
||||
CC BY 4.0 licence */
|
||||
|
||||
typedef struct {
|
||||
USHORT Flags;
|
||||
USHORT Length;
|
||||
ULONG TimeStamp;
|
||||
STRING DosPath;
|
||||
} RTL_DRIVE_LETTER_CURDIR;
|
||||
|
||||
/* RTL_USER_PROCESS_PARAMETERS struct from:
|
||||
https://github.com/processhacker/phnt/
|
||||
CC BY 4.0 licence */
|
||||
|
||||
typedef struct {
|
||||
ULONG MaximumLength;
|
||||
ULONG Length;
|
||||
ULONG Flags;
|
||||
ULONG DebugFlags;
|
||||
HANDLE ConsoleHandle;
|
||||
ULONG ConsoleFlags;
|
||||
HANDLE StandardInput;
|
||||
HANDLE StandardOutput;
|
||||
HANDLE StandardError;
|
||||
CURDIR CurrentDirectory;
|
||||
UNICODE_STRING DllPath;
|
||||
UNICODE_STRING ImagePathName;
|
||||
UNICODE_STRING CommandLine;
|
||||
PVOID Environment;
|
||||
ULONG StartingX;
|
||||
ULONG StartingY;
|
||||
ULONG CountX;
|
||||
ULONG CountY;
|
||||
ULONG CountCharsX;
|
||||
ULONG CountCharsY;
|
||||
ULONG FillAttribute;
|
||||
ULONG WindowFlags;
|
||||
ULONG ShowWindowFlags;
|
||||
UNICODE_STRING WindowTitle;
|
||||
UNICODE_STRING DesktopInfo;
|
||||
UNICODE_STRING ShellInfo;
|
||||
UNICODE_STRING RuntimeData;
|
||||
RTL_DRIVE_LETTER_CURDIR CurrentDirectories[32];
|
||||
ULONG_PTR EnvironmentSize;
|
||||
ULONG_PTR EnvironmentVersion;
|
||||
PVOID PackageDependencyData;
|
||||
ULONG ProcessGroupId;
|
||||
ULONG LoaderThreads;
|
||||
UNICODE_STRING RedirectionDllName;
|
||||
UNICODE_STRING HeapPartitionName;
|
||||
ULONG_PTR DefaultThreadpoolCpuSetMasks;
|
||||
ULONG DefaultThreadpoolCpuSetMaskCount;
|
||||
} RTL_USER_PROCESS_PARAMETERS_EXTENDED;
|
||||
|
||||
#if !defined(_MSC_VER)
|
||||
#pragma pack(pop)
|
||||
#else
|
||||
#include <poppack.h>
|
||||
#endif
|
||||
BOOST_PROCESS_V2_DECL std::wstring cwd_cmd_from_proc(HANDLE proc, int type, boost::system::error_code & ec);
|
||||
BOOST_PROCESS_V2_DECL HANDLE open_process_with_debug_privilege(boost::process::v2::pid_type pid, boost::system::error_code & ec);
|
||||
#endif
|
||||
|
||||
} // namespace ext
|
||||
|
||||
} // namespace detail
|
||||
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_HEADER_ONLY)
|
||||
|
||||
#include <boost/process/v2/ext/detail/impl/proc_info.ipp>
|
||||
|
||||
#endif
|
||||
|
||||
#endif // BOOST_PROCESS_V2_DETAIL_PROC_INFO_HPP
|
||||
|
||||
155
linx64/include/boost/process/v2/ext/env.hpp
Normal file
155
linx64/include/boost/process/v2/ext/env.hpp
Normal file
@@ -0,0 +1,155 @@
|
||||
// Copyright (c) 2022 Klemens D. Morgenstern
|
||||
// Copyright (c) 2022 Samuel Venable
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_PROCESS_V2_ENV_HPP
|
||||
#define BOOST_PROCESS_V2_ENV_HPP
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
#include <boost/process/v2/detail/throw_error.hpp>
|
||||
#include <boost/process/v2/process_handle.hpp>
|
||||
#include <boost/process/v2/pid.hpp>
|
||||
|
||||
#include <boost/process/v2/environment.hpp>
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
|
||||
namespace detail
|
||||
{
|
||||
namespace ext
|
||||
{
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
using native_env_handle_type = wchar_t *;
|
||||
using native_env_iterator = wchar_t *;
|
||||
#elif defined(__FreeBSD__)
|
||||
using native_env_handle_type = char **;
|
||||
using native_env_iterator = char **;
|
||||
#else
|
||||
using native_env_handle_type = char *;
|
||||
using native_env_iterator = char *;
|
||||
#endif
|
||||
|
||||
struct native_env_handle_deleter
|
||||
{
|
||||
BOOST_PROCESS_V2_DECL void operator()(native_env_handle_type) const;
|
||||
};
|
||||
|
||||
BOOST_PROCESS_V2_DECL native_env_iterator next(native_env_iterator nh);
|
||||
BOOST_PROCESS_V2_DECL native_env_iterator find_end(native_env_iterator nh);
|
||||
BOOST_PROCESS_V2_DECL const environment::char_type * dereference(native_env_iterator iterator);
|
||||
|
||||
} // namespace ext
|
||||
} // namespace detail
|
||||
|
||||
namespace ext {
|
||||
|
||||
/// The view of an environment
|
||||
struct env_view
|
||||
{
|
||||
using native_handle_type = detail::ext::native_env_handle_type;
|
||||
using value_type = environment::key_value_pair_view;
|
||||
|
||||
env_view() = default;
|
||||
env_view(env_view && nt) = default;
|
||||
|
||||
native_handle_type native_handle() { return handle_.get(); }
|
||||
|
||||
|
||||
struct iterator
|
||||
{
|
||||
using value_type = environment::key_value_pair_view;
|
||||
using difference_type = int;
|
||||
using reference = environment::key_value_pair_view;
|
||||
using pointer = environment::key_value_pair_view;
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
|
||||
iterator() = default;
|
||||
iterator(const iterator & ) = default;
|
||||
iterator(const detail::ext::native_env_iterator &native_handle) : iterator_(native_handle) {}
|
||||
|
||||
iterator & operator++()
|
||||
{
|
||||
iterator_ = detail::ext::next(iterator_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
iterator operator++(int)
|
||||
{
|
||||
auto last = *this;
|
||||
iterator_ = detail::ext::next(iterator_);
|
||||
return last;
|
||||
}
|
||||
environment::key_value_pair_view operator*() const
|
||||
{
|
||||
return detail::ext::dereference(iterator_);
|
||||
}
|
||||
|
||||
friend bool operator==(const iterator & l, const iterator & r) {return l.iterator_ == r.iterator_;}
|
||||
friend bool operator!=(const iterator & l, const iterator & r) {return l.iterator_ != r.iterator_;}
|
||||
|
||||
private:
|
||||
detail::ext::native_env_iterator iterator_;
|
||||
};
|
||||
|
||||
iterator begin() const {return iterator(handle_.get());}
|
||||
iterator end() const {return iterator(detail::ext::find_end(handle_.get()));}
|
||||
|
||||
private:
|
||||
friend BOOST_PROCESS_V2_DECL env_view env(pid_type pid, error_code & ec);
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
friend BOOST_PROCESS_V2_DECL env_view env(HANDLE handle, error_code & ec);
|
||||
#endif
|
||||
|
||||
std::unique_ptr<typename remove_pointer<detail::ext::native_env_handle_type>::type,
|
||||
detail::ext::native_env_handle_deleter> handle_;
|
||||
};
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
BOOST_PROCESS_V2_DECL env_view env(HANDLE handle, error_code & ec);
|
||||
BOOST_PROCESS_V2_DECL env_view env(HANDLE handle);
|
||||
#endif
|
||||
|
||||
/// @{
|
||||
/// Get the environment of another process.
|
||||
BOOST_PROCESS_V2_DECL env_view env(pid_type pid, error_code & ec);
|
||||
BOOST_PROCESS_V2_DECL env_view env(pid_type pid);
|
||||
|
||||
template<typename Executor>
|
||||
BOOST_PROCESS_V2_DECL env_view env(basic_process_handle<Executor> & handle, error_code & ec)
|
||||
{
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
return env(handle.native_handle(), ec);
|
||||
#else
|
||||
return env(handle.id(), ec);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename Executor>
|
||||
BOOST_PROCESS_V2_DECL env_view env(basic_process_handle<Executor> & handle)
|
||||
{
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
return env(handle.native_handle());
|
||||
#else
|
||||
return env(handle.id());
|
||||
#endif
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
|
||||
|
||||
} // namespace ext
|
||||
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_HEADER_ONLY)
|
||||
|
||||
#include <boost/process/v2/ext/impl/env.ipp>
|
||||
|
||||
#endif
|
||||
#endif // BOOST_PROCESS_V2_ENV_HPP
|
||||
62
linx64/include/boost/process/v2/ext/exe.hpp
Normal file
62
linx64/include/boost/process/v2/ext/exe.hpp
Normal file
@@ -0,0 +1,62 @@
|
||||
// Copyright (c) 2022 Klemens D. Morgenstern
|
||||
// Copyright (c) 2022 Samuel Venable
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_PROCESS_V2_EXE_HPP
|
||||
#define BOOST_PROCESS_V2_EXE_HPP
|
||||
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
#include <boost/process/v2/detail/throw_error.hpp>
|
||||
|
||||
#include <boost/process/v2/process_handle.hpp>
|
||||
#include <boost/process/v2/pid.hpp>
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
|
||||
namespace ext {
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
BOOST_PROCESS_V2_DECL filesystem::path exe(HANDLE handle, error_code & ec);
|
||||
BOOST_PROCESS_V2_DECL filesystem::path exe(HANDLE handle);
|
||||
#endif
|
||||
|
||||
/// @{
|
||||
/// Return the executable of another process by pid or handle.
|
||||
BOOST_PROCESS_V2_DECL filesystem::path exe(pid_type pid, error_code & ec);
|
||||
BOOST_PROCESS_V2_DECL filesystem::path exe(pid_type pid);
|
||||
|
||||
|
||||
|
||||
template<typename Executor>
|
||||
filesystem::path exe(basic_process_handle<Executor> & handle, error_code & ec)
|
||||
{
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
return exe(handle.native_handle(), ec);
|
||||
#else
|
||||
return exe(handle.id(), ec);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename Executor>
|
||||
filesystem::path exe(basic_process_handle<Executor> & handle)
|
||||
{
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
return exe(handle.native_handle());
|
||||
#else
|
||||
return exe(handle.id());
|
||||
#endif
|
||||
}
|
||||
|
||||
///@}
|
||||
|
||||
} // namespace ext
|
||||
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_HEADER_ONLY)
|
||||
#include <boost/process/v2/ext/impl/exe.ipp>
|
||||
#endif
|
||||
|
||||
#endif // BOOST_PROCESS_V2_EXE_HPP
|
||||
|
||||
460
linx64/include/boost/process/v2/ext/impl/cmd.ipp
Normal file
460
linx64/include/boost/process/v2/ext/impl/cmd.ipp
Normal file
@@ -0,0 +1,460 @@
|
||||
// Copyright (c) 2022 Klemens D. Morgenstern
|
||||
// Copyright (c) 2022 Samuel Venable
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_PROCESS_V2_IMPL_CMD_IPP
|
||||
#define BOOST_PROCESS_V2_IMPL_CMD_IPP
|
||||
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
#include <boost/process/v2/detail/last_error.hpp>
|
||||
#include <boost/process/v2/detail/throw_error.hpp>
|
||||
#include <boost/process/v2/ext/detail/proc_info.hpp>
|
||||
#include <boost/process/v2/ext/cmd.hpp>
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
#include <windows.h>
|
||||
#include <shellapi.h>
|
||||
#else
|
||||
#include <cstdlib>
|
||||
#endif
|
||||
|
||||
#if (defined(__linux__) || defined(__ANDROID__))
|
||||
#include <cstdio>
|
||||
#endif
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/user.h>
|
||||
#include <libprocstat.h>
|
||||
#endif
|
||||
|
||||
#if (defined(__DragonFly__) || defined(__OpenBSD__))
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/user.h>
|
||||
#include <kvm.h>
|
||||
#endif
|
||||
|
||||
#if defined(__NetBSD__)
|
||||
#include <sys/types.h>
|
||||
#include <kvm.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
|
||||
#if defined(__sun)
|
||||
#include <sys/types.h>
|
||||
#include <kvm.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/proc.h>
|
||||
#endif
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
|
||||
struct make_cmd_shell_
|
||||
{
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
static shell make(std::wstring data)
|
||||
{
|
||||
shell res;
|
||||
res.input_ = res.buffer_ = std::move(data);
|
||||
res.parse_();
|
||||
return res;
|
||||
}
|
||||
#else
|
||||
static shell make(std::string data,
|
||||
int argc, char ** argv,
|
||||
void(*free_func)(int, char**))
|
||||
{
|
||||
shell res;
|
||||
res.argc_ = argc;
|
||||
res.input_ = res.buffer_ = std::move(data);
|
||||
res.argv_ = argv;
|
||||
res.free_argv_ = free_func;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static shell clone(char ** cmd)
|
||||
{
|
||||
shell res;
|
||||
res.argc_ = 0;
|
||||
std::size_t str_lengths = 0;
|
||||
for (auto c = cmd; *c != nullptr; c++)
|
||||
{
|
||||
res.argc_++;
|
||||
str_lengths += (std::strlen(*c) + 1);
|
||||
}
|
||||
// yes, not the greatest solution.
|
||||
res.buffer_.resize(str_lengths);
|
||||
|
||||
res.argv_ = new char*[res.argc_ + 1];
|
||||
res.free_argv_ = +[](int argc, char ** argv) {delete[] argv;};
|
||||
res.argv_[res.argc_] = nullptr;
|
||||
auto p = &*res.buffer_.begin();
|
||||
|
||||
for (int i = 0; i < res.argc_; i++)
|
||||
{
|
||||
const auto ln = std::strlen(cmd[i]);
|
||||
res.argv_[i] = std::strcpy(p, cmd[i]);
|
||||
p += (ln + 1);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
namespace ext {
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
|
||||
shell cmd(HANDLE proc, error_code & ec)
|
||||
{
|
||||
std::wstring buffer = boost::process::v2::detail::ext::cwd_cmd_from_proc(proc, 0/*=MEMCMD*/, ec);
|
||||
|
||||
if (!ec)
|
||||
return make_cmd_shell_::make(std::move(buffer));
|
||||
else
|
||||
return {};
|
||||
}
|
||||
|
||||
shell cmd(HANDLE proc)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
auto res = cmd(proc, ec);
|
||||
if (ec)
|
||||
detail::throw_error(ec, "cmd");
|
||||
return res;
|
||||
}
|
||||
|
||||
shell cmd(boost::process::v2::pid_type pid, boost::system::error_code & ec)
|
||||
{
|
||||
struct del
|
||||
{
|
||||
void operator()(HANDLE h)
|
||||
{
|
||||
::CloseHandle(h);
|
||||
};
|
||||
};
|
||||
std::unique_ptr<void, del> proc{detail::ext::open_process_with_debug_privilege(pid, ec)};
|
||||
if (proc == nullptr)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
else
|
||||
return cmd(proc.get(), ec);
|
||||
|
||||
}
|
||||
|
||||
#elif (defined(__APPLE__) && defined(__MACH__))
|
||||
|
||||
shell cmd(boost::process::v2::pid_type pid, boost::system::error_code & ec)
|
||||
{
|
||||
int mib[3] = {CTL_KERN, KERN_ARGMAX, 0};
|
||||
int argmax = 0;
|
||||
auto size = sizeof(argmax);
|
||||
if (sysctl(mib, 2, &argmax, &size, nullptr, 0) == -1)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string procargs;
|
||||
procargs.resize(argmax - 1);
|
||||
mib[1] = KERN_PROCARGS;
|
||||
mib[2] = pid;
|
||||
|
||||
size = argmax;
|
||||
|
||||
if (sysctl(mib, 3, &*procargs.begin(), &size, nullptr, 0) != 0)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return {};
|
||||
}
|
||||
|
||||
int argc = *reinterpret_cast<const int*>(procargs.data());
|
||||
auto itr = procargs.begin() + sizeof(argc);
|
||||
|
||||
std::unique_ptr<char*[]> argv{new char*[argc + 1]};
|
||||
const auto end = procargs.end();
|
||||
|
||||
argv[argc] = nullptr; //args is a null-terminated list
|
||||
|
||||
for (auto n = 0u; n <= argc; n++)
|
||||
{
|
||||
auto e = std::find(itr, end, '\0');
|
||||
if (e == end && n < argc) // something off
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, EINVAL, system_category())
|
||||
return {};
|
||||
}
|
||||
argv[n] = &*itr;
|
||||
itr = e + 1; // start searching start
|
||||
}
|
||||
|
||||
auto fr_func = +[](int argc, char ** argv) {delete [] argv;};
|
||||
|
||||
return make_cmd_shell_::make(std::move(procargs), argc, argv.release(), fr_func);
|
||||
}
|
||||
|
||||
#elif (defined(__linux__) || defined(__ANDROID__))
|
||||
|
||||
shell cmd(boost::process::v2::pid_type pid, boost::system::error_code & ec)
|
||||
{
|
||||
std::string procargs;
|
||||
procargs.resize(4096);
|
||||
int f = ::open(("/proc/" + std::to_string(pid) + "/cmdline").c_str(), O_RDONLY);
|
||||
|
||||
while (procargs.back() != EOF)
|
||||
{
|
||||
auto r = ::read(f, &*(procargs.end() - 4096), 4096);
|
||||
if (r < 0)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
::close(f);
|
||||
return {};
|
||||
}
|
||||
if (r < 4096) // done!
|
||||
{
|
||||
procargs.resize(procargs.size() - 4096 + r);
|
||||
break;
|
||||
}
|
||||
procargs.resize(procargs.size() + 4096);
|
||||
}
|
||||
::close(f);
|
||||
|
||||
if (procargs.back() == EOF)
|
||||
procargs.pop_back();
|
||||
|
||||
auto argc = std::count(procargs.begin(), procargs.end(), '\0');
|
||||
|
||||
auto itr = procargs.begin();
|
||||
|
||||
std::unique_ptr<char*[]> argv{new char*[argc + 1]};
|
||||
const auto end = procargs.end();
|
||||
|
||||
argv[argc] = nullptr; //args is a null-terminated list
|
||||
|
||||
|
||||
for (auto n = 0u; n <= argc; n++)
|
||||
{
|
||||
auto e = std::find(itr, end, '\0');
|
||||
if (e == end && n < argc) // something off
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, EINVAL, system_category())
|
||||
return {};
|
||||
}
|
||||
argv[n] = &*itr;
|
||||
itr = e + 1; // start searching start
|
||||
}
|
||||
|
||||
auto fr_func = +[](int argc, char ** argv) {delete [] argv;};
|
||||
|
||||
return make_cmd_shell_::make(std::move(procargs), argc, argv.release(), fr_func);
|
||||
}
|
||||
|
||||
#elif defined(__FreeBSD__)
|
||||
|
||||
shell cmd(boost::process::v2::pid_type pid, boost::system::error_code & ec)
|
||||
{
|
||||
struct cl_proc_stat
|
||||
{
|
||||
void operator()(struct procstat *proc_stat)
|
||||
{
|
||||
procstat_close(proc_stat);
|
||||
}
|
||||
};
|
||||
std::unique_ptr<struct procstat, cl_proc_stat> proc_stat{procstat_open_sysctl()};
|
||||
if (!proc_stat)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return {};
|
||||
}
|
||||
|
||||
struct proc_info_close
|
||||
{
|
||||
struct procstat * proc_stat;
|
||||
|
||||
void operator()(struct kinfo_proc * proc_info)
|
||||
{
|
||||
procstat_freeprocs(proc_stat, proc_info);
|
||||
}
|
||||
};
|
||||
|
||||
unsigned cntp;
|
||||
std::unique_ptr<struct kinfo_proc, proc_info_close> proc_info{
|
||||
procstat_getprocs(proc_stat.get(), KERN_PROC_PID, pid, &cntp),
|
||||
proc_info_close{proc_stat.get()}};
|
||||
|
||||
if (!proc_info)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return {};
|
||||
}
|
||||
|
||||
char **cmd = procstat_getargv(proc_stat.get(), proc_info.get(), 0);
|
||||
if (!cmd)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return {};
|
||||
}
|
||||
auto res = make_cmd_shell_::clone(cmd);
|
||||
procstat_freeargv(proc_stat.get());
|
||||
return res;
|
||||
}
|
||||
|
||||
#elif defined(__DragonFly__)
|
||||
|
||||
shell cmd(boost::process::v2::pid_type pid, boost::system::error_code & ec)
|
||||
{
|
||||
int cntp = 0;
|
||||
kinfo_proc *proc_info = nullptr;
|
||||
const char *nlistf, *memf;
|
||||
nlistf = memf = "/dev/null";
|
||||
struct closer
|
||||
{
|
||||
void operator()(kvm_t * kd)
|
||||
{
|
||||
kvm_close(kd);
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<kvm_t, closer> kd{kvm_openfiles(nlistf, memf, nullptr, O_RDONLY, nullptr)};
|
||||
if (!kd) {BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return {};}
|
||||
if ((proc_info = kvm_getprocs(kd.get(), KERN_PROC_PID, pid, &cntp)))
|
||||
{
|
||||
char **cmd = kvm_getargv(kd.get(), proc_info, 0);
|
||||
if (cmd)
|
||||
return make_cmd_shell_::clone(cmd);
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return {};
|
||||
}
|
||||
|
||||
#elif defined(__NetBSD__)
|
||||
|
||||
shell cmd(boost::process::v2::pid_type pid, boost::system::error_code & ec)
|
||||
{
|
||||
|
||||
std::vector<std::string> vec;
|
||||
int cntp = 0;
|
||||
kinfo_proc2 *proc_info = nullptr;
|
||||
struct closer
|
||||
{
|
||||
void operator()(kvm_t * kd)
|
||||
{
|
||||
kvm_close(kd);
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<kvm_t, closer> kd{kvm_openfiles(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr)};
|
||||
|
||||
if (!kd) {BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return vec;}
|
||||
if ((proc_info = kvm_getproc2(kd.get(), KERN_PROC_PID, pid, sizeof(struct kinfo_proc2), &cntp)))
|
||||
{
|
||||
char **cmd = kvm_getargv2(kd.get(), proc_info, 0);
|
||||
if (cmd)
|
||||
return make_cmd_shell_::clone(cmd);
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return vec;
|
||||
}
|
||||
|
||||
#elif defined(__OpenBSD__)
|
||||
|
||||
shell cmd(boost::process::v2::pid_type pid, boost::system::error_code & ec)
|
||||
{
|
||||
std::vector<std::string> vec;
|
||||
int cntp = 0;
|
||||
kinfo_proc *proc_info = nullptr;
|
||||
|
||||
struct closer
|
||||
{
|
||||
void operator()(kvm_t * kd)
|
||||
{
|
||||
kvm_close(kd);
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<kvm_t, closer> kd{kvm_openfiles(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr)};
|
||||
if (!kd) {BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return vec;}
|
||||
if ((proc_info = kvm_getprocs(kd.get(), KERN_PROC_PID, pid, sizeof(struct kinfo_proc), &cntp)))
|
||||
{
|
||||
char **cmd = kvm_getargv(kd.get(), proc_info, 0);
|
||||
if (cmd)
|
||||
return make_cmd_shell_::clone(cmd);
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
kvm_close(kd);
|
||||
return {};
|
||||
}
|
||||
|
||||
#elif defined(__sun)
|
||||
|
||||
shell cmd(boost::process::v2::pid_type pid, boost::system::error_code & ec)
|
||||
{
|
||||
char **cmd = nullptr;
|
||||
proc *proc_info = nullptr;
|
||||
user *proc_user = nullptr;
|
||||
kd = kvm_open(nullptr, nullptr, nullptr, O_RDONLY, nullptr);
|
||||
if (!kd) {BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return {};}
|
||||
if ((proc_info = kvm_getproc(kd, pid)))
|
||||
{
|
||||
if ((proc_user = kvm_getu(kd, proc_info)))
|
||||
{
|
||||
if (!kvm_getcmd(kd, proc_info, proc_user, &cmd, nullptr))
|
||||
{
|
||||
int argc = 0;
|
||||
for (int i = 0; cmd[i] != nullptr; i++)
|
||||
argc ++;
|
||||
return make_cmd_shell_::make(
|
||||
{}, argc, cmd,
|
||||
+[](int, char ** argv) {::free(argv);})
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
|
||||
kvm_close(kd);
|
||||
return {};
|
||||
}
|
||||
|
||||
#else
|
||||
#error "Platform not supported"
|
||||
#endif
|
||||
|
||||
shell cmd(boost::process::v2::pid_type pid)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
auto res = cmd(pid, ec);
|
||||
if (ec)
|
||||
detail::throw_error(ec, "cmd");
|
||||
return res;
|
||||
}
|
||||
|
||||
} // namespace ext
|
||||
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#endif // BOOST_PROCESS_V2_IMPL_CMD_IPP
|
||||
|
||||
234
linx64/include/boost/process/v2/ext/impl/cwd.ipp
Normal file
234
linx64/include/boost/process/v2/ext/impl/cwd.ipp
Normal file
@@ -0,0 +1,234 @@
|
||||
// Copyright (c) 2022 Klemens D. Morgenstern
|
||||
// Copyright (c) 2022 Samuel Venable
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_PROCESS_V2_IMPL_CWD_IPP
|
||||
#define BOOST_PROCESS_V2_IMPL_CWD_IPP
|
||||
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
#include <boost/process/v2/detail/last_error.hpp>
|
||||
#include <boost/process/v2/detail/throw_error.hpp>
|
||||
#include <boost/process/v2/ext/detail/proc_info.hpp>
|
||||
#include <boost/process/v2/ext/cwd.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <climits>
|
||||
#endif
|
||||
|
||||
#if (defined(__APPLE__) && defined(__MACH__))
|
||||
#include <sys/proc_info.h>
|
||||
#include <libproc.h>
|
||||
#endif
|
||||
|
||||
#if (defined(BOOST_PROCESS_V2_WINDOWS) || defined(__linux__) || defined(__ANDROID__) || defined(__sun))
|
||||
#include <cstdlib>
|
||||
#endif
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/user.h>
|
||||
#include <libprocstat.h>
|
||||
#endif
|
||||
|
||||
#if (defined(__NetBSD__) || defined(__OpenBSD__))
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
|
||||
#if defined(__DragonFly__)
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_PROCESS_USE_STD_FS
|
||||
namespace filesystem = std::filesystem;
|
||||
#else
|
||||
namespace filesystem = boost::filesystem;
|
||||
#endif
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
|
||||
namespace ext {
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
|
||||
filesystem::path cwd(HANDLE proc, boost::system::error_code & ec)
|
||||
{
|
||||
auto buffer = boost::process::v2::detail::ext::cwd_cmd_from_proc(proc, 1/*=MEMCWD*/, ec);
|
||||
if (!buffer.empty())
|
||||
return filesystem::canonical(buffer, ec);
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return "";
|
||||
}
|
||||
|
||||
filesystem::path cwd(boost::process::v2::pid_type pid, boost::system::error_code & ec)
|
||||
{
|
||||
struct del
|
||||
{
|
||||
void operator()(HANDLE h)
|
||||
{
|
||||
::CloseHandle(h);
|
||||
};
|
||||
};
|
||||
std::unique_ptr<void, del> proc{detail::ext::open_process_with_debug_privilege(pid, ec)};
|
||||
if (proc == nullptr)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
else
|
||||
return cwd(proc.get(), ec);
|
||||
return {};
|
||||
}
|
||||
|
||||
filesystem::path cwd(HANDLE proc)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
auto res = cwd(proc, ec);
|
||||
if (ec)
|
||||
detail::throw_error(ec, "cwd");
|
||||
return res;
|
||||
}
|
||||
|
||||
#elif (defined(__APPLE__) && defined(__MACH__))
|
||||
|
||||
filesystem::path cwd(boost::process::v2::pid_type pid, boost::system::error_code & ec)
|
||||
{
|
||||
proc_vnodepathinfo vpi;
|
||||
if (proc_pidinfo(pid, PROC_PIDVNODEPATHINFO, 0, &vpi, sizeof(vpi)) > 0)
|
||||
return filesystem::canonical(vpi.pvi_cdir.vip_path, ec);
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return "";
|
||||
}
|
||||
|
||||
#elif (defined(__linux__) || defined(__ANDROID__) || defined(__sun))
|
||||
|
||||
filesystem::path cwd(boost::process::v2::pid_type pid, boost::system::error_code & ec)
|
||||
{
|
||||
return filesystem::canonical(
|
||||
filesystem::path("/proc") / std::to_string(pid) / "cwd", ec);
|
||||
}
|
||||
|
||||
#elif defined(__FreeBSD__)
|
||||
|
||||
// FIXME: Add error handling.
|
||||
filesystem::path cwd(boost::process::v2::pid_type pid, boost::system::error_code & ec)
|
||||
{
|
||||
filesystem::path path;
|
||||
unsigned cntp = 0;
|
||||
procstat *proc_stat = procstat_open_sysctl();
|
||||
if (proc_stat) {
|
||||
kinfo_proc *proc_info = procstat_getprocs(proc_stat, KERN_PROC_PID, pid, &cntp);
|
||||
if (proc_info) {
|
||||
filestat_list *head = procstat_getfiles(proc_stat, proc_info, 0);
|
||||
if (head) {
|
||||
filestat *fst = nullptr;
|
||||
STAILQ_FOREACH(fst, head, next) {
|
||||
if (fst->fs_uflags & PS_FST_UFLAG_CDIR)
|
||||
{
|
||||
path = filesystem::canonical(fst->fs_path, ec);
|
||||
}
|
||||
}
|
||||
procstat_freefiles(proc_stat, head);
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
procstat_freeprocs(proc_stat, proc_info);
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
procstat_close(proc_stat);
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return path;
|
||||
}
|
||||
|
||||
#elif defined(__DragonFly__)
|
||||
|
||||
// FIXME: Add error handling.
|
||||
filesystem::path cwd(boost::process::v2::pid_type pid, boost::system::error_code & ec)
|
||||
{
|
||||
filesystem::path path;
|
||||
/* Probably the hackiest thing ever we are doing here, because the "official" API is broken OS-level. */
|
||||
FILE *fp = popen(("pos=`ans=\\`/usr/bin/fstat -w -p " + std::to_string(pid) + " | /usr/bin/sed -n 1p\\`; " +
|
||||
"/usr/bin/awk -v ans=\"$ans\" 'BEGIN{print index(ans, \"INUM\")}'`; str=`/usr/bin/fstat -w -p " +
|
||||
std::to_string(pid) + " | /usr/bin/sed -n 3p`; /usr/bin/awk -v str=\"$str\" -v pos=\"$pos\" " +
|
||||
"'BEGIN{print substr(str, 0, pos + 4)}' | /usr/bin/awk 'NF{NF--};1 {$1=$2=$3=$4=\"\"; print" +
|
||||
" substr($0, 5)'}").c_str(), "r");
|
||||
if (fp)
|
||||
{
|
||||
char buffer[PATH_MAX];
|
||||
if (fgets(buffer, sizeof(buffer), fp))
|
||||
{
|
||||
std::string str = buffer;
|
||||
std::size_t pos = str.find("\n", strlen(buffer) - 1);
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
str.replace(pos, 1, "");
|
||||
}
|
||||
path = filesystem::canonical(str.c_str(), ec);
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
pclose(fp);
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return path;
|
||||
}
|
||||
|
||||
#elif (defined(__NetBSD__) || defined(__OpenBSD__))
|
||||
|
||||
filesystem::path cwd(boost::process::v2::pid_type pid, boost::system::error_code & ec)
|
||||
{
|
||||
std::string path;
|
||||
#if defined(__NetBSD__)
|
||||
int mib[4] = {CTL_KERN, KERN_PROC_ARGS, pid, KERN_PROC_CWD};
|
||||
const std::size_t sz = 4;
|
||||
#elif defined(__OpenBSD__)
|
||||
int mib[3] = {CTL_KERN, KERN_PROC_CWD, pid};
|
||||
const std::size_t sz = 3;
|
||||
#endif
|
||||
std::size_t len = 0;
|
||||
if (sysctl(mib, sz, nullptr, &len, nullptr, 0) == 0)
|
||||
{
|
||||
std::string strbuff;
|
||||
strbuff.resize(len);
|
||||
if (sysctl(mib, 4, &strbuff[0], &len, nullptr, 0) == 0)
|
||||
{
|
||||
filesystem::canonical(strbuff, ec);
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
#else
|
||||
#error "Platform not supported"
|
||||
#endif
|
||||
|
||||
filesystem::path cwd(boost::process::v2::pid_type pid)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
auto res = cwd(pid, ec);
|
||||
if (ec)
|
||||
detail::throw_error(ec, "cwd");
|
||||
return res;
|
||||
}
|
||||
|
||||
} // namespace ext
|
||||
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#endif // BOOST_PROCESS_V2_IMPL_CWD_IPP
|
||||
|
||||
389
linx64/include/boost/process/v2/ext/impl/env.ipp
Normal file
389
linx64/include/boost/process/v2/ext/impl/env.ipp
Normal file
@@ -0,0 +1,389 @@
|
||||
// Copyright (c) 2022 Klemens D. Morgenstern
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_PROCESS_V2_EXT_IMPL_ENV_IPP
|
||||
#define BOOST_PROCESS_V2_EXT_IMPL_ENV_IPP
|
||||
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
#include <boost/process/v2/detail/last_error.hpp>
|
||||
#include <boost/process/v2/detail/throw_error.hpp>
|
||||
#include <boost/process/v2/ext/detail/proc_info.hpp>
|
||||
#include <boost/process/v2/ext/env.hpp>
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
#include <shellapi.h>
|
||||
#else
|
||||
#include <cstdlib>
|
||||
#endif
|
||||
|
||||
#if (defined(__linux__) || defined(__ANDROID__))
|
||||
#include <cstdio>
|
||||
#endif
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
|
||||
namespace detail {
|
||||
namespace ext {
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
|
||||
void native_env_handle_deleter::operator()(native_env_handle_type h) const
|
||||
{
|
||||
delete [] h;
|
||||
}
|
||||
|
||||
native_env_iterator next(native_env_iterator nh)
|
||||
{
|
||||
while (*nh != L'\0')
|
||||
nh ++;
|
||||
return ++nh ;
|
||||
}
|
||||
native_env_iterator find_end(native_env_iterator nh)
|
||||
{
|
||||
while (*nh - 1 != L'\0' && *nh != L'\0')
|
||||
nh ++;
|
||||
return nh ;
|
||||
}
|
||||
|
||||
const environment::char_type * dereference(native_env_iterator iterator)
|
||||
{
|
||||
return iterator;
|
||||
}
|
||||
|
||||
#elif (defined(__linux__) || defined(__ANDROID__))
|
||||
//linux stores this as a blob with an EOF at the end
|
||||
|
||||
void native_env_handle_deleter::operator()(native_env_handle_type h) const
|
||||
{
|
||||
delete [] h;
|
||||
}
|
||||
|
||||
native_env_iterator next(native_env_iterator nh)
|
||||
{
|
||||
while (*nh != '\0')
|
||||
nh ++;
|
||||
return ++nh ;
|
||||
}
|
||||
native_env_iterator find_end(native_env_iterator nh)
|
||||
{
|
||||
while (*nh != EOF)
|
||||
nh ++;
|
||||
return nh ;
|
||||
}
|
||||
|
||||
const environment::char_type * dereference(native_env_iterator iterator)
|
||||
{
|
||||
return iterator;
|
||||
}
|
||||
|
||||
#elif (defined(__APPLE___) || defined(__MACH__))
|
||||
|
||||
void native_env_handle_deleter::operator()(native_env_handle_type h) const
|
||||
{
|
||||
delete [] h;
|
||||
}
|
||||
|
||||
native_env_iterator next(native_env_iterator nh)
|
||||
{
|
||||
while (*nh != '\0')
|
||||
nh ++;
|
||||
return ++nh ;
|
||||
}
|
||||
native_env_iterator find_end(native_env_iterator nh)
|
||||
{
|
||||
while (*nh - 1 != '\0' && *nh != '\0')
|
||||
nh ++;
|
||||
return nh ;
|
||||
}
|
||||
|
||||
const environment::char_type * dereference(native_env_iterator iterator)
|
||||
{
|
||||
return iterator;
|
||||
}
|
||||
|
||||
|
||||
#elif defined(__FreeBSD__)
|
||||
|
||||
void native_env_handle_deleter::operator()(native_env_handle_type h) const
|
||||
{
|
||||
delete [] h;
|
||||
}
|
||||
|
||||
native_env_iterator next(native_env_iterator nh)
|
||||
{
|
||||
return ++nh ;
|
||||
}
|
||||
native_env_iterator find_end(native_env_iterator nh)
|
||||
{
|
||||
while (*nh != nullptr)
|
||||
nh++;
|
||||
|
||||
return nh ;
|
||||
}
|
||||
|
||||
const environment::char_type * dereference(native_env_iterator iterator)
|
||||
{
|
||||
return *iterator;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
namespace ext
|
||||
{
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
|
||||
env_view env(HANDLE proc, boost::system::error_code & ec)
|
||||
{
|
||||
wchar_t *buffer = nullptr;
|
||||
PEB peb;
|
||||
SIZE_T nRead = 0;
|
||||
ULONG len = 0;
|
||||
PROCESS_BASIC_INFORMATION pbi;
|
||||
detail::ext::RTL_USER_PROCESS_PARAMETERS_EXTENDED upp;
|
||||
|
||||
NTSTATUS status = 0;
|
||||
PVOID buf = nullptr;
|
||||
status = NtQueryInformationProcess(proc, ProcessBasicInformation, &pbi, sizeof(pbi), &len);
|
||||
ULONG error = RtlNtStatusToDosError(status);
|
||||
|
||||
if (error)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, error, boost::system::system_category())
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!ReadProcessMemory(proc, pbi.PebBaseAddress, &peb, sizeof(peb), &nRead))
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!ReadProcessMemory(proc, peb.ProcessParameters, &upp, sizeof(upp), &nRead))
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return {};
|
||||
}
|
||||
|
||||
env_view ev;
|
||||
buf = upp.Environment;
|
||||
len = (ULONG)upp.EnvironmentSize;
|
||||
ev.handle_.reset(new wchar_t[len / 2 + 1]());
|
||||
|
||||
if (!ReadProcessMemory(proc, buf, ev.handle_.get(), len, &nRead))
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return {};
|
||||
}
|
||||
|
||||
ev.handle_.get()[len / 2] = L'\0';
|
||||
return ev;
|
||||
}
|
||||
|
||||
env_view env(HANDLE handle)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
auto res = env(handle, ec);
|
||||
if (ec)
|
||||
detail::throw_error(ec, "env");
|
||||
return res;
|
||||
}
|
||||
|
||||
env_view env(boost::process::v2::pid_type pid, boost::system::error_code & ec)
|
||||
{
|
||||
struct del
|
||||
{
|
||||
void operator()(HANDLE h)
|
||||
{
|
||||
::CloseHandle(h);
|
||||
};
|
||||
};
|
||||
std::unique_ptr<void, del> proc{detail::ext::open_process_with_debug_privilege(pid, ec)};
|
||||
if (proc == nullptr)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
else
|
||||
return env(proc.get(), ec);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
#elif (defined(__APPLE___) || defined(__MACH__))
|
||||
|
||||
env_view env(boost::process::v2::pid_type pid, boost::system::error_code & ec)
|
||||
{
|
||||
int mib[3] = {CTL_KERN, KERN_ARGMAX, 0};
|
||||
int argmax = 0;
|
||||
auto size = sizeof(argmax);
|
||||
if (sysctl(mib, 2, &argmax, &size, nullptr, 0) == -1)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string procargs;
|
||||
procargs.resize(argmax - 1);
|
||||
mib[1] = KERN_PROCARGS2;
|
||||
mib[2] = pid;
|
||||
|
||||
size = argmax;
|
||||
|
||||
if (sysctl(mib, 3, &*procargs.begin(), &size, nullptr, 0) != 0)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return {};
|
||||
}
|
||||
std::uint32_t nargs;
|
||||
memcpy(&nargs, &*procargs.begin(), sizeof(nargs));
|
||||
char *cp = &*procargs.begin() + sizeof(nargs);
|
||||
|
||||
for (; cp < &*procargs.end(); cp++)
|
||||
if (*cp == '\0')
|
||||
break;
|
||||
|
||||
|
||||
if (cp == &procargs[size])
|
||||
return {};
|
||||
|
||||
|
||||
for (; cp < &*procargs.end(); cp++)
|
||||
if (*cp != '\0') break;
|
||||
|
||||
|
||||
if (cp == &*procargs.end())
|
||||
return {};
|
||||
|
||||
|
||||
int i = 0;
|
||||
char *sp = cp;
|
||||
std::vector<char> vec;
|
||||
|
||||
while ((*sp != '\0' || i < nargs) && sp < &*procargs.end()) {
|
||||
if (i >= nargs)
|
||||
vec.push_back(*sp);
|
||||
|
||||
sp += 1;
|
||||
}
|
||||
|
||||
env_view ev;
|
||||
ev.handle_.reset(new char[vec.size()]());
|
||||
std::copy(vec.begin(), vec.end(), ev.handle_.get());
|
||||
return ev;
|
||||
}
|
||||
|
||||
#elif (defined(__linux__) || defined(__ANDROID__))
|
||||
|
||||
env_view env(boost::process::v2::pid_type pid, boost::system::error_code & ec)
|
||||
{
|
||||
std::size_t size = 0;
|
||||
std::unique_ptr<char, detail::ext::native_env_handle_deleter> procargs{};
|
||||
|
||||
int f = ::open(("/proc/" + std::to_string(pid) + "/environ").c_str(), O_RDONLY);
|
||||
|
||||
while (!procargs || procargs.get()[size - 1] != EOF)
|
||||
{
|
||||
std::unique_ptr<char, detail::ext::native_env_handle_deleter> buf{new char[size + 4096]};
|
||||
if (size > 0)
|
||||
std::memmove(buf.get(), procargs.get(), size);
|
||||
auto r = ::read(f, buf.get() + size, 4096);
|
||||
if (r < 0)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
::close(f);
|
||||
return {};
|
||||
}
|
||||
procargs = std::move(buf);
|
||||
size += r;
|
||||
if (r < 4096) // done!
|
||||
{
|
||||
procargs.get()[size] = EOF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
::close(f);
|
||||
|
||||
env_view ev;
|
||||
ev.handle_ = std::move(procargs);
|
||||
return ev;
|
||||
}
|
||||
|
||||
#elif defined(__FreeBSD__)
|
||||
env_view env(boost::process::v2::pid_type pid, boost::system::error_code & ec)
|
||||
{
|
||||
env_view ev;
|
||||
|
||||
unsigned cntp = 0;
|
||||
procstat *proc_stat = procstat_open_sysctl();
|
||||
if (proc_stat != nullptr)
|
||||
{
|
||||
kinfo_proc *proc_info = procstat_getprocs(proc_stat, KERN_PROC_PID, pid, &cntp);
|
||||
if (proc_info != nullptr)
|
||||
{
|
||||
char **env = procstat_getenvv(proc_stat, proc_info, 0);
|
||||
if (env != nullptr)
|
||||
{
|
||||
auto e = env;
|
||||
std::size_t n = 0u, len = 0u;
|
||||
while (e && *e != nullptr)
|
||||
{
|
||||
n ++;
|
||||
len += std::strlen(*e);
|
||||
e++;
|
||||
}
|
||||
std::size_t mem_needed =
|
||||
// environ - nullptr - strlen + null terminators
|
||||
(n * sizeof(char*)) + sizeof(char*) + len + n;
|
||||
|
||||
char * out = new (std::nothrow) char[mem_needed];
|
||||
if (out != nullptr)
|
||||
{
|
||||
auto eno = reinterpret_cast<char**>(out);
|
||||
auto eeo = eno;
|
||||
auto str = out + (n * sizeof(char*)) + sizeof(char*);
|
||||
e = env;
|
||||
while (*e != nullptr)
|
||||
{
|
||||
auto len = std::strlen(*e) + 1u;
|
||||
std::memcpy(str, *e, len);
|
||||
*eno = str;
|
||||
str += len;
|
||||
eno ++;
|
||||
e++;
|
||||
}
|
||||
*eno = nullptr;
|
||||
|
||||
ev.handle_.reset(eeo);
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
|
||||
}
|
||||
procstat_freeprocs(proc_stat, proc_info);
|
||||
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
procstat_close(proc_stat);
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return ev;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
env_view env(boost::process::v2::pid_type pid)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
auto res = env(pid, ec);
|
||||
if (ec)
|
||||
detail::throw_error(ec, "env");
|
||||
return res;
|
||||
}
|
||||
}
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#endif //BOOST_PROCESS_V2_EXT_IMPL_ENV_IPP
|
||||
193
linx64/include/boost/process/v2/ext/impl/exe.ipp
Normal file
193
linx64/include/boost/process/v2/ext/impl/exe.ipp
Normal file
@@ -0,0 +1,193 @@
|
||||
// Copyright (c) 2022 Klemens D. Morgenstern
|
||||
// Copyright (c) 2022 Samuel Venable
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_PROCESS_V2_IMPL_EXE_IPP
|
||||
#define BOOST_PROCESS_V2_IMPL_EXE_IPP
|
||||
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
#include <boost/process/v2/detail/last_error.hpp>
|
||||
#include <boost/process/v2/detail/throw_error.hpp>
|
||||
#include <boost/process/v2/ext/detail/proc_info.hpp>
|
||||
#include <boost/process/v2/ext/exe.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <climits>
|
||||
#endif
|
||||
|
||||
#if (defined(__APPLE__) && defined(__MACH__))
|
||||
#include <sys/proc_info.h>
|
||||
#include <libproc.h>
|
||||
#endif
|
||||
|
||||
#if (defined(BOOST_PROCESS_V2_WINDOWS) || defined(__linux__) || defined(__ANDROID__) || defined(__sun))
|
||||
#include <cstdlib>
|
||||
#endif
|
||||
|
||||
#if (defined(__FreeBSD__) || defined(__DragonFly__) || defined(__NetBSD__))
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
#if !defined(__FreeBSD__)
|
||||
#include <alloca.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__OpenBSD__)
|
||||
#include <boost/process/v2/ext/cwd.hpp>
|
||||
#include <boost/process/v2/ext/cmd.hpp>
|
||||
#include <boost/process/v2/ext/env.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/algorithm/string/split.hpp>
|
||||
#include <boost/algorithm/string/classification.hpp>
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <kvm.h>
|
||||
#endif
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
|
||||
namespace ext {
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
|
||||
filesystem::path exe(HANDLE process_handle)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
auto res = exe(process_handle, ec);
|
||||
if (ec)
|
||||
detail::throw_error(ec, "exe");
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
filesystem::path exe(HANDLE proc, boost::system::error_code & ec)
|
||||
{
|
||||
wchar_t buffer[MAX_PATH];
|
||||
// On input, specifies the size of the lpExeName buffer, in characters.
|
||||
DWORD size = MAX_PATH;
|
||||
if (QueryFullProcessImageNameW(proc, 0, buffer, &size))
|
||||
{
|
||||
return filesystem::canonical(buffer, ec);
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
filesystem::path exe(boost::process::v2::pid_type pid, boost::system::error_code & ec)
|
||||
{
|
||||
if (pid == GetCurrentProcessId())
|
||||
{
|
||||
wchar_t buffer[MAX_PATH];
|
||||
if (GetModuleFileNameW(nullptr, buffer, sizeof(buffer)))
|
||||
{
|
||||
return filesystem::canonical(buffer, ec);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
struct del
|
||||
{
|
||||
void operator()(HANDLE h)
|
||||
{
|
||||
::CloseHandle(h);
|
||||
};
|
||||
};
|
||||
std::unique_ptr<void, del> proc{detail::ext::open_process_with_debug_privilege(pid, ec)};
|
||||
if (proc == nullptr)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
else
|
||||
return exe(proc.get(), ec);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
#elif (defined(__APPLE__) && defined(__MACH__))
|
||||
|
||||
filesystem::path exe(boost::process::v2::pid_type pid, boost::system::error_code & ec)
|
||||
{
|
||||
char buffer[PROC_PIDPATHINFO_MAXSIZE];
|
||||
if (proc_pidpath(pid, buffer, sizeof(buffer)) > 0)
|
||||
{
|
||||
return filesystem::canonical(buffer, ec);
|
||||
}
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return "";
|
||||
}
|
||||
|
||||
#elif (defined(__linux__) || defined(__ANDROID__) || defined(__sun))
|
||||
|
||||
filesystem::path exe(boost::process::v2::pid_type pid, boost::system::error_code & ec)
|
||||
{
|
||||
#if (defined(__linux__) || defined(__ANDROID__))
|
||||
return filesystem::canonical(
|
||||
filesystem::path("/proc") / std::to_string(pid) / "exe", ec
|
||||
);
|
||||
#elif defined(__sun)
|
||||
return fileystem::canonical(
|
||||
filesystem::path("/proc") / std::to_string(pid) / "path/a.out"
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
#elif (defined(__FreeBSD__) || defined(__DragonFly__) || defined(__NetBSD__))
|
||||
|
||||
filesystem::path exe(boost::process::v2::pid_type pid, boost::system::error_code & ec)
|
||||
{
|
||||
#if (defined(__FreeBSD__) || defined(__DragonFly__))
|
||||
int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, pid};
|
||||
#elif defined(__NetBSD__)
|
||||
int mib[4] = {CTL_KERN, KERN_PROC_ARGS, pid, KERN_PROC_PATHNAME};
|
||||
#endif
|
||||
std::size_t len = 0;
|
||||
if (sysctl(mib, 4, nullptr, &len, nullptr, 0) == 0)
|
||||
{
|
||||
std::string strbuff;
|
||||
strbuff.resize(len);
|
||||
if (sysctl(mib, 4, &strbuff[0], &len, nullptr, 0) == 0)
|
||||
{
|
||||
strbuff.resize(len - 1);
|
||||
return filesystem::canonical(strbuff, ec);
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return "";
|
||||
}
|
||||
|
||||
#elif defined(__OpenBSD__)
|
||||
|
||||
filesystem::path exe(boost::process::v2::pid_type pid, boost::system::error_code & ec)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, ENOTSUP, boost::system::system_category())
|
||||
return "";
|
||||
}
|
||||
|
||||
#else
|
||||
#error "Platform not supported"
|
||||
#endif
|
||||
|
||||
filesystem::path exe(boost::process::v2::pid_type pid)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
auto res = exe(pid, ec);
|
||||
if (ec)
|
||||
detail::throw_error(ec, "exe");
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
} // namespace ext
|
||||
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#endif // BOOST_PROCESS_V2_IMPL_EXE_IPP
|
||||
|
||||
24
linx64/include/boost/process/v2/impl/default_launcher.ipp
Normal file
24
linx64/include/boost/process/v2/impl/default_launcher.ipp
Normal file
@@ -0,0 +1,24 @@
|
||||
//
|
||||
// boost/process/v2/default_launcher.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2022 Klemens D. Morgenstern (klemens dot morgenstern at gmx dot net)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BOOST_PROCESS_V2_IMPL_DEFAULT_LAUNCHER_IPP
|
||||
#define BOOST_PROCESS_V2_IMPL_DEFAULT_LAUNCHER_IPP
|
||||
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
#include <boost/process/v2/windows/impl/default_launcher.ipp>
|
||||
#else
|
||||
#include <boost/process/v2/posix/detail/close_handles.ipp>
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#endif //BOOST_PROCESS_V2_IMPL_DEFAULT_LAUNCHER_IPP
|
||||
47
linx64/include/boost/process/v2/impl/environment.ipp
Normal file
47
linx64/include/boost/process/v2/impl/environment.ipp
Normal file
@@ -0,0 +1,47 @@
|
||||
//
|
||||
// boost/process/v2/impl/environment.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2022 Klemens D. Morgenstern (klemens dot morgenstern at gmx dot net)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BOOST_PROCESS_V2_IMPL_ENVIRONMENT_IPP
|
||||
#define BOOST_PROCESS_V2_IMPL_ENVIRONMENT_IPP
|
||||
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
#include <boost/process/v2/default_launcher.hpp>
|
||||
#include <boost/process/v2/environment.hpp>
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
|
||||
error_code process_environment::on_setup(windows::default_launcher & launcher, const filesystem::path &, const std::wstring &)
|
||||
{
|
||||
if (!unicode_env.empty() && !ec)
|
||||
{
|
||||
launcher.creation_flags |= CREATE_UNICODE_ENVIRONMENT ;
|
||||
launcher.environment = unicode_env.data();
|
||||
}
|
||||
|
||||
return ec;
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
error_code process_environment::on_setup(posix::default_launcher & launcher, const filesystem::path &, const char * const *)
|
||||
{
|
||||
launcher.env = env.data();
|
||||
return error_code{};
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
|
||||
#endif //BOOST_PROCESS_V2_IMPL_ENVIRONMENT_IPP
|
||||
206
linx64/include/boost/process/v2/impl/error.ipp
Normal file
206
linx64/include/boost/process/v2/impl/error.ipp
Normal file
@@ -0,0 +1,206 @@
|
||||
// Copyright (c) 2021 Klemens D. Morgenstern
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_PROCESS_V2_IMPL_ERROR_IPP
|
||||
#define BOOST_PROCESS_V2_IMPL_ERROR_IPP
|
||||
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
#include <boost/process/v2/error.hpp>
|
||||
#include <boost/process/v2/exit_code.hpp>
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_POSIX)
|
||||
#include <sys/wait.h>
|
||||
#endif
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
|
||||
namespace error
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
struct utf8_category final : public error_category
|
||||
{
|
||||
utf8_category() : error_category(0xDAEDu) {}
|
||||
|
||||
const char* name() const noexcept
|
||||
{
|
||||
return "process.v2.utf8";
|
||||
}
|
||||
std::string message(int value) const
|
||||
{
|
||||
switch (static_cast<utf8_conv_error>(value))
|
||||
{
|
||||
case utf8_conv_error::insufficient_buffer:
|
||||
return "A supplied buffer size was not large enough";
|
||||
case utf8_conv_error::invalid_character:
|
||||
return "Invalid characters were found in a string.";
|
||||
default:
|
||||
return "process.v2.utf8 error";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct exit_code_category final : public error_category
|
||||
{
|
||||
exit_code_category() : error_category(0xDAEEu) {}
|
||||
|
||||
const char* name() const noexcept
|
||||
{
|
||||
return "process.v2.exit_code";
|
||||
}
|
||||
std::string message(int status) const
|
||||
{
|
||||
switch (evaluate_exit_code(status))
|
||||
{
|
||||
case v2::detail::still_active:
|
||||
return "still-active";
|
||||
case EXIT_SUCCESS:
|
||||
return "exit_success";
|
||||
case EXIT_FAILURE:
|
||||
return "exit_failure";
|
||||
default:
|
||||
#if defined(BOOST_PROCESS_V2_POSIX)
|
||||
if (WIFCONTINUED(status))
|
||||
return "continued";
|
||||
switch (WTERMSIG(status))
|
||||
{
|
||||
# if defined(SIGABRT)
|
||||
case SIGABRT: return "SIGABRT: Abort signal from abort(3)";
|
||||
# endif
|
||||
# if defined(SIGALRM)
|
||||
case SIGALRM: return "SIGALRM: Timer signal from alarm(2)";
|
||||
# endif
|
||||
# if defined(SIGBUS)
|
||||
case SIGBUS: return "SIGBUS: Bus error (bad memory access)";
|
||||
# endif
|
||||
# if defined(SIGCHLD)
|
||||
case SIGCHLD: return "SIGCHLD: Child stopped or terminated";
|
||||
# endif
|
||||
# if defined(SIGCONT)
|
||||
case SIGCONT: return "SIGCONT: Continue if stopped";
|
||||
# endif
|
||||
# if defined(SIGEMT)
|
||||
case SIGEMT: return "SIGEMT: Emulator trap";
|
||||
# endif
|
||||
# if defined(SIGFPE)
|
||||
case SIGFPE: return "SIGFPE: Floating-point exception";
|
||||
# endif
|
||||
# if defined(SIGHUP)
|
||||
case SIGHUP: return "SIGHUP: Hangup detected on controlling terminal";
|
||||
# endif
|
||||
# if defined(SIGILL)
|
||||
case SIGILL: return "SIGILL: Illegal Instruction";
|
||||
# endif
|
||||
# if defined(SIGINFO)
|
||||
case SIGINFO: return "SIGINFO: A synonym for SIGPWR";
|
||||
# endif
|
||||
# if defined(SIGINT)
|
||||
case SIGINT: return "SIGINT: Interrupt from keyboard";
|
||||
# endif
|
||||
# if defined(SIGIO)
|
||||
case SIGIO: return "SIGIO: I/O now possible (4.2BSD)";
|
||||
# endif
|
||||
# if defined(SIGKILL)
|
||||
case SIGKILL: return "SIGKILL: Kill signal";
|
||||
# endif
|
||||
# if defined(SIGLOST)
|
||||
case SIGLOST: return "SIGLOST: File lock lost (unused)";
|
||||
# endif
|
||||
# if defined(SIGPIPE)
|
||||
case SIGPIPE: return "SIGPIPE: Broken pipe: write to pipe with no";
|
||||
# endif
|
||||
# if defined(SIGPOLL) && !defined(SIGIO)
|
||||
case SIGPOLL: return "SIGPOLL: Pollable event (Sys V);";
|
||||
# endif
|
||||
# if defined(SIGPROF)
|
||||
case SIGPROF: return "SIGPROF: Profiling timer expired";
|
||||
# endif
|
||||
# if defined(SIGPWR)
|
||||
case SIGPWR: return "SIGPWR: Power failure (System V)";
|
||||
# endif
|
||||
# if defined(SIGQUIT)
|
||||
case SIGQUIT: return "SIGQUIT: Quit from keyboard";
|
||||
# endif
|
||||
# if defined(SIGSEGV)
|
||||
case SIGSEGV: return "SIGSEGV: Invalid memory reference";
|
||||
# endif
|
||||
# if defined(SIGSTKFLT)
|
||||
case SIGSTKFLT: return "SIGSTKFLT: Stack fault on coprocessor (unused)";
|
||||
# endif
|
||||
# if defined(SIGSTOP)
|
||||
case SIGSTOP: return "SIGSTOP: Stop process";
|
||||
# endif
|
||||
# if defined(SIGTSTP)
|
||||
case SIGTSTP: return "SIGTSTP: Stop typed at terminal";
|
||||
# endif
|
||||
# if defined(SIGSYS)
|
||||
case SIGSYS: return "SIGSYS: Bad system call (SVr4);";
|
||||
# endif
|
||||
# if defined(SIGTERM)
|
||||
case SIGTERM: return "SIGTERM: Termination signal";
|
||||
# endif
|
||||
# if defined(SIGTRAP)
|
||||
case SIGTRAP: return "SIGTRAP: Trace/breakpoint trap";
|
||||
# endif
|
||||
# if defined(SIGTTIN)
|
||||
case SIGTTIN: return "SIGTTIN: Terminal input for background process";
|
||||
# endif
|
||||
# if defined(SIGTTOU)
|
||||
case SIGTTOU: return "SIGTTOU: Terminal output for background process";
|
||||
# endif
|
||||
# if defined(SIGURG)
|
||||
case SIGURG: return "SIGURG: Urgent condition on socket (4.2BSD)";
|
||||
# endif
|
||||
# if defined(SIGUSR1)
|
||||
case SIGUSR1: return "SIGUSR1: User-defined signal 1";
|
||||
# endif
|
||||
# if defined(SIGUSR2)
|
||||
case SIGUSR2: return "SIGUSR2: User-defined signal 2";
|
||||
# endif
|
||||
# if defined(SIGVTALRM)
|
||||
case SIGVTALRM: return "SIGVTALRM: Virtual alarm clock (4.2BSD)";
|
||||
# endif
|
||||
# if defined(SIGXCPU)
|
||||
case SIGXCPU: return "SIGXCPU: CPU time limit exceeded (4.2BSD);";
|
||||
# endif
|
||||
# if defined(SIGXFSZ)
|
||||
case SIGXFSZ: return "SIGXFSZ: File size limit exceeded (4.2BSD);";
|
||||
# endif
|
||||
# if defined(SIGWINCH)
|
||||
case SIGWINCH: return "SIGWINCH: Window resize signal (4.3BSD, Sun)";
|
||||
# endif
|
||||
default: return "Unknown signal";
|
||||
}
|
||||
#endif
|
||||
return "exited with other error";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace detail
|
||||
|
||||
BOOST_PROCESS_V2_DECL const error_category& get_utf8_category()
|
||||
{
|
||||
static detail::utf8_category instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
BOOST_PROCESS_V2_DECL const error_category& get_exit_code_category()
|
||||
{
|
||||
static detail::exit_code_category instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#endif //BOOST_PROCESS_V2_IMPL_ERROR_IPP
|
||||
762
linx64/include/boost/process/v2/impl/pid.ipp
Normal file
762
linx64/include/boost/process/v2/impl/pid.ipp
Normal file
@@ -0,0 +1,762 @@
|
||||
// Copyright (c) 2022 Klemens D. Morgenstern
|
||||
// Copyright (c) 2022 Samuel Venable
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_PROCESS_V2_IMPL_PID_IPP
|
||||
#define BOOST_PROCESS_V2_IMPL_PID_IPP
|
||||
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
#include <boost/process/v2/detail/last_error.hpp>
|
||||
#include <boost/process/v2/detail/throw_error.hpp>
|
||||
#include <boost/process/v2/pid.hpp>
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
#include <windows.h>
|
||||
#include <tlhelp32.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if (defined(__APPLE__) && defined(__MACH__))
|
||||
#include <sys/proc_info.h>
|
||||
#include <libproc.h>
|
||||
#endif
|
||||
|
||||
#if (defined(__linux__) || defined(__ANDROID__))
|
||||
#include <dirent.h>
|
||||
#endif
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
#include <sys/types.h>
|
||||
#include <sys/user.h>
|
||||
#include <libutil.h>
|
||||
#include <cstdlib>
|
||||
#endif
|
||||
|
||||
#if (defined(__DragonFly__) || defined(__OpenBSD__))
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/user.h>
|
||||
#include <kvm.h>
|
||||
#endif
|
||||
|
||||
#if defined(__NetBSD__)
|
||||
#include <sys/types.h>
|
||||
#include <kvm.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
|
||||
#if defined(__sun)
|
||||
#include <sys/types.h>
|
||||
#include <kvm.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/proc.h>
|
||||
#endif
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
pid_type current_pid() {return ::GetCurrentProcessId();}
|
||||
#else
|
||||
pid_type current_pid() {return ::getpid();}
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
|
||||
std::vector<pid_type> all_pids(boost::system::error_code & ec)
|
||||
{
|
||||
std::vector<pid_type> vec;
|
||||
HANDLE hp = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||
if (!hp)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return vec;
|
||||
}
|
||||
PROCESSENTRY32 pe;
|
||||
pe.dwSize = sizeof(PROCESSENTRY32);
|
||||
if (Process32First(hp, &pe))
|
||||
{
|
||||
do
|
||||
{
|
||||
vec.push_back(pe.th32ProcessID);
|
||||
} while (Process32Next(hp, &pe));
|
||||
}
|
||||
CloseHandle(hp);
|
||||
return vec;
|
||||
}
|
||||
|
||||
pid_type parent_pid(pid_type pid, boost::system::error_code & ec)
|
||||
{
|
||||
pid_type ppid = static_cast<pid_type>(-1);
|
||||
HANDLE hp = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||
if (!hp)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return ppid;
|
||||
}
|
||||
PROCESSENTRY32 pe;
|
||||
pe.dwSize = sizeof(PROCESSENTRY32);
|
||||
if (Process32First(hp, &pe))
|
||||
{
|
||||
do
|
||||
{
|
||||
if (pe.th32ProcessID == pid)
|
||||
{
|
||||
ppid = pe.th32ParentProcessID;
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (Process32Next(hp, &pe));
|
||||
}
|
||||
CloseHandle(hp);
|
||||
return ppid;
|
||||
}
|
||||
|
||||
std::vector<pid_type> child_pids(pid_type pid, boost::system::error_code & ec)
|
||||
{
|
||||
std::vector<pid_type> vec;
|
||||
HANDLE hp = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||
if (!hp)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return vec;
|
||||
}
|
||||
PROCESSENTRY32 pe;
|
||||
pe.dwSize = sizeof(PROCESSENTRY32);
|
||||
if (Process32First(hp, &pe))
|
||||
{
|
||||
do
|
||||
{
|
||||
if (pe.th32ParentProcessID == pid)
|
||||
{
|
||||
vec.push_back(pe.th32ProcessID);
|
||||
}
|
||||
}
|
||||
while (Process32Next(hp, &pe));
|
||||
}
|
||||
CloseHandle(hp);
|
||||
return vec;
|
||||
}
|
||||
|
||||
#elif (defined(__APPLE__) && defined(__MACH__))
|
||||
|
||||
std::vector<pid_type> all_pids(boost::system::error_code & ec)
|
||||
{
|
||||
std::vector<pid_type> vec;
|
||||
vec.resize(proc_listpids(PROC_ALL_PIDS, 0, nullptr, 0) / sizeof(pid_type));
|
||||
const auto sz = proc_listpids(PROC_ALL_PIDS, 0, &vec[0], sizeof(pid_type) * vec.size());
|
||||
if (sz < 0)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return {};
|
||||
}
|
||||
vec.resize(sz);
|
||||
return vec;
|
||||
}
|
||||
|
||||
pid_type parent_pid(pid_type pid, boost::system::error_code & ec)
|
||||
{
|
||||
pid_type ppid = static_cast<pid_type>(-1);
|
||||
proc_bsdinfo proc_info;
|
||||
if (proc_pidinfo(pid, PROC_PIDTBSDINFO, 0, &proc_info, sizeof(proc_info)) <= 0)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return ppid;
|
||||
}
|
||||
else
|
||||
ppid = proc_info.pbi_ppid;
|
||||
return ppid;
|
||||
}
|
||||
|
||||
std::vector<pid_type> child_pids(pid_type pid, boost::system::error_code & ec)
|
||||
{
|
||||
std::vector<pid_type> vec;
|
||||
vec.resize(proc_listpids(PROC_PPID_ONLY, (uint32_t)pid, nullptr, 0) / sizeof(pid_type));
|
||||
const auto sz = proc_listpids(PROC_PPID_ONLY, (uint32_t)pid, &vec[0], sizeof(pid_type) * vec.size());
|
||||
if (sz < 0)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return {};
|
||||
}
|
||||
vec.resize(sz);
|
||||
return vec;
|
||||
}
|
||||
|
||||
#elif (defined(__linux__) || defined(__ANDROID__))
|
||||
|
||||
std::vector<pid_type> all_pids(boost::system::error_code & ec)
|
||||
{
|
||||
std::vector<pid_type> vec;
|
||||
DIR *proc = opendir("/proc");
|
||||
if (!proc)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return vec;
|
||||
}
|
||||
struct dirent *ent = nullptr;
|
||||
while ((ent = readdir(proc)))
|
||||
{
|
||||
if (!isdigit(*ent->d_name))
|
||||
continue;
|
||||
vec.push_back(atoi(ent->d_name));
|
||||
}
|
||||
closedir(proc);
|
||||
return vec;
|
||||
}
|
||||
|
||||
pid_type parent_pid(pid_type pid, boost::system::error_code & ec)
|
||||
{
|
||||
pid_type ppid = static_cast<pid_type>(-1);
|
||||
char buffer[BUFSIZ];
|
||||
sprintf(buffer, "/proc/%d/stat", pid);
|
||||
FILE *stat = fopen(buffer, "r");
|
||||
if (!stat)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return ppid;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::size_t size = fread(buffer, sizeof(char), sizeof(buffer), stat);
|
||||
if (size > 0)
|
||||
{
|
||||
char *token = nullptr;
|
||||
if ((token = strtok(buffer, " ")))
|
||||
{
|
||||
if ((token = strtok(nullptr, " ")))
|
||||
{
|
||||
if ((token = strtok(nullptr, " ")))
|
||||
{
|
||||
if ((token = strtok(nullptr, " ")))
|
||||
{
|
||||
ppid = (pid_type)strtoul(token, nullptr, 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!token)
|
||||
{
|
||||
fclose(stat);
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return ppid;
|
||||
}
|
||||
}
|
||||
fclose(stat);
|
||||
}
|
||||
return ppid;
|
||||
}
|
||||
|
||||
std::vector<pid_type> child_pids(pid_type pid, boost::system::error_code & ec)
|
||||
{
|
||||
std::vector<pid_type> vec;
|
||||
std::vector<pid_type> pids = all_pids(ec);
|
||||
if (!pids.empty())
|
||||
vec.reserve(pids.size());
|
||||
for (std::size_t i = 0; i < pids.size(); i++)
|
||||
{
|
||||
pid_type ppid = parent_pid(pids[i], ec);
|
||||
if (ppid != -1 && ppid == pid)
|
||||
{
|
||||
vec.push_back(pids[i]);
|
||||
}
|
||||
}
|
||||
return vec;
|
||||
}
|
||||
|
||||
#elif defined(__FreeBSD__)
|
||||
|
||||
std::vector<pid_type> all_pids(boost::system::error_code & ec)
|
||||
{
|
||||
std::vector<pid_type> vec;
|
||||
int cntp = 0;
|
||||
kinfo_proc *proc_info = kinfo_getallproc(&cntp);
|
||||
if (proc_info)
|
||||
{
|
||||
vec.reserve(cntp);
|
||||
for (int i = 0; i < cntp; i++)
|
||||
vec.push_back(proc_info[i].ki_pid);
|
||||
free(proc_info);
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return vec;
|
||||
}
|
||||
|
||||
pid_type parent_pid(pid_type pid, boost::system::error_code & ec)
|
||||
{
|
||||
pid_type ppid = static_cast<pid_type>(-1);
|
||||
kinfo_proc *proc_info = kinfo_getproc(pid);
|
||||
if (proc_info)
|
||||
{
|
||||
ppid = proc_info->ki_ppid;
|
||||
free(proc_info);
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return ppid;
|
||||
}
|
||||
|
||||
std::vector<pid_type> child_pids(pid_type pid, boost::system::error_code & ec)
|
||||
{
|
||||
std::vector<pid_type> vec;
|
||||
int cntp = 0;
|
||||
kinfo_proc *proc_info = kinfo_getallproc(&cntp);
|
||||
if (proc_info)
|
||||
{
|
||||
vec.reserve(cntp);
|
||||
for (int i = 0; i < cntp; i++)
|
||||
{
|
||||
if (proc_info[i].ki_ppid == pid)
|
||||
{
|
||||
vec.push_back(proc_info[i].ki_pid);
|
||||
}
|
||||
}
|
||||
free(proc_info);
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return vec;
|
||||
}
|
||||
|
||||
#elif defined(__DragonFly__)
|
||||
|
||||
std::vector<pid_type> all_pids(boost::system::error_code & ec)
|
||||
{
|
||||
std::vector<pid_type> vec;
|
||||
int cntp = 0;
|
||||
kinfo_proc *proc_info = nullptr;
|
||||
const char *nlistf, *memf;
|
||||
nlistf = memf = "/dev/null";
|
||||
struct closer
|
||||
{
|
||||
void operator()(kvm_t * kd)
|
||||
{
|
||||
kvm_close(kd);
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<kvm_t, closer> kd{kvm_openfiles(nlistf, memf, nullptr, O_RDONLY, nullptr)};
|
||||
if (!kd)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return vec;
|
||||
}
|
||||
if ((proc_info = kvm_getprocs(kd.get(), KERN_PROC_ALL, 0, &cntp)))
|
||||
{
|
||||
vec.reserve(cntp);
|
||||
for (int i = 0; i < cntp; i++)
|
||||
if (proc_info[i].kp_pid >= 0)
|
||||
vec.push_back(proc_info[i].kp_pid);
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return vec;
|
||||
}
|
||||
|
||||
pid_type parent_pid(pid_type pid, boost::system::error_code & ec)
|
||||
{
|
||||
pid_type ppid = static_cast<pid_type>(-1);
|
||||
int cntp = 0;
|
||||
kinfo_proc *proc_info = nullptr;
|
||||
const char *nlistf, *memf;
|
||||
nlistf = memf = "/dev/null";
|
||||
struct closer
|
||||
{
|
||||
void operator()(kvm_t * kd)
|
||||
{
|
||||
kvm_close(kd);
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<kvm_t, closer> kd{kvm_openfiles(nlistf, memf, nullptr, O_RDONLY, nullptr)};
|
||||
if (!kd)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return ppid;
|
||||
}
|
||||
if ((proc_info = kvm_getprocs(kd.get(), KERN_PROC_PID, pid, &cntp)))
|
||||
{
|
||||
if (proc_info->kp_ppid >= 0)
|
||||
{
|
||||
ppid = proc_info->kp_ppid;
|
||||
}
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return ppid;
|
||||
}
|
||||
|
||||
std::vector<pid_type> child_pids(pid_type pid, boost::system::error_code & ec)
|
||||
{
|
||||
std::vector<pid_type> vec;
|
||||
int cntp = 0;
|
||||
kinfo_proc *proc_info = nullptr;
|
||||
const char *nlistf, *memf;
|
||||
nlistf = memf = "/dev/null";
|
||||
struct closer
|
||||
{
|
||||
void operator()(kvm_t * kd)
|
||||
{
|
||||
kvm_close(kd);
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<kvm_t, closer> kd{kvm_openfiles(nlistf, memf, nullptr, O_RDONLY, nullptr)};
|
||||
if (!kd)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return vec;
|
||||
}
|
||||
if ((proc_info = kvm_getprocs(kd.get(), KERN_PROC_ALL, 0, &cntp)))
|
||||
{
|
||||
vec.reserve(cntp);
|
||||
for (int i = 0; i < cntp; i++)
|
||||
{
|
||||
if (proc_info[i].kp_pid >= 0 && proc_info[i].kp_ppid >= 0 && proc_info[i].kp_ppid == pid)
|
||||
{
|
||||
vec.push_back(proc_info[i].kp_pid);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return vec;
|
||||
}
|
||||
|
||||
#elif defined(__NetBSD__)
|
||||
|
||||
std::vector<pid_type> all_pids(boost::system::error_code & ec)
|
||||
{
|
||||
std::vector<pid_type> vec;
|
||||
int cntp = 0;
|
||||
kinfo_proc2 *proc_info = nullptr;
|
||||
struct closer
|
||||
{
|
||||
void operator()(kvm_t * kd)
|
||||
{
|
||||
kvm_close(kd);
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<kvm_t, closer> kd{kvm_openfiles(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr)};
|
||||
if (!kd)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return vec;
|
||||
}
|
||||
if ((proc_info = kvm_getproc2(kd.get(), KERN_PROC_ALL, 0, sizeof(struct kinfo_proc2), &cntp)))
|
||||
{
|
||||
vec.reserve(cntp);
|
||||
for (int i = cntp - 1; i >= 0; i--)
|
||||
{
|
||||
vec.push_back(proc_info[i].p_pid);
|
||||
}
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return vec;
|
||||
}
|
||||
|
||||
pid_type parent_pid(pid_type pid, boost::system::error_code & ec)
|
||||
{
|
||||
pid_type ppid = static_cast<pid_type>(-1);
|
||||
int cntp = 0;
|
||||
kinfo_proc2 *proc_info = nullptr;
|
||||
struct closer
|
||||
{
|
||||
void operator()(kvm_t * kd)
|
||||
{
|
||||
kvm_close(kd);
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<kvm_t, closer> kd{kvm_openfiles(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr)};
|
||||
if (!kd)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return ppid;
|
||||
}
|
||||
if ((proc_info = kvm_getproc2(kd.get(), KERN_PROC_PID, pid, sizeof(struct kinfo_proc2), &cntp)))
|
||||
{
|
||||
ppid = proc_info->p_ppid;
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return ppid;
|
||||
}
|
||||
|
||||
std::vector<pid_type> child_pids(pid_type pid, boost::system::error_code & ec)
|
||||
{
|
||||
std::vector<pid_type> vec;
|
||||
int cntp = 0;
|
||||
kinfo_proc2 *proc_info = nullptr;
|
||||
struct closer
|
||||
{
|
||||
void operator()(kvm_t * kd)
|
||||
{
|
||||
kvm_close(kd);
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<kvm_t, closer> kd{kvm_openfiles(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr)};
|
||||
if (!kd)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return vec;
|
||||
}
|
||||
if ((proc_info = kvm_getproc2(kd.get(), KERN_PROC_ALL, 0, sizeof(struct kinfo_proc2), &cntp)))
|
||||
{
|
||||
vec.reserve(cntp);
|
||||
for (int i = cntp - 1; i >= 0; i--)
|
||||
{
|
||||
if (proc_info[i].p_ppid == pid)
|
||||
{
|
||||
vec.push_back(proc_info[i].p_pid);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return vec;
|
||||
}
|
||||
|
||||
#elif defined(__OpenBSD__)
|
||||
|
||||
std::vector<pid_type> all_pids(boost::system::error_code & ec)
|
||||
{
|
||||
std::vector<pid_type> vec;
|
||||
int cntp = 0;
|
||||
kinfo_proc *proc_info = nullptr;
|
||||
struct closer
|
||||
{
|
||||
void operator()(kvm_t * kd)
|
||||
{
|
||||
kvm_close(kd);
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<kvm_t, closer> kd{kvm_openfiles(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr)};
|
||||
if (!kd)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return vec;
|
||||
}
|
||||
if ((proc_info = kvm_getprocs(kd.get(), KERN_PROC_ALL, 0, sizeof(struct kinfo_proc), &cntp)))
|
||||
{
|
||||
vec.reserve(cntp);
|
||||
for (int i = cntp - 1; i >= 0; i--)
|
||||
{
|
||||
if (proc_info[i].kp_pid >= 0)
|
||||
{
|
||||
vec.push_back(proc_info[i].kp_pid);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return vec;
|
||||
}
|
||||
|
||||
pid_type parent_pid(pid_type pid, boost::system::error_code & ec)
|
||||
{
|
||||
pid_type ppid = static_cast<pid_type>(-1);
|
||||
int cntp = 0;
|
||||
kinfo_proc *proc_info = nullptr;
|
||||
struct closer
|
||||
{
|
||||
void operator()(kvm_t * kd)
|
||||
{
|
||||
kvm_close(kd);
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<kvm_t, closer> kd{kvm_openfiles(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr)};
|
||||
if (!kd)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return ppid;
|
||||
}
|
||||
if ((proc_info = kvm_getprocs(kd.get(), KERN_PROC_PID, pid, sizeof(struct kinfo_proc), &cntp)))
|
||||
{
|
||||
ppid = proc_info->p_ppid;
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return ppid;
|
||||
}
|
||||
|
||||
std::vector<pid_type> child_pids(pid_type pid, boost::system::error_code & ec)
|
||||
{
|
||||
std::vector<pid_type> vec;
|
||||
int cntp = 0;
|
||||
kinfo_proc *proc_info = nullptr;
|
||||
struct closer
|
||||
{
|
||||
void operator()(kvm_t * kd)
|
||||
{
|
||||
kvm_close(kd);
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<kvm_t, closer> kd{kvm_openfiles(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr)};
|
||||
if (!kd)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return vec;
|
||||
}
|
||||
if ((proc_info = kvm_getprocs(kd.get(), KERN_PROC_ALL, 0, sizeof(struct kinfo_proc), &cntp)))
|
||||
{
|
||||
vec.reserve(cntp);
|
||||
for (int i = cntp - 1; i >= 0; i--)
|
||||
{
|
||||
if (proc_info[i].p_ppid == pid)
|
||||
{
|
||||
vec.push_back(proc_info[i].p_pid);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return vec;
|
||||
}
|
||||
|
||||
|
||||
#elif defined(__sun)
|
||||
|
||||
std::vector<pid_type> all_pids(boost::system::error_code & ec)
|
||||
{
|
||||
std::vector<pid_type> vec;
|
||||
struct pid cur_pid;
|
||||
proc *proc_info = nullptr;
|
||||
struct closer
|
||||
{
|
||||
void operator()(kvm_t * kd)
|
||||
{
|
||||
kvm_close(kd);
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<kvm_t, closer> kd{kvm_open(nullptr, nullptr, nullptr, O_RDONLY, nullptr)};
|
||||
if (!kd)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return vec;
|
||||
}
|
||||
while ((proc_info = kvm_nextproc(kd)))
|
||||
{
|
||||
if (kvm_kread(kd, (std::uintptr_t)proc_info->p_pidp, &cur_pid, sizeof(cur_pid)) != -1)
|
||||
{
|
||||
vec.insert(vec.begin(), cur_pid.pid_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
break;
|
||||
}
|
||||
}
|
||||
return vec;
|
||||
}
|
||||
|
||||
pid_type parent_pid(pid_type pid, boost::system::error_code & ec)
|
||||
{
|
||||
pid_type ppid = static_cast<pid_type>(-1);
|
||||
proc *proc_info = nullptr;
|
||||
struct closer
|
||||
{
|
||||
void operator()(kvm_t * kd)
|
||||
{
|
||||
kvm_close(kd);
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<kvm_t, closer> kd{kvm_open(nullptr, nullptr, nullptr, O_RDONLY, nullptr)};
|
||||
if (!kd)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return ppid;
|
||||
}
|
||||
if ((proc_info = kvm_getproc(kd, pid)))
|
||||
{
|
||||
ppid = proc_info->p_ppid;
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return ppid;
|
||||
}
|
||||
|
||||
std::vector<pid_type> child_pids(pid_type pid, boost::system::error_code & ec)
|
||||
{
|
||||
std::vector<pid_type> vec;
|
||||
struct pid cur_pid;
|
||||
proc *proc_info = nullptr;
|
||||
struct closer
|
||||
{
|
||||
void operator()(kvm_t * kd)
|
||||
{
|
||||
kvm_close(kd);
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<kvm_t, closer> kd{kvm_open(nullptr, nullptr, nullptr, O_RDONLY, nullptr);
|
||||
if (!kd)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return vec;
|
||||
}
|
||||
while ((proc_info = kvm_nextproc(kd)))
|
||||
{
|
||||
if (proc_info->p_ppid == pid)
|
||||
{
|
||||
if (kvm_kread(kd, (std::uintptr_t)proc_info->p_pidp, &cur_pid, sizeof(cur_pid)) != -1)
|
||||
{
|
||||
vec.insert(vec.begin(), cur_pid.pid_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return vec;
|
||||
}
|
||||
|
||||
#else
|
||||
#error "Platform not supported"
|
||||
#endif
|
||||
|
||||
std::vector<pid_type> all_pids()
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
auto res = all_pids(ec);
|
||||
if (ec)
|
||||
detail::throw_error(ec, "all_pids");
|
||||
return res;
|
||||
}
|
||||
|
||||
pid_type parent_pid(pid_type pid)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
auto res = parent_pid(pid, ec);
|
||||
if (ec)
|
||||
detail::throw_error(ec, "parent_pid");
|
||||
return res;
|
||||
}
|
||||
|
||||
std::vector<pid_type> child_pids(pid_type pid)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
auto res = child_pids(pid, ec);
|
||||
if (ec)
|
||||
detail::throw_error(ec, "child_pids");
|
||||
return res;
|
||||
}
|
||||
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#endif // BOOST_PROCESS_V2_IMPL_PID_IPP
|
||||
|
||||
17
linx64/include/boost/process/v2/impl/process_handle.ipp
Normal file
17
linx64/include/boost/process/v2/impl/process_handle.ipp
Normal file
@@ -0,0 +1,17 @@
|
||||
// Copyright (c) 2022 Klemens D. Morgenstern
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_PROCESS_V2_IMPL_PROCESS_HANDLE_IPP
|
||||
#define BOOST_PROCESS_V2_IMPL_PROCESS_HANDLE_IPP
|
||||
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
#include <boost/process/v2/detail/impl/process_handle_windows.ipp>
|
||||
#else
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#endif //BOOST_PROCESS_V2_IMPL_PROCESS_HANDLE_IPP
|
||||
137
linx64/include/boost/process/v2/impl/shell.ipp
Normal file
137
linx64/include/boost/process/v2/impl/shell.ipp
Normal file
@@ -0,0 +1,137 @@
|
||||
// Copyright (c) 2022 Klemens D. Morgenstern
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_PROCESS_V2_IMPL_SHELL_IPP
|
||||
#define BOOST_PROCESS_V2_IMPL_SHELL_IPP
|
||||
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
#include <boost/process/v2/detail/last_error.hpp>
|
||||
#include <boost/process/v2/detail/throw_error.hpp>
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
#include <boost/process/v2/error.hpp>
|
||||
#include <boost/process/v2/shell.hpp>
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
#include <shellapi.h>
|
||||
#else
|
||||
#include <wordexp.h>
|
||||
#endif
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
BOOST_PROCESS_V2_DECL const error_category& get_shell_category()
|
||||
{
|
||||
return system_category();
|
||||
}
|
||||
#else
|
||||
|
||||
struct shell_category_t final : public error_category
|
||||
{
|
||||
shell_category_t() : error_category(0xDAF1u) {}
|
||||
|
||||
const char* name() const noexcept
|
||||
{
|
||||
return "process.v2.utf8";
|
||||
}
|
||||
std::string message(int value) const
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case WRDE_BADCHAR:
|
||||
return "Illegal occurrence of newline or one of |, &, ;, <, >, (, ), {, }.";
|
||||
case WRDE_BADVAL:
|
||||
return "An undefined shell variable was referenced, and the WRDE_UNDEF flag told us to consider this an error.";
|
||||
case WRDE_CMDSUB:
|
||||
return "Command substitution occurred, and the WRDE_NOCMD flag told us to consider this an error.";
|
||||
case WRDE_NOSPACE:
|
||||
return "Out of memory.";
|
||||
case WRDE_SYNTAX:
|
||||
return "Shell syntax error, such as unbalanced parentheses or unmatched quotes.";
|
||||
default:
|
||||
return "process.v2.wordexp error";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
BOOST_PROCESS_V2_DECL const error_category& get_shell_category()
|
||||
{
|
||||
static shell_category_t instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined (BOOST_PROCESS_V2_WINDOWS)
|
||||
|
||||
void shell::parse_()
|
||||
{
|
||||
argv_ = ::CommandLineToArgvW(input_.c_str(), &argc_);
|
||||
if (argv_ == nullptr)
|
||||
{
|
||||
error_code ec;
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
throw system_error(ec, "shell::parse");
|
||||
}
|
||||
}
|
||||
|
||||
shell::~shell()
|
||||
{
|
||||
if (argv_ != nullptr)
|
||||
LocalFree(argv_);
|
||||
}
|
||||
|
||||
auto shell::args() const-> args_type
|
||||
{
|
||||
return input_.c_str();
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void shell::parse_()
|
||||
{
|
||||
wordexp_t we{};
|
||||
auto cd = wordexp(input_.c_str(), &we, WRDE_NOCMD);
|
||||
|
||||
if (cd != 0)
|
||||
detail::throw_error(error_code(cd, get_shell_category()), "shell::parse");
|
||||
else
|
||||
{
|
||||
argc_ = static_cast<int>(we.we_wordc);
|
||||
argv_ = we.we_wordv;
|
||||
}
|
||||
|
||||
free_argv_ = +[](int argc, char ** argv)
|
||||
{
|
||||
wordexp_t we{
|
||||
.we_wordc = static_cast<std::size_t>(argc),
|
||||
.we_wordv = argv,
|
||||
.we_offs = 0
|
||||
};
|
||||
wordfree(&we);
|
||||
};
|
||||
}
|
||||
|
||||
shell::~shell()
|
||||
{
|
||||
if (argv_ != nullptr && free_argv_ != nullptr)
|
||||
free_argv_(argc_, argv_);
|
||||
}
|
||||
|
||||
auto shell::args() const -> args_type
|
||||
{
|
||||
if (argc() == 0)
|
||||
{
|
||||
static const char * helper = nullptr;
|
||||
return &helper;
|
||||
}
|
||||
else
|
||||
return const_cast<const char**>(argv());
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#endif //BOOST_PROCESS_V2_IMPL_SHELL_IPP
|
||||
66
linx64/include/boost/process/v2/pid.hpp
Normal file
66
linx64/include/boost/process/v2/pid.hpp
Normal file
@@ -0,0 +1,66 @@
|
||||
// Copyright (c) 2022 Klemens D. Morgenstern
|
||||
// Copyright (c) 2022 Samuel Venable
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_PROCESS_V2_PID_HPP
|
||||
#define BOOST_PROCESS_V2_PID_HPP
|
||||
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
#include <boost/process/v2/detail/throw_error.hpp>
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
|
||||
#if defined(GENERATING_DOCUMENTATION)
|
||||
|
||||
//An integral type representing a process id.
|
||||
typedef implementation_defined pid_type;
|
||||
|
||||
#else
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
|
||||
typedef unsigned long pid_type;
|
||||
|
||||
#else
|
||||
|
||||
typedef int pid_type;
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if (defined(BOOST_PROCESS_V2_WINDOWS) || defined(__FreeBSD__) || defined(__DragonFly__) || defined(__NetBSD__) || defined(__sun))
|
||||
constexpr static pid_type root_pid = 0;
|
||||
#elif (defined(__APPLE__) && defined(__MACH__) || defined(__linux__) || defined(__ANDROID__) || defined(__OpenBSD__))
|
||||
constexpr static pid_type root_pid = 1;
|
||||
#endif
|
||||
|
||||
/// Get the process id of the current process.
|
||||
BOOST_PROCESS_V2_DECL pid_type current_pid();
|
||||
|
||||
/// List all available pids.
|
||||
BOOST_PROCESS_V2_DECL std::vector<pid_type> all_pids(boost::system::error_code & ec);
|
||||
|
||||
/// List all available pids.
|
||||
BOOST_PROCESS_V2_DECL std::vector<pid_type> all_pids();
|
||||
|
||||
// return parent pid of pid.
|
||||
BOOST_PROCESS_V2_DECL pid_type parent_pid(pid_type pid, boost::system::error_code & ec);
|
||||
|
||||
// return parent pid of pid.
|
||||
BOOST_PROCESS_V2_DECL pid_type parent_pid(pid_type pid);
|
||||
|
||||
// return child pids of pid.
|
||||
BOOST_PROCESS_V2_DECL std::vector<pid_type> child_pids(pid_type pid, boost::system::error_code & ec);
|
||||
|
||||
// return child pids of pid.
|
||||
BOOST_PROCESS_V2_DECL std::vector<pid_type> child_pids(pid_type pid);
|
||||
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_HEADER_ONLY)
|
||||
#include <boost/process/v2/impl/pid.ipp>
|
||||
#endif
|
||||
|
||||
#endif // BOOST_PROCESS_V2_PID_HPP
|
||||
|
||||
478
linx64/include/boost/process/v2/popen.hpp
Normal file
478
linx64/include/boost/process/v2/popen.hpp
Normal file
@@ -0,0 +1,478 @@
|
||||
// Copyright (c) 2022 Klemens D. Morgenstern
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_PROCESS_V2_POPEN_HPP
|
||||
#define BOOST_PROCESS_V2_POPEN_HPP
|
||||
|
||||
#include <boost/process/v2/process.hpp>
|
||||
#include <boost/process/v2/stdio.hpp>
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_STANDALONE)
|
||||
#include <asio/connect_pipe.hpp>
|
||||
#include <asio/readable_pipe.hpp>
|
||||
#include <asio/writable_pipe.hpp>
|
||||
#else
|
||||
#include <boost/asio/connect_pipe.hpp>
|
||||
#include <boost/asio/readable_pipe.hpp>
|
||||
#include <boost/asio/writable_pipe.hpp>
|
||||
#endif
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
|
||||
/// A subprocess with automatically assigned pipes.
|
||||
/** The purpose os the popen is to provide a convenient way
|
||||
* to use the stdin & stdout of a process.
|
||||
*
|
||||
* @code {.cpp}
|
||||
* popen proc(executor, find_executable("addr2line"), {argv[0]});
|
||||
* asio::write(proc, asio::buffer("main\n"));
|
||||
* std::string line;
|
||||
* asio::read_until(proc, asio::dynamic_buffer(line), '\n');
|
||||
* @endcode
|
||||
*
|
||||
*
|
||||
* Popen can be used as a stream object in other protocols.
|
||||
*/
|
||||
template<typename Executor = BOOST_PROCESS_V2_ASIO_NAMESPACE::any_io_executor>
|
||||
struct basic_popen : basic_process<Executor>
|
||||
{
|
||||
/// The executor of the process
|
||||
using executor_type = Executor;
|
||||
|
||||
/// Rebinds the popen type to another executor.
|
||||
template <typename Executor1>
|
||||
struct rebind_executor
|
||||
{
|
||||
/// The pipe type when rebound to the specified executor.
|
||||
typedef basic_popen<Executor1> other;
|
||||
};
|
||||
|
||||
/// Move construct a popen
|
||||
basic_popen(basic_popen &&) = default;
|
||||
/// Move assign a popen
|
||||
basic_popen& operator=(basic_popen &&) = default;
|
||||
|
||||
/// Move construct a popen and change the executor type.
|
||||
template<typename Executor1>
|
||||
basic_popen(basic_popen<Executor1>&& lhs)
|
||||
: basic_process<Executor>(std::move(lhs)),
|
||||
stdin_(std::move(lhs.stdin_)), stdout_(std::move(lhs.stdout_))
|
||||
{
|
||||
}
|
||||
|
||||
/// Create a closed process handle
|
||||
explicit basic_popen(executor_type exec) : basic_process<Executor>{std::move(exec)} {}
|
||||
|
||||
/// Create a closed process handle
|
||||
template <typename ExecutionContext>
|
||||
explicit basic_popen(ExecutionContext & context,
|
||||
typename std::enable_if<
|
||||
is_convertible<ExecutionContext&,
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context&>::value, void *>::type = nullptr)
|
||||
: basic_process<Executor>{context}
|
||||
{
|
||||
}
|
||||
|
||||
/// Construct a child from a property list and launch it using the default process launcher.
|
||||
template<typename ... Inits>
|
||||
explicit basic_popen(
|
||||
executor_type executor,
|
||||
const filesystem::path& exe,
|
||||
std::initializer_list<string_view> args,
|
||||
Inits&&... inits)
|
||||
: basic_process<Executor>(executor)
|
||||
{
|
||||
this->basic_process<Executor>::operator=(
|
||||
default_process_launcher()(
|
||||
this->get_executor(), exe, args,
|
||||
std::forward<Inits>(inits)...,
|
||||
process_stdio{stdin_, stdout_}
|
||||
));
|
||||
}
|
||||
|
||||
/// Construct a child from a property list and launch it using the default process launcher.
|
||||
template<typename Launcher, typename ... Inits>
|
||||
explicit basic_popen(
|
||||
Launcher && launcher,
|
||||
executor_type executor,
|
||||
const filesystem::path& exe,
|
||||
std::initializer_list<string_view> args,
|
||||
Inits&&... inits)
|
||||
: basic_process<Executor>(executor)
|
||||
{
|
||||
this->basic_process<Executor>::operator=(
|
||||
std::forward<Launcher>(launcher)(
|
||||
this->get_executor(), exe, args,
|
||||
std::forward<Inits>(inits)...,
|
||||
process_stdio{stdin_, stdout_}
|
||||
));
|
||||
}
|
||||
|
||||
/// Construct a child from a property list and launch it using the default process launcher.
|
||||
template<typename Args, typename ... Inits>
|
||||
explicit basic_popen(
|
||||
executor_type executor,
|
||||
const filesystem::path& exe,
|
||||
Args&& args, Inits&&... inits)
|
||||
: basic_process<Executor>(executor)
|
||||
{
|
||||
this->basic_process<Executor>::operator=(
|
||||
default_process_launcher()(
|
||||
std::move(executor), exe, args,
|
||||
std::forward<Inits>(inits)...,
|
||||
process_stdio{stdin_, stdout_}
|
||||
));
|
||||
}
|
||||
|
||||
/// Construct a child from a property list and launch it using the default process launcher.
|
||||
template<typename Launcher, typename Args, typename ... Inits>
|
||||
explicit basic_popen(
|
||||
Launcher && launcher,
|
||||
executor_type executor,
|
||||
const filesystem::path& exe,
|
||||
Args&& args, Inits&&... inits)
|
||||
: basic_process<Executor>(executor)
|
||||
{
|
||||
this->basic_process<Executor>::operator=(
|
||||
std::forward<Launcher>(launcher)(
|
||||
std::move(executor), exe, args,
|
||||
std::forward<Inits>(inits)...,
|
||||
process_stdio{stdin_, stdout_}
|
||||
));
|
||||
}
|
||||
|
||||
/// Construct a child from a property list and launch it using the default process launcher.
|
||||
template<typename ExecutionContext, typename ... Inits>
|
||||
explicit basic_popen(
|
||||
ExecutionContext & context,
|
||||
typename std::enable_if<
|
||||
std::is_convertible<ExecutionContext&,
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context&>::value,
|
||||
const filesystem::path&>::type exe,
|
||||
std::initializer_list<string_view> args,
|
||||
Inits&&... inits)
|
||||
: basic_process<Executor>(context)
|
||||
{
|
||||
this->basic_process<Executor>::operator=(
|
||||
default_process_launcher()(
|
||||
this->get_executor(), exe, args,
|
||||
std::forward<Inits>(inits)...,
|
||||
process_stdio{stdin_, stdout_}
|
||||
));
|
||||
}
|
||||
|
||||
/// Construct a child from a property list and launch it using the default process launcher.
|
||||
template<typename Launcher, typename ExecutionContext, typename ... Inits>
|
||||
explicit basic_popen(
|
||||
Launcher && launcher,
|
||||
ExecutionContext & context,
|
||||
typename std::enable_if<
|
||||
std::is_convertible<ExecutionContext&,
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context&>::value,
|
||||
const filesystem::path&>::type exe,
|
||||
std::initializer_list<string_view> args,
|
||||
Inits&&... inits)
|
||||
: basic_process<Executor>(context)
|
||||
{
|
||||
this->basic_process<Executor>::operator=(
|
||||
std::forward<Launcher>(launcher)(
|
||||
this->get_executor(), exe, args,
|
||||
std::forward<Inits>(inits)...,
|
||||
process_stdio{stdin_, stdout_}
|
||||
));
|
||||
}
|
||||
|
||||
/// Construct a child from a property list and launch it using the default process launcher.
|
||||
template<typename ExecutionContext, typename Args, typename ... Inits>
|
||||
explicit basic_popen(
|
||||
ExecutionContext & context,
|
||||
typename std::enable_if<
|
||||
std::is_convertible<ExecutionContext&,
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context&>::value,
|
||||
const filesystem::path&>::type exe,
|
||||
Args&& args, Inits&&... inits)
|
||||
: basic_process<Executor>(context)
|
||||
{
|
||||
this->basic_process<Executor>::operator=(
|
||||
default_process_launcher()(
|
||||
this->get_executor(), exe, args,
|
||||
std::forward<Inits>(inits)...,
|
||||
process_stdio{stdin_, stdout_}
|
||||
));
|
||||
}
|
||||
|
||||
/// Construct a child from a property list and launch it using the default process launcher.
|
||||
template<typename Launcher, typename ExecutionContext, typename Args, typename ... Inits>
|
||||
explicit basic_popen(
|
||||
Launcher && launcher,
|
||||
ExecutionContext & context,
|
||||
typename std::enable_if<
|
||||
std::is_convertible<ExecutionContext&,
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context&>::value,
|
||||
const filesystem::path&>::type exe,
|
||||
Args&& args, Inits&&... inits)
|
||||
: basic_process<Executor>(context)
|
||||
{
|
||||
this->basic_process<Executor>::operator=(
|
||||
std::forward<Launcher>(launcher)(
|
||||
this->get_executor(), exe, args,
|
||||
std::forward<Inits>(inits)...,
|
||||
process_stdio{stdin_, stdout_}
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
/// The type used for stdin on the parent process side.
|
||||
using stdin_type = BOOST_PROCESS_V2_ASIO_NAMESPACE::basic_writable_pipe<Executor>;
|
||||
/// The type used for stdout on the parent process side.
|
||||
using stdout_type = BOOST_PROCESS_V2_ASIO_NAMESPACE::basic_readable_pipe<Executor>;
|
||||
|
||||
/// Get the stdin pipe.
|
||||
stdin_type & get_stdin() {return stdin_; }
|
||||
/// Get the stdout pipe.
|
||||
stdout_type & get_stdout() {return stdout_; }
|
||||
|
||||
/// Get the stdin pipe.
|
||||
const stdin_type & get_stdin() const {return stdin_; }
|
||||
/// Get the stdout pipe.
|
||||
const stdout_type & get_stdout() const {return stdout_; }
|
||||
|
||||
/// Write some data to the pipe.
|
||||
/**
|
||||
* This function is used to write data to the pipe. The function call will
|
||||
* block until one or more bytes of the data has been written successfully,
|
||||
* or until an error occurs.
|
||||
*
|
||||
* @param buffers One or more data buffers to be written to the pipe.
|
||||
*
|
||||
* @returns The number of bytes written.
|
||||
*
|
||||
* @throws boost::system::system_error Thrown on failure. An error code of
|
||||
* boost::asio::error::eof indicates that the connection was closed by the
|
||||
* subprocess.
|
||||
*
|
||||
* @note The write_some operation may not transmit all of the data to the
|
||||
* peer. Consider using the @ref write function if you need to ensure that
|
||||
* all data is written before the blocking operation completes.
|
||||
*
|
||||
* @par Example
|
||||
* To write a single data buffer use the @ref buffer function as follows:
|
||||
* @code
|
||||
* pipe.write_some(boost::asio::buffer(data, size));
|
||||
* @endcode
|
||||
* See the @ref buffer documentation for information on writing multiple
|
||||
* buffers in one go, and how to use it with arrays, boost::array or
|
||||
* std::vector.
|
||||
*/
|
||||
template <typename ConstBufferSequence>
|
||||
std::size_t write_some(const ConstBufferSequence& buffers)
|
||||
{
|
||||
return stdin_.write_some(buffers);
|
||||
}
|
||||
|
||||
/// Write some data to the pipe.
|
||||
/**
|
||||
* This function is used to write data to the pipe. The function call will
|
||||
* block until one or more bytes of the data has been written successfully,
|
||||
* or until an error occurs.
|
||||
*
|
||||
* @param buffers One or more data buffers to be written to the pipe.
|
||||
*
|
||||
* @param ec Set to indicate what error occurred, if any.
|
||||
*
|
||||
* @returns The number of bytes written. Returns 0 if an error occurred.
|
||||
*
|
||||
* @note The write_some operation may not transmit all of the data to the
|
||||
* subprocess. Consider using the @ref write function if you need to ensure that
|
||||
* all data is written before the blocking operation completes.
|
||||
*/
|
||||
template <typename ConstBufferSequence>
|
||||
std::size_t write_some(const ConstBufferSequence& buffers,
|
||||
boost::system::error_code& ec)
|
||||
{
|
||||
return stdin_.write_some(buffers, ec);
|
||||
}
|
||||
|
||||
/// Start an asynchronous write.
|
||||
/**
|
||||
* This function is used to asynchronously write data to the pipe. It is an
|
||||
* initiating function for an @ref asynchronous_operation, and always returns
|
||||
* immediately.
|
||||
*
|
||||
* @param buffers One or more data buffers to be written to the pipe.
|
||||
* Although the buffers object may be copied as necessary, ownership of the
|
||||
* underlying memory blocks is retained by the caller, which must guarantee
|
||||
* that they remain valid until the completion handler is called.
|
||||
*
|
||||
* @param token The @ref completion_token that will be used to produce a
|
||||
* completion handler, which will be called when the write completes.
|
||||
* Potential completion tokens include @ref use_future, @ref use_awaitable,
|
||||
* @ref yield_context, or a function object with the correct completion
|
||||
* signature. The function signature of the completion handler must be:
|
||||
* @code void handler(
|
||||
* const boost::system::error_code& error, // Result of operation.
|
||||
* std::size_t bytes_transferred // Number of bytes written.
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the completion handler will not be invoked from within this function.
|
||||
* On immediate completion, invocation of the handler will be performed in a
|
||||
* manner equivalent to using boost::asio::post().
|
||||
*
|
||||
* @par Completion Signature
|
||||
* @code void(boost::system::error_code, std::size_t) @endcode
|
||||
*
|
||||
* @note The write operation may not transmit all of the data to the peer.
|
||||
* Consider using the @ref async_write function if you need to ensure that all
|
||||
* data is written before the asynchronous operation completes.
|
||||
*
|
||||
* @par Example
|
||||
* To write a single data buffer use the @ref buffer function as follows:
|
||||
* @code
|
||||
* popen.async_write_some(boost::asio::buffer(data, size), handler);
|
||||
* @endcode
|
||||
* See the @ref buffer documentation for information on writing multiple
|
||||
* buffers in one go, and how to use it with arrays, boost::array or
|
||||
* std::vector.
|
||||
*/
|
||||
template <typename ConstBufferSequence,
|
||||
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
|
||||
std::size_t)) WriteToken
|
||||
BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
|
||||
BOOST_PROCESS_V2_INITFN_AUTO_RESULT_TYPE(WriteToken,
|
||||
void (boost::system::error_code, std::size_t))
|
||||
async_write_some(const ConstBufferSequence& buffers,
|
||||
BOOST_ASIO_MOVE_ARG(WriteToken) token
|
||||
BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
|
||||
{
|
||||
return stdin_.async_write_some(buffers, std::forward<WriteToken>(token));
|
||||
}
|
||||
|
||||
|
||||
/// Read some data from the pipe.
|
||||
/**
|
||||
* This function is used to read data from the pipe. The function call will
|
||||
* block until one or more bytes of data has been read successfully, or until
|
||||
* an error occurs.
|
||||
*
|
||||
* @param buffers One or more buffers into which the data will be read.
|
||||
*
|
||||
* @returns The number of bytes read.
|
||||
*
|
||||
* @throws boost::system::system_error Thrown on failure. An error code of
|
||||
* boost::asio::error::eof indicates that the connection was closed by the
|
||||
* peer.
|
||||
*
|
||||
* @note The read_some operation may not read all of the requested number of
|
||||
* bytes. Consider using the @ref read function if you need to ensure that
|
||||
* the requested amount of data is read before the blocking operation
|
||||
* completes.
|
||||
*
|
||||
* @par Example
|
||||
* To read into a single data buffer use the @ref buffer function as follows:
|
||||
* @code
|
||||
* basic_readable_pipe.read_some(boost::asio::buffer(data, size));
|
||||
* @endcode
|
||||
* See the @ref buffer documentation for information on reading into multiple
|
||||
* buffers in one go, and how to use it with arrays, boost::array or
|
||||
* std::vector.
|
||||
*/
|
||||
template <typename MutableBufferSequence>
|
||||
std::size_t read_some(const MutableBufferSequence& buffers)
|
||||
{
|
||||
return stdout_.read_some(buffers);
|
||||
}
|
||||
|
||||
/// Read some data from the pipe.
|
||||
/**
|
||||
* This function is used to read data from the pipe. The function call will
|
||||
* block until one or more bytes of data has been read successfully, or until
|
||||
* an error occurs.
|
||||
*
|
||||
* @param buffers One or more buffers into which the data will be read.
|
||||
*
|
||||
* @param ec Set to indicate what error occurred, if any.
|
||||
*
|
||||
* @returns The number of bytes read. Returns 0 if an error occurred.
|
||||
*
|
||||
* @note The read_some operation may not read all of the requested number of
|
||||
* bytes. Consider using the @ref read function if you need to ensure that
|
||||
* the requested amount of data is read before the blocking operation
|
||||
* completes.
|
||||
*/
|
||||
template <typename MutableBufferSequence>
|
||||
std::size_t read_some(const MutableBufferSequence& buffers,
|
||||
boost::system::error_code& ec)
|
||||
{
|
||||
return stdout_.read_some(buffers, ec);
|
||||
}
|
||||
|
||||
/// Start an asynchronous read.
|
||||
/**
|
||||
* This function is used to asynchronously read data from the pipe. It is an
|
||||
* initiating function for an @ref asynchronous_operation, and always returns
|
||||
* immediately.
|
||||
*
|
||||
* @param buffers One or more buffers into which the data will be read.
|
||||
* Although the buffers object may be copied as necessary, ownership of the
|
||||
* underlying memory blocks is retained by the caller, which must guarantee
|
||||
* that they remain valid until the completion handler is called.
|
||||
*
|
||||
* @param token The @ref completion_token that will be used to produce a
|
||||
* completion handler, which will be called when the read completes.
|
||||
* Potential completion tokens include @ref use_future, @ref use_awaitable,
|
||||
* @ref yield_context, or a function object with the correct completion
|
||||
* signature. The function signature of the completion handler must be:
|
||||
* @code void handler(
|
||||
* const boost::system::error_code& error, // Result of operation.
|
||||
* std::size_t bytes_transferred // Number of bytes read.
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the completion handler will not be invoked from within this function.
|
||||
* On immediate completion, invocation of the handler will be performed in a
|
||||
* manner equivalent to using boost::asio::post().
|
||||
*
|
||||
* @par Completion Signature
|
||||
* @code void(boost::system::error_code, std::size_t) @endcode
|
||||
*
|
||||
* @note The read operation may not read all of the requested number of bytes.
|
||||
* Consider using the @ref async_read function if you need to ensure that the
|
||||
* requested amount of data is read before the asynchronous operation
|
||||
* completes.
|
||||
*
|
||||
* @par Example
|
||||
* To read into a single data buffer use the @ref buffer function as follows:
|
||||
* @code
|
||||
* basic_readable_pipe.async_read_some(
|
||||
* boost::asio::buffer(data, size), handler);
|
||||
* @endcode
|
||||
* See the @ref buffer documentation for information on reading into multiple
|
||||
* buffers in one go, and how to use it with arrays, boost::array or
|
||||
* std::vector.
|
||||
*/
|
||||
template <typename MutableBufferSequence,
|
||||
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
|
||||
std::size_t)) ReadToken
|
||||
BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
|
||||
BOOST_PROCESS_V2_INITFN_AUTO_RESULT_TYPE(ReadToken,
|
||||
void (boost::system::error_code, std::size_t))
|
||||
async_read_some(const MutableBufferSequence& buffers,
|
||||
BOOST_ASIO_MOVE_ARG(ReadToken) token
|
||||
BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
|
||||
{
|
||||
return stdout_.async_read_some(buffers, std::forward<ReadToken>(token));
|
||||
}
|
||||
|
||||
|
||||
|
||||
private:
|
||||
stdin_type stdin_ {basic_process<Executor>::get_executor()};
|
||||
stdout_type stdout_{basic_process<Executor>::get_executor()};
|
||||
};
|
||||
|
||||
/// A popen object with the default executor.
|
||||
using popen = basic_popen<>;
|
||||
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#endif //BOOST_PROCESS_V2_POPEN_HPP
|
||||
113
linx64/include/boost/process/v2/posix/bind_fd.hpp
Normal file
113
linx64/include/boost/process/v2/posix/bind_fd.hpp
Normal file
@@ -0,0 +1,113 @@
|
||||
// Copyright (c) 2022 Klemens D. Morgenstern
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_PROCESS_V2_POSIX_BIND_FD_HPP
|
||||
#define BOOST_PROCESS_V2_POSIX_BIND_FD_HPP
|
||||
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
#include <boost/process/v2/default_launcher.hpp>
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
|
||||
namespace posix
|
||||
{
|
||||
|
||||
/// Utility class to bind a file descriptor to an explicit file descriptor for the child process.
|
||||
struct bind_fd
|
||||
{
|
||||
int target;
|
||||
int fd;
|
||||
bool fd_needs_closing{false};
|
||||
|
||||
~bind_fd()
|
||||
{
|
||||
if (fd_needs_closing)
|
||||
::close(fd);
|
||||
}
|
||||
|
||||
bind_fd() = delete;
|
||||
/// Inherit file descriptor with the same value.
|
||||
/**
|
||||
* This will pass descriptor 42 as 42 to the child process:
|
||||
* @code
|
||||
* process p{"test", {}, posix::bind_fd(42)};
|
||||
* @endcode
|
||||
*/
|
||||
bind_fd(int target) : target(target), fd(target) {}
|
||||
|
||||
/// Inherit an asio io-object as a given file descriptor to the child process.
|
||||
/**
|
||||
* This will pass the tcp::socket, as 42 to the child process:
|
||||
* @code
|
||||
* extern tcp::socket sock;
|
||||
* process p{"test", {}, posix::bind_fd(42, sock)};
|
||||
* @endcode
|
||||
*/
|
||||
|
||||
template<typename Stream>
|
||||
bind_fd(int target, Stream && str, decltype(std::declval<Stream>().native_handle()) = -1)
|
||||
: bind_fd(target, str.native_handle())
|
||||
{}
|
||||
|
||||
/// Inherit a `FILE` as a given file descriptor to the child process.
|
||||
/**
|
||||
* This will pass the given `FILE*`, as 42 to the child process:
|
||||
* @code
|
||||
* process p{"test", {}, posix::bind_fd(42, stderr)};
|
||||
* @endcode
|
||||
*/
|
||||
bind_fd(int target, FILE * f) : bind_fd(target, fileno(f)) {}
|
||||
|
||||
/// Inherit a file descriptor with as a different value.
|
||||
/**
|
||||
* This will pass 24 as 42 to the child process:
|
||||
* @code
|
||||
* process p{"test", {}, posix::bind_fd(42, 24)};
|
||||
* @endcode
|
||||
*/
|
||||
bind_fd(int target, int fd) : target(target), fd(fd) {}
|
||||
|
||||
/// Inherit a null device as a set descriptor.
|
||||
/**
|
||||
* This will pass 24 as 42 to the child process:
|
||||
* @code
|
||||
* process p{"test", {}, posix::bind_fd(42, nullptr)};
|
||||
* @endcode
|
||||
*/
|
||||
bind_fd(int target, std::nullptr_t) : bind_fd(target, filesystem::path("/dev/null")) {}
|
||||
|
||||
/// Inherit a newly opened-file as a set descriptor.
|
||||
/**
|
||||
* This will pass 24 as 42 to the child process:
|
||||
* @code
|
||||
* process p{"test", {}, posix::bind_fd(42, "extra-output.txt")};
|
||||
* @endcode
|
||||
*/
|
||||
bind_fd(int target, const filesystem::path & pth, int flags = O_RDWR | O_CREAT)
|
||||
: target(target), fd(::open(pth.c_str(), flags, 0660)), fd_needs_closing(true)
|
||||
{
|
||||
}
|
||||
|
||||
error_code on_setup(posix::default_launcher & launcher, const filesystem::path &, const char * const *)
|
||||
{
|
||||
launcher.fd_whitelist.push_back(target);
|
||||
return {};
|
||||
}
|
||||
|
||||
/// Implementation of the initialization function.
|
||||
error_code on_exec_setup(posix::default_launcher & launcher, const filesystem::path &, const char * const *)
|
||||
{
|
||||
if (::dup2(fd, target) == -1)
|
||||
return error_code(errno, system_category());
|
||||
return error_code ();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#endif //BOOST_PROCESS_V2_POSIX_BIND_FD_HPP
|
||||
524
linx64/include/boost/process/v2/posix/default_launcher.hpp
Normal file
524
linx64/include/boost/process/v2/posix/default_launcher.hpp
Normal file
@@ -0,0 +1,524 @@
|
||||
// Copyright (c) 2022 Klemens D. Morgenstern
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_PROCESS_V2_POSIX_DEFAULT_LAUNCHER
|
||||
#define BOOST_PROCESS_V2_POSIX_DEFAULT_LAUNCHER
|
||||
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
#include <boost/process/v2/cstring_ref.hpp>
|
||||
#include <boost/process/v2/posix/detail/close_handles.hpp>
|
||||
#include <boost/process/v2/detail/throw_error.hpp>
|
||||
#include <boost/process/v2/detail/utf8.hpp>
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_STANDALONE)
|
||||
#include <asio/execution/executor.hpp>
|
||||
#include <asio/is_executor.hpp>
|
||||
#include <asio/execution_context.hpp>
|
||||
#include <asio/execution/context.hpp>
|
||||
#include <asio/query.hpp>
|
||||
#else
|
||||
#include <boost/asio/execution/executor.hpp>
|
||||
#include <boost/asio/is_executor.hpp>
|
||||
#include <boost/asio/execution_context.hpp>
|
||||
#include <boost/asio/execution/context.hpp>
|
||||
#include <boost/asio/query.hpp>
|
||||
#endif
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__APPLE__) || defined(__MACH__)
|
||||
extern "C" { extern char **environ; }
|
||||
#endif
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
|
||||
template<typename Executor>
|
||||
struct basic_process;
|
||||
|
||||
namespace posix
|
||||
{
|
||||
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
struct base {};
|
||||
struct derived : base {};
|
||||
|
||||
template<typename Launcher, typename Init>
|
||||
inline error_code invoke_on_setup(Launcher & launcher, const filesystem::path &executable,
|
||||
const char * const * (&cmd_line),
|
||||
Init && init, base && )
|
||||
{
|
||||
return error_code{};
|
||||
}
|
||||
|
||||
template<typename Launcher, typename Init>
|
||||
inline auto invoke_on_setup(Launcher & launcher, const filesystem::path &executable,
|
||||
const char * const * (&cmd_line),
|
||||
Init && init, derived && )
|
||||
-> decltype(init.on_setup(launcher, executable, cmd_line))
|
||||
{
|
||||
return init.on_setup(launcher, executable, cmd_line);
|
||||
}
|
||||
|
||||
template<typename Launcher>
|
||||
inline error_code on_setup(Launcher & launcher, const filesystem::path &executable,
|
||||
const char * const * (&cmd_line))
|
||||
{
|
||||
return error_code{};
|
||||
}
|
||||
|
||||
template<typename Launcher, typename Init1, typename ... Inits>
|
||||
inline error_code on_setup(Launcher & launcher, const filesystem::path &executable,
|
||||
const char * const * (&cmd_line),
|
||||
Init1 && init1, Inits && ... inits)
|
||||
{
|
||||
auto ec = invoke_on_setup(launcher, executable, cmd_line, init1, derived{});
|
||||
if (ec)
|
||||
return ec;
|
||||
else
|
||||
return on_setup(launcher, executable, cmd_line, inits...);
|
||||
}
|
||||
|
||||
|
||||
template<typename Launcher, typename Init>
|
||||
inline void invoke_on_error(Launcher & launcher, const filesystem::path &executable,
|
||||
const char * const * (&cmd_line),
|
||||
const error_code & ec, Init && init, base && )
|
||||
{
|
||||
}
|
||||
|
||||
template<typename Launcher, typename Init>
|
||||
inline auto invoke_on_error(Launcher & launcher, const filesystem::path &executable,
|
||||
const char * const * (&cmd_line),
|
||||
const error_code & ec, Init && init, derived && )
|
||||
-> decltype(init.on_error(launcher, ec, executable, cmd_line, ec))
|
||||
{
|
||||
init.on_error(launcher, executable, cmd_line, ec);
|
||||
}
|
||||
|
||||
template<typename Launcher>
|
||||
inline void on_error(Launcher & launcher, const filesystem::path &executable,
|
||||
const char * const * (&cmd_line),
|
||||
const error_code & ec)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename Launcher, typename Init1, typename ... Inits>
|
||||
inline void on_error(Launcher & launcher, const filesystem::path &executable,
|
||||
const char * const * (&cmd_line),
|
||||
const error_code & ec,
|
||||
Init1 && init1, Inits && ... inits)
|
||||
{
|
||||
invoke_on_error(launcher, executable, cmd_line, ec, init1, derived{});
|
||||
on_error(launcher, executable, cmd_line, ec, inits...);
|
||||
}
|
||||
|
||||
template<typename Launcher, typename Init>
|
||||
inline void invoke_on_success(Launcher & launcher, const filesystem::path &executable,
|
||||
const char * const * (&cmd_line),
|
||||
Init && init, base && )
|
||||
{
|
||||
}
|
||||
|
||||
template<typename Launcher, typename Init>
|
||||
inline auto invoke_on_success(Launcher & launcher, const filesystem::path &executable,
|
||||
const char * const * (&cmd_line),
|
||||
Init && init, derived && )
|
||||
-> decltype(init.on_success(launcher, executable, cmd_line))
|
||||
{
|
||||
init.on_success(launcher, executable, cmd_line);
|
||||
}
|
||||
|
||||
template<typename Launcher>
|
||||
inline void on_success(Launcher & launcher, const filesystem::path &executable,
|
||||
const char * const * (&cmd_line))
|
||||
{
|
||||
}
|
||||
|
||||
template<typename Launcher, typename Init1, typename ... Inits>
|
||||
inline void on_success(Launcher & launcher, const filesystem::path &executable,
|
||||
const char * const * (&cmd_line),
|
||||
Init1 && init1, Inits && ... inits)
|
||||
{
|
||||
invoke_on_success(launcher, executable, cmd_line, init1, derived{});
|
||||
on_success(launcher, executable, cmd_line, inits...);
|
||||
}
|
||||
|
||||
template<typename Launcher, typename Init>
|
||||
inline void invoke_on_fork_error(Launcher & launcher, const filesystem::path &executable,
|
||||
const char * const * (&cmd_line),
|
||||
const error_code & ec, Init && init, base && )
|
||||
{
|
||||
}
|
||||
|
||||
template<typename Launcher, typename Init>
|
||||
inline auto invoke_on_fork_error(Launcher & launcher, const filesystem::path &executable,
|
||||
const char * const * (&cmd_line),
|
||||
const error_code & ec, Init && init, derived && )
|
||||
-> decltype(init.on_fork_error(launcher, ec, executable, cmd_line, ec))
|
||||
{
|
||||
init.on_fork_error(launcher, executable, cmd_line, ec);
|
||||
}
|
||||
|
||||
template<typename Launcher>
|
||||
inline void on_fork_error(Launcher & launcher, const filesystem::path &executable,
|
||||
const char * const * (&cmd_line),
|
||||
const error_code & ec)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename Launcher, typename Init1, typename ... Inits>
|
||||
inline void on_fork_error(Launcher & launcher, const filesystem::path &executable,
|
||||
const char * const * (&cmd_line),
|
||||
const error_code & ec,
|
||||
Init1 && init1, Inits && ... inits)
|
||||
{
|
||||
invoke_on_fork_error(launcher, executable, cmd_line, ec, init1, derived{});
|
||||
on_fork_error(launcher, executable, cmd_line, ec, inits...);
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<typename Launcher, typename Init>
|
||||
inline void invoke_on_fork_success(Launcher & launcher, const filesystem::path &executable,
|
||||
const char * const * (&cmd_line),
|
||||
Init && init, base && )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
template<typename Launcher, typename Init>
|
||||
inline auto invoke_on_fork_success(Launcher & launcher, const filesystem::path &executable,
|
||||
const char * const * (&cmd_line),
|
||||
Init && init, derived && )
|
||||
-> decltype(init.on_fork_success(launcher, executable, cmd_line))
|
||||
{
|
||||
init.on_fork_success(launcher, executable, cmd_line);
|
||||
}
|
||||
|
||||
template<typename Launcher>
|
||||
inline void on_fork_success(Launcher & launcher, const filesystem::path &executable,
|
||||
const char * const * (&cmd_line))
|
||||
{
|
||||
}
|
||||
|
||||
template<typename Launcher, typename Init1, typename ... Inits>
|
||||
inline void on_fork_success(Launcher & launcher, const filesystem::path &executable,
|
||||
const char * const * (&cmd_line),
|
||||
Init1 && init1, Inits && ... inits)
|
||||
{
|
||||
invoke_on_fork_success(launcher, executable, cmd_line, init1, derived{});
|
||||
on_fork_success(launcher, executable, cmd_line, inits...);
|
||||
}
|
||||
|
||||
|
||||
template<typename Launcher, typename Init>
|
||||
inline error_code invoke_on_exec_setup(Launcher & launcher, const filesystem::path &executable,
|
||||
const char * const * (&cmd_line),
|
||||
Init && init, base && )
|
||||
{
|
||||
return error_code{};
|
||||
}
|
||||
|
||||
template<typename Launcher, typename Init>
|
||||
inline auto invoke_on_exec_setup(Launcher & launcher, const filesystem::path &executable,
|
||||
const char * const * (&cmd_line),
|
||||
Init && init, derived && )
|
||||
-> decltype(init.on_exec_setup(launcher, executable, cmd_line))
|
||||
{
|
||||
return init.on_exec_setup(launcher, executable, cmd_line);
|
||||
}
|
||||
|
||||
template<typename Launcher>
|
||||
inline error_code on_exec_setup(Launcher & launcher, const filesystem::path &executable,
|
||||
const char * const * (&cmd_line))
|
||||
{
|
||||
return error_code{};
|
||||
}
|
||||
|
||||
template<typename Launcher, typename Init1, typename ... Inits>
|
||||
inline error_code on_exec_setup(Launcher & launcher, const filesystem::path &executable,
|
||||
const char * const * (&cmd_line),
|
||||
Init1 && init1, Inits && ... inits)
|
||||
{
|
||||
auto ec = invoke_on_exec_setup(launcher, executable, cmd_line, init1, derived{});
|
||||
if (ec)
|
||||
return ec;
|
||||
else
|
||||
return on_exec_setup(launcher, executable, cmd_line, inits...);
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<typename Launcher, typename Init>
|
||||
inline void invoke_on_exec_error(Launcher & launcher, const filesystem::path &executable,
|
||||
const char * const * (&cmd_line),
|
||||
const error_code & ec, Init && init, base && )
|
||||
{
|
||||
}
|
||||
|
||||
template<typename Launcher, typename Init>
|
||||
inline auto invoke_on_exec_error(Launcher & launcher, const filesystem::path &executable,
|
||||
const char * const * (&cmd_line),
|
||||
const error_code & ec, Init && init, derived && )
|
||||
-> decltype(init.on_exec_error(launcher, ec, executable, cmd_line, ec))
|
||||
{
|
||||
init.on_exec_error(launcher, executable, cmd_line, ec);
|
||||
}
|
||||
|
||||
template<typename Launcher>
|
||||
inline void on_exec_error(Launcher & launcher, const filesystem::path &executable,
|
||||
const char * const * (&cmd_line),
|
||||
const error_code & ec)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename Launcher, typename Init1, typename ... Inits>
|
||||
inline void on_exec_error(Launcher & launcher, const filesystem::path &executable,
|
||||
const char * const * (&cmd_line),
|
||||
const error_code & ec,
|
||||
Init1 && init1, Inits && ... inits)
|
||||
{
|
||||
invoke_on_exec_error(launcher, executable, cmd_line, ec, init1, derived{});
|
||||
on_exec_error(launcher, executable, cmd_line, ec, inits...);
|
||||
}
|
||||
}
|
||||
|
||||
/// The default launcher for processes on windows.
|
||||
struct default_launcher
|
||||
{
|
||||
/// The pointer to the environment forwarded to the subprocess.
|
||||
const char * const * env = ::environ;
|
||||
/// The pid of the subprocess - will be assigned after fork.
|
||||
int pid = -1;
|
||||
|
||||
/// The whitelist for file descriptors.
|
||||
std::vector<int> fd_whitelist = {STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO};
|
||||
|
||||
default_launcher() = default;
|
||||
|
||||
template<typename ExecutionContext, typename Args, typename ... Inits>
|
||||
auto operator()(ExecutionContext & context,
|
||||
const typename std::enable_if<std::is_convertible<
|
||||
ExecutionContext&, BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context&>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<typename ExecutionContext::executor_type>
|
||||
{
|
||||
error_code ec;
|
||||
auto proc = (*this)(context, ec, executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
|
||||
|
||||
if (ec)
|
||||
v2::detail::throw_error(ec, "default_launcher");
|
||||
|
||||
return proc;
|
||||
}
|
||||
|
||||
|
||||
template<typename ExecutionContext, typename Args, typename ... Inits>
|
||||
auto operator()(ExecutionContext & context,
|
||||
error_code & ec,
|
||||
const typename std::enable_if<std::is_convertible<
|
||||
ExecutionContext&, BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context&>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<typename ExecutionContext::executor_type>
|
||||
{
|
||||
return (*this)(context.get_executor(), executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
|
||||
}
|
||||
|
||||
template<typename Executor, typename Args, typename ... Inits>
|
||||
auto operator()(Executor exec,
|
||||
const typename std::enable_if<
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::execution::is_executor<Executor>::value ||
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::is_executor<Executor>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<Executor>
|
||||
{
|
||||
error_code ec;
|
||||
auto proc = (*this)(std::move(exec), ec, executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
|
||||
|
||||
if (ec)
|
||||
v2::detail::throw_error(ec, "default_launcher");
|
||||
|
||||
return proc;
|
||||
}
|
||||
|
||||
template<typename Executor, typename Args, typename ... Inits>
|
||||
auto operator()(Executor exec,
|
||||
error_code & ec,
|
||||
const typename std::enable_if<
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::execution::is_executor<Executor>::value ||
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::is_executor<Executor>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<Executor>
|
||||
{
|
||||
auto argv = this->build_argv_(executable, std::forward<Args>(args));
|
||||
{
|
||||
pipe_guard pg;
|
||||
if (::pipe(pg.p))
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, errno, system_category())
|
||||
return basic_process<Executor>{exec};
|
||||
}
|
||||
if (::fcntl(pg.p[1], F_SETFD, FD_CLOEXEC))
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, errno, system_category())
|
||||
return basic_process<Executor>{exec};
|
||||
}
|
||||
ec = detail::on_setup(*this, executable, argv, inits ...);
|
||||
if (ec)
|
||||
{
|
||||
detail::on_error(*this, executable, argv, ec, inits...);
|
||||
return basic_process<Executor>(exec);
|
||||
}
|
||||
fd_whitelist.push_back(pg.p[1]);
|
||||
|
||||
auto & ctx = BOOST_PROCESS_V2_ASIO_NAMESPACE::query(
|
||||
exec, BOOST_PROCESS_V2_ASIO_NAMESPACE::execution::context);
|
||||
ctx.notify_fork(BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context::fork_prepare);
|
||||
pid = ::fork();
|
||||
if (pid == -1)
|
||||
{
|
||||
ctx.notify_fork(BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context::fork_parent);
|
||||
detail::on_fork_error(*this, executable, argv, ec, inits...);
|
||||
detail::on_error(*this, executable, argv, ec, inits...);
|
||||
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, errno, system_category())
|
||||
return basic_process<Executor>{exec};
|
||||
}
|
||||
else if (pid == 0)
|
||||
{
|
||||
::close(pg.p[0]);
|
||||
ctx.notify_fork(BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context::fork_child);
|
||||
ec = detail::on_exec_setup(*this, executable, argv, inits...);
|
||||
if (!ec)
|
||||
{
|
||||
close_all_fds(ec);
|
||||
}
|
||||
if (!ec)
|
||||
::execve(executable.c_str(), const_cast<char * const *>(argv), const_cast<char * const *>(env));
|
||||
|
||||
ignore_unused(::write(pg.p[1], &errno, sizeof(int)));
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, errno, system_category())
|
||||
detail::on_exec_error(*this, executable, argv, ec, inits...);
|
||||
::exit(EXIT_FAILURE);
|
||||
return basic_process<Executor>{exec};
|
||||
}
|
||||
|
||||
ctx.notify_fork(BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context::fork_parent);
|
||||
::close(pg.p[1]);
|
||||
pg.p[1] = -1;
|
||||
int child_error{0};
|
||||
int count = -1;
|
||||
while ((count = ::read(pg.p[0], &child_error, sizeof(child_error))) == -1)
|
||||
{
|
||||
int err = errno;
|
||||
if ((err != EAGAIN) && (err != EINTR))
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, err, system_category())
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (count != 0)
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, child_error, system_category())
|
||||
|
||||
if (ec)
|
||||
{
|
||||
detail::on_error(*this, executable, argv, ec, inits...);
|
||||
return basic_process<Executor>{exec};
|
||||
}
|
||||
}
|
||||
basic_process<Executor> proc(exec, pid);
|
||||
detail::on_success(*this, executable, argv, ec, inits...);
|
||||
return proc;
|
||||
|
||||
}
|
||||
protected:
|
||||
|
||||
void ignore_unused(std::size_t ) {}
|
||||
void close_all_fds(error_code & ec)
|
||||
{
|
||||
std::sort(fd_whitelist.begin(), fd_whitelist.end());
|
||||
detail::close_all(fd_whitelist, ec);
|
||||
fd_whitelist = {STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO};
|
||||
}
|
||||
|
||||
struct pipe_guard
|
||||
{
|
||||
int p[2];
|
||||
pipe_guard() : p{-1,-1} {}
|
||||
|
||||
~pipe_guard()
|
||||
{
|
||||
if (p[0] != -1)
|
||||
::close(p[0]);
|
||||
if (p[1] != -1)
|
||||
::close(p[1]);
|
||||
}
|
||||
};
|
||||
|
||||
//if we need to allocate something
|
||||
std::vector<std::string> argv_buffer_;
|
||||
std::vector<const char *> argv_;
|
||||
|
||||
template<typename Args>
|
||||
const char * const * build_argv_(const filesystem::path & pt, const Args & args,
|
||||
typename std::enable_if<
|
||||
std::is_convertible<
|
||||
decltype(*std::begin(std::declval<Args>())),
|
||||
cstring_ref>::value>::type * = nullptr)
|
||||
{
|
||||
const auto arg_cnt = std::distance(std::begin(args), std::end(args));
|
||||
argv_.reserve(arg_cnt + 2);
|
||||
argv_.push_back(pt.native().data());
|
||||
for (auto && arg : args)
|
||||
argv_.push_back(arg.c_str());
|
||||
|
||||
argv_.push_back(nullptr);
|
||||
return argv_.data();
|
||||
}
|
||||
|
||||
const char * const * build_argv_(const filesystem::path &, const char ** argv)
|
||||
{
|
||||
return argv;
|
||||
}
|
||||
|
||||
template<typename Args>
|
||||
const char * const * build_argv_(const filesystem::path & pt, const Args & args,
|
||||
typename std::enable_if<
|
||||
!std::is_convertible<
|
||||
decltype(*std::begin(std::declval<Args>())),
|
||||
cstring_ref>::value>::type * = nullptr)
|
||||
{
|
||||
const auto arg_cnt = std::distance(std::begin(args), std::end(args));
|
||||
argv_.reserve(arg_cnt + 2);
|
||||
argv_buffer_.reserve(arg_cnt);
|
||||
argv_.push_back(pt.native().data());
|
||||
|
||||
using char_type = typename decay<decltype((*std::begin(std::declval<Args>()))[0])>::type;
|
||||
|
||||
for (basic_string_view<char_type> arg : args)
|
||||
argv_buffer_.push_back(v2::detail::conv_string<char>(arg.data(), arg.size()));
|
||||
|
||||
for (auto && arg : argv_buffer_)
|
||||
argv_.push_back(arg.c_str());
|
||||
|
||||
argv_.push_back(nullptr);
|
||||
return argv_.data();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#endif //BOOST_PROCESS_V2_POSIX_DEFAULT_LAUNCHER
|
||||
@@ -0,0 +1,29 @@
|
||||
// Copyright (c) 2022 Klemens D. Morgenstern
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_PROCESS_V2_POSIX_DETAIL_CLOSE_HANDLES_HPP
|
||||
#define BOOST_PROCESS_V2_POSIX_DETAIL_CLOSE_HANDLES_HPP
|
||||
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
#include <vector>
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
|
||||
namespace posix
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
// whitelist must be ordered
|
||||
BOOST_PROCESS_V2_DECL void close_all(const std::vector<int> & whitelist,
|
||||
error_code & ec);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#endif //BOOST_PROCESS_V2_POSIX_DETAIL_CLOSE_HANDLES_HPP
|
||||
194
linx64/include/boost/process/v2/posix/detail/close_handles.ipp
Normal file
194
linx64/include/boost/process/v2/posix/detail/close_handles.ipp
Normal file
@@ -0,0 +1,194 @@
|
||||
//
|
||||
// boost/process/v2/posix/detail/close_handles.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2022 Klemens D. Morgenstern (klemens dot morgenstern at gmx dot net)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BOOST_PROCESS_V2_POSIX_DETAIL_CLOSE_HANDLES_IPP
|
||||
#define BOOST_PROCESS_V2_POSIX_DETAIL_CLOSE_HANDLES_IPP
|
||||
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
#include <boost/process/v2/detail/last_error.hpp>
|
||||
#include <boost/process/v2/posix/detail/close_handles.hpp>
|
||||
// linux has close_range since 5.19
|
||||
|
||||
|
||||
#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
|
||||
|
||||
// https://www.freebsd.org/cgi/man.cgi?query=close_range&apropos=0&sektion=0&manpath=FreeBSD+13.1-RELEASE+and+Ports&arch=default&format=html
|
||||
// https://man.netbsd.org/closefrom.3
|
||||
// __FreeBSD__
|
||||
//
|
||||
// gives us
|
||||
//
|
||||
// int closefrom(int fd);
|
||||
// int close_range(u_int lowfd, u_int highfd, int flags);
|
||||
|
||||
#include <unistd.h>
|
||||
#define BOOST_PROCESS_V2_HAS_CLOSE_RANGE_AND_CLOSEFROM 1
|
||||
|
||||
#elif defined(__sun)
|
||||
|
||||
/*https://docs.oracle.com/cd/E36784_01/html/E36874/closefrom-3c.html
|
||||
|
||||
int fdwalk(int (*func)(void *, int), void *cd);
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#define BOOST_PROCESS_V2_HAS_PDFORK 1
|
||||
|
||||
#elif defined(__linux__)
|
||||
|
||||
#include <linux/version.h>
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,11,0)
|
||||
|
||||
// https://man7.org/linux/man-pages/man2/close_range.2.html
|
||||
#include <linux/close_range.h>
|
||||
#define BOOST_PROCESS_V2_HAS_CLOSE_RANGE 1
|
||||
#else
|
||||
|
||||
#include <dirent.h>
|
||||
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#include <dirent.h>
|
||||
|
||||
#endif
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
|
||||
namespace posix
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_HAS_PDFORK)
|
||||
|
||||
void close_all(const std::vector<int> & whitelist, error_code & ec)
|
||||
{
|
||||
fdwalk(+[](void * p, int fd)
|
||||
{
|
||||
const auto & wl = *static_cast<const std::vector<int>*>(p);
|
||||
if (std::find(wl.begin(), wl.end(), fd) == wl.end())
|
||||
return ::close(fd);
|
||||
else
|
||||
return 0;
|
||||
}, const_cast<void*>(static_cast<const void*>(&whitelist)) );
|
||||
ec = BOOST_PROCESS_V2_NAMESPACE::detail::get_last_error();
|
||||
}
|
||||
|
||||
#elif defined(BOOST_PROCESS_V2_HAS_CLOSE_RANGE_AND_CLOSEFROM)
|
||||
|
||||
// freeBSD impl - whitelist must be ordered
|
||||
void close_all(const std::vector<int> & whitelist, error_code & ec)
|
||||
{
|
||||
//the most common scenario is whitelist = {0,1,2}
|
||||
if (!whitelist.empty())
|
||||
{
|
||||
if (whitelist.front() != 0)
|
||||
::close_range(0, whitelist.front() - 1, 0);
|
||||
|
||||
for (std::size_t idx = 0u;
|
||||
idx < (whitelist.size() - 1u);
|
||||
idx++)
|
||||
{
|
||||
const auto mine = whitelist[idx];
|
||||
const auto next = whitelist[idx];
|
||||
if ((mine + 1) != next && (mine != next))
|
||||
{
|
||||
::close_range(mine + 1, next - 1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
::closefrom(whitelist.back() + 1);
|
||||
}
|
||||
else
|
||||
::closefrom(0);
|
||||
}
|
||||
|
||||
#elif defined(BOOST_PROCESS_V2_HAS_CLOSE_RANGE)
|
||||
|
||||
|
||||
// linux impl - whitelist must be ordered
|
||||
void close_all(const std::vector<int> & whitelist, error_code & ec)
|
||||
{
|
||||
// https://patchwork.kernel.org/project/linux-fsdevel/cover/20200602204219.186620-1-christian.brauner@ubuntu.com/
|
||||
//the most common scenario is whitelist = {0,1,2}
|
||||
if (!whitelist.empty())
|
||||
{
|
||||
if (whitelist.front() != 0)
|
||||
::close_range(0, whitelist.front() - 1, CLOSE_RANGE_UNSHARE);
|
||||
|
||||
for (std::size_t idx = 0u;
|
||||
idx < (whitelist.size() - 1u);
|
||||
idx++)
|
||||
{
|
||||
const auto mine = whitelist[idx];
|
||||
const auto next = whitelist[idx];
|
||||
if ((mine + 1) != next && (mine != next))
|
||||
{
|
||||
::close_range(mine + 1, next - 1, CLOSE_RANGE_UNSHARE);
|
||||
}
|
||||
}
|
||||
|
||||
::close_range(whitelist.back() + 1, std::numeric_limits<int>::max(), CLOSE_RANGE_UNSHARE);
|
||||
}
|
||||
else
|
||||
::close_range(0, std::numeric_limits<int>::max(), CLOSE_RANGE_UNSHARE);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// default one
|
||||
void close_all(const std::vector<int> & whitelist, error_code & ec)
|
||||
{
|
||||
std::unique_ptr<DIR, void(*)(DIR*)> dir{::opendir("/dev/fd"), +[](DIR* p){::closedir(p);}};
|
||||
if (dir.get() == nullptr)
|
||||
{
|
||||
ec = BOOST_PROCESS_V2_NAMESPACE::detail::get_last_error();
|
||||
return ;
|
||||
}
|
||||
|
||||
auto dir_fd = ::dirfd(dir.get());
|
||||
if (dir_fd == -1)
|
||||
{
|
||||
ec = BOOST_PROCESS_V2_NAMESPACE::detail::get_last_error();
|
||||
return ;
|
||||
}
|
||||
|
||||
struct ::dirent * ent_p;
|
||||
|
||||
while ((ent_p = ::readdir(dir.get())) != nullptr)
|
||||
{
|
||||
if (ent_p->d_name[0] == '.')
|
||||
continue;
|
||||
|
||||
const auto conv = std::atoi(ent_p->d_name);
|
||||
if (conv == 0 && (ent_p->d_name[0] != '0' && ent_p->d_name[1] != '\0'))
|
||||
continue;
|
||||
|
||||
if (conv == dir_fd
|
||||
|| (std::find(whitelist.begin(), whitelist.end(), conv) != whitelist.end()))
|
||||
continue;
|
||||
|
||||
::close(conv);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#endif //BOOST_PROCESS_V2_POSIX_DETAIL_CLOSE_HANDLES_IPP
|
||||
@@ -0,0 +1,135 @@
|
||||
// Copyright (c) 2022 Klemens D. Morgenstern
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_PROCESS_V2_POSIX_FORK_AND_FORGET_LAUNCHER_HPP
|
||||
#define BOOST_PROCESS_V2_POSIX_FORK_AND_FORGET_LAUNCHER_HPP
|
||||
|
||||
#include <boost/process/v2/posix/default_launcher.hpp>
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
|
||||
namespace posix
|
||||
{
|
||||
|
||||
/// A posix fork launcher that ignores errors after `fork`.
|
||||
struct fork_and_forget_launcher : default_launcher
|
||||
{
|
||||
fork_and_forget_launcher() = default;
|
||||
|
||||
template<typename ExecutionContext, typename Args, typename ... Inits>
|
||||
auto operator()(ExecutionContext & context,
|
||||
const typename std::enable_if<is_convertible<
|
||||
ExecutionContext&, BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context&>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<typename ExecutionContext::executor_type>
|
||||
{
|
||||
error_code ec;
|
||||
auto proc = (*this)(context, ec, executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
|
||||
|
||||
if (ec)
|
||||
v2::detail::throw_error(ec, "fork_and_forget_launcher");
|
||||
|
||||
return proc;
|
||||
}
|
||||
|
||||
|
||||
template<typename ExecutionContext, typename Args, typename ... Inits>
|
||||
auto operator()(ExecutionContext & context,
|
||||
error_code & ec,
|
||||
const typename std::enable_if<is_convertible<
|
||||
ExecutionContext&, BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context&>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<typename ExecutionContext::executor_type>
|
||||
{
|
||||
return (*this)(context.get_executor(), executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
|
||||
}
|
||||
|
||||
template<typename Executor, typename Args, typename ... Inits>
|
||||
auto operator()(Executor exec,
|
||||
const typename std::enable_if<
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::execution::is_executor<Executor>::value ||
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::is_executor<Executor>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<Executor>
|
||||
{
|
||||
error_code ec;
|
||||
auto proc = (*this)(std::move(exec), ec, executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
|
||||
|
||||
if (ec)
|
||||
v2::detail::throw_error(ec, "fork_and_forget_launcher");
|
||||
|
||||
return proc;
|
||||
}
|
||||
|
||||
template<typename Executor, typename Args, typename ... Inits>
|
||||
auto operator()(Executor exec,
|
||||
error_code & ec,
|
||||
const typename std::enable_if<
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::execution::is_executor<Executor>::value ||
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::is_executor<Executor>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<Executor>
|
||||
{
|
||||
auto argv = this->build_argv_(executable, std::forward<Args>(args));
|
||||
{
|
||||
ec = detail::on_setup(*this, executable, argv, inits ...);
|
||||
if (ec)
|
||||
{
|
||||
detail::on_error(*this, executable, argv, ec, inits...);
|
||||
return basic_process<Executor>(exec);
|
||||
}
|
||||
|
||||
auto & ctx = BOOST_PROCESS_V2_ASIO_NAMESPACE::query(
|
||||
exec, BOOST_PROCESS_V2_ASIO_NAMESPACE::execution::context);
|
||||
ctx.notify_fork(BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context::fork_prepare);
|
||||
pid = ::fork();
|
||||
if (pid == -1)
|
||||
{
|
||||
ctx.notify_fork(BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context::fork_parent);
|
||||
detail::on_fork_error(*this, executable, argv, ec, inits...);
|
||||
detail::on_error(*this, executable, argv, ec, inits...);
|
||||
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, errno, system_category())
|
||||
return basic_process<Executor>{exec};
|
||||
}
|
||||
else if (pid == 0)
|
||||
{
|
||||
ctx.notify_fork(BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context::fork_child);
|
||||
|
||||
ec = detail::on_exec_setup(*this, executable, argv, inits...);
|
||||
if (!ec)
|
||||
close_all_fds(ec);
|
||||
if (!ec)
|
||||
::execve(executable.c_str(), const_cast<char * const *>(argv), const_cast<char * const *>(env));
|
||||
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, errno, system_category())
|
||||
detail::on_exec_error(*this, executable, argv, ec, inits...);
|
||||
::exit(EXIT_FAILURE);
|
||||
return basic_process<Executor>{exec};
|
||||
}
|
||||
ctx.notify_fork(BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context::fork_parent);
|
||||
if (ec)
|
||||
{
|
||||
detail::on_error(*this, executable, argv, ec, inits...);
|
||||
return basic_process<Executor>{exec};
|
||||
}
|
||||
}
|
||||
basic_process<Executor> proc(exec, pid);
|
||||
detail::on_success(*this, executable, argv, ec, inits...);
|
||||
return proc;
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
|
||||
#endif //BOOST_PROCESS_V2_POSIX_FORK_AND_FORGET_LAUNCHER_HPP
|
||||
171
linx64/include/boost/process/v2/posix/pdfork_launcher.hpp
Normal file
171
linx64/include/boost/process/v2/posix/pdfork_launcher.hpp
Normal file
@@ -0,0 +1,171 @@
|
||||
// Copyright (c) 2022 Klemens D. Morgenstern
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_PROCESS_V2_POSIX_PDFORK_LAUNCHER_HPP
|
||||
#define BOOST_PROCESS_V2_POSIX_PDFORK_LAUNCHER_HPP
|
||||
|
||||
#include <boost/process/v2/posix/default_launcher.hpp>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/procdesc.h>
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
|
||||
namespace posix
|
||||
{
|
||||
|
||||
/// A launcher using `pdfork`. Default on FreeBSD
|
||||
struct pdfork_launcher : default_launcher
|
||||
{
|
||||
/// The file descriptor of the subprocess. Set after fork.
|
||||
int fd;
|
||||
pdfork_launcher() = default;
|
||||
|
||||
template<typename ExecutionContext, typename Args, typename ... Inits>
|
||||
auto operator()(ExecutionContext & context,
|
||||
const typename std::enable_if<is_convertible<
|
||||
ExecutionContext&, BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context&>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<typename ExecutionContext::executor_type>
|
||||
{
|
||||
error_code ec;
|
||||
auto proc = (*this)(context, ec, executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
|
||||
|
||||
if (ec)
|
||||
v2::detail::throw_error(ec, "pdfork_launcher");
|
||||
|
||||
return proc;
|
||||
}
|
||||
|
||||
|
||||
template<typename ExecutionContext, typename Args, typename ... Inits>
|
||||
auto operator()(ExecutionContext & context,
|
||||
error_code & ec,
|
||||
const typename std::enable_if<is_convertible<
|
||||
ExecutionContext&, BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context&>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<typename ExecutionContext::executor_type>
|
||||
{
|
||||
return (*this)(context.get_executor(), executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
|
||||
}
|
||||
|
||||
template<typename Executor, typename Args, typename ... Inits>
|
||||
auto operator()(Executor exec,
|
||||
const typename std::enable_if<
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::execution::is_executor<Executor>::value ||
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::is_executor<Executor>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<Executor>
|
||||
{
|
||||
error_code ec;
|
||||
auto proc = (*this)(std::move(exec), ec, executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
|
||||
|
||||
if (ec)
|
||||
v2::detail::throw_error(ec, "pdfork_launcher");
|
||||
|
||||
return proc;
|
||||
}
|
||||
|
||||
template<typename Executor, typename Args, typename ... Inits>
|
||||
auto operator()(Executor exec,
|
||||
error_code & ec,
|
||||
const typename std::enable_if<
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::execution::is_executor<Executor>::value ||
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::is_executor<Executor>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<Executor>
|
||||
{
|
||||
auto argv = this->build_argv_(executable, std::forward<Args>(args));
|
||||
{
|
||||
pipe_guard pg;
|
||||
if (::pipe(pg.p))
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, errno, system_category())
|
||||
return basic_process<Executor>{exec};
|
||||
}
|
||||
if (::fcntl(pg.p[1], F_SETFD, FD_CLOEXEC))
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, errno, system_category())
|
||||
return basic_process<Executor>{exec};
|
||||
}
|
||||
ec = detail::on_setup(*this, executable, argv, inits ...);
|
||||
if (ec)
|
||||
{
|
||||
detail::on_error(*this, executable, argv, ec, inits...);
|
||||
return basic_process<Executor>(exec);
|
||||
}
|
||||
fd_whitelist.push_back(pg.p[1]);
|
||||
|
||||
auto & ctx = BOOST_PROCESS_V2_ASIO_NAMESPACE::query(
|
||||
exec, BOOST_PROCESS_V2_ASIO_NAMESPACE::execution::context);
|
||||
ctx.notify_fork(BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context::fork_prepare);
|
||||
pid = ::pdfork(&fd, PD_DAEMON | PD_CLOEXEC);
|
||||
if (pid == -1)
|
||||
{
|
||||
ctx.notify_fork(BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context::fork_parent);
|
||||
detail::on_fork_error(*this, executable, argv, ec, inits...);
|
||||
detail::on_error(*this, executable, argv, ec, inits...);
|
||||
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, errno, system_category())
|
||||
return basic_process<Executor>{exec};
|
||||
}
|
||||
else if (pid == 0)
|
||||
{
|
||||
ctx.notify_fork(BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context::fork_child);
|
||||
::close(pg.p[0]);
|
||||
|
||||
ec = detail::on_exec_setup(*this, executable, argv, inits...);
|
||||
if (!ec)
|
||||
{
|
||||
close_all_fds(ec);
|
||||
}
|
||||
if (!ec)
|
||||
::execve(executable.c_str(), const_cast<char * const *>(argv), const_cast<char * const *>(env));
|
||||
|
||||
default_launcher::ignore_unused(::write(pg.p[1], &errno, sizeof(int)));
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, errno, system_category())
|
||||
detail::on_exec_error(*this, executable, argv, ec, inits...);
|
||||
::exit(EXIT_FAILURE);
|
||||
return basic_process<Executor>{exec};
|
||||
}
|
||||
ctx.notify_fork(BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context::fork_parent);
|
||||
::close(pg.p[1]);
|
||||
pg.p[1] = -1;
|
||||
int child_error{0};
|
||||
int count = -1;
|
||||
while ((count = ::read(pg.p[0], &child_error, sizeof(child_error))) == -1)
|
||||
{
|
||||
int err = errno;
|
||||
if ((err != EAGAIN) && (err != EINTR))
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, err, system_category())
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (count != 0)
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, child_error, system_category())
|
||||
|
||||
if (ec)
|
||||
{
|
||||
detail::on_error(*this, executable, argv, ec, inits...);
|
||||
return basic_process<Executor>{exec};
|
||||
}
|
||||
}
|
||||
basic_process<Executor> proc(exec, pid, fd);
|
||||
detail::on_success(*this, executable, argv, ec, inits...);
|
||||
return proc;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
|
||||
#endif //BOOST_PROCESS_V2_POSIX_PDFORK_LAUNCHER_HPP
|
||||
135
linx64/include/boost/process/v2/posix/vfork_launcher.hpp
Normal file
135
linx64/include/boost/process/v2/posix/vfork_launcher.hpp
Normal file
@@ -0,0 +1,135 @@
|
||||
// Copyright (c) 2022 Klemens D. Morgenstern
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_PROCESS_V2_POSIX_VFORK_LAUNCHER_HPP
|
||||
#define BOOST_PROCESS_V2_POSIX_VFORK_LAUNCHER_HPP
|
||||
|
||||
#include <boost/process/v2/posix/default_launcher.hpp>
|
||||
#include <unistd.h>
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
|
||||
namespace posix
|
||||
{
|
||||
|
||||
|
||||
/// A launcher using vfork instead of fork.
|
||||
struct vfork_launcher : default_launcher
|
||||
{
|
||||
vfork_launcher() = default;
|
||||
|
||||
template<typename ExecutionContext, typename Args, typename ... Inits>
|
||||
auto operator()(ExecutionContext & context,
|
||||
const typename std::enable_if<std::is_convertible<
|
||||
ExecutionContext&, BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context&>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<typename ExecutionContext::executor_type>
|
||||
{
|
||||
error_code ec;
|
||||
auto proc = (*this)(context, ec, executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
|
||||
|
||||
if (ec)
|
||||
v2::detail::throw_error(ec, "default_launcher");
|
||||
|
||||
return proc;
|
||||
}
|
||||
|
||||
|
||||
template<typename ExecutionContext, typename Args, typename ... Inits>
|
||||
auto operator()(ExecutionContext & context,
|
||||
error_code & ec,
|
||||
const typename std::enable_if<std::is_convertible<
|
||||
ExecutionContext&, BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context&>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<typename ExecutionContext::executor_type>
|
||||
{
|
||||
return (*this)(context.get_executor(), executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
|
||||
}
|
||||
|
||||
template<typename Executor, typename Args, typename ... Inits>
|
||||
auto operator()(Executor exec,
|
||||
const typename std::enable_if<
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::execution::is_executor<Executor>::value ||
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::is_executor<Executor>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<Executor>
|
||||
{
|
||||
error_code ec;
|
||||
auto proc = (*this)(std::move(exec), ec, executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
|
||||
|
||||
if (ec)
|
||||
v2::detail::throw_error(ec, "default_launcher");
|
||||
|
||||
return proc;
|
||||
}
|
||||
|
||||
template<typename Executor, typename Args, typename ... Inits>
|
||||
auto operator()(Executor exec,
|
||||
error_code & ec,
|
||||
const typename std::enable_if<
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::execution::is_executor<Executor>::value ||
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::is_executor<Executor>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<Executor>
|
||||
{
|
||||
auto argv = this->build_argv_(executable, std::forward<Args>(args));
|
||||
|
||||
ec = detail::on_setup(*this, executable, argv, inits ...);
|
||||
if (ec)
|
||||
{
|
||||
detail::on_error(*this, executable, argv, ec, inits...);
|
||||
return basic_process<Executor>(exec);
|
||||
}
|
||||
|
||||
auto & ctx = BOOST_PROCESS_V2_ASIO_NAMESPACE::query(
|
||||
exec, BOOST_PROCESS_V2_ASIO_NAMESPACE::execution::context);
|
||||
ctx.notify_fork(BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context::fork_prepare);
|
||||
pid = ::vfork();
|
||||
if (pid == -1)
|
||||
{
|
||||
ctx.notify_fork(BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context::fork_parent);
|
||||
detail::on_fork_error(*this, executable, argv, ec, inits...);
|
||||
detail::on_error(*this, executable, argv, ec, inits...);
|
||||
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, errno, system_category())
|
||||
return basic_process<Executor>{exec};
|
||||
}
|
||||
else if (pid == 0)
|
||||
{
|
||||
ec = detail::on_exec_setup(*this, executable, argv, inits...);
|
||||
if (!ec)
|
||||
close_all_fds(ec);
|
||||
if (!ec)
|
||||
::execve(executable.c_str(), const_cast<char * const *>(argv), const_cast<char * const *>(env));
|
||||
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, errno, system_category())
|
||||
detail::on_exec_error(*this, executable, argv, ec, inits...);
|
||||
::_exit(EXIT_FAILURE);
|
||||
return basic_process<Executor>{exec};
|
||||
}
|
||||
ctx.notify_fork(BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context::fork_parent);
|
||||
|
||||
if (ec)
|
||||
{
|
||||
detail::on_error(*this, executable, argv, ec, inits...);
|
||||
return basic_process<Executor>{exec};
|
||||
}
|
||||
|
||||
basic_process<Executor> proc(exec, pid);
|
||||
detail::on_success(*this, executable, argv, ec, inits...);
|
||||
return proc;
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#endif //BOOST_PROCESS_V2_POSIX_VFORK_LAUNCHER_HPP
|
||||
394
linx64/include/boost/process/v2/process.hpp
Normal file
394
linx64/include/boost/process/v2/process.hpp
Normal file
@@ -0,0 +1,394 @@
|
||||
// Copyright (c) 2021 Klemens D. Morgenstern (klemens dot morgenstern at gmx dot net)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
//
|
||||
// process.hpp
|
||||
// ~~~~~~~~~~~~~~
|
||||
//
|
||||
|
||||
#ifndef BOOST_PROCESS_V2_PROCESS_HPP
|
||||
#define BOOST_PROCESS_V2_PROCESS_HPP
|
||||
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
#include <boost/process/v2/default_launcher.hpp>
|
||||
#include <boost/process/v2/exit_code.hpp>
|
||||
#include <boost/process/v2/pid.hpp>
|
||||
#include <boost/process/v2/ext/exe.hpp>
|
||||
#include <boost/process/v2/process_handle.hpp>
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_STANDALONE)
|
||||
#include <asio/any_io_executor.hpp>
|
||||
#include <asio/post.hpp>
|
||||
#include <utility>
|
||||
#else
|
||||
#include <boost/asio/any_io_executor.hpp>
|
||||
#include <boost/asio/post.hpp>
|
||||
#include <boost/core/exchange.hpp>
|
||||
#endif
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
|
||||
/// A class managing a subprocess
|
||||
/* A `basic_process` object manages a subprocess; it tracks the status and exit-code,
|
||||
* and will terminate the process on destruction if `detach` was not called.
|
||||
*/
|
||||
template<typename Executor = BOOST_PROCESS_V2_ASIO_NAMESPACE::any_io_executor>
|
||||
struct basic_process
|
||||
{
|
||||
/// The executor of the process
|
||||
using executor_type = Executor;
|
||||
/// Get the executor of the process
|
||||
executor_type get_executor() {return process_handle_.get_executor();}
|
||||
|
||||
/// The non-closing handle type
|
||||
using handle_type = basic_process_handle<executor_type>;
|
||||
|
||||
/// Get the underlying non-closing handle
|
||||
handle_type & handle() { return process_handle_; }
|
||||
|
||||
/// Get the underlying non-closing handle
|
||||
const handle_type & handle() const { return process_handle_; }
|
||||
|
||||
/// Provides access to underlying operating system facilities
|
||||
using native_handle_type = typename handle_type::native_handle_type;
|
||||
|
||||
/// Rebinds the process_handle to another executor.
|
||||
template <typename Executor1>
|
||||
struct rebind_executor
|
||||
{
|
||||
/// The socket type when rebound to the specified executor.
|
||||
typedef basic_process<Executor1> other;
|
||||
};
|
||||
|
||||
/** An empty process is similar to a default constructed thread. It holds an empty
|
||||
handle and is a place holder for a process that is to be launched later. */
|
||||
basic_process() = default;
|
||||
|
||||
basic_process(const basic_process&) = delete;
|
||||
basic_process& operator=(const basic_process&) = delete;
|
||||
|
||||
/// Move construct the process. It will be detached from `lhs`.
|
||||
basic_process(basic_process&& lhs) = default;
|
||||
|
||||
/// Move assign a process. It will be detached from `lhs`.
|
||||
basic_process& operator=(basic_process&& lhs) = default;
|
||||
|
||||
/// Move construct and rebind the executor.
|
||||
template<typename Executor1>
|
||||
basic_process(basic_process<Executor1>&& lhs)
|
||||
: process_handle_(std::move(lhs.process_handle_)),
|
||||
exit_status_{lhs.exit_status_}
|
||||
{
|
||||
}
|
||||
|
||||
/// Construct a child from a property list and launch it using the default launcher..
|
||||
template<typename ... Inits>
|
||||
explicit basic_process(
|
||||
executor_type executor,
|
||||
const filesystem::path& exe,
|
||||
std::initializer_list<string_view> args,
|
||||
Inits&&... inits)
|
||||
: basic_process(default_process_launcher()(std::move(executor), exe, args, std::forward<Inits>(inits)...))
|
||||
{
|
||||
}
|
||||
|
||||
/// Construct a child from a property list and launch it using the default launcher..
|
||||
template<typename Args, typename ... Inits>
|
||||
explicit basic_process(
|
||||
executor_type executor,
|
||||
const filesystem::path& exe,
|
||||
Args&& args, Inits&&... inits)
|
||||
: basic_process(default_process_launcher()(std::move(executor), exe,
|
||||
std::forward<Args>(args), std::forward<Inits>(inits)...))
|
||||
{
|
||||
}
|
||||
|
||||
/// Construct a child from a property list and launch it using the default launcher..
|
||||
template<typename ExecutionContext, typename ... Inits>
|
||||
explicit basic_process(
|
||||
ExecutionContext & context,
|
||||
typename std::enable_if<
|
||||
std::is_convertible<ExecutionContext&,
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context&>::value,
|
||||
const filesystem::path&>::type exe,
|
||||
std::initializer_list<string_view> args,
|
||||
Inits&&... inits)
|
||||
: basic_process(default_process_launcher()(executor_type(context.get_executor()),
|
||||
exe, args, std::forward<Inits>(inits)...))
|
||||
{
|
||||
}
|
||||
/// Construct a child from a property list and launch it using the default launcher.
|
||||
template<typename ExecutionContext, typename Args, typename ... Inits>
|
||||
explicit basic_process(
|
||||
ExecutionContext & context,
|
||||
typename std::enable_if<
|
||||
std::is_convertible<ExecutionContext&,
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context&>::value,
|
||||
const filesystem::path&>::type exe,
|
||||
Args&& args, Inits&&... inits)
|
||||
: basic_process(default_process_launcher()(executor_type(context.get_executor()),
|
||||
exe, std::forward<Args>(args), std::forward<Inits>(inits)...))
|
||||
{
|
||||
}
|
||||
|
||||
/// Attach to an existing process
|
||||
explicit basic_process(executor_type exec, pid_type pid) : process_handle_(std::move(exec), pid) {}
|
||||
|
||||
/// Attach to an existing process and the internal handle
|
||||
explicit basic_process(executor_type exec, pid_type pid, native_handle_type native_handle)
|
||||
: process_handle_(std::move(exec), pid, native_handle) {}
|
||||
|
||||
/// Create an invalid handle
|
||||
explicit basic_process(executor_type exec) : process_handle_{std::move(exec)} {}
|
||||
|
||||
/// Attach to an existing process
|
||||
template <typename ExecutionContext>
|
||||
explicit basic_process(ExecutionContext & context, pid_type pid,
|
||||
typename std::enable_if<
|
||||
std::is_convertible<ExecutionContext&,
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context&>::value, void *>::type = nullptr)
|
||||
: process_handle_(context, pid) {}
|
||||
|
||||
/// Attach to an existing process and the internal handle
|
||||
template <typename ExecutionContext>
|
||||
explicit basic_process(ExecutionContext & context, pid_type pid, native_handle_type native_handle,
|
||||
typename std::enable_if<
|
||||
std::is_convertible<ExecutionContext&,
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context&>::value, void *>::type = nullptr)
|
||||
: process_handle_(context.get_executor(), pid, native_handle) {}
|
||||
|
||||
/// Create an invalid handle
|
||||
template <typename ExecutionContext>
|
||||
explicit basic_process(ExecutionContext & context,
|
||||
typename std::enable_if<
|
||||
is_convertible<ExecutionContext&,
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context&>::value, void *>::type = nullptr)
|
||||
: process_handle_(context.get_executor()) {}
|
||||
|
||||
|
||||
|
||||
/// Destruct the handle and terminate the process if it wasn't detached.
|
||||
~basic_process()
|
||||
{
|
||||
process_handle_.terminate_if_running();
|
||||
}
|
||||
|
||||
/// Sends the process a signal to ask for an interrupt, which the process may interpret as a shutdown.
|
||||
/** Maybe be ignored by the subprocess. */
|
||||
void interrupt()
|
||||
{
|
||||
error_code ec;
|
||||
interrupt(ec);
|
||||
if (ec)
|
||||
throw system_error(ec, "interrupt failed");
|
||||
|
||||
}
|
||||
/// Throwing @overload void interrupt()
|
||||
void interrupt(error_code & ec)
|
||||
{
|
||||
process_handle_.interrupt(ec);
|
||||
}
|
||||
|
||||
/// Throwing @overload void request_exit(error_code & ec)
|
||||
void request_exit()
|
||||
{
|
||||
error_code ec;
|
||||
request_exit(ec);
|
||||
if (ec)
|
||||
throw system_error(ec, "request_exit failed");
|
||||
}
|
||||
/// Sends the process a signal to ask for a graceful shutdown. Maybe be ignored by the subprocess.
|
||||
void request_exit(error_code & ec)
|
||||
{
|
||||
process_handle_.request_exit(ec);
|
||||
}
|
||||
|
||||
/// Send the process a signal requesting it to stop. This may rely on undocumented functions.
|
||||
void suspend(error_code &ec)
|
||||
{
|
||||
process_handle_.suspend(ec);
|
||||
}
|
||||
|
||||
/// Send the process a signal requesting it to stop. This may rely on undocumented functions.
|
||||
void suspend()
|
||||
{
|
||||
error_code ec;
|
||||
suspend(ec);
|
||||
if (ec)
|
||||
detail::throw_error(ec, "suspend");
|
||||
}
|
||||
|
||||
|
||||
/// Send the process a signal requesting it to resume. This may rely on undocumented functions.
|
||||
void resume(error_code &ec)
|
||||
{
|
||||
process_handle_.resume(ec);
|
||||
}
|
||||
|
||||
/// Send the process a signal requesting it to resume. This may rely on undocumented functions.
|
||||
void resume()
|
||||
{
|
||||
error_code ec;
|
||||
suspend(ec);
|
||||
if (ec)
|
||||
detail::throw_error(ec, "resume");
|
||||
}
|
||||
|
||||
/// Throwing @overload void terminate(native_exit_code_type &exit_code, error_code & ec)
|
||||
void terminate()
|
||||
{
|
||||
error_code ec;
|
||||
terminate(ec);
|
||||
if (ec)
|
||||
detail::throw_error(ec, "terminate failed");
|
||||
}
|
||||
/// Unconditionally terminates the process and stores the exit code in exit_status.
|
||||
void terminate(error_code & ec)
|
||||
{
|
||||
process_handle_.terminate(exit_status_, ec);
|
||||
}
|
||||
|
||||
/// Throwing @overload wait(error_code & ec)
|
||||
int wait()
|
||||
{
|
||||
error_code ec;
|
||||
if (running(ec))
|
||||
process_handle_.wait(exit_status_, ec);
|
||||
if (ec)
|
||||
detail::throw_error(ec, "wait failed");
|
||||
return exit_code();
|
||||
}
|
||||
/// Waits for the process to exit, store the exit code internally and return it.
|
||||
int wait(error_code & ec)
|
||||
{
|
||||
if (running(ec))
|
||||
process_handle_.wait(exit_status_, ec);
|
||||
return exit_code();
|
||||
}
|
||||
|
||||
/// Detach the process.
|
||||
handle_type detach()
|
||||
{
|
||||
#if defined(BOOST_PROCESS_V2_STANDALONE)
|
||||
return std::exchange(process_handle_, get_executor());
|
||||
#else
|
||||
return boost::exchange(process_handle_, get_executor());
|
||||
#endif
|
||||
}
|
||||
/// Get the native
|
||||
native_handle_type native_handle() {return process_handle_.native_handle(); }
|
||||
/// Return the evaluated exit_code.
|
||||
int exit_code() const
|
||||
{
|
||||
return evaluate_exit_code(exit_status_);
|
||||
}
|
||||
|
||||
/// Get the id of the process;
|
||||
pid_type id() const {return process_handle_.id();}
|
||||
|
||||
/// The native handle of the process.
|
||||
/** This might be undefined on posix systems that only support signals */
|
||||
native_exit_code_type native_exit_code() const
|
||||
{
|
||||
return exit_status_;
|
||||
}
|
||||
/// Checks if the current process is running.
|
||||
/** If it has already completed the exit code will be stored internally
|
||||
* and can be obtained by calling `exit_code.
|
||||
*/
|
||||
bool running()
|
||||
{
|
||||
error_code ec;
|
||||
native_exit_code_type exit_code{};
|
||||
auto r = process_handle_.running(exit_code, ec);
|
||||
if (!ec && !r)
|
||||
exit_status_ = exit_code;
|
||||
else
|
||||
detail::throw_error(ec, "running failed");
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/// Throwing @overload bool running(error_code & ec)
|
||||
bool running(error_code & ec) noexcept
|
||||
{
|
||||
native_exit_code_type exit_code{};
|
||||
auto r = process_handle_.running(exit_code, ec);
|
||||
if (!ec && !r)
|
||||
exit_status_ = exit_code;
|
||||
return r;
|
||||
}
|
||||
|
||||
/// Check if the process is referring to an existing process.
|
||||
/** Note that this might be a process that already exited.*/
|
||||
bool is_open() const { return process_handle_.is_open(); }
|
||||
|
||||
/// Asynchronously wait for the process to exit and deliver the native exit-code in the completion handler.
|
||||
template <BOOST_PROCESS_V2_COMPLETION_TOKEN_FOR(void (error_code, int))
|
||||
WaitHandler BOOST_PROCESS_V2_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
|
||||
BOOST_PROCESS_V2_INITFN_AUTO_RESULT_TYPE(WaitHandler, void (error_code, int))
|
||||
async_wait(WaitHandler && handler BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
|
||||
{
|
||||
return BOOST_PROCESS_V2_ASIO_NAMESPACE::async_compose<WaitHandler, void (error_code, int)>(
|
||||
async_wait_op_{process_handle_, exit_status_}, handler, process_handle_);
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename Executor1>
|
||||
friend struct basic_process;
|
||||
|
||||
basic_process_handle<Executor> process_handle_;
|
||||
native_exit_code_type exit_status_{detail::still_active};
|
||||
|
||||
|
||||
struct async_wait_op_
|
||||
{
|
||||
basic_process_handle<Executor> & handle;
|
||||
native_exit_code_type & res;
|
||||
|
||||
template<typename Self>
|
||||
void operator()(Self && self)
|
||||
{
|
||||
if (!process_is_running(res))
|
||||
{
|
||||
struct completer
|
||||
{
|
||||
int code;
|
||||
typename std::decay<Self>::type self;
|
||||
void operator()()
|
||||
{
|
||||
self.complete(error_code{}, evaluate_exit_code(code));
|
||||
}
|
||||
};
|
||||
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::post(handle.get_executor(),
|
||||
completer{static_cast<int>(res), std::move(self)});
|
||||
}
|
||||
else
|
||||
handle.async_wait(std::move(self));
|
||||
}
|
||||
|
||||
template<typename Self>
|
||||
void operator()(Self && self, error_code ec, native_exit_code_type code)
|
||||
{
|
||||
if (!ec && process_is_running(code))
|
||||
handle.async_wait(std::move(self));
|
||||
else
|
||||
{
|
||||
if (!ec)
|
||||
res = code;
|
||||
std::move(self).complete(ec, evaluate_exit_code(code));
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/// Process with the default executor.
|
||||
typedef basic_process<> process;
|
||||
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
|
||||
#endif //BOOST_PROCESS_V2_PROCESS_HPP
|
||||
169
linx64/include/boost/process/v2/process_handle.hpp
Normal file
169
linx64/include/boost/process/v2/process_handle.hpp
Normal file
@@ -0,0 +1,169 @@
|
||||
// Copyright (c) 2022 Klemens D. Morgenstern
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_PROCESS_V2_PROCESS_HANDLE_HPP
|
||||
#define BOOST_PROCESS_V2_PROCESS_HANDLE_HPP
|
||||
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
#include <boost/process/v2/detail/process_handle_windows.hpp>
|
||||
#else
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_PIDFD_OPEN)
|
||||
#include <boost/process/v2/detail/process_handle_fd.hpp>
|
||||
#elif defined(BOOST_PROCESS_V2_PDFORK)
|
||||
#include <boost/process/v2/detail/process_handle_fd_or_signal.hpp>
|
||||
#else
|
||||
// with asio support we could use EVFILT_PROC:NOTE_EXIT as well.
|
||||
#include <boost/process/v2/detail/process_handle_signal.hpp>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
|
||||
|
||||
#if defined(GENERATING_DOCUMENTATION)
|
||||
/** A process handle is an unmanaged version of a process.
|
||||
* This means it does not terminate the proces on destruction and
|
||||
* will not keep track of the exit-code.
|
||||
*
|
||||
* Note that the exit code might be discovered early, during a call to `running`.
|
||||
* Thus it can only be discovered that process has exited already.
|
||||
*/
|
||||
template<typename Executor = BOOST_PROCESS_V2_ASIO_NAMESPACE::any_io_executor>
|
||||
struct basic_process_handle
|
||||
{
|
||||
/// The native handle of the process.
|
||||
/** This might be undefined on posix systems that only support signals */
|
||||
using native_handle_type = implementation_defined;
|
||||
|
||||
/// The executor_type of the process_handle
|
||||
using executor_type = Executor;
|
||||
|
||||
/// Getter for the executor
|
||||
executor_type get_executor();
|
||||
|
||||
/// Rebinds the process_handle to another executor.
|
||||
template<typename Executor1>
|
||||
struct rebind_executor
|
||||
{
|
||||
/// The socket type when rebound to the specified executor.
|
||||
typedef basic_process_handle<Executor1> other;
|
||||
};
|
||||
|
||||
|
||||
/// Construct a basic_process_handle from an execution_context.
|
||||
/**
|
||||
* @tparam ExecutionContext The context must fulfill the asio::execution_context requirements
|
||||
*/
|
||||
template<typename ExecutionContext>
|
||||
basic_process_handle(ExecutionContext &context);
|
||||
|
||||
/// Construct an empty process_handle from an executor.
|
||||
basic_process_handle(executor_type executor);
|
||||
|
||||
/// Construct an empty process_handle from an executor and bind it to a pid.
|
||||
/** On NON-linux posix systems this call is not able to obtain a file-descriptor and will thus
|
||||
* rely on signals.
|
||||
*/
|
||||
basic_process_handle(executor_type executor, pid_type pid);
|
||||
|
||||
/// Construct an empty process_handle from an executor and bind it to a pid and the native-handle
|
||||
/** On some non-linux posix systems this overload is not present.
|
||||
*/
|
||||
basic_process_handle(executor_type executor, pid_type pid, native_handle_type process_handle);
|
||||
|
||||
/// Move construct and rebind the executor.
|
||||
template<typename Executor1>
|
||||
basic_process_handle(basic_process_handle<Executor1> &&handle);
|
||||
|
||||
/// Get the id of the process
|
||||
pid_type id() const
|
||||
{ return pid_; }
|
||||
|
||||
/// Terminate the process if it's still running and ignore the result
|
||||
void terminate_if_running(error_code &);
|
||||
|
||||
/// Throwing @overload void terminate_if_running(error_code & ec;
|
||||
void terminate_if_running();
|
||||
/// wait for the process to exit and store the exit code in exit_status.
|
||||
void wait(native_exit_code_type &exit_status, error_code &ec);
|
||||
/// Throwing @overload wait(native_exit_code_type &exit_code, error_code & ec)
|
||||
void wait(native_exit_code_type &exit_status);
|
||||
|
||||
/// Sends the process a signal to ask for an interrupt, which the process may interpret as a shutdown.
|
||||
/** Maybe be ignored by the subprocess. */
|
||||
void interrupt(error_code &ec);
|
||||
|
||||
/// Throwing @overload void interrupt()
|
||||
void interrupt();
|
||||
|
||||
/// Sends the process a signal to ask for a graceful shutdown. Maybe be ignored by the subprocess.
|
||||
void request_exit(error_code &ec);
|
||||
|
||||
/// Throwing @overload void request_exit(error_code & ec)
|
||||
void request_exit()
|
||||
|
||||
/// Unconditionally terminates the process and stores the exit code in exit_status.
|
||||
void terminate(native_exit_code_type &exit_status, error_code &ec);\
|
||||
/// Throwing @overload void terminate(native_exit_code_type &exit_code, error_code & ec)
|
||||
void terminate(native_exit_code_type &exit_status);/
|
||||
|
||||
/// Checks if the current process is running.
|
||||
/**If it has already completed, it assigns the exit code to `exit_code`.
|
||||
*/
|
||||
bool running(native_exit_code_type &exit_code, error_code &ec);
|
||||
/// Throwing @overload bool running(native_exit_code_type &exit_code, error_code & ec)
|
||||
bool running(native_exit_code_type &exit_code);
|
||||
|
||||
/// Check if the process handle is referring to an existing process.
|
||||
bool is_open() const;
|
||||
|
||||
/// Asynchronously wait for the process to exit and deliver the native exit-code in the completion handler.
|
||||
template<BOOST_PROCESS_V2_COMPLETION_TOKEN_FOR(void(error_code, native_exit_code_type))
|
||||
WaitHandler BOOST_PROCESS_V2_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
|
||||
BOOST_PROCESS_V2_INITFN_AUTO_RESULT_TYPE(WaitHandler, void (error_code, native_exit_code_type))
|
||||
async_wait(WaitHandler &&handler BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type));
|
||||
|
||||
};
|
||||
|
||||
|
||||
#else
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
template<typename Executor = BOOST_PROCESS_V2_ASIO_NAMESPACE::any_io_executor>
|
||||
using basic_process_handle = detail::basic_process_handle_win<Executor>;
|
||||
#else
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_PIDFD_OPEN)
|
||||
template<typename Executor = BOOST_PROCESS_V2_ASIO_NAMESPACE::any_io_executor>
|
||||
using basic_process_handle = detail::basic_process_handle_fd<Executor>;
|
||||
#elif defined(BOOST_PROCESS_V2_PDFORK)
|
||||
template<typename Executor = BOOST_PROCESS_V2_ASIO_NAMESPACE::any_io_executor>
|
||||
using basic_process_handle = detail::basic_process_handle_fd_or_signal<Executor>;
|
||||
#else
|
||||
|
||||
template<typename Executor = BOOST_PROCESS_V2_ASIO_NAMESPACE::any_io_executor>
|
||||
using basic_process_handle = detail::basic_process_handle_signal<Executor>;
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/// Process handle with the default executor.
|
||||
using process_handle = basic_process_handle<>;
|
||||
|
||||
#endif
|
||||
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_HEADER_ONLY)
|
||||
|
||||
#include <boost/process/v2/impl/process_handle.ipp>
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
#endif //BOOST_PROCESS_V2_PROCESS_HANDLE_HPP
|
||||
149
linx64/include/boost/process/v2/shell.hpp
Normal file
149
linx64/include/boost/process/v2/shell.hpp
Normal file
@@ -0,0 +1,149 @@
|
||||
// Copyright (c) 2022 Klemens D. Morgenstern
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_PROCESS_V2_SHELL_HPP
|
||||
#define BOOST_PROCESS_V2_SHELL_HPP
|
||||
|
||||
#include <boost/core/exchange.hpp>
|
||||
#include <boost/process/v2/cstring_ref.hpp>
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
#include <boost/process/v2/detail/utf8.hpp>
|
||||
#include <boost/process/v2/detail/throw_error.hpp>
|
||||
#include <boost/process/v2/environment.hpp>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
|
||||
/// Error category used by the shell parser.
|
||||
extern BOOST_PROCESS_V2_DECL const error_category& get_shell_category();
|
||||
static const error_category& shell_category = get_shell_category();
|
||||
|
||||
/// Utility to parse commands
|
||||
/** This utility class parses command lines into tokens
|
||||
* and allows users to executed based on textual inputs.
|
||||
*
|
||||
* In v1, this was possible directly when starting a process,
|
||||
* but has been removed based on the security risks associated with this.
|
||||
*
|
||||
* By making the shell parsing explicitly, it encourages
|
||||
* a user to run a sanity check on the executable before launching it.
|
||||
*
|
||||
* @par Example
|
||||
* @code {.cpp}
|
||||
* asio::io_context ctx;
|
||||
*
|
||||
* auto cmd = shell("my-app --help");
|
||||
* auto exe = cmd.exe();
|
||||
* check_if_malicious(exe);
|
||||
*
|
||||
* process proc{ctx, exe, cmd.args()};
|
||||
*
|
||||
* @endcode
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct shell
|
||||
{
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
using char_type = wchar_t;
|
||||
using args_type = const wchar_t *;
|
||||
#else
|
||||
using char_type = char;
|
||||
using args_type = const char **;
|
||||
#endif
|
||||
|
||||
shell() = default;
|
||||
|
||||
template<typename Char, typename Traits>
|
||||
shell(basic_string_view<Char, Traits> input)
|
||||
: buffer_(detail::conv_string<char_type>(input.data(), input.size()))
|
||||
{
|
||||
parse_();
|
||||
}
|
||||
|
||||
shell(basic_cstring_ref<char_type> input) : input_(input) {parse_();}
|
||||
shell(basic_string_view<
|
||||
typename std::conditional<
|
||||
std::is_same<char_type, char>::value,
|
||||
wchar_t, char>::type> input) : buffer_(detail::conv_string<char_type>(input.data(), input.size()))
|
||||
{
|
||||
parse_();
|
||||
}
|
||||
|
||||
shell(const shell &) = delete;
|
||||
shell& operator=(const shell &) = delete;
|
||||
|
||||
shell(shell && lhs) noexcept
|
||||
: buffer_(std::move(lhs.buffer_)),
|
||||
input_(std::move(lhs.input_)),
|
||||
argc_(boost::exchange(lhs.argc_, 0)),
|
||||
argv_(boost::exchange(lhs.argv_, nullptr))
|
||||
#if defined(BOOST_PROCESS_V2_POSIX)
|
||||
, free_argv_(boost::exchange(lhs.free_argv_, nullptr))
|
||||
#endif
|
||||
{
|
||||
}
|
||||
shell& operator=(shell && lhs) noexcept
|
||||
{
|
||||
shell tmp(std::move(*this));
|
||||
buffer_ = std::move(lhs.buffer_);
|
||||
input_ = std::move(lhs.input_);
|
||||
argc_ = boost::exchange(lhs.argc_, 0);
|
||||
argv_ = boost::exchange(lhs.argv_, nullptr);
|
||||
#if defined(BOOST_PROCESS_V2_POSIX)
|
||||
free_argv_ = boost::exchange(lhs.free_argv_, nullptr);
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
// the length of the parsed shell, including the executable
|
||||
int argc() const { return argc_; }
|
||||
char_type** argv() const { return argv_; }
|
||||
|
||||
char_type** begin() const {return argv();}
|
||||
char_type** end() const {return argv() + argc();}
|
||||
|
||||
bool empty() const {return argc() == 0;}
|
||||
std::size_t size() const {return static_cast<std::size_t>(argc()); }
|
||||
/// Native representation of the arguments to be used - excluding the executable
|
||||
BOOST_PROCESS_V2_DECL args_type args() const;
|
||||
template<typename Environment = environment::current_view>
|
||||
filesystem::path exe(Environment && env = environment::current()) const
|
||||
{
|
||||
if (argc() == 0)
|
||||
return "";
|
||||
else
|
||||
return environment::find_executable(0[argv()], std::forward<Environment>(env));
|
||||
}
|
||||
BOOST_PROCESS_V2_DECL ~shell();
|
||||
|
||||
private:
|
||||
|
||||
friend struct make_cmd_shell_;
|
||||
|
||||
BOOST_PROCESS_V2_DECL void parse_();
|
||||
|
||||
// storage in case we need a conversion
|
||||
std::basic_string<char_type> buffer_;
|
||||
basic_cstring_ref<char_type> input_{buffer_};
|
||||
// impl details
|
||||
int argc_ = 0;
|
||||
char_type ** argv_ = nullptr;
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_POSIX)
|
||||
void(*free_argv_)(int, char **);
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_HEADER_ONLY)
|
||||
|
||||
#include <boost/process/v2/impl/shell.ipp>
|
||||
|
||||
#endif
|
||||
|
||||
#endif //BOOST_PROCESS_V2_ERROR_HPP
|
||||
32
linx64/include/boost/process/v2/src.hpp
Normal file
32
linx64/include/boost/process/v2/src.hpp
Normal file
@@ -0,0 +1,32 @@
|
||||
// Copyright (c) 2021 Klemens D. Morgenstern
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_PROCESS_V2_SRC_HPP
|
||||
#define BOOST_PROCESS_V2_SRC_HPP
|
||||
|
||||
#define BOOST_PROCESS_V2_SOURCE
|
||||
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_HEADER_ONLY)
|
||||
# error Do not compile Process V2 library source with BOOST_PROCESS_V2_HEADER_ONLY defined. You should probably define BOOST_PROCESS_V2_SEPARATE_COMPILATION
|
||||
#endif
|
||||
|
||||
#include <boost/process/v2/impl/error.ipp>
|
||||
#include <boost/process/v2/impl/pid.ipp>
|
||||
#include <boost/process/v2/ext/impl/exe.ipp>
|
||||
#include <boost/process/v2/ext/impl/cwd.ipp>
|
||||
#include <boost/process/v2/ext/impl/cmd.ipp>
|
||||
#include <boost/process/v2/ext/impl/env.ipp>
|
||||
#include <boost/process/v2/ext/detail/impl/proc_info.ipp>
|
||||
#include <boost/process/v2/detail/impl/environment.ipp>
|
||||
#include <boost/process/v2/detail/impl/last_error.ipp>
|
||||
#include <boost/process/v2/detail/impl/throw_error.ipp>
|
||||
#include <boost/process/v2/detail/impl/utf8.ipp>
|
||||
#include <boost/process/v2/impl/default_launcher.ipp>
|
||||
#include <boost/process/v2/impl/environment.ipp>
|
||||
#include <boost/process/v2/impl/process_handle.ipp>
|
||||
#include <boost/process/v2/impl/shell.ipp>
|
||||
|
||||
#endif //BOOST_PROCESS_V2_SRC_HPP
|
||||
51
linx64/include/boost/process/v2/start_dir.hpp
Normal file
51
linx64/include/boost/process/v2/start_dir.hpp
Normal file
@@ -0,0 +1,51 @@
|
||||
//
|
||||
// process/start_dir.hpp
|
||||
// ~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2021 Klemens D. Morgenstern (klemens dot morgenstern at gmx dot net)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_PROCESS_v2_START_DIR_HPP
|
||||
#define BOOST_PROCESS_v2_START_DIR_HPP
|
||||
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
#include <boost/process/v2/detail/last_error.hpp>
|
||||
#include <boost/process/v2/default_launcher.hpp>
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
|
||||
/// Initializer for the starting directory of a subprocess to be launched.
|
||||
struct process_start_dir
|
||||
{
|
||||
filesystem::path start_dir;
|
||||
|
||||
process_start_dir(filesystem::path start_dir) : start_dir(std::move(start_dir))
|
||||
{
|
||||
}
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
error_code on_setup(windows::default_launcher & launcher,
|
||||
const filesystem::path &, const std::wstring &)
|
||||
{
|
||||
launcher.current_directory = start_dir;
|
||||
return error_code {};
|
||||
};
|
||||
|
||||
#else
|
||||
error_code on_exec_setup(posix::default_launcher & launcher,
|
||||
const filesystem::path &, const char * const *)
|
||||
{
|
||||
if (::chdir(start_dir.c_str()) == -1)
|
||||
return detail::get_last_error();
|
||||
else
|
||||
return error_code ();
|
||||
}
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#endif // BOOST_PROCESS_v2_START_DIR_HPP
|
||||
334
linx64/include/boost/process/v2/stdio.hpp
Normal file
334
linx64/include/boost/process/v2/stdio.hpp
Normal file
@@ -0,0 +1,334 @@
|
||||
//
|
||||
// process/stdio.hpp
|
||||
// ~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2021 Klemens D. Morgenstern (klemens dot morgenstern at gmx dot net)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_PROCESS_V2_STDIO_HPP
|
||||
#define BOOST_PROCESS_V2_STDIO_HPP
|
||||
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
#include <boost/process/v2/detail/last_error.hpp>
|
||||
#include <boost/process/v2/default_launcher.hpp>
|
||||
#include <cstddef>
|
||||
#if defined(BOOST_PROCESS_V2_STANDALONE)
|
||||
#include <asio/connect_pipe.hpp>
|
||||
#else
|
||||
#include <boost/asio/connect_pipe.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_POSIX)
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
namespace detail
|
||||
{
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
|
||||
extern "C" intptr_t _get_osfhandle(int fd);
|
||||
|
||||
struct handle_closer
|
||||
{
|
||||
handle_closer() = default;
|
||||
handle_closer(bool close) : close(close) {}
|
||||
handle_closer(DWORD flags) : close(false), flags{flags} {}
|
||||
|
||||
|
||||
void operator()(HANDLE h) const
|
||||
{
|
||||
if (close)
|
||||
::CloseHandle(h);
|
||||
else if (flags != 0xFFFFFFFFu)
|
||||
::SetHandleInformation(h, 0xFFFFFFFFu, flags);
|
||||
|
||||
}
|
||||
|
||||
bool close{false};
|
||||
DWORD flags{0xFFFFFFFFu};
|
||||
};
|
||||
|
||||
template<DWORD Target>
|
||||
struct process_io_binding
|
||||
{
|
||||
HANDLE prepare()
|
||||
{
|
||||
auto hh = h.get();
|
||||
::SetHandleInformation(hh, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT);
|
||||
return hh;
|
||||
}
|
||||
|
||||
std::unique_ptr<void, handle_closer> h{::GetStdHandle(Target), false};
|
||||
|
||||
static DWORD get_flags(HANDLE h)
|
||||
{
|
||||
DWORD res;
|
||||
if (!::GetHandleInformation(h, &res))
|
||||
{
|
||||
error_code ec;
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
throw system_error(ec, "get_flags");
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
process_io_binding() = default;
|
||||
|
||||
template<typename Stream>
|
||||
process_io_binding(Stream && str, decltype(std::declval<Stream>().native_handle()) = nullptr)
|
||||
: process_io_binding(str.native_handle())
|
||||
{}
|
||||
|
||||
process_io_binding(FILE * f) : process_io_binding(_get_osfhandle(_fileno(f))) {}
|
||||
process_io_binding(HANDLE h) : h{h, get_flags(h)} {}
|
||||
process_io_binding(std::nullptr_t) : process_io_binding(filesystem::path("NUL")) {}
|
||||
template<typename T, typename = typename std::enable_if<std::is_same<T, filesystem::path>::value>::type>
|
||||
process_io_binding(const T & pth)
|
||||
: h(::CreateFileW(
|
||||
pth.c_str(),
|
||||
Target == STD_INPUT_HANDLE ? GENERIC_READ : GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
nullptr,
|
||||
OPEN_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
nullptr
|
||||
), true)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
template<typename Executor>
|
||||
process_io_binding(BOOST_PROCESS_V2_ASIO_NAMESPACE::basic_readable_pipe<Executor> & pipe)
|
||||
{
|
||||
if (Target == STD_INPUT_HANDLE)
|
||||
{
|
||||
auto h_ = pipe.native_handle();
|
||||
h = std::unique_ptr<void, handle_closer>{h_, get_flags(h_)};
|
||||
return ;
|
||||
}
|
||||
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::detail::native_pipe_handle p[2];
|
||||
error_code ec;
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::detail::create_pipe(p, ec);
|
||||
if (ec)
|
||||
detail::throw_error(ec, "create_pipe");
|
||||
|
||||
h = std::unique_ptr<void, handle_closer>{p[1], true};
|
||||
pipe.assign(p[0]);
|
||||
}
|
||||
|
||||
|
||||
template<typename Executor>
|
||||
process_io_binding(BOOST_PROCESS_V2_ASIO_NAMESPACE::basic_writable_pipe<Executor> & pipe)
|
||||
{
|
||||
if (Target != STD_INPUT_HANDLE)
|
||||
{
|
||||
auto h_ = pipe.native_handle();
|
||||
h = std::unique_ptr<void, handle_closer>{h_, get_flags(h_)};
|
||||
return ;
|
||||
}
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::detail::native_pipe_handle p[2];
|
||||
error_code ec;
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::detail::create_pipe(p, ec);
|
||||
if (ec)
|
||||
detail::throw_error(ec, "create_pipe");
|
||||
|
||||
h = std::unique_ptr<void, handle_closer>{p[0], true};
|
||||
pipe.assign(p[1]);
|
||||
}
|
||||
};
|
||||
|
||||
typedef process_io_binding<STD_INPUT_HANDLE> process_input_binding;
|
||||
typedef process_io_binding<STD_OUTPUT_HANDLE> process_output_binding;
|
||||
typedef process_io_binding<STD_ERROR_HANDLE> process_error_binding;
|
||||
|
||||
#else
|
||||
|
||||
template<int Target>
|
||||
struct process_io_binding
|
||||
{
|
||||
constexpr static int target = Target;
|
||||
int fd{target};
|
||||
bool fd_needs_closing{false};
|
||||
error_code ec;
|
||||
|
||||
~process_io_binding()
|
||||
{
|
||||
if (fd_needs_closing)
|
||||
::close(fd);
|
||||
}
|
||||
|
||||
process_io_binding() = default;
|
||||
|
||||
template<typename Stream>
|
||||
process_io_binding(Stream && str, decltype(std::declval<Stream>().native_handle()) = -1)
|
||||
: process_io_binding(str.native_handle())
|
||||
{}
|
||||
|
||||
process_io_binding(FILE * f) : process_io_binding(fileno(f)) {}
|
||||
process_io_binding(int fd) : fd(fd) {}
|
||||
process_io_binding(std::nullptr_t) : process_io_binding(filesystem::path("/dev/null")) {}
|
||||
process_io_binding(const filesystem::path & pth)
|
||||
: fd(::open(pth.c_str(),
|
||||
Target == STDIN_FILENO ? O_RDONLY : (O_WRONLY | O_CREAT),
|
||||
0660)), fd_needs_closing(true)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename Executor>
|
||||
process_io_binding(BOOST_PROCESS_V2_ASIO_NAMESPACE::basic_readable_pipe<Executor> & readable_pipe)
|
||||
{
|
||||
if (Target == STDIN_FILENO)
|
||||
{
|
||||
fd = readable_pipe.native_handle();
|
||||
return ;
|
||||
}
|
||||
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::detail::native_pipe_handle p[2];
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::detail::create_pipe(p, ec);
|
||||
if (ec)
|
||||
detail::throw_error(ec, "create_pipe");
|
||||
|
||||
fd = p[1];
|
||||
if (::fcntl(p[0], F_SETFD, FD_CLOEXEC) == -1)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return ;
|
||||
}
|
||||
fd_needs_closing = true;
|
||||
readable_pipe.assign(p[0], ec);
|
||||
}
|
||||
|
||||
|
||||
template<typename Executor>
|
||||
process_io_binding(BOOST_PROCESS_V2_ASIO_NAMESPACE::basic_writable_pipe<Executor> & writable_pipe)
|
||||
{
|
||||
|
||||
if (Target != STDIN_FILENO)
|
||||
{
|
||||
fd = writable_pipe.native_handle();
|
||||
return ;
|
||||
}
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::detail::native_pipe_handle p[2];
|
||||
error_code ec;
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::detail::create_pipe(p, ec);
|
||||
if (ec)
|
||||
detail::throw_error(ec, "create_pipe");
|
||||
|
||||
fd = p[0];
|
||||
if (::fcntl(p[1], F_SETFD, FD_CLOEXEC) == -1)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return ;
|
||||
}
|
||||
fd_needs_closing = true;
|
||||
writable_pipe.assign(p[1], ec);
|
||||
}
|
||||
|
||||
error_code on_setup(posix::default_launcher &,
|
||||
const filesystem::path &, const char * const *)
|
||||
{
|
||||
return ec;
|
||||
}
|
||||
|
||||
error_code on_exec_setup(posix::default_launcher & launcher,
|
||||
const filesystem::path &, const char * const *)
|
||||
{
|
||||
if (::dup2(fd, target) == -1)
|
||||
return get_last_error();
|
||||
else
|
||||
return error_code();
|
||||
}
|
||||
};
|
||||
|
||||
typedef process_io_binding<STDIN_FILENO> process_input_binding;
|
||||
typedef process_io_binding<STDOUT_FILENO> process_output_binding;
|
||||
typedef process_io_binding<STDERR_FILENO> process_error_binding;
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// The initializer for the stdio of a subprocess
|
||||
/** The subprocess initializer has three members:
|
||||
*
|
||||
* - in for stdin
|
||||
* - out for stdout
|
||||
* - err for stderr
|
||||
*
|
||||
* If the initializer is present all three will be set for the subprocess.
|
||||
* By default they will inherit the stdio handles from the parent process.
|
||||
* This means that this will forward stdio to the subprocess:
|
||||
*
|
||||
* @code {.cpp}
|
||||
* asio::io_context ctx;
|
||||
* v2::process proc(ctx, "/bin/bash", {}, v2::process_stdio{});
|
||||
* @endcode
|
||||
*
|
||||
* No constructors are provided in order to support designated initializers
|
||||
* in later version of C++.
|
||||
*
|
||||
* * @code {.cpp}
|
||||
* asio::io_context ctx;
|
||||
* /// C++17
|
||||
* v2::process proc17(ctx, "/bin/bash", {}, v2::process_stdio{.stderr=nullptr});
|
||||
* /// C++11 & C++14
|
||||
* v2::process proc17(ctx, "/bin/bash", {}, v2::process_stdio{ {}, {}, nullptr});
|
||||
* stdin ^ ^ stderr
|
||||
* @endcode
|
||||
*
|
||||
* Valid initializers for any stdio are:
|
||||
*
|
||||
* - `std::nullptr_t` assigning a null-device
|
||||
* - `FILE*` any open file, including `stdin`, `stdout` and `stderr`
|
||||
* - a filesystem::path, which will open a readable or writable depending on the direction of the stream
|
||||
* - `native_handle` any native file handle (`HANDLE` on windows) or file descriptor (`int` on posix)
|
||||
* - any io-object with a .native_handle() function that is compatible with the above. E.g. a asio::ip::tcp::socket
|
||||
* - an asio::basic_writeable_pipe for stdin or asio::basic_readable_pipe for stderr/stdout.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct process_stdio
|
||||
{
|
||||
detail::process_input_binding in;
|
||||
detail::process_output_binding out;
|
||||
detail::process_error_binding err;
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
error_code on_setup(windows::default_launcher & launcher, const filesystem::path &, const std::wstring &)
|
||||
{
|
||||
|
||||
launcher.startup_info.StartupInfo.dwFlags |= STARTF_USESTDHANDLES;
|
||||
launcher.startup_info.StartupInfo.hStdInput = in.prepare();
|
||||
launcher.startup_info.StartupInfo.hStdOutput = out.prepare();
|
||||
launcher.startup_info.StartupInfo.hStdError = err.prepare();
|
||||
launcher.inherit_handles = true;
|
||||
return error_code {};
|
||||
};
|
||||
#else
|
||||
error_code on_exec_setup(posix::default_launcher & launcher, const filesystem::path &, const char * const *)
|
||||
{
|
||||
if (::dup2(in.fd, in.target) == -1)
|
||||
return error_code(errno, system_category());
|
||||
|
||||
if (::dup2(out.fd, out.target) == -1)
|
||||
return error_code(errno, system_category());
|
||||
|
||||
if (::dup2(err.fd, err.target) == -1)
|
||||
return error_code(errno, system_category());
|
||||
|
||||
return error_code {};
|
||||
};
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#endif // BOOST_PROCESS_V2_STDIO_HPP
|
||||
136
linx64/include/boost/process/v2/windows/as_user_launcher.hpp
Normal file
136
linx64/include/boost/process/v2/windows/as_user_launcher.hpp
Normal file
@@ -0,0 +1,136 @@
|
||||
//
|
||||
// boost/process/v2/windows/default_launcher.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2022 Klemens D. Morgenstern (klemens dot morgenstern at gmx dot net)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BOOST_PROCESS_V2_WINDOWS_AS_USER_LAUNCHER_HPP
|
||||
#define BOOST_PROCESS_V2_WINDOWS_AS_USER_LAUNCHER_HPP
|
||||
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
#include <boost/process/v2/windows/default_launcher.hpp>
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
namespace windows
|
||||
{
|
||||
|
||||
/// A windows launcher using CreateProcessAsUser instead of CreateProcess
|
||||
struct as_user_launcher : default_launcher
|
||||
{
|
||||
/// The token to be used in CreateProcessAsUser.
|
||||
HANDLE token;
|
||||
as_user_launcher(HANDLE token = INVALID_HANDLE_VALUE) : token(token) {}
|
||||
|
||||
template<typename ExecutionContext, typename Args, typename ... Inits>
|
||||
auto operator()(ExecutionContext & context,
|
||||
const typename std::enable_if<std::is_convertible<
|
||||
ExecutionContext&, BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context&>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<typename ExecutionContext::executor_type>
|
||||
{
|
||||
error_code ec;
|
||||
auto proc = (*this)(context, ec, executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
|
||||
|
||||
if (ec)
|
||||
v2::detail::throw_error(ec, "as_user_launcher");
|
||||
|
||||
return proc;
|
||||
}
|
||||
|
||||
|
||||
template<typename ExecutionContext, typename Args, typename ... Inits>
|
||||
auto operator()(ExecutionContext & context,
|
||||
error_code & ec,
|
||||
const typename std::enable_if<std::is_convertible<
|
||||
ExecutionContext&, BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context&>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<typename ExecutionContext::executor_type>
|
||||
{
|
||||
return (*this)(context.get_executor(), executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
|
||||
}
|
||||
|
||||
template<typename Executor, typename Args, typename ... Inits>
|
||||
auto operator()(Executor exec,
|
||||
const typename std::enable_if<
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::execution::is_executor<Executor>::value ||
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::is_executor<Executor>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<Executor>
|
||||
{
|
||||
error_code ec;
|
||||
auto proc = (*this)(std::move(exec), ec, executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
|
||||
|
||||
if (ec)
|
||||
detail::throw_error(ec, "as_user_launcher");
|
||||
|
||||
return proc;
|
||||
}
|
||||
|
||||
template<typename Executor, typename Args, typename ... Inits>
|
||||
auto operator()(Executor exec,
|
||||
error_code & ec,
|
||||
const typename std::enable_if<
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::execution::is_executor<Executor>::value ||
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::is_executor<Executor>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<Executor>
|
||||
{
|
||||
auto command_line = this->build_command_line(executable, args);
|
||||
|
||||
ec = detail::on_setup(*this, executable, command_line, inits...);
|
||||
if (ec)
|
||||
{
|
||||
detail::on_error(*this, executable, command_line, ec, inits...);
|
||||
return basic_process<Executor>(exec);
|
||||
}
|
||||
auto ok = ::CreateProcessAsUserW(
|
||||
token,
|
||||
executable.empty() ? nullptr : executable.c_str(),
|
||||
command_line.empty() ? nullptr : &command_line.front(),
|
||||
process_attributes,
|
||||
thread_attributes,
|
||||
inherit_handles ? TRUE : FALSE,
|
||||
creation_flags,
|
||||
environment,
|
||||
current_directory.empty() ? nullptr : current_directory.c_str(),
|
||||
&startup_info.StartupInfo,
|
||||
&process_information);
|
||||
|
||||
|
||||
if (ok == 0)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
detail::on_error(*this, executable, command_line, ec, inits...);
|
||||
|
||||
if (process_information.hProcess != INVALID_HANDLE_VALUE)
|
||||
::CloseHandle(process_information.hProcess);
|
||||
if (process_information.hThread != INVALID_HANDLE_VALUE)
|
||||
::CloseHandle(process_information.hThread);
|
||||
|
||||
return basic_process<Executor>(exec);
|
||||
} else
|
||||
{
|
||||
detail::on_success(*this, executable, command_line, inits...);
|
||||
|
||||
if (process_information.hThread != INVALID_HANDLE_VALUE)
|
||||
::CloseHandle(process_information.hThread);
|
||||
|
||||
return basic_process<Executor>(exec,
|
||||
this->process_information.dwProcessId,
|
||||
this->process_information.hProcess);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#endif // BOOST_PROCESS_V2_WINDOWS_AS_USER_LAUNCHER_HPP
|
||||
45
linx64/include/boost/process/v2/windows/creation_flags.hpp
Normal file
45
linx64/include/boost/process/v2/windows/creation_flags.hpp
Normal file
@@ -0,0 +1,45 @@
|
||||
//
|
||||
// boost/process/v2/windows/default_launcher.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2022 Klemens D. Morgenstern (klemens dot morgenstern at gmx dot net)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BOOST_PROCESS_V2_WINDOWS_CREATION_FLAGS_HPP
|
||||
#define BOOST_PROCESS_V2_WINDOWS_CREATION_FLAGS_HPP
|
||||
|
||||
#include <boost/process/v2/windows/default_launcher.hpp>
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
namespace windows
|
||||
{
|
||||
|
||||
|
||||
/// An initializers to add to the dwFlags in the startup-info
|
||||
/**
|
||||
* @tparam Flags The flags to be set.
|
||||
*/
|
||||
template<DWORD Flags>
|
||||
struct process_creation_flags
|
||||
{
|
||||
constexpr process_creation_flags () {}
|
||||
|
||||
error_code on_setup(windows::default_launcher & launcher,
|
||||
const filesystem::path &,
|
||||
const std::wstring &) const
|
||||
{
|
||||
launcher.startup_info.StartupInfo.dwFlags |= Flags;
|
||||
return error_code {};
|
||||
};
|
||||
};
|
||||
|
||||
/// A flag to create a new process group. Necessary to allow interrupts for the subprocess.
|
||||
constexpr static process_creation_flags<CREATE_NEW_PROCESS_GROUP> create_new_process_group;
|
||||
|
||||
}
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#endif // BOOST_PROCESS_V2_WINDOWS_CREATION_FLAGS_HPP
|
||||
416
linx64/include/boost/process/v2/windows/default_launcher.hpp
Normal file
416
linx64/include/boost/process/v2/windows/default_launcher.hpp
Normal file
@@ -0,0 +1,416 @@
|
||||
//
|
||||
// boost/process/v2/windows/default_launcher.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2022 Klemens D. Morgenstern (klemens dot morgenstern at gmx dot net)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BOOST_PROCESS_V2_WINDOWS_DEFAULT_LAUNCHER_HPP
|
||||
#define BOOST_PROCESS_V2_WINDOWS_DEFAULT_LAUNCHER_HPP
|
||||
|
||||
#include <boost/process/v2/cstring_ref.hpp>
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
#include <boost/process/v2/detail/last_error.hpp>
|
||||
#include <boost/process/v2/detail/throw_error.hpp>
|
||||
#include <boost/process/v2/detail/utf8.hpp>
|
||||
#include <boost/process/v2/error.hpp>
|
||||
|
||||
#include <numeric>
|
||||
#include <windows.h>
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_STANDALONE)
|
||||
#include <asio/execution/executor.hpp>
|
||||
#include <asio/is_executor.hpp>
|
||||
#include <asio/execution_context.hpp>
|
||||
#else
|
||||
#include <boost/asio/execution/executor.hpp>
|
||||
#include <boost/asio/is_executor.hpp>
|
||||
#include <boost/asio/execution_context.hpp>
|
||||
#endif
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
|
||||
template<typename Executor>
|
||||
struct basic_process;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
struct base {};
|
||||
struct derived : base {};
|
||||
|
||||
template<typename Launcher, typename Init>
|
||||
inline error_code invoke_on_setup(Launcher & launcher, const filesystem::path &executable, std::wstring &cmd_line,
|
||||
Init && init, base && )
|
||||
{
|
||||
return error_code{};
|
||||
}
|
||||
|
||||
template<typename Launcher, typename Init>
|
||||
inline auto invoke_on_setup(Launcher & launcher, const filesystem::path &executable, std::wstring &cmd_line,
|
||||
Init && init, derived && )
|
||||
-> decltype(init.on_setup(launcher, executable, cmd_line))
|
||||
{
|
||||
return init.on_setup(launcher, executable, cmd_line);
|
||||
}
|
||||
|
||||
template<typename Launcher, typename Init>
|
||||
inline std::false_type probe_on_setup(
|
||||
Launcher & launcher, Init && init, base && );
|
||||
|
||||
template<typename Launcher, typename Init>
|
||||
inline auto probe_on_setup(Launcher & launcher, Init && init, derived && )
|
||||
-> std::is_same<error_code, decltype(init.on_setup(launcher, std::declval<const filesystem::path &>(), std::declval<std::wstring &>()))>;
|
||||
|
||||
template<typename Launcher, typename Init>
|
||||
using has_on_setup = decltype(probe_on_setup(std::declval<Launcher&>(), std::declval<Init>(), derived{}));
|
||||
|
||||
template<typename Launcher>
|
||||
inline error_code on_setup(Launcher & launcher, const filesystem::path &executable, std::wstring &cmd_line)
|
||||
{
|
||||
return error_code{};
|
||||
}
|
||||
|
||||
template<typename Launcher, typename Init1, typename ... Inits>
|
||||
inline error_code on_setup(Launcher & launcher, const filesystem::path &executable, std::wstring &cmd_line,
|
||||
Init1 && init1, Inits && ... inits)
|
||||
{
|
||||
auto ec = invoke_on_setup(launcher, executable, cmd_line, init1, derived{});
|
||||
if (ec)
|
||||
return ec;
|
||||
else
|
||||
return on_setup(launcher, executable, cmd_line, inits...);
|
||||
}
|
||||
|
||||
|
||||
template<typename Launcher, typename Init>
|
||||
inline void invoke_on_error(Launcher & launcher, const filesystem::path &executable, std::wstring &cmd_line,
|
||||
const error_code & ec, Init && init, base && )
|
||||
{
|
||||
}
|
||||
|
||||
template<typename Launcher, typename Init>
|
||||
inline auto invoke_on_error(Launcher & launcher, const filesystem::path &executable, std::wstring &cmd_line,
|
||||
const error_code & ec, Init && init, derived && )
|
||||
-> decltype(init.on_error(launcher, ec, executable, cmd_line, ec))
|
||||
{
|
||||
init.on_error(launcher, executable, cmd_line, ec);
|
||||
}
|
||||
|
||||
|
||||
template<typename Launcher, typename Init>
|
||||
inline std::false_type probe_on_error(
|
||||
Launcher & launcher, Init && init, base && );
|
||||
|
||||
template<typename Launcher, typename Init>
|
||||
inline auto probe_on_error(Launcher & launcher, Init && init, derived && )
|
||||
-> std::is_same<error_code, decltype(init.on_error(launcher, std::declval<const filesystem::path &>(), std::declval<std::wstring &>(), std::declval<std::error_code&>()))>;
|
||||
|
||||
template<typename Launcher, typename Init>
|
||||
using has_on_error = decltype(probe_on_error(std::declval<Launcher&>(), std::declval<Init>(), derived{}));
|
||||
|
||||
|
||||
template<typename Launcher>
|
||||
inline void on_error(Launcher & launcher, const filesystem::path &executable, std::wstring &cmd_line,
|
||||
const error_code & ec)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename Launcher, typename Init1, typename ... Inits>
|
||||
inline void on_error(Launcher & launcher, const filesystem::path &executable, std::wstring &cmd_line,
|
||||
const error_code & ec,
|
||||
Init1 && init1,
|
||||
Inits && ... inits)
|
||||
{
|
||||
invoke_on_error(launcher, executable, cmd_line, ec, init1, derived{});
|
||||
on_error(launcher, executable, cmd_line, ec, inits...);
|
||||
}
|
||||
|
||||
template<typename Launcher, typename Init>
|
||||
inline void invoke_on_success(Launcher & launcher, const filesystem::path &executable, std::wstring &cmd_line,
|
||||
Init && init, base && )
|
||||
{
|
||||
}
|
||||
|
||||
template<typename Launcher, typename Init>
|
||||
inline auto invoke_on_success(Launcher & launcher, const filesystem::path &executable, std::wstring &cmd_line,
|
||||
Init && init, derived && )
|
||||
-> decltype(init.on_success(launcher, executable, cmd_line))
|
||||
{
|
||||
init.on_success(launcher, executable, cmd_line);
|
||||
}
|
||||
|
||||
template<typename Launcher, typename Init>
|
||||
inline std::false_type probe_on_success(
|
||||
Launcher & launcher, Init && init, base && );
|
||||
|
||||
template<typename Launcher, typename Init>
|
||||
inline auto probe_on_success(Launcher & launcher, Init && init, derived && )
|
||||
-> std::is_same<error_code, decltype(init.on_success(launcher, std::declval<const filesystem::path &>(), std::declval<std::wstring &>()))>;
|
||||
|
||||
template<typename Launcher, typename Init>
|
||||
using has_on_success = decltype(probe_on_success(std::declval<Launcher&>(), std::declval<Init>(), derived{}));
|
||||
|
||||
template<typename Launcher>
|
||||
inline void on_success(Launcher & launcher, const filesystem::path &executable, std::wstring &cmd_line)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename Launcher, typename Init1, typename ... Inits>
|
||||
inline void on_success(Launcher & launcher, const filesystem::path &executable, std::wstring &cmd_line,
|
||||
Init1 && init1, Inits && ... inits)
|
||||
{
|
||||
invoke_on_success(launcher, executable, cmd_line, init1, derived{});
|
||||
on_success(launcher, executable, cmd_line, inits...);
|
||||
}
|
||||
|
||||
template<typename Launcher, typename Init>
|
||||
struct is_initializer : std::integral_constant<bool,
|
||||
has_on_setup<Launcher, Init>::value ||
|
||||
has_on_error<Launcher, Init>::value ||
|
||||
has_on_success<Launcher, Init>::value>
|
||||
{
|
||||
};
|
||||
|
||||
template<typename Launcher, typename ... Inits>
|
||||
struct all_are_initializers;
|
||||
|
||||
template<typename Launcher>
|
||||
struct all_are_initializers<Launcher> : std::true_type {};
|
||||
|
||||
|
||||
template<typename Launcher, typename Init>
|
||||
struct all_are_initializers<Launcher, Init> : is_initializer<Launcher, Init> {};
|
||||
|
||||
template<typename Launcher, typename Init, typename ... Tail>
|
||||
struct all_are_initializers<Launcher, Init, Tail...>
|
||||
: std::integral_constant<bool, is_initializer<Launcher, Init>::value && all_are_initializers<Launcher, Tail...>::value>
|
||||
{
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
template<typename Executor>
|
||||
struct basic_process;
|
||||
|
||||
namespace windows
|
||||
{
|
||||
|
||||
/// The default launcher for processes on windows.
|
||||
struct default_launcher
|
||||
{
|
||||
//// The process_attributes passed to CreateProcess
|
||||
SECURITY_ATTRIBUTES * process_attributes = nullptr;
|
||||
//// The thread_attributes passed to CreateProcess
|
||||
SECURITY_ATTRIBUTES * thread_attributes = nullptr;
|
||||
/// The bInheritHandles option. Needs to be set to true by any initializers using handles.
|
||||
bool inherit_handles = false;
|
||||
/// The creation flags of the process. Initializers may add to them; extended startupinfo is assumed.
|
||||
DWORD creation_flags{EXTENDED_STARTUPINFO_PRESENT};
|
||||
/// A pointer to the subprocess environment.
|
||||
void * environment = nullptr;
|
||||
/// The startup director. An empty path will get ignored.
|
||||
filesystem::path current_directory{};
|
||||
|
||||
/// The full startup info passed to CreateProcess
|
||||
STARTUPINFOEXW startup_info{{sizeof(STARTUPINFOEXW), nullptr, nullptr, nullptr,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, nullptr,
|
||||
INVALID_HANDLE_VALUE,
|
||||
INVALID_HANDLE_VALUE,
|
||||
INVALID_HANDLE_VALUE},
|
||||
nullptr};
|
||||
/// The process_information that gets assigned after a call to CreateProcess
|
||||
PROCESS_INFORMATION process_information{nullptr, nullptr, 0,0};
|
||||
|
||||
template<typename Executor, typename ... Inits>
|
||||
using enable_init = typename std::enable_if<
|
||||
detail::all_are_initializers<default_launcher, Inits...>::value,
|
||||
basic_process<Executor>>::type;
|
||||
|
||||
default_launcher() = default;
|
||||
|
||||
template<typename ExecutionContext, typename Args, typename ... Inits>
|
||||
auto operator()(ExecutionContext & context,
|
||||
const typename std::enable_if<std::is_convertible<
|
||||
ExecutionContext&, BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context&>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> enable_init<typename ExecutionContext::executor_type, Inits...>
|
||||
{
|
||||
error_code ec;
|
||||
auto proc = (*this)(context, ec, executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
|
||||
|
||||
if (ec)
|
||||
v2::detail::throw_error(ec, "default_launcher");
|
||||
|
||||
return proc;
|
||||
}
|
||||
|
||||
|
||||
template<typename ExecutionContext, typename Args, typename ... Inits>
|
||||
auto operator()(ExecutionContext & context,
|
||||
error_code & ec,
|
||||
const typename std::enable_if<std::is_convertible<
|
||||
ExecutionContext&, BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context&>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> enable_init<typename ExecutionContext::executor_type, Inits...>
|
||||
{
|
||||
return (*this)(context.get_executor(), ec, executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
|
||||
}
|
||||
|
||||
template<typename Executor, typename Args, typename ... Inits>
|
||||
auto operator()(Executor exec,
|
||||
const typename std::enable_if<
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::execution::is_executor<Executor>::value
|
||||
|| BOOST_PROCESS_V2_ASIO_NAMESPACE::is_executor<Executor>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> enable_init<Executor, Inits...>
|
||||
{
|
||||
error_code ec;
|
||||
auto proc = (*this)(std::move(exec), ec, executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
|
||||
|
||||
if (ec)
|
||||
detail::throw_error(ec, "default_launcher");
|
||||
|
||||
return proc;
|
||||
}
|
||||
|
||||
template<typename Executor, typename Args, typename ... Inits>
|
||||
auto operator()(Executor exec,
|
||||
error_code & ec,
|
||||
const typename std::enable_if<
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::execution::is_executor<Executor>::value ||
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::is_executor<Executor>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> enable_init<Executor, Inits...>
|
||||
{
|
||||
auto command_line = this->build_command_line(executable, std::forward<Args>(args));
|
||||
|
||||
ec = detail::on_setup(*this, executable, command_line, inits...);
|
||||
if (ec)
|
||||
{
|
||||
detail::on_error(*this, executable, command_line, ec, inits...);
|
||||
return basic_process<Executor>(exec);
|
||||
}
|
||||
|
||||
auto ok = ::CreateProcessW(
|
||||
executable.empty() ? nullptr : executable.c_str(),
|
||||
command_line.empty() ? nullptr : &command_line.front(),
|
||||
process_attributes,
|
||||
thread_attributes,
|
||||
inherit_handles ? TRUE : FALSE,
|
||||
creation_flags,
|
||||
environment,
|
||||
current_directory.empty() ? nullptr : current_directory.c_str(),
|
||||
&startup_info.StartupInfo,
|
||||
&process_information);
|
||||
|
||||
if (ok == 0)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
detail::on_error(*this, executable, command_line, ec, inits...);
|
||||
|
||||
if (process_information.hProcess != INVALID_HANDLE_VALUE)
|
||||
::CloseHandle(process_information.hProcess);
|
||||
if (process_information.hThread != INVALID_HANDLE_VALUE)
|
||||
::CloseHandle(process_information.hThread);
|
||||
|
||||
return basic_process<Executor>(exec);
|
||||
}
|
||||
else
|
||||
{
|
||||
detail::on_success(*this, executable, command_line, inits...);
|
||||
|
||||
if (process_information.hThread != INVALID_HANDLE_VALUE)
|
||||
::CloseHandle(process_information.hThread);
|
||||
|
||||
return basic_process<Executor>(exec,
|
||||
this->process_information.dwProcessId,
|
||||
this->process_information.hProcess);
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_PROCESS_V2_DECL static
|
||||
std::size_t escaped_argv_length(basic_string_view<wchar_t> ws);
|
||||
BOOST_PROCESS_V2_DECL static
|
||||
std::size_t escape_argv_string(wchar_t * itr, std::size_t max_size,
|
||||
basic_string_view<wchar_t> ws);
|
||||
|
||||
|
||||
|
||||
|
||||
template<typename Argv>
|
||||
static std::wstring build_command_line_impl(
|
||||
const filesystem::path & pt,
|
||||
const Argv & argv,
|
||||
basic_string_view<wchar_t> args)
|
||||
{
|
||||
std::size_t req_size = std::accumulate(
|
||||
std::begin(argv), std::end(argv), escaped_argv_length(pt.native()),
|
||||
[](std::size_t sz, basic_string_view<wchar_t> arg) -> std::size_t
|
||||
{
|
||||
return sz + 1u + escaped_argv_length(arg);
|
||||
});
|
||||
|
||||
std::wstring res;
|
||||
res.resize(req_size, L' ');
|
||||
|
||||
wchar_t * itr = &res.front();
|
||||
itr += escape_argv_string(itr, res.size(), pt.native());
|
||||
for (const auto & a : argv)
|
||||
{
|
||||
itr++;
|
||||
itr += escape_argv_string(itr, std::distance(itr, &res.back() + 1), a);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
template<typename Argv>
|
||||
static std::wstring build_command_line_impl(
|
||||
const filesystem::path & pt,
|
||||
const Argv & argv,
|
||||
basic_string_view<char> args)
|
||||
{
|
||||
std::vector<std::wstring> argw;
|
||||
argw.resize(std::distance(std::begin(argv), std::end(argv)));
|
||||
std::transform(std::begin(argv), std::end(argv), argw.begin(),
|
||||
[](basic_string_view <char> arg)
|
||||
{
|
||||
return detail::conv_string<wchar_t>(arg.data(), arg.size());
|
||||
});
|
||||
return build_command_line_impl(pt, argw, L"");
|
||||
}
|
||||
|
||||
template<typename Args,
|
||||
typename Char = decltype(*std::begin(std::declval<Args>()))>
|
||||
static std::wstring build_command_line(const filesystem::path & pt, const Args & args)
|
||||
{
|
||||
if (std::begin(args) == std::end(args))
|
||||
return pt.native();
|
||||
|
||||
return build_command_line_impl(pt, args, *std::begin(args));
|
||||
}
|
||||
|
||||
static std::wstring build_command_line(const filesystem::path & pt, const wchar_t * args)
|
||||
{
|
||||
return args;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_HEADER_ONLY)
|
||||
#include <boost/process/v2/windows/impl/default_launcher.ipp>
|
||||
#endif
|
||||
|
||||
#endif //BOOST_PROCESS_V2_WINDOWS_DEFAULT_LAUNCHER_HPP
|
||||
@@ -0,0 +1,80 @@
|
||||
//
|
||||
// boost/process/v2/windows/impl/default_launcher.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2022 Klemens D. Morgenstern (klemens dot morgenstern at gmx dot net)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#ifndef BOOST_PROCESS_V2_WINDOWS_IMPL_DEFAULT_LAUNCHER_IPP
|
||||
#define BOOST_PROCESS_V2_WINDOWS_IMPL_DEFAULT_LAUNCHER_IPP
|
||||
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
#include <boost/process/v2/windows/default_launcher.hpp>
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
namespace windows
|
||||
{
|
||||
|
||||
std::size_t default_launcher::escaped_argv_length(basic_string_view<wchar_t> ws)
|
||||
{
|
||||
if (ws.empty())
|
||||
return 2u; // just quotes
|
||||
|
||||
constexpr static auto space = L' ';
|
||||
constexpr static auto quote = L'"';
|
||||
|
||||
const auto has_space = ws.find(space) != basic_string_view<wchar_t>::npos;
|
||||
const auto quoted = (ws.front() == quote) && (ws.back() == quote);
|
||||
const auto needs_escape = has_space && !quoted ;
|
||||
|
||||
if (!needs_escape)
|
||||
return ws.size();
|
||||
else
|
||||
return ws.size() + std::count(ws.begin(), ws.end(), quote) + 2u;
|
||||
}
|
||||
|
||||
|
||||
std::size_t default_launcher::escape_argv_string(wchar_t * itr, std::size_t max_size,
|
||||
basic_string_view<wchar_t> ws)
|
||||
{
|
||||
const auto sz = escaped_argv_length(ws);
|
||||
if (sz > max_size)
|
||||
return 0u;
|
||||
if (ws.empty())
|
||||
{
|
||||
itr[0] = L'"';
|
||||
itr[1] = L'"';
|
||||
return 2u;
|
||||
}
|
||||
|
||||
const auto has_space = ws.find(L' ') != basic_string_view<wchar_t>::npos;
|
||||
const auto quoted = (ws.front() == L'"') && (ws.back() == L'"');
|
||||
const auto needs_escape = has_space && !quoted;
|
||||
|
||||
if (!needs_escape)
|
||||
return std::copy(ws.begin(), ws.end(), itr) - itr;
|
||||
|
||||
if (sz < (2u + ws.size()))
|
||||
return 0u;
|
||||
|
||||
const auto end = itr + sz;
|
||||
const auto begin = itr;
|
||||
*(itr ++) = L'"';
|
||||
for (auto wc : ws)
|
||||
{
|
||||
if (wc == L'"')
|
||||
*(itr++) = L'\\';
|
||||
*(itr++) = wc;
|
||||
}
|
||||
|
||||
*(itr ++) = L'"';
|
||||
return itr - begin;
|
||||
}
|
||||
|
||||
}
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
|
||||
#endif //BOOST_PROCESS_V2_WINDOWS_IMPL_DEFAULT_LAUNCHER_IPP
|
||||
53
linx64/include/boost/process/v2/windows/show_window.hpp
Normal file
53
linx64/include/boost/process/v2/windows/show_window.hpp
Normal file
@@ -0,0 +1,53 @@
|
||||
//
|
||||
// boost/process/v2/windows/default_launcher.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2022 Klemens D. Morgenstern (klemens dot morgenstern at gmx dot net)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BOOST_PROCESS_V2_WINDOWS_SHOW_WINDOW_HPP
|
||||
#define BOOST_PROCESS_V2_WINDOWS_SHOW_WINDOW_HPP
|
||||
|
||||
#include <boost/process/v2/windows/default_launcher.hpp>
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
namespace windows
|
||||
{
|
||||
|
||||
/// A templated initializer to add wShowWindow flags.
|
||||
template<DWORD Flags>
|
||||
struct process_show_window
|
||||
{
|
||||
constexpr process_show_window() {}
|
||||
|
||||
error_code on_setup(windows::default_launcher & launcher,
|
||||
const filesystem::path &,
|
||||
const std::wstring &) const
|
||||
{
|
||||
launcher.startup_info.StartupInfo.dwFlags |= STARTF_USESHOWWINDOW;
|
||||
launcher.startup_info.StartupInfo.wShowWindow |= Flags;
|
||||
|
||||
return error_code {};
|
||||
};
|
||||
};
|
||||
|
||||
///Hides the window and activates another window.
|
||||
constexpr static process_show_window<SW_HIDE > show_window_hide;
|
||||
///Activates the window and displays it as a maximized window.
|
||||
constexpr static process_show_window<SW_SHOWMAXIMIZED > show_window_maximized;
|
||||
///Activates the window and displays it as a minimized window.
|
||||
constexpr static process_show_window<SW_SHOWMINIMIZED > show_window_minimized;
|
||||
///Displays the window as a minimized window. This value is similar to `minimized`, except the window is not activated.
|
||||
constexpr static process_show_window<SW_SHOWMINNOACTIVE> show_window_minimized_not_active;
|
||||
///Displays a window in its most recent size and position. This value is similar to show_normal`, except that the window is not activated.
|
||||
constexpr static process_show_window<SW_SHOWNOACTIVATE > show_window_not_active;
|
||||
///Activates and displays a window. If the window is minimized or maximized, the system restores it to its original size and position. An application should specify this flag when displaying the window for the first time.
|
||||
constexpr static process_show_window<SW_SHOWNORMAL > show_window_normal;
|
||||
|
||||
}
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#endif // BOOST_PROCESS_V2_WINDOWS_SHOW_WINDOW_HPP
|
||||
140
linx64/include/boost/process/v2/windows/with_logon_launcher.hpp
Normal file
140
linx64/include/boost/process/v2/windows/with_logon_launcher.hpp
Normal file
@@ -0,0 +1,140 @@
|
||||
//
|
||||
// boost/process/v2/windows/default_launcher.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2022 Klemens D. Morgenstern (klemens dot morgenstern at gmx dot net)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BOOST_PROCESS_V2_WINDOWS_WITH_LOGON_LAUNCHER_HPP
|
||||
#define BOOST_PROCESS_V2_WINDOWS_WITH_LOGON_LAUNCHER_HPP
|
||||
|
||||
#include <boost/process/v2/windows/default_launcher.hpp>
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
namespace windows
|
||||
{
|
||||
|
||||
/// A windows launcher using CreateProcessWithLogon instead of CreateProcess
|
||||
struct with_logon_launcher : default_launcher
|
||||
{
|
||||
std::wstring username, password, domain;
|
||||
DWORD logon_flags{0u};
|
||||
|
||||
with_logon_launcher(std::wstring username = L"",
|
||||
std::wstring password = L"",
|
||||
std::wstring domain = L"",
|
||||
DWORD logon_flags = 0u) :
|
||||
username(std::move(username)),
|
||||
password(std::move(password)),
|
||||
domain(std::move(domain)),
|
||||
logon_flags(logon_flags)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
template<typename ExecutionContext, typename Args, typename ... Inits>
|
||||
auto operator()(ExecutionContext & context,
|
||||
error_code & ec,
|
||||
const typename std::enable_if<std::is_convertible<
|
||||
ExecutionContext&, BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context&>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<typename ExecutionContext::executor_type>
|
||||
{
|
||||
return (*this)(context.get_executor(), ec, executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
|
||||
}
|
||||
|
||||
|
||||
template<typename ExecutionContext, typename Args, typename ... Inits>
|
||||
auto operator()(ExecutionContext & context,
|
||||
const typename std::enable_if<std::is_convertible<
|
||||
ExecutionContext&, BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context&>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<typename ExecutionContext::executor_type>
|
||||
{
|
||||
return (*this)(context.get_executor(), executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
|
||||
}
|
||||
|
||||
template<typename Executor, typename Args, typename ... Inits>
|
||||
auto operator()(Executor exec,
|
||||
const typename std::enable_if<
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::execution::is_executor<Executor>::value ||
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::is_executor<Executor>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<Executor>
|
||||
{
|
||||
error_code ec;
|
||||
auto proc = (*this)(std::move(exec), ec, executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
|
||||
|
||||
if (ec)
|
||||
v2::detail::throw_error(ec, "with_logon_launcher");
|
||||
|
||||
return proc;
|
||||
}
|
||||
|
||||
template<typename Executor, typename Args, typename ... Inits>
|
||||
auto operator()(Executor exec,
|
||||
error_code & ec,
|
||||
const typename std::enable_if<
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::execution::is_executor<Executor>::value ||
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::is_executor<Executor>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<Executor>
|
||||
{
|
||||
auto command_line = this->build_command_line(executable, args);
|
||||
|
||||
ec = detail::on_setup(*this, executable, command_line, inits...);
|
||||
if (ec)
|
||||
{
|
||||
detail::on_error(*this, executable, command_line, ec, inits...);
|
||||
return basic_process<Executor>(exec);
|
||||
}
|
||||
auto ok = ::CreateProcessWithLogonW(
|
||||
username.c_str(),
|
||||
domain.empty() ? nullptr : domain.c_str(),
|
||||
password.c_str(),
|
||||
logon_flags,
|
||||
executable.empty() ? nullptr : executable.c_str(),
|
||||
command_line.empty() ? nullptr : &command_line.front(),
|
||||
creation_flags,
|
||||
environment,
|
||||
current_directory.empty() ? nullptr : current_directory.c_str(),
|
||||
&startup_info.StartupInfo,
|
||||
&process_information);
|
||||
|
||||
|
||||
if (ok == 0)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
detail::on_error(*this, executable, command_line, ec, inits...);
|
||||
|
||||
if (process_information.hProcess != INVALID_HANDLE_VALUE)
|
||||
::CloseHandle(process_information.hProcess);
|
||||
if (process_information.hThread != INVALID_HANDLE_VALUE)
|
||||
::CloseHandle(process_information.hThread);
|
||||
|
||||
return basic_process<Executor>(exec);
|
||||
} else
|
||||
{
|
||||
detail::on_success(*this, executable, command_line, inits...);
|
||||
|
||||
if (process_information.hThread != INVALID_HANDLE_VALUE)
|
||||
::CloseHandle(process_information.hThread);
|
||||
|
||||
return basic_process<Executor>(exec,
|
||||
this->process_information.dwProcessId,
|
||||
this->process_information.hProcess);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#endif // BOOST_PROCESS_V2_WINDOWS_WITH_LOGON_LAUNCHER_HPP
|
||||
135
linx64/include/boost/process/v2/windows/with_token_launcher.hpp
Normal file
135
linx64/include/boost/process/v2/windows/with_token_launcher.hpp
Normal file
@@ -0,0 +1,135 @@
|
||||
//
|
||||
// boost/process/v2/windows/default_launcher.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2022 Klemens D. Morgenstern (klemens dot morgenstern at gmx dot net)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BOOST_PROCESS_V2_WINDOWS_WITH_TOKEN_LAUNCHER_HPP
|
||||
#define BOOST_PROCESS_V2_WINDOWS_WITH_TOKEN_LAUNCHER_HPP
|
||||
|
||||
#include <boost/process/v2/windows/default_launcher.hpp>
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
namespace windows
|
||||
{
|
||||
|
||||
/// A windows launcher using CreateProcessWithToken instead of CreateProcess
|
||||
struct with_token_launcher : default_launcher
|
||||
{
|
||||
HANDLE token;
|
||||
DWORD logon_flags;
|
||||
with_token_launcher(HANDLE token = INVALID_HANDLE_VALUE,
|
||||
DWORD logon_flags = 0u) : token(token), logon_flags(logon_flags) {}
|
||||
|
||||
|
||||
template<typename ExecutionContext, typename Args, typename ... Inits>
|
||||
auto operator()(ExecutionContext & context,
|
||||
const typename std::enable_if<std::is_convertible<
|
||||
ExecutionContext&, BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context&>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<typename ExecutionContext::executor_type>
|
||||
{
|
||||
error_code ec;
|
||||
auto proc = (*this)(context, ec, executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
|
||||
|
||||
if (ec)
|
||||
v2::detail::throw_error(ec, "with_token_launcher");
|
||||
|
||||
return proc;
|
||||
}
|
||||
|
||||
|
||||
template<typename ExecutionContext, typename Args, typename ... Inits>
|
||||
auto operator()(ExecutionContext & context,
|
||||
error_code & ec,
|
||||
const typename std::enable_if<std::is_convertible<
|
||||
ExecutionContext&, BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context&>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<typename ExecutionContext::executor_type>
|
||||
{
|
||||
return (*this)(context.get_executor(), ec, executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
|
||||
}
|
||||
|
||||
template<typename Executor, typename Args, typename ... Inits>
|
||||
auto operator()(Executor exec,
|
||||
const typename std::enable_if<
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::execution::is_executor<Executor>::value ||
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::is_executor<Executor>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<Executor>
|
||||
{
|
||||
error_code ec;
|
||||
auto proc = (*this)(std::move(exec), ec, executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
|
||||
|
||||
if (ec)
|
||||
detail::throw_error(ec, "with_token_launcher");
|
||||
|
||||
return proc;
|
||||
}
|
||||
|
||||
template<typename Executor, typename Args, typename ... Inits>
|
||||
auto operator()(Executor exec,
|
||||
error_code & ec,
|
||||
const typename std::enable_if<
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::execution::is_executor<Executor>::value ||
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::is_executor<Executor>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<Executor>
|
||||
{
|
||||
auto command_line = this->build_command_line(executable, args);
|
||||
|
||||
ec = detail::on_setup(*this, executable, command_line, inits...);
|
||||
if (ec)
|
||||
{
|
||||
detail::on_error(*this, executable, command_line, ec, inits...);
|
||||
return basic_process<Executor>(exec);
|
||||
}
|
||||
auto ok = ::CreateProcessWithTokenW(
|
||||
token,
|
||||
logon_flags,
|
||||
executable.empty() ? nullptr : executable.c_str(),
|
||||
command_line.empty() ? nullptr : &command_line.front(),
|
||||
creation_flags,
|
||||
environment,
|
||||
current_directory.empty() ? nullptr : current_directory.c_str(),
|
||||
&startup_info.StartupInfo,
|
||||
&process_information);
|
||||
|
||||
|
||||
if (ok == 0)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
detail::on_error(*this, executable, command_line, ec, inits...);
|
||||
|
||||
if (process_information.hProcess != INVALID_HANDLE_VALUE)
|
||||
::CloseHandle(process_information.hProcess);
|
||||
if (process_information.hThread != INVALID_HANDLE_VALUE)
|
||||
::CloseHandle(process_information.hThread);
|
||||
|
||||
return basic_process<Executor>(exec);
|
||||
} else
|
||||
{
|
||||
detail::on_success(*this, executable, command_line, inits...);
|
||||
|
||||
if (process_information.hThread != INVALID_HANDLE_VALUE)
|
||||
::CloseHandle(process_information.hThread);
|
||||
|
||||
return basic_process<Executor>(exec,
|
||||
this->process_information.dwProcessId,
|
||||
this->process_information.hProcess);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#endif // BOOST_PROCESS_V2_WINDOWS_WITH_TOKEN_LAUNCHER_HPP
|
||||
Reference in New Issue
Block a user