mirror of
https://github.com/boostorg/process.git
synced 2026-01-20 16:52:14 +00:00
Compare commits
27 Commits
boost-1.86
...
pty
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
626dd5f1bc | ||
|
|
e4070119ce | ||
|
|
c8499e02c6 | ||
|
|
adf3d62786 | ||
|
|
22c2ad08c9 | ||
|
|
1bbdde8d04 | ||
|
|
e0158d8006 | ||
|
|
07af239503 | ||
|
|
8826a7502d | ||
|
|
e1e594540f | ||
|
|
15d0275b87 | ||
|
|
1e41629759 | ||
|
|
7777db84a8 | ||
|
|
b20e874701 | ||
|
|
606d4d89e4 | ||
|
|
05e8eb3005 | ||
|
|
efd5cc85a5 | ||
|
|
e68491df4d | ||
|
|
02044bcad7 | ||
|
|
41a4a5acc9 | ||
|
|
fae23e60b1 | ||
|
|
34cfc32311 | ||
|
|
4d28e34dfa | ||
|
|
0501b88d7e | ||
|
|
9515f4e1df | ||
|
|
26906fe9f9 | ||
|
|
e8b59f66e6 |
47
build.jam
Normal file
47
build.jam
Normal file
@@ -0,0 +1,47 @@
|
||||
# Copyright René Ferdinand Rivera Morell 2024
|
||||
# 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)
|
||||
|
||||
require-b2 5.2 ;
|
||||
|
||||
import feature : feature ;
|
||||
|
||||
feature boost.process.fs : boost std : optional propagated ;
|
||||
feature boost.process.disable-close-range : on off : optional ;
|
||||
|
||||
constant boost_dependencies :
|
||||
/boost/algorithm//boost_algorithm
|
||||
/boost/asio//boost_asio
|
||||
/boost/assert//boost_assert
|
||||
/boost/config//boost_config
|
||||
/boost/core//boost_core
|
||||
/boost/fusion//boost_fusion
|
||||
/boost/io//boost_io
|
||||
/boost/iterator//boost_iterator
|
||||
/boost/move//boost_move
|
||||
/boost/optional//boost_optional
|
||||
/boost/system//boost_system
|
||||
/boost/throw_exception//boost_throw_exception
|
||||
/boost/tokenizer//boost_tokenizer
|
||||
/boost/type_index//boost_type_index
|
||||
/boost/type_traits//boost_type_traits
|
||||
/boost/utility//boost_utility
|
||||
/boost/winapi//boost_winapi ;
|
||||
|
||||
project /boost/process
|
||||
: common-requirements
|
||||
<include>include
|
||||
: default-build
|
||||
<boost.process.fs>boost
|
||||
;
|
||||
|
||||
explicit
|
||||
[ alias boost_process : build//boost_process ]
|
||||
[ alias all : boost_process example example/v2 test ]
|
||||
;
|
||||
|
||||
call-if : boost-library process
|
||||
: install boost_process
|
||||
;
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
|
||||
import os ;
|
||||
import feature ;
|
||||
import ../../config/checks/config : requires ;
|
||||
import-search /boost/config/checks ;
|
||||
import config : requires ;
|
||||
|
||||
project : requirements
|
||||
<define>BOOST_ASIO_NO_DEPRECATED
|
||||
@@ -15,11 +16,11 @@ project : requirements
|
||||
<target-os>windows:<define>WIN32_LEAN_AND_MEAN
|
||||
<target-os>linux:<linkflags>-lpthread
|
||||
: source-location ../src
|
||||
: common-requirements
|
||||
<library>$(boost_dependencies)
|
||||
<boost.process.fs>std:<define>BOOST_PROCESS_USE_STD_FS=1
|
||||
;
|
||||
|
||||
feature.feature boost.process.fs : boost std : propagated composite ;
|
||||
feature.compose <boost.process.fs>std : <define>BOOST_PROCESS_USE_STD_FS=1 ;
|
||||
|
||||
alias process_sources
|
||||
: detail/environment_posix.cpp
|
||||
detail/environment_win.cpp
|
||||
@@ -40,26 +41,33 @@ alias process_sources
|
||||
shell.cpp
|
||||
;
|
||||
|
||||
if [ os.name ] = NT
|
||||
{
|
||||
lib shell32 ;
|
||||
lib advapi32 ;
|
||||
lib ntdll ;
|
||||
lib user32 ;
|
||||
explicit shell32 advapi32 ntdll user32 ;
|
||||
}
|
||||
lib shell32 ;
|
||||
lib advapi32 ;
|
||||
lib ntdll ;
|
||||
lib user32 ;
|
||||
lib ws2_32 ;
|
||||
|
||||
lib kvm ;
|
||||
lib procstat ;
|
||||
|
||||
lib boost_process
|
||||
: process_sources
|
||||
: requirements <define>BOOST_PROCESS_SOURCE=1
|
||||
<link>shared:<define>BOOST_PROCESS_DYN_LINK=1
|
||||
<boost.process.fs>boost:<library>/boost//filesystem
|
||||
<boost.process.fs>boost:<library>/boost/filesystem//boost_filesystem
|
||||
<boost.process.disable-close-range>on:<define>BOOST_PROCESS_V2_POSIX_FORCE_DISABLE_CLOSE_RANGE=1
|
||||
<target-os>windows:<library>shell32
|
||||
<target-os>windows:<library>user32
|
||||
<target-os>windows:<library>ntdll
|
||||
<target-os>windows:<library>advapi32
|
||||
<target-os>windows:<library>ws2_32
|
||||
<target-os>bsd:<library>kvm
|
||||
<target-os>freebsd:<library>kvm
|
||||
<target-os>freebsd:<library>procstat
|
||||
<target-os>netbsd:<library>kvm
|
||||
<target-os>openbsd:<library>kvm
|
||||
<target-os>solaris:<library>kvm
|
||||
: usage-requirements
|
||||
<link>shared:<define>BOOST_PROCESS_DYN_LINK=1
|
||||
<boost.process.fs>boost:<library>/boost/filesystem//boost_filesystem
|
||||
;
|
||||
|
||||
boost-install boost_process ;
|
||||
|
||||
@@ -19,12 +19,12 @@ install images_glob : $(images) : <location>$(BOOST_ROOT)/doc/html/boost_process
|
||||
import type ;
|
||||
type.register XMLPROCESSWORKAROUND : : XML ;
|
||||
import generators ;
|
||||
generators.register-standard common.copy : XML : XMLPROCESSWORKAROUND ;
|
||||
generators.register-standard common.copy : XML : XMLPROCESSWORKAROUND ;
|
||||
|
||||
xmlprocessworkaround posix_pseudocode : v1/posix_pseudocode.xml ;
|
||||
xmlprocessworkaround windows_pseudocode : v1/windows_pseudocode.xml ;
|
||||
|
||||
path-constant INCLUDES : ../../.. ;
|
||||
path-constant INCLUDES : ../include ;
|
||||
|
||||
doxygen reference_v1
|
||||
:
|
||||
@@ -66,7 +66,7 @@ doxygen reference_v2
|
||||
BOOST_PROCESS_V2_INITFN_AUTO_RESULT_TYPE(x,y)=deduced \\
|
||||
BOOST_PROCESS_V2_COMPLETION_TOKEN_FOR(X)=Token \\
|
||||
BOOST_PROCESS_V2_DEFAULT_COMPLETION_TOKEN_TYPE(E)=DEFAULT_TYPE \\
|
||||
BOOST_ASIO_DEFAULT_COMPLETION_TOKEN=DEFAULT \\
|
||||
BOOST_ASIO_DEFAULT_COMPLETION_TOKEN=DEFAULT \\
|
||||
BOOST_CONSTEXPR=constexpr \\
|
||||
BOOST_CXX14_CONSTEXPR=constexpr \\
|
||||
BOOST_PROCESS_V2_INLINE= \\
|
||||
@@ -98,7 +98,7 @@ boostbook standalone
|
||||
###############################################################################
|
||||
alias boostdoc
|
||||
: standalone/<format>docbook
|
||||
:
|
||||
:
|
||||
: <dependency>images_glob
|
||||
: ;
|
||||
explicit boostdoc ;
|
||||
|
||||
@@ -73,14 +73,6 @@ Instead of using ascii-APIs on windows, process V2 just assumes UTF-8 everywhere
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:src Separate compilation]
|
||||
|
||||
Boost.process v2 supports separate compilation similar to other boost libraries.
|
||||
It can be achieved by defining `BOOST_PROCESS_V2_SEPARATE_COMPILATION` and including
|
||||
`<process/v2/src.hpp>` in a single compile unit.
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:limit_fd Fd safe by default]
|
||||
|
||||
While not a problem on windows (since HANDLEs get manually enabled for inheritance),
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
project : requirements
|
||||
<include>../../..
|
||||
<library>/boost/process//boost_process
|
||||
<toolset>msvc:<define>_SCL_SECURE_NO_WARNINGS
|
||||
<target-os>windows:<define>WIN32_LEAN_AND_MEAN
|
||||
;
|
||||
|
||||
@@ -4,14 +4,12 @@
|
||||
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
project : requirements
|
||||
<include>../../..
|
||||
<toolset>msvc:<define>_SCL_SECURE_NO_WARNINGS
|
||||
<target-os>windows:<define>WIN32_LEAN_AND_MEAN
|
||||
<link>static
|
||||
;
|
||||
|
||||
import testing ;
|
||||
|
||||
alias filesystem : /boost//filesystem : <link>static ;
|
||||
|
||||
exe intro : intro.cpp filesystem ;
|
||||
exe intro_popen : intro_popen.cpp filesystem ;
|
||||
exe intro : intro.cpp ;
|
||||
exe intro_popen : intro_popen.cpp : <boost.process.fs>boost ;
|
||||
|
||||
@@ -257,7 +257,16 @@ struct basic_pipebuf : std::basic_streambuf<CharT, Traits>
|
||||
{
|
||||
if (!is_open())
|
||||
return nullptr;
|
||||
overflow(Traits::eof());
|
||||
try {
|
||||
overflow(Traits::eof());
|
||||
_pipe.close();
|
||||
return this;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
_pipe.close();
|
||||
throw ;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
private:
|
||||
|
||||
@@ -71,7 +71,7 @@ struct bound_launcher
|
||||
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,
|
||||
ExecutionContext&, net::execution_context&>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits) -> basic_process<typename ExecutionContext::executor_type>
|
||||
@@ -88,7 +88,7 @@ struct bound_launcher
|
||||
auto operator()(ExecutionContext & context,
|
||||
error_code & ec,
|
||||
const typename std::enable_if<std::is_convertible<
|
||||
ExecutionContext&, BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context&>::value,
|
||||
ExecutionContext&, net::execution_context&>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<typename ExecutionContext::executor_type>
|
||||
@@ -103,8 +103,8 @@ struct bound_launcher
|
||||
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,
|
||||
net::execution::is_executor<Executor>::value ||
|
||||
net::is_executor<Executor>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<Executor>
|
||||
@@ -120,8 +120,8 @@ struct bound_launcher
|
||||
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,
|
||||
net::execution::is_executor<Executor>::value ||
|
||||
net::is_executor<Executor>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<Executor>
|
||||
@@ -138,7 +138,7 @@ struct bound_launcher
|
||||
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,
|
||||
ExecutionContext&, net::execution_context&>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits) -> basic_process<typename ExecutionContext::executor_type>
|
||||
@@ -156,7 +156,7 @@ struct bound_launcher
|
||||
ExecutionContext & context,
|
||||
error_code & ec,
|
||||
const typename std::enable_if<std::is_convertible<
|
||||
ExecutionContext&, BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context&>::value,
|
||||
ExecutionContext&, net::execution_context&>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<typename ExecutionContext::executor_type>
|
||||
@@ -172,8 +172,8 @@ struct bound_launcher
|
||||
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,
|
||||
net::execution::is_executor<Executor>::value ||
|
||||
net::is_executor<Executor>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<Executor>
|
||||
@@ -190,8 +190,8 @@ struct bound_launcher
|
||||
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,
|
||||
net::execution::is_executor<Executor>::value ||
|
||||
net::is_executor<Executor>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<Executor>
|
||||
|
||||
@@ -7,12 +7,7 @@
|
||||
|
||||
#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>
|
||||
@@ -24,10 +19,6 @@
|
||||
#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)
|
||||
@@ -38,14 +29,14 @@
|
||||
#define BOOST_PROCESS_V2_END_NAMESPACE }
|
||||
#define BOOST_PROCESS_V2_NAMESPACE process_v2
|
||||
|
||||
namespace asio {}
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
namespace net = ::asio;
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#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>
|
||||
@@ -57,10 +48,6 @@
|
||||
#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
|
||||
|
||||
@@ -94,6 +81,11 @@
|
||||
#define BOOST_PROCESS_V2_END_NAMESPACE } } }
|
||||
#define BOOST_PROCESS_V2_NAMESPACE boost::process::v2
|
||||
|
||||
namespace boost { namespace asio {} }
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
namespace net = ::boost::asio;
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#endif
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
@@ -108,9 +100,6 @@ 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()); \
|
||||
@@ -131,23 +120,21 @@ namespace filesystem = std::filesystem;
|
||||
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, ...) \
|
||||
do \
|
||||
{ \
|
||||
static constexpr auto loc##__LINE__((BOOST_CURRENT_LOCATION)); \
|
||||
ec.assign(__VA_ARGS__, &loc##__LINE__); \
|
||||
}
|
||||
} \
|
||||
while (false)
|
||||
|
||||
#define BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) \
|
||||
do \
|
||||
{ \
|
||||
static constexpr auto loc##__LINE__((BOOST_CURRENT_LOCATION)); \
|
||||
ec.assign(::BOOST_PROCESS_V2_NAMESPACE::detail::get_last_error(), &loc##__LINE__); \
|
||||
}
|
||||
} \
|
||||
while (false)
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -69,7 +69,12 @@ 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_DECL bool has_x_access(const char * pth);
|
||||
|
||||
inline bool is_executable(const filesystem::path & pth, error_code & ec)
|
||||
{
|
||||
return filesystem::is_regular_file(pth, ec) && has_x_access(pth.c_str());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -203,7 +203,15 @@ struct native_handle_deleter
|
||||
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_DECL bool is_exec_type(const wchar_t * pth);
|
||||
|
||||
inline bool is_executable(const filesystem::path & pth, error_code & ec)
|
||||
{
|
||||
return filesystem::is_regular_file(pth, ec) && is_exec_type(pth.c_str());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template<typename Executor = BOOST_PROCESS_V2_ASIO_NAMESPACE::any_io_executor>
|
||||
template<typename Executor = net::any_io_executor>
|
||||
struct basic_process_handle_fd
|
||||
{
|
||||
using native_handle_type = int;
|
||||
@@ -56,7 +56,7 @@ struct basic_process_handle_fd
|
||||
basic_process_handle_fd(ExecutionContext &context,
|
||||
typename std::enable_if<
|
||||
std::is_convertible<ExecutionContext &,
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context &>::value>::type * = nullptr)
|
||||
net::execution_context &>::value>::type * = nullptr)
|
||||
: pid_(-1), descriptor_(context)
|
||||
{
|
||||
}
|
||||
@@ -275,35 +275,27 @@ struct basic_process_handle_fd
|
||||
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_;
|
||||
net::posix::basic_stream_descriptor<Executor> descriptor_;
|
||||
|
||||
struct async_wait_op_
|
||||
{
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::posix::basic_descriptor<Executor> &descriptor;
|
||||
net::posix::basic_descriptor<Executor> &descriptor;
|
||||
pid_type pid_;
|
||||
|
||||
template<typename Self>
|
||||
void operator()(Self &&self)
|
||||
{
|
||||
self.reset_cancellation_state(asio::enable_total_cancellation());
|
||||
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;
|
||||
ec = net::error::bad_descriptor;
|
||||
else
|
||||
{
|
||||
wait_res = ::waitpid(pid_, &exit_code, WNOHANG);
|
||||
@@ -314,8 +306,7 @@ struct basic_process_handle_fd
|
||||
|
||||
if (!ec && (wait_res == 0))
|
||||
{
|
||||
descriptor.async_wait(
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::posix::descriptor_base::wait_read, std::move(self));
|
||||
descriptor.async_wait(net::posix::descriptor_base::wait_read, std::move(self));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -330,8 +321,7 @@ struct basic_process_handle_fd
|
||||
self.complete(ec, code);
|
||||
}
|
||||
};
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::post(descriptor.get_executor(),
|
||||
completer{ec, exit_code, std::move(self)});
|
||||
net::post(descriptor.get_executor(), completer{ec, exit_code, std::move(self)});
|
||||
|
||||
}
|
||||
|
||||
@@ -345,6 +335,18 @@ struct basic_process_handle_fd
|
||||
std::move(self).complete(ec, exit_code);
|
||||
}
|
||||
};
|
||||
public:
|
||||
|
||||
template<BOOST_PROCESS_V2_COMPLETION_TOKEN_FOR(void(error_code, native_exit_code_type))
|
||||
WaitHandler = net::default_completion_token_t<executor_type>>
|
||||
auto async_wait(WaitHandler &&handler = net::default_completion_token_t<executor_type>())
|
||||
-> decltype(net::async_compose<WaitHandler, void(error_code, native_exit_code_type)>(
|
||||
async_wait_op_{descriptor_, pid_}, handler, descriptor_))
|
||||
{
|
||||
return net::async_compose<WaitHandler, void(error_code, native_exit_code_type)>(
|
||||
async_wait_op_{descriptor_, pid_}, handler, descriptor_);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template<typename Executor = BOOST_PROCESS_V2_ASIO_NAMESPACE::any_io_executor>
|
||||
template<typename Executor = net::any_io_executor>
|
||||
struct basic_process_handle_fd_or_signal
|
||||
{
|
||||
using native_handle_type = int;
|
||||
@@ -59,7 +59,7 @@ struct basic_process_handle_fd_or_signal
|
||||
basic_process_handle_fd_or_signal(ExecutionContext &context,
|
||||
typename std::enable_if<
|
||||
std::is_convertible<ExecutionContext &,
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context &>::value
|
||||
net::execution_context &>::value
|
||||
>::type * = nullptr)
|
||||
: pid_(-1), descriptor_(context)
|
||||
{
|
||||
@@ -70,7 +70,7 @@ struct basic_process_handle_fd_or_signal
|
||||
pid_type pid,
|
||||
typename std::enable_if<
|
||||
std::is_convertible<ExecutionContext &,
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context &>::value
|
||||
net::execution_context &>::value
|
||||
>::type * = nullptr)
|
||||
: pid_(pid), descriptor_(context)
|
||||
{
|
||||
@@ -81,7 +81,7 @@ struct basic_process_handle_fd_or_signal
|
||||
pid_type pid, native_handle_type process_handle,
|
||||
typename std::enable_if<
|
||||
std::is_convertible<ExecutionContext &,
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context &>::value
|
||||
net::execution_context &>::value
|
||||
>::type * = nullptr)
|
||||
: pid_(pid), descriptor_(context, process_handle)
|
||||
{
|
||||
@@ -305,37 +305,35 @@ struct basic_process_handle_fd_or_signal
|
||||
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};
|
||||
net::posix::basic_stream_descriptor<Executor> descriptor_;
|
||||
net::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;
|
||||
net::posix::basic_descriptor<Executor> &descriptor;
|
||||
net::basic_signal_set<Executor> &handle;
|
||||
pid_type pid_;
|
||||
bool needs_post = true;
|
||||
|
||||
template<typename Self>
|
||||
void operator()(Self &&self, error_code ec = {}, int = 0)
|
||||
void operator()(Self && self)
|
||||
{
|
||||
self.reset_cancellation_state(asio::enable_total_cancellation());
|
||||
(*this)(std::move(self), error_code{});
|
||||
}
|
||||
|
||||
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;
|
||||
ec = net::error::bad_descriptor;
|
||||
else
|
||||
{
|
||||
wait_res = ::waitpid(pid_, &exit_code, WNOHANG);
|
||||
@@ -348,7 +346,7 @@ struct basic_process_handle_fd_or_signal
|
||||
needs_post = false;
|
||||
if (descriptor.is_open())
|
||||
descriptor.async_wait(
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::posix::descriptor_base::wait_read,
|
||||
net::posix::descriptor_base::wait_read,
|
||||
std::move(self));
|
||||
else
|
||||
handle.async_wait(std::move(self));
|
||||
@@ -370,12 +368,22 @@ struct basic_process_handle_fd_or_signal
|
||||
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));
|
||||
net::post(exec, std::move(cpl));
|
||||
else
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::dispatch(exec, std::move(cpl));
|
||||
net::dispatch(exec, std::move(cpl));
|
||||
|
||||
}
|
||||
};
|
||||
public:
|
||||
template<BOOST_PROCESS_V2_COMPLETION_TOKEN_FOR(void(error_code, int))
|
||||
WaitHandler = net::default_completion_token_t<executor_type>>
|
||||
auto async_wait(WaitHandler &&handler = net::default_completion_token_t<executor_type>())
|
||||
-> decltype(net::async_compose<WaitHandler, void(error_code, native_exit_code_type)>(
|
||||
async_wait_op_{descriptor_, signal_set_, pid_}, handler, descriptor_))
|
||||
{
|
||||
return net::async_compose<WaitHandler, void(error_code, native_exit_code_type)>(
|
||||
async_wait_op_{descriptor_, signal_set_, pid_}, handler, descriptor_);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template<typename Executor = BOOST_PROCESS_V2_ASIO_NAMESPACE::any_io_executor>
|
||||
template<typename Executor = net::any_io_executor>
|
||||
struct basic_process_handle_signal
|
||||
{
|
||||
struct native_handle_type
|
||||
@@ -61,7 +61,7 @@ struct basic_process_handle_signal
|
||||
basic_process_handle_signal(ExecutionContext &context,
|
||||
typename std::enable_if<
|
||||
std::is_convertible<ExecutionContext &,
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context &>::value
|
||||
net::execution_context &>::value
|
||||
>::type * = nullptr)
|
||||
: pid_(-1), signal_set_(context, SIGCHLD)
|
||||
{
|
||||
@@ -87,7 +87,7 @@ struct basic_process_handle_signal
|
||||
{
|
||||
pid_ = handle.id();
|
||||
signal_set_.~basic_signal_set();
|
||||
using ss = BOOST_PROCESS_V2_ASIO_NAMESPACE::basic_signal_set<Executor>;
|
||||
using ss = net::basic_signal_set<Executor>;
|
||||
new (&signal_set_) ss(handle.get_executor(), SIGCHLD);
|
||||
handle.pid_ = -1;
|
||||
return *this;
|
||||
@@ -269,29 +269,21 @@ struct basic_process_handle_signal
|
||||
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_;
|
||||
net::basic_signal_set<Executor> signal_set_;
|
||||
|
||||
struct async_wait_op_
|
||||
{
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::basic_signal_set<Executor> &handle;
|
||||
net::basic_signal_set<Executor> &handle;
|
||||
pid_type pid_;
|
||||
|
||||
template<typename Self>
|
||||
void operator()(Self &&self)
|
||||
{
|
||||
self.reset_cancellation_state(asio::enable_total_cancellation());
|
||||
handle.async_wait(std::move(self));
|
||||
handle.cancel();
|
||||
// we cancel so we end up on the signal-sets executor
|
||||
@@ -300,16 +292,16 @@ struct basic_process_handle_signal
|
||||
template<typename Self>
|
||||
void operator()(Self &&self, error_code ec, int sig)
|
||||
{
|
||||
if (ec == BOOST_PROCESS_V2_ASIO_NAMESPACE::error::operation_aborted &&
|
||||
if (ec == net::error::operation_aborted &&
|
||||
self.get_cancellation_state().cancelled()
|
||||
== BOOST_PROCESS_V2_ASIO_NAMESPACE::cancellation_type::none)
|
||||
== net::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;
|
||||
ec = net::error::bad_descriptor;
|
||||
else if (!ec)
|
||||
{
|
||||
wait_res = ::waitpid(pid_, &exit_code, WNOHANG);
|
||||
@@ -336,9 +328,19 @@ struct basic_process_handle_signal
|
||||
};
|
||||
|
||||
const auto exec = self.get_executor();
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::dispatch(exec, completer{ec, exit_code, std::move(self)});
|
||||
net::dispatch(exec, completer{ec, exit_code, std::move(self)});
|
||||
}
|
||||
};
|
||||
public:
|
||||
template<BOOST_PROCESS_V2_COMPLETION_TOKEN_FOR(void(error_code, int))
|
||||
WaitHandler = net::default_completion_token_t<executor_type>>
|
||||
auto async_wait(WaitHandler &&handler = net::default_completion_token_t<executor_type>())
|
||||
-> decltype(net::async_compose<WaitHandler, void(error_code, native_exit_code_type)>(
|
||||
async_wait_op_{signal_set_, pid_}, handler, signal_set_))
|
||||
{
|
||||
return net::async_compose<WaitHandler, void(error_code, native_exit_code_type)>(
|
||||
async_wait_op_{signal_set_, pid_}, handler, signal_set_);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -38,10 +38,10 @@ BOOST_PROCESS_V2_DECL void terminate_(void * handle, error_code & ec, native_exi
|
||||
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>
|
||||
template<typename Executor = net::any_io_executor>
|
||||
struct basic_process_handle_win
|
||||
{
|
||||
typedef BOOST_PROCESS_V2_ASIO_NAMESPACE::windows::basic_object_handle<Executor> handle_type;
|
||||
typedef net::windows::basic_object_handle<Executor> handle_type;
|
||||
typedef typename handle_type::native_handle_type native_handle_type;
|
||||
|
||||
typedef Executor executor_type;
|
||||
@@ -61,7 +61,7 @@ struct basic_process_handle_win
|
||||
basic_process_handle_win(ExecutionContext &context,
|
||||
typename std::enable_if<
|
||||
std::is_convertible<ExecutionContext &,
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context &>::value
|
||||
net::execution_context &>::value
|
||||
>::type = 0)
|
||||
: pid_(0), handle_(context)
|
||||
{
|
||||
@@ -266,15 +266,6 @@ struct basic_process_handle_win
|
||||
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:
|
||||
@@ -288,6 +279,17 @@ struct basic_process_handle_win
|
||||
template<typename Self>
|
||||
void operator()(Self &&self)
|
||||
{
|
||||
|
||||
self.reset_cancellation_state(asio::enable_total_cancellation());
|
||||
auto sl = self.get_cancellation_state().slot();
|
||||
auto & h = handle;
|
||||
if (sl.is_connected())
|
||||
sl.assign(
|
||||
[&h](asio::cancellation_type ct)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
h.cancel(ec);
|
||||
});
|
||||
handle.async_wait(std::move(self));
|
||||
}
|
||||
|
||||
@@ -295,11 +297,25 @@ struct basic_process_handle_win
|
||||
void operator()(Self &&self, error_code ec)
|
||||
{
|
||||
native_exit_code_type exit_code{};
|
||||
if (ec == asio::error::operation_aborted && !self.get_cancellation_state().cancelled())
|
||||
return handle.async_wait(std::move(self));
|
||||
|
||||
if (!ec)
|
||||
detail::get_exit_code_(handle.native_handle(), exit_code, ec);
|
||||
std::move(self).complete(ec, exit_code);
|
||||
}
|
||||
};
|
||||
public:
|
||||
template<BOOST_PROCESS_V2_COMPLETION_TOKEN_FOR(void(error_code, native_exit_code_type))
|
||||
WaitHandler = net::default_completion_token_t<executor_type>>
|
||||
auto async_wait(WaitHandler &&handler = default_completion_token_t<executor_type>())
|
||||
-> decltype(net::async_compose<WaitHandler, void(error_code, native_exit_code_type)>(
|
||||
async_wait_op_{handle_}, handler, handle_))
|
||||
{
|
||||
return net::async_compose<WaitHandler, void(error_code, native_exit_code_type)>(
|
||||
async_wait_op_{handle_}, handler, handle_
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
extern template struct basic_process_handle_win<>;
|
||||
|
||||
@@ -23,8 +23,7 @@ BOOST_PROCESS_V2_DECL std::size_t convert_to_wide(const char * in, std::size_
|
||||
|
||||
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
|
||||
typename = typename std::enable_if<std::is_same<CharOut, CharIn>::value>::type>
|
||||
std::basic_string<CharOut, Traits, Allocator> conv_string(
|
||||
const CharIn * data, std::size_t size,
|
||||
const Allocator allocator = Allocator{})
|
||||
@@ -35,8 +34,7 @@ std::basic_string<CharOut, Traits, Allocator> conv_string(
|
||||
|
||||
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
|
||||
typename = typename std::enable_if<std::is_same<CharOut, char>::value>::type>
|
||||
std::basic_string<CharOut, Traits, Allocator> conv_string(
|
||||
const wchar_t * data, std::size_t size,
|
||||
const Allocator allocator = Allocator{})
|
||||
@@ -59,8 +57,7 @@ std::basic_string<CharOut, Traits, Allocator> conv_string(
|
||||
|
||||
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
|
||||
typename = typename std::enable_if<std::is_same<CharOut, wchar_t>::value>::type>
|
||||
std::basic_string<CharOut, Traits, Allocator> conv_string(
|
||||
const char * data, std::size_t size,
|
||||
const Allocator allocator = Allocator{})
|
||||
|
||||
@@ -764,7 +764,7 @@ struct value
|
||||
value& operator=( const Source& source )
|
||||
{
|
||||
value_ = BOOST_PROCESS_V2_NAMESPACE::detail::conv_string<char_type, traits_type>(
|
||||
source.data(), source.size);
|
||||
source.data(), source.size());
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ struct execute_op
|
||||
|
||||
struct cancel
|
||||
{
|
||||
using cancellation_type = BOOST_PROCESS_V2_ASIO_NAMESPACE::cancellation_type;
|
||||
using cancellation_type = net::cancellation_type;
|
||||
basic_process<Executor> * proc;
|
||||
cancel(basic_process<Executor> * proc) : proc(proc) {}
|
||||
|
||||
@@ -66,15 +66,15 @@ struct execute_op
|
||||
template<typename Self>
|
||||
void operator()(Self && self)
|
||||
{
|
||||
self.reset_cancellation_state(BOOST_PROCESS_V2_ASIO_NAMESPACE::enable_total_cancellation());
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::cancellation_slot s = self.get_cancellation_state().slot();
|
||||
self.reset_cancellation_state(net::enable_total_cancellation());
|
||||
net::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(),
|
||||
net::bind_cancellation_slot(
|
||||
net::cancellation_slot(),
|
||||
std::move(self)));
|
||||
}
|
||||
|
||||
@@ -101,17 +101,18 @@ struct execute_op
|
||||
* 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,
|
||||
template<typename Executor = net::any_io_executor,
|
||||
BOOST_PROCESS_V2_COMPLETION_TOKEN_FOR(void (error_code, int))
|
||||
WaitHandler BOOST_PROCESS_V2_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)>
|
||||
WaitHandler = net::default_completion_token_t<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))
|
||||
auto async_execute(basic_process<Executor> proc,
|
||||
WaitHandler && handler = net::default_completion_token_t<Executor>())
|
||||
-> decltype(net::async_compose<WaitHandler, void(error_code, int)>(
|
||||
detail::execute_op<Executor>{nullptr}, handler, std::declval<Executor>()))
|
||||
{
|
||||
std::unique_ptr<basic_process<Executor>> pro_(new basic_process<Executor>(std::move(proc)));
|
||||
auto exec = pro_->get_executor();
|
||||
return BOOST_PROCESS_V2_ASIO_NAMESPACE::async_compose<WaitHandler, void(error_code, int)>(
|
||||
return net::async_compose<WaitHandler, void(error_code, int)>(
|
||||
detail::execute_op<Executor>{std::move(pro_)}, handler, exec);
|
||||
}
|
||||
|
||||
|
||||
741
include/boost/process/v2/experimental/basic_pty.hpp
Normal file
741
include/boost/process/v2/experimental/basic_pty.hpp
Normal file
@@ -0,0 +1,741 @@
|
||||
//
|
||||
// Copyright (c) 2024 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_VS_EXPERIMENTAL_BASIC_PTY_HPP
|
||||
#define BOOST_PROCESS_VS_EXPERIMENTAL_BASIC_PTY_HPP
|
||||
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
#include <boost/process/v2/detail/last_error.hpp>
|
||||
#include <boost/process/v2/experimental/console_size.hpp>
|
||||
|
||||
#define NTDDI_VERSION 0x0A000006
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS) && !defined(NTDDI_VERSION)
|
||||
#include <sdkddkver.h>
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_PROCESS_V2_WINDOWS) || (NTDDI_VERSION >= 0x0A000006)
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
#if defined(BOOST_PROCESS_V2_STANDALONE)
|
||||
#include <asio/basic_readable_pipe.hpp>
|
||||
#include <asio/basic_writable_pipe.hpp>
|
||||
#include <asio/connect_pipe.hpp>
|
||||
#else
|
||||
#include <boost/asio/basic_readable_pipe.hpp>
|
||||
#include <boost/asio/basic_writable_pipe.hpp>
|
||||
#include <boost/asio/connect_pipe.hpp>
|
||||
#endif
|
||||
#include <boost/process/v2/windows/default_launcher.hpp>
|
||||
#else
|
||||
#if defined(BOOST_PROCESS_V2_STANDALONE)
|
||||
#include <asio/posix/basic_stream_descriptor.hpp>
|
||||
#else
|
||||
#include <boost/asio/posix/basic_stream_descriptor.hpp>
|
||||
#endif
|
||||
#include <boost/process/v2/posix/default_launcher.hpp>
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
|
||||
namespace experimental
|
||||
{
|
||||
|
||||
|
||||
template<typename Executor = net::any_io_executor>
|
||||
class basic_pty
|
||||
{
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
struct handle_t_
|
||||
{
|
||||
net::basic_readable_pipe<Executor> rm, rs{rm.get_executor()};
|
||||
net::basic_writable_pipe<Executor> wm{rm.get_executor()}, ws{rm.get_executor()};
|
||||
template<typename Arg>
|
||||
handle_t_(Arg && arg) : rm{arg} {}
|
||||
|
||||
bool is_open() const {return rm.is_open();}
|
||||
};
|
||||
|
||||
handle_t_ handle_;
|
||||
net::basic_readable_pipe<Executor> & read_handle_() {return handle_.rm;}
|
||||
net::basic_writable_pipe<Executor> & write_handle_() {return handle_.wm;}
|
||||
struct hcon_deleter_
|
||||
{
|
||||
void operator()(HPCON con)
|
||||
{
|
||||
ClosePseudoConsole(con);
|
||||
}
|
||||
};
|
||||
std::unique_ptr<void, hcon_deleter_> con_;
|
||||
|
||||
#else
|
||||
net::posix::basic_stream_descriptor<Executor> handle_;
|
||||
|
||||
net::posix::basic_stream_descriptor<Executor> & read_handle_() { return handle_; };
|
||||
net::posix::basic_stream_descriptor<Executor> & write_handle_() { return handle_; };
|
||||
#endif
|
||||
public:
|
||||
/// The type of the executor associated with the object.
|
||||
typedef Executor executor_type;
|
||||
|
||||
/// Rebinds the descriptor type to another executor.
|
||||
template <typename Executor1>
|
||||
struct rebind_executor
|
||||
{
|
||||
/// The descriptor type when rebound to the specified executor.
|
||||
typedef basic_pty<Executor1> other;
|
||||
};
|
||||
|
||||
/// A descriptor is always the lowest layer.
|
||||
typedef basic_pty lowest_layer_type ;
|
||||
|
||||
|
||||
/// Construct a stream descriptor without opening it.
|
||||
/**
|
||||
* This constructor creates a stream descriptor without opening it. The
|
||||
* descriptor needs to be opened and then connected or accepted before data
|
||||
* can be sent or received on it.
|
||||
*
|
||||
* @param ex The I/O executor that the descriptor will use, by default, to
|
||||
* dispatch handlers for any asynchronous operations performed on the
|
||||
* descriptor.
|
||||
*/
|
||||
explicit basic_pty(const executor_type& ex)
|
||||
: handle_(ex)
|
||||
{
|
||||
}
|
||||
|
||||
/// Construct a stream descriptor without opening it.
|
||||
/**
|
||||
* This constructor creates a stream descriptor without opening it. The
|
||||
* descriptor needs to be opened and then connected or accepted before data
|
||||
* can be sent or received on it.
|
||||
*
|
||||
* @param context An execution context which provides the I/O executor that
|
||||
* the descriptor will use, by default, to dispatch handlers for any
|
||||
* asynchronous operations performed on the descriptor.
|
||||
*/
|
||||
template <typename ExecutionContext>
|
||||
explicit basic_pty(ExecutionContext& context,
|
||||
net::constraint_t<
|
||||
std::is_convertible<ExecutionContext&, net::execution_context&>::value,
|
||||
net::defaulted_constraint
|
||||
> = net::defaulted_constraint())
|
||||
: handle_(context)
|
||||
{
|
||||
}
|
||||
|
||||
/// Move-construct a stream descriptor from another.
|
||||
/**
|
||||
* This constructor moves a stream descriptor from one object to another.
|
||||
*
|
||||
* @param other The other stream descriptor object from which the move
|
||||
* will occur.
|
||||
*
|
||||
* @note Following the move, the moved-from object is in the same state as if
|
||||
* constructed using the @c basic_pty(const executor_type&)
|
||||
* constructor.
|
||||
*/
|
||||
basic_pty(basic_pty&& other) noexcept
|
||||
: handle_(std::move(other))
|
||||
{
|
||||
}
|
||||
|
||||
/// Move-assign a stream descriptor from another.
|
||||
/**
|
||||
* This assignment operator moves a stream descriptor from one object to
|
||||
* another.
|
||||
*
|
||||
* @param other The other stream descriptor object from which the move
|
||||
* will occur.
|
||||
*
|
||||
* @note Following the move, the moved-from object is in the same state as if
|
||||
* constructed using the @c basic_pty(const executor_type&)
|
||||
* constructor.
|
||||
*/
|
||||
basic_pty& operator=(basic_pty&& other)
|
||||
{
|
||||
handle_= std::move(other.handle_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Move-construct a basic_pty from a descriptor of another
|
||||
/// executor type.
|
||||
/**
|
||||
* This constructor moves a descriptor from one object to another.
|
||||
*
|
||||
* @param other The other basic_pty object from which the move
|
||||
* will occur.
|
||||
*
|
||||
* @note Following the move, the moved-from object is in the same state as if
|
||||
* constructed using the @c basic_pty(const executor_type&)
|
||||
* constructor.
|
||||
*/
|
||||
template <typename Executor1>
|
||||
basic_pty(basic_pty<Executor1>&& other,
|
||||
net::constraint_t<
|
||||
net::is_convertible<Executor1, Executor>::value,
|
||||
net::defaulted_constraint
|
||||
> = net::defaulted_constraint())
|
||||
: handle_(std::move(other))
|
||||
{
|
||||
}
|
||||
|
||||
/// Move-assign a basic_pty from a descriptor of another
|
||||
/// executor type.
|
||||
/**
|
||||
* This assignment operator moves a descriptor from one object to another.
|
||||
*
|
||||
* @param other The other basic_pty object from which the move
|
||||
* will occur.
|
||||
*
|
||||
* @note Following the move, the moved-from object is in the same state as if
|
||||
* constructed using the @c basic_pty(const executor_type&)
|
||||
* constructor.
|
||||
*/
|
||||
template <typename Executor1>
|
||||
net::constraint_t<
|
||||
net::is_convertible<Executor1, Executor>::value,
|
||||
basic_pty&
|
||||
> operator=(basic_pty<Executor1> && other)
|
||||
{
|
||||
handle_ = std::move(other.handle_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
/// Get the executor associated with the object.
|
||||
const executor_type& get_executor() noexcept
|
||||
{
|
||||
return handle_.get_executor();
|
||||
}
|
||||
|
||||
/// Get a reference to the lowest layer.
|
||||
/**
|
||||
* This function returns a reference to the lowest layer in a stack of
|
||||
* layers. Since a descriptor cannot contain any further layers, it
|
||||
* simply returns a reference to itself.
|
||||
*
|
||||
* @return A reference to the lowest layer in the stack of layers. Ownership
|
||||
* is not transferred to the caller.
|
||||
*/
|
||||
lowest_layer_type& lowest_layer()
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Get a const reference to the lowest layer.
|
||||
/**
|
||||
* This function returns a const reference to the lowest layer in a stack of
|
||||
* layers. Since a descriptor cannot contain any further layers, it
|
||||
* simply returns a reference to itself.
|
||||
*
|
||||
* @return A const reference to the lowest layer in the stack of layers.
|
||||
* Ownership is not transferred to the caller.
|
||||
*/
|
||||
const lowest_layer_type& lowest_layer() const
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Determine whether the descriptor is open.
|
||||
bool is_open() const
|
||||
{
|
||||
return handle_.is_open();
|
||||
}
|
||||
|
||||
/// Close the descriptor.
|
||||
/**
|
||||
* This function is used to close the descriptor. Any asynchronous read or
|
||||
* write operations will be cancelled immediately, and will complete with the
|
||||
* boost::asio::error::operation_aborted error.
|
||||
*
|
||||
* @throws boost::system::system_error Thrown on failure. Note that, even if
|
||||
* the function indicates an error, the underlying descriptor is closed.
|
||||
*/
|
||||
void close()
|
||||
{
|
||||
#if defined(BOOST_PROCESS_V2_POSIX)
|
||||
handle_.close();
|
||||
#else
|
||||
handle_.rm.close();
|
||||
handle_.wm.close();
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Close the descriptor.
|
||||
/**
|
||||
* This function is used to close the descriptor. Any asynchronous read or
|
||||
* write operations will be cancelled immediately, and will complete with the
|
||||
* boost::asio::error::operation_aborted error.
|
||||
*
|
||||
* @param ec Set to indicate what error occurred, if any. Note that, even if
|
||||
* the function indicates an error, the underlying descriptor is closed.
|
||||
*/
|
||||
void close(boost::system::error_code& ec)
|
||||
{
|
||||
#if defined(BOOST_PROCESS_V2_POSIX)
|
||||
handle_.close(ec);
|
||||
#else
|
||||
handle_.wm.close(ec);
|
||||
handle_.rm.close(ec);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Cancel all asynchronous operations associated with the descriptor.
|
||||
/**
|
||||
* This function causes all outstanding asynchronous read or write operations
|
||||
* to finish immediately, and the handlers for cancelled operations will be
|
||||
* passed the boost::asio::error::operation_aborted error.
|
||||
*
|
||||
* @throws boost::system::system_error Thrown on failure.
|
||||
*/
|
||||
void cancel()
|
||||
{
|
||||
#if defined(BOOST_PROCESS_V2_POSIX)
|
||||
handle_.cancel();
|
||||
#else
|
||||
handle_.rm.cancel();
|
||||
handle_.wm.cancel();
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Cancel all asynchronous operations associated with the descriptor.
|
||||
/**
|
||||
* This function causes all outstanding asynchronous read or write operations
|
||||
* to finish immediately, and the handlers for cancelled operations will be
|
||||
* passed the boost::asio::error::operation_aborted error.
|
||||
*
|
||||
* @param ec Set to indicate what error occurred, if any.
|
||||
*/
|
||||
void cancel(boost::system::error_code& ec)
|
||||
{
|
||||
#if defined(BOOST_PROCESS_V2_POSIX)
|
||||
handle_.cancel(ec);
|
||||
#else
|
||||
handle_.rm.cancel(ec);
|
||||
handle_.wm.cancel(ec);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Write some data to the descriptor.
|
||||
/**
|
||||
* This function is used to write data to the stream descriptor. 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 descriptor.
|
||||
*
|
||||
* @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
|
||||
* peer.
|
||||
*
|
||||
* @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
|
||||
* descriptor.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 write_handle_().write_some(buffers);
|
||||
}
|
||||
|
||||
/// Write some data to the descriptor.
|
||||
/**
|
||||
* This function is used to write data to the stream descriptor. 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 descriptor.
|
||||
*
|
||||
* @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
|
||||
* peer. 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 write_handle_().write_some(buffers, ec);
|
||||
}
|
||||
|
||||
/// Start an asynchronous write.
|
||||
/**
|
||||
* This function is used to asynchronously write data to the stream
|
||||
* descriptor. 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 descriptor.
|
||||
* 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::async_immediate().
|
||||
*
|
||||
* @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
|
||||
* descriptor.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.
|
||||
*
|
||||
* @par Per-Operation Cancellation
|
||||
* This asynchronous operation supports cancellation for the following
|
||||
* boost::asio::cancellation_type values:
|
||||
*
|
||||
* @li @c cancellation_type::terminal
|
||||
*
|
||||
* @li @c cancellation_type::partial
|
||||
*
|
||||
* @li @c cancellation_type::total
|
||||
*/
|
||||
template <typename ConstBufferSequence,
|
||||
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
|
||||
std::size_t)) WriteToken = net::default_completion_token_t<executor_type>>
|
||||
auto async_write_some(const ConstBufferSequence& buffers,
|
||||
WriteToken&& token = net::default_completion_token_t<executor_type>())
|
||||
-> decltype(write_handle_().async_write_some(buffers, std::forward<WriteToken>(token)))
|
||||
{
|
||||
return write_handle_().async_write_some(buffers, std::forward<WriteToken>(token));
|
||||
}
|
||||
|
||||
/// Read some data from the descriptor.
|
||||
/**
|
||||
* This function is used to read data from the stream descriptor. 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
|
||||
* descriptor.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 read_handle_().read_some(buffers);
|
||||
}
|
||||
|
||||
/// Read some data from the descriptor.
|
||||
/**
|
||||
* This function is used to read data from the stream descriptor. 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 read_handle_().read_some(buffers, ec);
|
||||
}
|
||||
|
||||
/// Start an asynchronous read.
|
||||
/**
|
||||
* This function is used to asynchronously read data from the stream
|
||||
* descriptor. 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::async_immediate().
|
||||
*
|
||||
* @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
|
||||
* descriptor.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.
|
||||
*
|
||||
* @par Per-Operation Cancellation
|
||||
* This asynchronous operation supports cancellation for the following
|
||||
* boost::asio::cancellation_type values:
|
||||
*
|
||||
* @li @c cancellation_type::terminal
|
||||
*
|
||||
* @li @c cancellation_type::partial
|
||||
*
|
||||
* @li @c cancellation_type::total
|
||||
*/
|
||||
template <typename MutableBufferSequence,
|
||||
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
|
||||
std::size_t)) ReadToken = net::default_completion_token_t<executor_type>>
|
||||
auto async_read_some(const MutableBufferSequence& buffers,
|
||||
ReadToken&& token = net::default_completion_token_t<executor_type>())
|
||||
-> decltype(read_handle_().async_read_some(buffers, std::forward<ReadToken>(token)))
|
||||
{
|
||||
return read_handle_().async_read_some(buffers, std::forward<ReadToken>(token));
|
||||
}
|
||||
|
||||
void open(console_size_t size, error_code & ec)
|
||||
{
|
||||
#if defined(BOOST_PROCESS_V2_POSIX)
|
||||
auto res = posix_openpt(O_RDWR | O_NOCTTY);
|
||||
if (res < 0)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return ;
|
||||
}
|
||||
else
|
||||
handle_.assign(res, ec);
|
||||
|
||||
|
||||
winsize ws{size.rows, size.columns};
|
||||
if (ioctl(res, TIOCSWINSZ, &ws) != 0)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
|
||||
/* struct termios tios;
|
||||
if (!ec && ioctl(res, TCGETS, &tios))
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
|
||||
#if defined (IUTF8)
|
||||
tios.c_iflag |= IUTF8;
|
||||
#endif
|
||||
tios.c_lflag &= ~(ECHOE | ECHOK | ECHONL | ICANON);
|
||||
|
||||
|
||||
if (!ec && ioctl(res, TCSETSW, &tios))
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
*/
|
||||
|
||||
if (ec)
|
||||
return ;
|
||||
|
||||
if (grantpt(res) || unlockpt(res))
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
this->close(ec);
|
||||
}
|
||||
#else
|
||||
net::connect_pipe(handle_.rm, handle_.ws, ec); // output
|
||||
if (!ec)
|
||||
{
|
||||
net::connect_pipe(handle_.rs, handle_.wm, ec); // input
|
||||
if (ec)
|
||||
handle_.rm.close(ec);
|
||||
}
|
||||
if (ec)
|
||||
return ;
|
||||
|
||||
HPCON out;
|
||||
auto res = CreatePseudoConsole(
|
||||
COORD{static_cast<short>(size.columns), static_cast<short>(size.rows)},
|
||||
handle_.rs.native_handle(),
|
||||
handle_.ws.native_handle(), 0, &out);
|
||||
if (res != S_OK)
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, HRESULT_CODE(res), system_category());
|
||||
else
|
||||
con_.reset(out);
|
||||
#endif
|
||||
}
|
||||
|
||||
void open(console_size_t size)
|
||||
{
|
||||
error_code ec;
|
||||
open(size, ec);
|
||||
if (ec)
|
||||
boost::process::v2::detail::throw_error(ec, "open");
|
||||
}
|
||||
|
||||
void resize(console_size_t size, error_code & ec)
|
||||
{
|
||||
#if defined(BOOST_PROCESS_V2_POSIX)
|
||||
winsize ws{size.rows, size.columns, 0, 0};
|
||||
if (ioctl(handle_.native_handle(), TIOCSWINSZ, &ws) != 0)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
|
||||
#else
|
||||
auto res = ::ResizePseudoConsole(con_.get(),
|
||||
COORD{static_cast<short>(size.columns), static_cast<short>(size.rows)});
|
||||
if (res != S_OK)
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, HRESULT_CODE(res), system_category());
|
||||
#endif
|
||||
}
|
||||
|
||||
void resize(console_size_t size)
|
||||
{
|
||||
error_code ec;
|
||||
resize(size, ec);
|
||||
if (ec)
|
||||
boost::process::v2::detail::throw_error(ec, "resize");
|
||||
}
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_POSIX)
|
||||
error_code on_setup(posix::default_launcher & launcher, const filesystem::path &, const char * const *)
|
||||
{
|
||||
error_code ec;
|
||||
if (!is_open())
|
||||
this->open(console_size_t{80, 24}, ec);
|
||||
return ec;
|
||||
}
|
||||
|
||||
error_code on_exec_setup(posix::default_launcher & launcher, const filesystem::path &, const char * const *)
|
||||
{
|
||||
error_code ec;
|
||||
auto nm = ptsname(handle_.native_handle());
|
||||
if (nm == nullptr)
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, ENODEV, system_category());
|
||||
else
|
||||
{
|
||||
auto s = ::open(nm, O_WRONLY);
|
||||
if (s < 0)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
|
||||
auto t = ::open(nm, O_RDONLY);
|
||||
if (t < 0)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
|
||||
if ((::dup2(t, STDIN_FILENO) == -1)
|
||||
|| (::dup2(s, STDOUT_FILENO) == -1)
|
||||
|| (::dup2(s, STDERR_FILENO) == -1)
|
||||
|| (::setsid() == -1)
|
||||
#ifdef TIOCSCTTY
|
||||
|| ::ioctl(t, TIOCSCTTY, 0)
|
||||
#endif
|
||||
|| ::close(handle_.native_handle())
|
||||
|| ::close(s)
|
||||
|| ::close(t))
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
}
|
||||
return error_code ();
|
||||
}
|
||||
#else
|
||||
|
||||
error_code on_setup(windows::default_launcher & launcher, const filesystem::path &, const std::wstring &)
|
||||
{
|
||||
error_code ec;
|
||||
if (!is_open())
|
||||
open(console_size_t{80, 24}, ec);
|
||||
|
||||
auto &si = launcher.startup_info;
|
||||
launcher.startup_info.StartupInfo.dwFlags |= STARTF_USESTDHANDLES;
|
||||
// https://github.com/microsoft/terminal/issues/11276
|
||||
launcher.startup_info.StartupInfo.hStdOutput = NULL;
|
||||
launcher.startup_info.StartupInfo.hStdError = NULL;
|
||||
launcher.startup_info.StartupInfo.hStdInput = NULL;
|
||||
size_t bytes_required;
|
||||
InitializeProcThreadAttributeList(NULL, 1, 0, &bytes_required);
|
||||
si.lpAttributeList = (PPROC_THREAD_ATTRIBUTE_LIST)HeapAlloc(GetProcessHeap(), 0, bytes_required);
|
||||
if (!si.lpAttributeList)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, ENOMEM, system_category());
|
||||
return ec;
|
||||
}
|
||||
|
||||
// Initialize the list memory location
|
||||
if (!InitializeProcThreadAttributeList(si.lpAttributeList, 1, 0, &bytes_required)
|
||||
|| !UpdateProcThreadAttribute(si.lpAttributeList,
|
||||
0,
|
||||
PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE,
|
||||
con_.get(),
|
||||
sizeof(con_.get()),
|
||||
NULL,
|
||||
NULL))
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, si.lpAttributeList);
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return ec;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#endif // windows version
|
||||
#endif //BOOST_PROCESS_VS_EXPERIMENTAL_BASIC_PTY_HPP
|
||||
1085
include/boost/process/v2/experimental/basic_stream.hpp
Normal file
1085
include/boost/process/v2/experimental/basic_stream.hpp
Normal file
File diff suppressed because it is too large
Load Diff
25
include/boost/process/v2/experimental/console_size.hpp
Normal file
25
include/boost/process/v2/experimental/console_size.hpp
Normal file
@@ -0,0 +1,25 @@
|
||||
//
|
||||
// Copyright (c) 2024 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_CONSOLE_SIZE_CONSOLE_SIZE_HPP
|
||||
#define BOOST_PROCESS_V2_CONSOLE_SIZE_CONSOLE_SIZE_HPP
|
||||
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
namespace experimental
|
||||
{
|
||||
|
||||
struct console_size_t
|
||||
{
|
||||
unsigned short columns, rows;
|
||||
};
|
||||
|
||||
}
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#endif //BOOST_PROCESS_V2_CONSOLE_SIZE_CONSOLE_SIZE_HPP
|
||||
@@ -0,0 +1,398 @@
|
||||
//
|
||||
// Copyright (c) 2024 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_EXPERIMENTAL_DETAIL_BASIC_STREAM_HANDLE_HPP
|
||||
#define BOOST_PROCESS_V2_EXPERIMENTAL_DETAIL_BASIC_STREAM_HANDLE_HPP
|
||||
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
|
||||
#include <boost/process/v2/detail/throw_error.hpp>
|
||||
#include <boost/process/v2/detail/last_error.hpp>
|
||||
#include <boost/process/v2/experimental/console_size.hpp>
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_STANDALONE)
|
||||
#include <asio/append.hpp>
|
||||
#include <asio/compose.hpp>
|
||||
#include <asio/dispatch.hpp>
|
||||
#include <asio/steady_timer.hpp>
|
||||
#include <asio/windows/basic_object_handle.hpp>
|
||||
#include <asio/windows/basic_stream_handle.hpp>
|
||||
#else
|
||||
#include <boost/asio/append.hpp>
|
||||
#include <boost/asio/compose.hpp>
|
||||
#include <boost/asio/dispatch.hpp>
|
||||
#include <boost/asio/steady_timer.hpp>
|
||||
#include <boost/asio/windows/basic_object_handle.hpp>
|
||||
#include <boost/asio/windows/basic_stream_handle.hpp>
|
||||
#endif
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
namespace detail
|
||||
{
|
||||
namespace experimental
|
||||
{
|
||||
|
||||
template<typename Executor>
|
||||
struct basic_stream_handle
|
||||
{
|
||||
net::windows::basic_object_handle<Executor> object;
|
||||
net::windows::basic_stream_handle<Executor> stream;
|
||||
v2::experimental::console_size_t cs_buf_{0u, 0u};
|
||||
|
||||
template<typename Arg>
|
||||
basic_stream_handle(Arg &&arg) : object{arg}, stream{arg} {}
|
||||
|
||||
template<typename Executor1>
|
||||
basic_stream_handle(basic_stream_handle<Executor1> &&lhs)
|
||||
: object(std::move(lhs.object)), stream(std::move(lhs.stream)), cs_buf_(lhs.cs_buf_) {}
|
||||
|
||||
using executor_type = Executor;
|
||||
executor_type get_executor() noexcept { return object.get_executor(); }
|
||||
|
||||
|
||||
void assign(HANDLE h, error_code &ec)
|
||||
{
|
||||
assert(GetFileType(h) == FILE_TYPE_CHAR);
|
||||
if (GetFileType(h) == FILE_TYPE_CHAR)
|
||||
{
|
||||
stream.close(ec);
|
||||
object.assign(h, ec);
|
||||
DWORD flags;
|
||||
if (!::GetConsoleMode(h, &flags)) {
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!::SetConsoleMode(h, flags | ENABLE_VIRTUAL_TERMINAL_INPUT)) // probably output!
|
||||
if (!::SetConsoleMode(h, flags | ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING ))
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
if (!::SetConsoleCP(CP_UTF8))
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
if (!::SetConsoleOutputCP(CP_UTF8))
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
|
||||
|
||||
CONSOLE_SCREEN_BUFFER_INFO bi;
|
||||
if (::GetConsoleScreenBufferInfo(h, &bi))
|
||||
{
|
||||
cs_buf_.columns = bi.dwSize.X;
|
||||
cs_buf_.rows = bi.dwSize.Y;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
object.close(ec);
|
||||
stream.assign(h, ec);
|
||||
}
|
||||
}
|
||||
|
||||
void assign(HANDLE h)
|
||||
{
|
||||
error_code ec;
|
||||
assign(h, ec);
|
||||
if (ec)
|
||||
detail::throw_error(ec, "assign");
|
||||
}
|
||||
|
||||
void close(error_code &ec)
|
||||
{
|
||||
object.close(ec);
|
||||
stream.close(ec);
|
||||
}
|
||||
|
||||
void close()
|
||||
{
|
||||
object.close();
|
||||
stream.close();
|
||||
}
|
||||
|
||||
HANDLE native_handle()
|
||||
{
|
||||
return object.is_open() ? object.native_handle() : stream.native_handle();
|
||||
}
|
||||
|
||||
HANDLE release()
|
||||
{
|
||||
return object.is_open() ? object.release() : stream.release();
|
||||
}
|
||||
|
||||
void cancel(error_code &ec)
|
||||
{
|
||||
if (object.is_open())
|
||||
object.cancel(ec);
|
||||
else if (stream.is_open())
|
||||
stream.cancel(ec);
|
||||
|
||||
trigger_size_.cancel(ec);
|
||||
}
|
||||
|
||||
void cancel()
|
||||
{
|
||||
if (object.is_open())
|
||||
object.cancel();
|
||||
else if (stream.is_open())
|
||||
stream.cancel();
|
||||
|
||||
trigger_size_.cancel();
|
||||
}
|
||||
|
||||
bool is_open() const { return object.is_open() || stream.is_open(); }
|
||||
|
||||
void wait(error_code &ec)
|
||||
{
|
||||
if (object.is_open())
|
||||
object.wait(ec);
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, net::error::operation_not_supported);
|
||||
}
|
||||
|
||||
void wait()
|
||||
{
|
||||
error_code ec;
|
||||
wait(ec);
|
||||
if (ec)
|
||||
detail::throw_error(ec);
|
||||
}
|
||||
|
||||
struct async_wait_op
|
||||
{
|
||||
template<typename Handler>
|
||||
void operator()(Handler &&handler, basic_stream_handle *this_)
|
||||
{
|
||||
if (this_->object.is_open())
|
||||
this_->object.async_wait(std::move(handler));
|
||||
else {
|
||||
auto e = net::get_associated_immediate_executor(handler, this_->stream.get_executor());
|
||||
net::dispatch(e, net::append(std::move(handler), net::error::operation_not_supported));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Token>
|
||||
auto async_wait(Token &&token)
|
||||
{
|
||||
return net::async_initiate<Token, void(error_code)>(async_wait_op{}, token, this);
|
||||
}
|
||||
|
||||
template<typename MutableBufferSequence>
|
||||
std::size_t read_some(const MutableBufferSequence &mbs, error_code &ec)
|
||||
{
|
||||
if (stream.is_open())
|
||||
return stream.read_some(mbs, ec);
|
||||
|
||||
|
||||
asio::mutable_buffer buf;
|
||||
|
||||
for (auto itr = net::buffer_sequence_begin(mbs);
|
||||
itr != net::buffer_sequence_end(mbs); itr++)
|
||||
if (itr->size() > 0)
|
||||
{
|
||||
buf = *itr;
|
||||
break;
|
||||
}
|
||||
|
||||
if (buf.size() == 0u)
|
||||
return 0u;
|
||||
|
||||
DWORD read_size = 0u;
|
||||
if (!::ReadFile(object.native_handle(), buf.data(), buf.size(), &read_size, NULL))
|
||||
{
|
||||
const DWORD last_error = ::GetLastError();
|
||||
if (ERROR_END_OF_MEDIA == last_error)
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, net::error::eof);
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, last_error, system_category());
|
||||
}
|
||||
|
||||
return static_cast<std::size_t>(read_size);
|
||||
}
|
||||
|
||||
template<typename MutableBuffer>
|
||||
struct async_read_some_op
|
||||
{
|
||||
basic_stream_handle *this_;
|
||||
MutableBuffer buffer;
|
||||
|
||||
template<typename Self>
|
||||
void operator()(Self &&self)
|
||||
{
|
||||
if (this_->stream.is_open())
|
||||
return this_->stream.async_read_some(buffer, std::move(self));
|
||||
|
||||
this_->async_wait(std::move(self));
|
||||
}
|
||||
|
||||
template<typename Self>
|
||||
void operator()(Self &&self, error_code ec)
|
||||
{
|
||||
asio::mutable_buffer buf;
|
||||
|
||||
for (auto itr = net::buffer_sequence_begin(buffer);
|
||||
itr != net::buffer_sequence_end(buffer); itr++)
|
||||
if (itr->size() > 0)
|
||||
{
|
||||
buf = *itr;
|
||||
break;
|
||||
}
|
||||
|
||||
if (buf.size() == 0u)
|
||||
return self.complete(error_code{}, 0u);
|
||||
|
||||
INPUT_RECORD in_buffer[8092];
|
||||
DWORD read_size = 0u;
|
||||
if (!::PeekConsoleInputW(this_->object.native_handle(), in_buffer, 8092, &read_size))
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return self.complete(ec, 0u);
|
||||
}
|
||||
auto begin = in_buffer,
|
||||
end = in_buffer + read_size;
|
||||
|
||||
std::size_t keys = 0u;
|
||||
bool has_cr = false;
|
||||
for (auto itr = begin; itr != end; itr++)
|
||||
{
|
||||
if (itr->EventType == KEY_EVENT)
|
||||
{
|
||||
keys += itr->Event.KeyEvent.wRepeatCount;
|
||||
has_cr |= itr->Event.KeyEvent.uChar.AsciiChar == '\r';
|
||||
}
|
||||
}
|
||||
|
||||
if (keys == 0u)
|
||||
{
|
||||
if (!::FlushConsoleInputBuffer(this_->object.native_handle()))
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return self.complete(ec, 0u);
|
||||
}
|
||||
else
|
||||
return this_->async_wait(std::move(self));
|
||||
}
|
||||
|
||||
if (!has_cr)
|
||||
{
|
||||
DWORD mode = 0;
|
||||
if (!::GetConsoleMode(this_->object.native_handle(), &mode))
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
else if ((mode & ENABLE_LINE_INPUT) != 0)
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, net::error::would_block); // line mode would block on windows
|
||||
}
|
||||
if (ec)
|
||||
return self.complete(ec, 0u);
|
||||
|
||||
DWORD to_read = (std::min)(keys, buf.size());
|
||||
|
||||
read_size = 0u;
|
||||
if (!ReadFile(this_->object.native_handle(), buf.data(), to_read, &read_size, NULL))
|
||||
{
|
||||
const DWORD last_error = ::GetLastError();
|
||||
if (ERROR_END_OF_MEDIA == last_error)
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, net::error::eof);
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, last_error, system_category());
|
||||
}
|
||||
|
||||
self.complete(ec, static_cast<std::size_t>(read_size));
|
||||
}
|
||||
|
||||
template<typename Self>
|
||||
void operator()(Self &&self, error_code ec, std::size_t n_)
|
||||
{
|
||||
self.complete(ec, n_);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template<typename MutableBuffer, typename CompletionToken>
|
||||
auto async_read_some(const MutableBuffer &buffer, CompletionToken &&token)
|
||||
-> decltype(net::async_initiate<CompletionToken,
|
||||
void(boost::system::error_code, std::size_t)>(
|
||||
net::composed(async_read_some_op<MutableBuffer>{this, buffer}, stream), token))
|
||||
{
|
||||
return net::async_initiate<CompletionToken,
|
||||
void(boost::system::error_code, std::size_t)>(
|
||||
net::composed(async_read_some_op<MutableBuffer>{this, buffer}, stream), token);
|
||||
}
|
||||
|
||||
template<typename ConstBufferSequence>
|
||||
std::size_t write_some(const ConstBufferSequence &cbs, error_code &ec)
|
||||
{
|
||||
if (stream.is_open())
|
||||
return stream.write_some(cbs, ec);
|
||||
|
||||
net::const_buffer buf;
|
||||
for (auto itr = net::buffer_sequence_begin(cbs);
|
||||
itr != net::buffer_sequence_end(cbs); itr++)
|
||||
if (itr->size() > 0)
|
||||
{
|
||||
buf = *itr;
|
||||
break;
|
||||
}
|
||||
|
||||
if (buf.size() == 0u)
|
||||
return 0u;
|
||||
|
||||
// get one screen size, that's how much we'll write
|
||||
CONSOLE_SCREEN_BUFFER_INFO bi;
|
||||
if (!GetConsoleScreenBufferInfo(object.native_handle(), &bi)) {
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return 0u;
|
||||
}
|
||||
|
||||
const auto sz = (std::min)(static_cast<std::size_t>(bi.dwSize.X * bi.dwSize.Y), buf.size());
|
||||
|
||||
DWORD wr = 0u;
|
||||
if (!WriteConsoleA(object.native_handle(), buf.data(), sz, &wr, NULL))
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
|
||||
return static_cast<std::size_t>(wr);
|
||||
}
|
||||
|
||||
template<typename ConstBufferSequence>
|
||||
struct async_write_op
|
||||
{
|
||||
basic_stream_handle *this_;
|
||||
ConstBufferSequence buffer;
|
||||
|
||||
template<typename Handler>
|
||||
void operator()(Handler &&handler)
|
||||
{
|
||||
if (this_->stream.is_open())
|
||||
return this_->stream.async_write_some(buffer, std::move(handler));
|
||||
|
||||
error_code ec;
|
||||
auto n = this_->write_some(buffer, ec);
|
||||
auto exec = net::get_associated_immediate_executor(
|
||||
handler, this_->object.get_executor());
|
||||
net::dispatch(exec, net::append(std::move(handler), ec, n));
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
template<typename ConstBufferSequence, typename CompletionToken>
|
||||
auto async_write_some(const ConstBufferSequence & buffer, CompletionToken && token)
|
||||
-> decltype(net::async_initiate<CompletionToken,
|
||||
void(boost::system::error_code, std::size_t)>(
|
||||
async_write_op<ConstBufferSequence>{this, buffer}, token))
|
||||
{
|
||||
return net::async_initiate<CompletionToken,
|
||||
void(boost::system::error_code, std::size_t)>(
|
||||
async_write_op<ConstBufferSequence>{this, buffer}, token);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#endif
|
||||
#endif //BOOST_PROCESS_V2_EXPERIMENTAL_DETAIL_BASIC_STREAM_HANDLE_HPP
|
||||
25
include/boost/process/v2/experimental/pty.hpp
Normal file
25
include/boost/process/v2/experimental/pty.hpp
Normal file
@@ -0,0 +1,25 @@
|
||||
//
|
||||
// Copyright (c) 2024 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_VS_EXPERIMENTAL_PTY_HPP
|
||||
#define BOOST_PROCESS_VS_EXPERIMENTAL_PTY_HPP
|
||||
|
||||
#include <boost/process/v2/experimental/basic_pty.hpp>
|
||||
|
||||
#if !defined(BOOST_PROCESS_V2_WINDOWS) || (NTDDI_VERSION >= 0x0A000006)
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
namespace experimental
|
||||
{
|
||||
|
||||
typedef basic_pty<> pty;
|
||||
|
||||
}
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#endif // windows version
|
||||
#endif //BOOST_PROCESS_VS_EXPERIMENTAL_PTY_HPP
|
||||
24
include/boost/process/v2/experimental/stream.hpp
Normal file
24
include/boost/process/v2/experimental/stream.hpp
Normal file
@@ -0,0 +1,24 @@
|
||||
//
|
||||
// Copyright (c) 2024 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_EXPERIMENTAL_PROCESS_STREAM_HPP
|
||||
#define BOOST_PROCESS_V2_EXPERIMENTAL_PROCESS_STREAM_HPP
|
||||
|
||||
#include <boost/process/v2/experimental/basic_stream.hpp>
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
|
||||
namespace experimental
|
||||
{
|
||||
|
||||
typedef basic_stream<> stream;
|
||||
|
||||
}
|
||||
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#endif //BOOST_PROCESS_V2_EXPERIMENTAL_PROCESS_STREAM_HPP
|
||||
@@ -36,7 +36,7 @@ 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)
|
||||
inline shell cmd(basic_process_handle<Executor> & handle, error_code & ec)
|
||||
{
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
return cmd(handle.native_handle(), ec);
|
||||
@@ -46,7 +46,7 @@ BOOST_PROCESS_V2_DECL shell cmd(basic_process_handle<Executor> & handle, error_c
|
||||
}
|
||||
|
||||
template<typename Executor>
|
||||
BOOST_PROCESS_V2_DECL shell cmd(basic_process_handle<Executor> & handle)
|
||||
inline shell cmd(basic_process_handle<Executor> & handle)
|
||||
{
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
return cmd(handle.native_handle());
|
||||
|
||||
@@ -27,7 +27,7 @@ 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)
|
||||
inline filesystem::path cwd(basic_process_handle<Executor> & handle, error_code & ec)
|
||||
{
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
return cwd(handle.native_handle(), ec);
|
||||
@@ -37,7 +37,7 @@ BOOST_PROCESS_V2_DECL filesystem::path cwd(basic_process_handle<Executor> & hand
|
||||
}
|
||||
|
||||
template<typename Executor>
|
||||
BOOST_PROCESS_V2_DECL filesystem::path cwd(basic_process_handle<Executor> & handle)
|
||||
inline filesystem::path cwd(basic_process_handle<Executor> & handle)
|
||||
{
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
return cwd(handle.native_handle());
|
||||
|
||||
@@ -120,7 +120,7 @@ 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)
|
||||
inline env_view env(basic_process_handle<Executor> & handle, error_code & ec)
|
||||
{
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
return env(handle.native_handle(), ec);
|
||||
@@ -130,7 +130,7 @@ BOOST_PROCESS_V2_DECL env_view env(basic_process_handle<Executor> & handle, erro
|
||||
}
|
||||
|
||||
template<typename Executor>
|
||||
BOOST_PROCESS_V2_DECL env_view env(basic_process_handle<Executor> & handle)
|
||||
inline env_view env(basic_process_handle<Executor> & handle)
|
||||
{
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
return env(handle.native_handle());
|
||||
|
||||
@@ -34,7 +34,7 @@ BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
*
|
||||
* Popen can be used as a stream object in other protocols.
|
||||
*/
|
||||
template<typename Executor = BOOST_PROCESS_V2_ASIO_NAMESPACE::any_io_executor>
|
||||
template<typename Executor = net::any_io_executor>
|
||||
struct basic_popen : basic_process<Executor>
|
||||
{
|
||||
/// The executor of the process
|
||||
@@ -69,7 +69,7 @@ struct basic_popen : basic_process<Executor>
|
||||
explicit basic_popen(ExecutionContext & context,
|
||||
typename std::enable_if<
|
||||
is_convertible<ExecutionContext&,
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context&>::value, void *>::type = nullptr)
|
||||
net::execution_context&>::value, void *>::type = nullptr)
|
||||
: basic_process<Executor>{context}
|
||||
{
|
||||
}
|
||||
@@ -148,7 +148,7 @@ struct basic_popen : basic_process<Executor>
|
||||
ExecutionContext & context,
|
||||
typename std::enable_if<
|
||||
std::is_convertible<ExecutionContext&,
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context&>::value,
|
||||
net::execution_context&>::value,
|
||||
const filesystem::path&>::type exe,
|
||||
std::initializer_list<string_view> args,
|
||||
Inits&&... inits)
|
||||
@@ -169,7 +169,7 @@ struct basic_popen : basic_process<Executor>
|
||||
ExecutionContext & context,
|
||||
typename std::enable_if<
|
||||
std::is_convertible<ExecutionContext&,
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context&>::value,
|
||||
net::execution_context&>::value,
|
||||
const filesystem::path&>::type exe,
|
||||
std::initializer_list<string_view> args,
|
||||
Inits&&... inits)
|
||||
@@ -189,7 +189,7 @@ struct basic_popen : basic_process<Executor>
|
||||
ExecutionContext & context,
|
||||
typename std::enable_if<
|
||||
std::is_convertible<ExecutionContext&,
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context&>::value,
|
||||
net::execution_context&>::value,
|
||||
const filesystem::path&>::type exe,
|
||||
Args&& args, Inits&&... inits)
|
||||
: basic_process<Executor>(context)
|
||||
@@ -209,7 +209,7 @@ struct basic_popen : basic_process<Executor>
|
||||
ExecutionContext & context,
|
||||
typename std::enable_if<
|
||||
std::is_convertible<ExecutionContext&,
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context&>::value,
|
||||
net::execution_context&>::value,
|
||||
const filesystem::path&>::type exe,
|
||||
Args&& args, Inits&&... inits)
|
||||
: basic_process<Executor>(context)
|
||||
@@ -224,9 +224,9 @@ struct basic_popen : basic_process<Executor>
|
||||
|
||||
|
||||
/// The type used for stdin on the parent process side.
|
||||
using stdin_type = BOOST_PROCESS_V2_ASIO_NAMESPACE::basic_writable_pipe<Executor>;
|
||||
using stdin_type = net::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>;
|
||||
using stdout_type = net::basic_readable_pipe<Executor>;
|
||||
|
||||
/// Get the stdin pipe.
|
||||
stdin_type & get_stdin() {return stdin_; }
|
||||
@@ -336,14 +336,11 @@ struct basic_popen : basic_process<Executor>
|
||||
* 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))
|
||||
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, std::size_t))
|
||||
WriteToken = net::default_completion_token_t<executor_type>>
|
||||
auto async_write_some(const ConstBufferSequence& buffers,
|
||||
WriteToken && token = net::default_completion_token_t<executor_type>())
|
||||
-> decltype(std::declval<stdin_type&>().async_write_some(buffers, std::forward<WriteToken>(token)))
|
||||
{
|
||||
return stdin_.async_write_some(buffers, std::forward<WriteToken>(token));
|
||||
}
|
||||
@@ -451,14 +448,12 @@ struct basic_popen : basic_process<Executor>
|
||||
* 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_COMPLETION_TOKEN_FOR(void (boost::system::error_code, std::size_t))
|
||||
ReadToken = net::default_completion_token_t<executor_type>>
|
||||
auto async_read_some(const MutableBufferSequence& buffers,
|
||||
BOOST_ASIO_MOVE_ARG(ReadToken) token
|
||||
BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
|
||||
= net::default_completion_token_t<executor_type>())
|
||||
-> decltype(std::declval<stdout_type&>().async_read_some(buffers, std::forward<ReadToken>(token)))
|
||||
{
|
||||
return stdout_.async_read_some(buffers, std::forward<ReadToken>(token));
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__APPLE__) || defined(__MACH__)
|
||||
#if defined(__APPLE__) || defined(__MACH__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
extern "C" { extern char **environ; }
|
||||
#endif
|
||||
|
||||
@@ -305,7 +305,7 @@ struct default_launcher
|
||||
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,
|
||||
ExecutionContext&, net::execution_context&>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<typename ExecutionContext::executor_type>
|
||||
@@ -324,7 +324,7 @@ struct default_launcher
|
||||
auto operator()(ExecutionContext & context,
|
||||
error_code & ec,
|
||||
const typename std::enable_if<std::is_convertible<
|
||||
ExecutionContext&, BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context&>::value,
|
||||
ExecutionContext&, net::execution_context&>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<typename ExecutionContext::executor_type>
|
||||
@@ -335,8 +335,8 @@ struct default_launcher
|
||||
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,
|
||||
net::execution::is_executor<Executor>::value ||
|
||||
net::is_executor<Executor>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<Executor>
|
||||
@@ -354,8 +354,8 @@ struct default_launcher
|
||||
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,
|
||||
net::execution::is_executor<Executor>::value ||
|
||||
net::is_executor<Executor>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<Executor>
|
||||
@@ -365,12 +365,12 @@ struct default_launcher
|
||||
pipe_guard pg;
|
||||
if (::pipe(pg.p))
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, errno, system_category())
|
||||
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())
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, errno, system_category());
|
||||
return basic_process<Executor>{exec};
|
||||
}
|
||||
ec = detail::on_setup(*this, executable, argv, inits ...);
|
||||
@@ -381,23 +381,23 @@ struct default_launcher
|
||||
}
|
||||
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);
|
||||
auto & ctx = net::query(
|
||||
exec, net::execution::context);
|
||||
ctx.notify_fork(net::execution_context::fork_prepare);
|
||||
pid = ::fork();
|
||||
if (pid == -1)
|
||||
{
|
||||
ctx.notify_fork(BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context::fork_parent);
|
||||
ctx.notify_fork(net::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())
|
||||
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);
|
||||
ctx.notify_fork(net::execution_context::fork_child);
|
||||
ec = detail::on_exec_setup(*this, executable, argv, inits...);
|
||||
if (!ec)
|
||||
{
|
||||
@@ -407,13 +407,13 @@ struct default_launcher
|
||||
::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())
|
||||
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);
|
||||
ctx.notify_fork(net::execution_context::fork_parent);
|
||||
::close(pg.p[1]);
|
||||
pg.p[1] = -1;
|
||||
int child_error{0};
|
||||
@@ -423,12 +423,12 @@ struct default_launcher
|
||||
int err = errno;
|
||||
if ((err != EAGAIN) && (err != EINTR))
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, err, system_category())
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, err, system_category());
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (count != 0)
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, child_error, system_category())
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, child_error, system_category());
|
||||
|
||||
if (ec)
|
||||
{
|
||||
|
||||
@@ -20,7 +20,7 @@ struct fork_and_forget_launcher : default_launcher
|
||||
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,
|
||||
ExecutionContext&, net::execution_context&>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<typename ExecutionContext::executor_type>
|
||||
@@ -39,7 +39,7 @@ struct fork_and_forget_launcher : default_launcher
|
||||
auto operator()(ExecutionContext & context,
|
||||
error_code & ec,
|
||||
const typename std::enable_if<is_convertible<
|
||||
ExecutionContext&, BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context&>::value,
|
||||
ExecutionContext&, net::execution_context&>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<typename ExecutionContext::executor_type>
|
||||
@@ -50,8 +50,8 @@ struct fork_and_forget_launcher : default_launcher
|
||||
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,
|
||||
net::execution::is_executor<Executor>::value ||
|
||||
net::is_executor<Executor>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<Executor>
|
||||
@@ -69,8 +69,8 @@ struct fork_and_forget_launcher : default_launcher
|
||||
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,
|
||||
net::execution::is_executor<Executor>::value ||
|
||||
net::is_executor<Executor>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<Executor>
|
||||
@@ -84,22 +84,22 @@ struct fork_and_forget_launcher : default_launcher
|
||||
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);
|
||||
auto & ctx = net::query(
|
||||
exec, net::execution::context);
|
||||
ctx.notify_fork(net::execution_context::fork_prepare);
|
||||
pid = ::fork();
|
||||
if (pid == -1)
|
||||
{
|
||||
ctx.notify_fork(BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context::fork_parent);
|
||||
ctx.notify_fork(net::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())
|
||||
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);
|
||||
ctx.notify_fork(net::execution_context::fork_child);
|
||||
|
||||
ec = detail::on_exec_setup(*this, executable, argv, inits...);
|
||||
if (!ec)
|
||||
@@ -107,12 +107,12 @@ struct fork_and_forget_launcher : default_launcher
|
||||
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())
|
||||
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);
|
||||
ctx.notify_fork(net::execution_context::fork_parent);
|
||||
if (ec)
|
||||
{
|
||||
detail::on_error(*this, executable, argv, ec, inits...);
|
||||
|
||||
@@ -25,7 +25,7 @@ struct pdfork_launcher : default_launcher
|
||||
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,
|
||||
ExecutionContext&, net::execution_context&>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<typename ExecutionContext::executor_type>
|
||||
@@ -44,7 +44,7 @@ struct pdfork_launcher : default_launcher
|
||||
auto operator()(ExecutionContext & context,
|
||||
error_code & ec,
|
||||
const typename std::enable_if<is_convertible<
|
||||
ExecutionContext&, BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context&>::value,
|
||||
ExecutionContext&, net::execution_context&>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<typename ExecutionContext::executor_type>
|
||||
@@ -55,8 +55,8 @@ struct pdfork_launcher : default_launcher
|
||||
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,
|
||||
net::execution::is_executor<Executor>::value ||
|
||||
net::is_executor<Executor>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<Executor>
|
||||
@@ -74,8 +74,8 @@ struct pdfork_launcher : default_launcher
|
||||
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,
|
||||
net::execution::is_executor<Executor>::value ||
|
||||
net::is_executor<Executor>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<Executor>
|
||||
@@ -85,12 +85,12 @@ struct pdfork_launcher : default_launcher
|
||||
pipe_guard pg;
|
||||
if (::pipe(pg.p))
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, errno, system_category())
|
||||
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())
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, errno, system_category());
|
||||
return basic_process<Executor>{exec};
|
||||
}
|
||||
ec = detail::on_setup(*this, executable, argv, inits ...);
|
||||
@@ -101,22 +101,22 @@ struct pdfork_launcher : default_launcher
|
||||
}
|
||||
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);
|
||||
auto & ctx = net::query(
|
||||
exec, net::execution::context);
|
||||
ctx.notify_fork(net::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);
|
||||
ctx.notify_fork(net::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())
|
||||
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);
|
||||
ctx.notify_fork(net::execution_context::fork_child);
|
||||
::close(pg.p[0]);
|
||||
|
||||
ec = detail::on_exec_setup(*this, executable, argv, inits...);
|
||||
@@ -128,12 +128,12 @@ struct pdfork_launcher : default_launcher
|
||||
::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())
|
||||
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);
|
||||
ctx.notify_fork(net::execution_context::fork_parent);
|
||||
::close(pg.p[1]);
|
||||
pg.p[1] = -1;
|
||||
int child_error{0};
|
||||
@@ -143,12 +143,12 @@ struct pdfork_launcher : default_launcher
|
||||
int err = errno;
|
||||
if ((err != EAGAIN) && (err != EINTR))
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, err, system_category())
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, err, system_category());
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (count != 0)
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, child_error, system_category())
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, child_error, system_category());
|
||||
|
||||
if (ec)
|
||||
{
|
||||
|
||||
@@ -22,7 +22,7 @@ struct vfork_launcher : default_launcher
|
||||
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,
|
||||
ExecutionContext&, net::execution_context&>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<typename ExecutionContext::executor_type>
|
||||
@@ -41,7 +41,7 @@ struct vfork_launcher : default_launcher
|
||||
auto operator()(ExecutionContext & context,
|
||||
error_code & ec,
|
||||
const typename std::enable_if<std::is_convertible<
|
||||
ExecutionContext&, BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context&>::value,
|
||||
ExecutionContext&, net::execution_context&>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<typename ExecutionContext::executor_type>
|
||||
@@ -52,8 +52,8 @@ struct vfork_launcher : default_launcher
|
||||
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,
|
||||
net::execution::is_executor<Executor>::value ||
|
||||
net::is_executor<Executor>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<Executor>
|
||||
@@ -71,8 +71,8 @@ struct vfork_launcher : default_launcher
|
||||
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,
|
||||
net::execution::is_executor<Executor>::value ||
|
||||
net::is_executor<Executor>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<Executor>
|
||||
@@ -86,17 +86,17 @@ struct vfork_launcher : default_launcher
|
||||
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);
|
||||
auto & ctx = net::query(
|
||||
exec, net::execution::context);
|
||||
ctx.notify_fork(net::execution_context::fork_prepare);
|
||||
pid = ::vfork();
|
||||
if (pid == -1)
|
||||
{
|
||||
ctx.notify_fork(BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context::fork_parent);
|
||||
ctx.notify_fork(net::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())
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, errno, system_category());
|
||||
return basic_process<Executor>{exec};
|
||||
}
|
||||
else if (pid == 0)
|
||||
@@ -107,12 +107,12 @@ struct vfork_launcher : default_launcher
|
||||
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())
|
||||
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);
|
||||
ctx.notify_fork(net::execution_context::fork_parent);
|
||||
|
||||
if (ec)
|
||||
{
|
||||
|
||||
@@ -34,7 +34,7 @@ BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
/* 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>
|
||||
template<typename Executor = net::any_io_executor>
|
||||
struct basic_process
|
||||
{
|
||||
/// The executor of the process
|
||||
@@ -111,7 +111,7 @@ struct basic_process
|
||||
ExecutionContext & context,
|
||||
typename std::enable_if<
|
||||
std::is_convertible<ExecutionContext&,
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context&>::value,
|
||||
net::execution_context&>::value,
|
||||
const filesystem::path&>::type exe,
|
||||
std::initializer_list<string_view> args,
|
||||
Inits&&... inits)
|
||||
@@ -125,7 +125,7 @@ struct basic_process
|
||||
ExecutionContext & context,
|
||||
typename std::enable_if<
|
||||
std::is_convertible<ExecutionContext&,
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context&>::value,
|
||||
net::execution_context&>::value,
|
||||
const filesystem::path&>::type exe,
|
||||
Args&& args, Inits&&... inits)
|
||||
: basic_process(default_process_launcher()(executor_type(context.get_executor()),
|
||||
@@ -148,7 +148,7 @@ struct basic_process
|
||||
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)
|
||||
net::execution_context&>::value, void *>::type = nullptr)
|
||||
: process_handle_(context, pid) {}
|
||||
|
||||
/// Attach to an existing process and the internal handle
|
||||
@@ -156,7 +156,7 @@ struct basic_process
|
||||
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)
|
||||
net::execution_context&>::value, void *>::type = nullptr)
|
||||
: process_handle_(context.get_executor(), pid, native_handle) {}
|
||||
|
||||
/// Create an invalid handle
|
||||
@@ -164,7 +164,7 @@ struct basic_process
|
||||
explicit basic_process(ExecutionContext & context,
|
||||
typename std::enable_if<
|
||||
is_convertible<ExecutionContext&,
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context&>::value, void *>::type = nullptr)
|
||||
net::execution_context&>::value, void *>::type = nullptr)
|
||||
: process_handle_(context.get_executor()) {}
|
||||
|
||||
|
||||
@@ -325,15 +325,7 @@ struct basic_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>
|
||||
@@ -363,7 +355,7 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::post(handle.get_executor(),
|
||||
net::post(handle.get_executor(),
|
||||
completer{static_cast<int>(res), std::move(self)});
|
||||
}
|
||||
else
|
||||
@@ -383,6 +375,18 @@ private:
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
/// 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 = net::default_completion_token_t<executor_type>>
|
||||
auto async_wait(WaitHandler && handler = net::default_completion_token_t<executor_type>())
|
||||
-> decltype(net::async_compose<WaitHandler, void (error_code, int)>(
|
||||
async_wait_op_{process_handle_, exit_status_}, handler, process_handle_))
|
||||
{
|
||||
return net::async_compose<WaitHandler, void (error_code, int)>(
|
||||
async_wait_op_{process_handle_, exit_status_}, handler, process_handle_);
|
||||
}
|
||||
};
|
||||
|
||||
/// Process with the default executor.
|
||||
|
||||
@@ -32,7 +32,7 @@ BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
* 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>
|
||||
template<typename Executor = net::any_io_executor>
|
||||
struct basic_process_handle
|
||||
{
|
||||
/// The native handle of the process.
|
||||
@@ -123,28 +123,26 @@ struct basic_process_handle
|
||||
|
||||
/// 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));
|
||||
|
||||
WaitHandler = net::default_completion_token_t<executor_type>>
|
||||
auto async_wait(WaitHandler &&handler = net::default_completion_token_t<executor_type>());
|
||||
};
|
||||
|
||||
|
||||
#else
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
template<typename Executor = BOOST_PROCESS_V2_ASIO_NAMESPACE::any_io_executor>
|
||||
template<typename Executor = net::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>
|
||||
template<typename Executor = net::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>
|
||||
template<typename Executor = net::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>
|
||||
template<typename Executor = net::any_io_executor>
|
||||
using basic_process_handle = detail::basic_process_handle_signal<Executor>;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -103,7 +103,7 @@ struct process_io_binding
|
||||
|
||||
|
||||
template<typename Executor>
|
||||
process_io_binding(BOOST_PROCESS_V2_ASIO_NAMESPACE::basic_readable_pipe<Executor> & pipe)
|
||||
process_io_binding(net::basic_readable_pipe<Executor> & pipe)
|
||||
{
|
||||
if (Target == STD_INPUT_HANDLE)
|
||||
{
|
||||
@@ -112,9 +112,9 @@ struct process_io_binding
|
||||
return ;
|
||||
}
|
||||
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::detail::native_pipe_handle p[2];
|
||||
net::detail::native_pipe_handle p[2];
|
||||
error_code ec;
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::detail::create_pipe(p, ec);
|
||||
net::detail::create_pipe(p, ec);
|
||||
if (ec)
|
||||
detail::throw_error(ec, "create_pipe");
|
||||
|
||||
@@ -124,7 +124,7 @@ struct process_io_binding
|
||||
|
||||
|
||||
template<typename Executor>
|
||||
process_io_binding(BOOST_PROCESS_V2_ASIO_NAMESPACE::basic_writable_pipe<Executor> & pipe)
|
||||
process_io_binding(net::basic_writable_pipe<Executor> & pipe)
|
||||
{
|
||||
if (Target != STD_INPUT_HANDLE)
|
||||
{
|
||||
@@ -132,9 +132,9 @@ struct process_io_binding
|
||||
h = std::unique_ptr<void, handle_closer>{h_, get_flags(h_)};
|
||||
return ;
|
||||
}
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::detail::native_pipe_handle p[2];
|
||||
net::detail::native_pipe_handle p[2];
|
||||
error_code ec;
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::detail::create_pipe(p, ec);
|
||||
net::detail::create_pipe(p, ec);
|
||||
if (ec)
|
||||
detail::throw_error(ec, "create_pipe");
|
||||
|
||||
@@ -181,7 +181,7 @@ struct process_io_binding
|
||||
}
|
||||
|
||||
template<typename Executor>
|
||||
process_io_binding(BOOST_PROCESS_V2_ASIO_NAMESPACE::basic_readable_pipe<Executor> & readable_pipe)
|
||||
process_io_binding(net::basic_readable_pipe<Executor> & readable_pipe)
|
||||
{
|
||||
if (Target == STDIN_FILENO)
|
||||
{
|
||||
@@ -189,15 +189,15 @@ struct process_io_binding
|
||||
return ;
|
||||
}
|
||||
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::detail::native_pipe_handle p[2];
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::detail::create_pipe(p, ec);
|
||||
net::detail::native_pipe_handle p[2];
|
||||
net::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)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return ;
|
||||
}
|
||||
fd_needs_closing = true;
|
||||
@@ -206,7 +206,7 @@ struct process_io_binding
|
||||
|
||||
|
||||
template<typename Executor>
|
||||
process_io_binding(BOOST_PROCESS_V2_ASIO_NAMESPACE::basic_writable_pipe<Executor> & writable_pipe)
|
||||
process_io_binding(net::basic_writable_pipe<Executor> & writable_pipe)
|
||||
{
|
||||
|
||||
if (Target != STDIN_FILENO)
|
||||
@@ -214,16 +214,16 @@ struct process_io_binding
|
||||
fd = writable_pipe.native_handle();
|
||||
return ;
|
||||
}
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::detail::native_pipe_handle p[2];
|
||||
net::detail::native_pipe_handle p[2];
|
||||
error_code ec;
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::detail::create_pipe(p, ec);
|
||||
net::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)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return ;
|
||||
}
|
||||
fd_needs_closing = true;
|
||||
|
||||
@@ -28,7 +28,7 @@ struct as_user_launcher : default_launcher
|
||||
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,
|
||||
ExecutionContext&, net::execution_context&>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<typename ExecutionContext::executor_type>
|
||||
@@ -47,7 +47,7 @@ struct as_user_launcher : default_launcher
|
||||
auto operator()(ExecutionContext & context,
|
||||
error_code & ec,
|
||||
const typename std::enable_if<std::is_convertible<
|
||||
ExecutionContext&, BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context&>::value,
|
||||
ExecutionContext&, net::execution_context&>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<typename ExecutionContext::executor_type>
|
||||
@@ -58,8 +58,8 @@ struct as_user_launcher : default_launcher
|
||||
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,
|
||||
net::execution::is_executor<Executor>::value ||
|
||||
net::is_executor<Executor>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<Executor>
|
||||
@@ -77,8 +77,8 @@ struct as_user_launcher : default_launcher
|
||||
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,
|
||||
net::execution::is_executor<Executor>::value ||
|
||||
net::is_executor<Executor>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<Executor>
|
||||
@@ -107,7 +107,7 @@ struct as_user_launcher : default_launcher
|
||||
|
||||
if (ok == 0)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
detail::on_error(*this, executable, command_line, ec, inits...);
|
||||
|
||||
if (process_information.hProcess != INVALID_HANDLE_VALUE)
|
||||
|
||||
@@ -236,7 +236,7 @@ struct default_launcher
|
||||
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,
|
||||
ExecutionContext&, net::execution_context&>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> enable_init<typename ExecutionContext::executor_type, Inits...>
|
||||
@@ -255,7 +255,7 @@ struct default_launcher
|
||||
auto operator()(ExecutionContext & context,
|
||||
error_code & ec,
|
||||
const typename std::enable_if<std::is_convertible<
|
||||
ExecutionContext&, BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context&>::value,
|
||||
ExecutionContext&, net::execution_context&>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> enable_init<typename ExecutionContext::executor_type, Inits...>
|
||||
@@ -266,8 +266,8 @@ struct default_launcher
|
||||
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,
|
||||
net::execution::is_executor<Executor>::value
|
||||
|| net::is_executor<Executor>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> enable_init<Executor, Inits...>
|
||||
@@ -285,8 +285,8 @@ struct default_launcher
|
||||
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,
|
||||
net::execution::is_executor<Executor>::value ||
|
||||
net::is_executor<Executor>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> enable_init<Executor, Inits...>
|
||||
@@ -314,7 +314,7 @@ struct default_launcher
|
||||
|
||||
if (ok == 0)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
detail::on_error(*this, executable, command_line, ec, inits...);
|
||||
|
||||
if (process_information.hProcess != INVALID_HANDLE_VALUE)
|
||||
|
||||
@@ -39,7 +39,7 @@ struct with_logon_launcher : default_launcher
|
||||
auto operator()(ExecutionContext & context,
|
||||
error_code & ec,
|
||||
const typename std::enable_if<std::is_convertible<
|
||||
ExecutionContext&, BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context&>::value,
|
||||
ExecutionContext&, net::execution_context&>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<typename ExecutionContext::executor_type>
|
||||
@@ -51,7 +51,7 @@ struct with_logon_launcher : default_launcher
|
||||
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,
|
||||
ExecutionContext&, net::execution_context&>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<typename ExecutionContext::executor_type>
|
||||
@@ -62,8 +62,8 @@ struct with_logon_launcher : default_launcher
|
||||
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,
|
||||
net::execution::is_executor<Executor>::value ||
|
||||
net::is_executor<Executor>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<Executor>
|
||||
@@ -81,8 +81,8 @@ struct with_logon_launcher : default_launcher
|
||||
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,
|
||||
net::execution::is_executor<Executor>::value ||
|
||||
net::is_executor<Executor>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<Executor>
|
||||
@@ -111,7 +111,7 @@ struct with_logon_launcher : default_launcher
|
||||
|
||||
if (ok == 0)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
detail::on_error(*this, executable, command_line, ec, inits...);
|
||||
|
||||
if (process_information.hProcess != INVALID_HANDLE_VALUE)
|
||||
|
||||
@@ -29,7 +29,7 @@ struct with_token_launcher : default_launcher
|
||||
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,
|
||||
ExecutionContext&, net::execution_context&>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<typename ExecutionContext::executor_type>
|
||||
@@ -48,7 +48,7 @@ struct with_token_launcher : default_launcher
|
||||
auto operator()(ExecutionContext & context,
|
||||
error_code & ec,
|
||||
const typename std::enable_if<std::is_convertible<
|
||||
ExecutionContext&, BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context&>::value,
|
||||
ExecutionContext&, net::execution_context&>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<typename ExecutionContext::executor_type>
|
||||
@@ -59,8 +59,8 @@ struct with_token_launcher : default_launcher
|
||||
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,
|
||||
net::execution::is_executor<Executor>::value ||
|
||||
net::is_executor<Executor>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<Executor>
|
||||
@@ -78,8 +78,8 @@ struct with_token_launcher : default_launcher
|
||||
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,
|
||||
net::execution::is_executor<Executor>::value ||
|
||||
net::is_executor<Executor>::value,
|
||||
filesystem::path >::type & executable,
|
||||
Args && args,
|
||||
Inits && ... inits ) -> basic_process<Executor>
|
||||
@@ -106,7 +106,7 @@ struct with_token_launcher : default_launcher
|
||||
|
||||
if (ok == 0)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
detail::on_error(*this, executable, command_line, ec, inits...);
|
||||
|
||||
if (process_information.hProcess != INVALID_HANDLE_VALUE)
|
||||
|
||||
@@ -30,7 +30,7 @@ basic_cstring_ref<char_type, value_char_traits<char>> get(
|
||||
auto res = ::getenv(key.c_str());
|
||||
if (res == nullptr)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, ENOENT, system_category())
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, ENOENT, system_category());
|
||||
return {};
|
||||
}
|
||||
return res;
|
||||
@@ -41,13 +41,13 @@ void set(basic_cstring_ref<char_type, key_char_traits<char_type>> key,
|
||||
error_code & ec)
|
||||
{
|
||||
if (::setenv(key.c_str(), value.c_str(), true))
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
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)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
}
|
||||
|
||||
|
||||
@@ -65,9 +65,10 @@ native_iterator find_end(native_handle_type nh)
|
||||
nh++;
|
||||
return nh;
|
||||
}
|
||||
bool is_executable(const filesystem::path & p, error_code & ec)
|
||||
|
||||
bool has_x_access(const char * pth)
|
||||
{
|
||||
return filesystem::is_regular_file(p, ec) && (::access(p.c_str(), X_OK) == 0);
|
||||
return (::access(pth, X_OK) == 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ std::basic_string<char_type, value_char_traits<char_type>> get(
|
||||
buf.resize(size);
|
||||
|
||||
if (buf.size() == 0)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
|
||||
return buf;
|
||||
}
|
||||
@@ -55,14 +55,14 @@ void set(basic_cstring_ref<char_type, key_char_traits<char_type>> key,
|
||||
error_code & ec)
|
||||
{
|
||||
if (!::SetEnvironmentVariableW(key.c_str(), value.c_str()))
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
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)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
}
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ std::basic_string<char, value_char_traits<char>> get(
|
||||
buf.resize(size);
|
||||
|
||||
if (buf.size() == 0)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
|
||||
return buf;
|
||||
}
|
||||
@@ -93,14 +93,14 @@ void set(basic_cstring_ref<char, key_char_traits<char>> key,
|
||||
error_code & ec)
|
||||
{
|
||||
if (!::SetEnvironmentVariableA(key.c_str(), value.c_str()))
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
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)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
}
|
||||
|
||||
|
||||
@@ -125,9 +125,9 @@ native_iterator find_end(native_handle_type nh)
|
||||
return ++nh;
|
||||
}
|
||||
|
||||
bool is_executable(const filesystem::path & pth, error_code & ec)
|
||||
bool is_exec_type(const wchar_t * pth)
|
||||
{
|
||||
return filesystem::is_regular_file(pth, ec) && SHGetFileInfoW(pth.native().c_str(), 0,0,0, SHGFI_EXETYPE);
|
||||
return SHGetFileInfoW(pth, 0,0,0, SHGFI_EXETYPE);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ void get_exit_code_(
|
||||
error_code & ec)
|
||||
{
|
||||
if (!::GetExitCodeProcess(handle, &exit_code))
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ HANDLE open_process_(DWORD pid)
|
||||
if (proc == nullptr)
|
||||
{
|
||||
error_code ec;
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
throw system_error(ec, "open_process()");
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ 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())
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, ERROR_INVALID_HANDLE_STATE, system_category());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -77,7 +77,7 @@ bool check_pid_(pid_type pid_, error_code & ec)
|
||||
{
|
||||
if (pid_ == 0)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, ERROR_INVALID_HANDLE_STATE, system_category())
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, ERROR_INVALID_HANDLE_STATE, system_category());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -100,7 +100,7 @@ static BOOL CALLBACK enum_window(HWND hwnd, LPARAM param)
|
||||
LRESULT res = ::SendMessageW(hwnd, WM_CLOSE, 0, 0);
|
||||
|
||||
if (res)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(data->ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(data->ec);
|
||||
return res == 0;
|
||||
}
|
||||
|
||||
@@ -109,25 +109,25 @@ 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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
}
|
||||
|
||||
#if !defined(BOOST_PROCESS_V2_DISABLE_UNDOCUMENTED_API)
|
||||
@@ -136,7 +136,7 @@ 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)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
}
|
||||
|
||||
void resume_(HANDLE handle, error_code & ec)
|
||||
@@ -144,17 +144,17 @@ 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)
|
||||
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())
|
||||
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())
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, ERROR_CALL_NOT_IMPLEMENTED, system_category());
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -25,13 +25,13 @@ inline void handle_error(error_code & ec)
|
||||
switch (err)
|
||||
{
|
||||
case ERROR_INSUFFICIENT_BUFFER:
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, error::insufficient_buffer, error::utf8_category)
|
||||
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)
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, error::invalid_character, error::utf8_category);
|
||||
break;
|
||||
default:
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, err, system_category())
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, err, system_category());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,7 +240,7 @@ std::size_t convert_to_utf8(const wchar_t * in, std::size_t size,
|
||||
if (*from > max_wchar) {
|
||||
from_next = from;
|
||||
to_next = to;
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, error::invalid_character, error::get_utf8_category())
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, error::invalid_character, error::get_utf8_category());
|
||||
return 0u;
|
||||
}
|
||||
|
||||
@@ -268,7 +268,7 @@ std::size_t convert_to_utf8(const wchar_t * in, std::size_t size,
|
||||
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())
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, error::insufficient_buffer, error::get_utf8_category());
|
||||
return 0u;
|
||||
}
|
||||
++from;
|
||||
@@ -278,7 +278,7 @@ std::size_t convert_to_utf8(const wchar_t * in, std::size_t size,
|
||||
|
||||
// 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())
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, error::insufficient_buffer, error::get_utf8_category());
|
||||
|
||||
return to_next - out;
|
||||
}
|
||||
@@ -313,7 +313,7 @@ std::size_t convert_to_wide(const char * in, std::size_t size,
|
||||
if (invalid_leading_octet(*from)) {
|
||||
from_next = from;
|
||||
to_next = to;
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, error::invalid_character, error::get_utf8_category())
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, error::invalid_character, error::get_utf8_category());
|
||||
return 0u;
|
||||
}
|
||||
|
||||
@@ -337,7 +337,7 @@ std::size_t convert_to_wide(const char * in, std::size_t size,
|
||||
if (invalid_continuing_octet(*from)) {
|
||||
from_next = from;
|
||||
to_next = to;
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, error::invalid_character, error::get_utf8_category())
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, error::invalid_character, error::get_utf8_category());
|
||||
return 0u;
|
||||
}
|
||||
|
||||
@@ -354,7 +354,7 @@ std::size_t convert_to_wide(const char * in, std::size_t size,
|
||||
// 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())
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, error::insufficient_buffer, error::get_utf8_category());
|
||||
return 0u;
|
||||
}
|
||||
*to++ = ucs_result;
|
||||
@@ -363,7 +363,7 @@ std::size_t convert_to_wide(const char * in, std::size_t size,
|
||||
to_next = to;
|
||||
|
||||
if (from != from_end)
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, error::insufficient_buffer, error::get_utf8_category())
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, error::insufficient_buffer, error::get_utf8_category());
|
||||
|
||||
return to_next - out;
|
||||
}
|
||||
|
||||
@@ -23,9 +23,12 @@
|
||||
#endif
|
||||
|
||||
#if (defined(__APPLE__) && defined(__MACH__))
|
||||
#include <sys/proc_info.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <libproc.h>
|
||||
#include <TargetConditionals.h>
|
||||
#if !TARGET_OS_IOS
|
||||
#include <sys/proc_info.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <libproc.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if (defined(__linux__) || defined(__ANDROID__))
|
||||
@@ -156,7 +159,7 @@ shell cmd(boost::process::v2::pid_type pid, boost::system::error_code & ec)
|
||||
|
||||
}
|
||||
|
||||
#elif (defined(__APPLE__) && defined(__MACH__))
|
||||
#elif (defined(__APPLE__) && defined(__MACH__)) && !TARGET_OS_IOS
|
||||
|
||||
shell cmd(boost::process::v2::pid_type pid, boost::system::error_code & ec)
|
||||
{
|
||||
@@ -165,7 +168,7 @@ shell cmd(boost::process::v2::pid_type pid, boost::system::error_code & ec)
|
||||
auto size = sizeof(argmax);
|
||||
if (sysctl(mib, 2, &argmax, &size, nullptr, 0) == -1)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -178,7 +181,7 @@ shell cmd(boost::process::v2::pid_type pid, boost::system::error_code & ec)
|
||||
|
||||
if (sysctl(mib, 3, &*procargs.begin(), &size, nullptr, 0) != 0)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -195,7 +198,7 @@ shell cmd(boost::process::v2::pid_type pid, boost::system::error_code & ec)
|
||||
auto e = std::find(itr, end, '\0');
|
||||
if (e == end && n < argc) // something off
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, EINVAL, system_category())
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, EINVAL, system_category());
|
||||
return {};
|
||||
}
|
||||
argv[n] = &*itr;
|
||||
@@ -220,7 +223,7 @@ shell cmd(boost::process::v2::pid_type pid, boost::system::error_code & ec)
|
||||
auto r = ::read(f, &*(procargs.end() - 4096), 4096);
|
||||
if (r < 0)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
::close(f);
|
||||
return {};
|
||||
}
|
||||
@@ -251,7 +254,7 @@ shell cmd(boost::process::v2::pid_type pid, boost::system::error_code & ec)
|
||||
auto e = std::find(itr, end, '\0');
|
||||
if (e == end && n < argc) // something off
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, EINVAL, system_category())
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, EINVAL, system_category());
|
||||
return {};
|
||||
}
|
||||
argv[n] = &*itr;
|
||||
@@ -287,10 +290,10 @@ shell cmd(boost::process::v2::pid_type pid, boost::system::error_code & ec)
|
||||
if (cmd)
|
||||
return make_cmd_shell_::clone(cmd);
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -319,10 +322,10 @@ shell cmd(boost::process::v2::pid_type pid, boost::system::error_code & ec)
|
||||
if (cmd)
|
||||
return make_cmd_shell_::clone(cmd);
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return vec;
|
||||
}
|
||||
|
||||
@@ -350,11 +353,10 @@ shell cmd(boost::process::v2::pid_type pid, boost::system::error_code & ec)
|
||||
if (cmd)
|
||||
return make_cmd_shell_::clone(cmd);
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
kvm_close(kd);
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -365,7 +367,7 @@ 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);
|
||||
kvm_t *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)))
|
||||
{
|
||||
@@ -376,25 +378,31 @@ shell cmd(boost::process::v2::pid_type pid, boost::system::error_code & ec)
|
||||
int argc = 0;
|
||||
for (int i = 0; cmd[i] != nullptr; i++)
|
||||
argc ++;
|
||||
return make_cmd_shell_::make(
|
||||
shell res = make_cmd_shell_::make(
|
||||
{}, argc, cmd,
|
||||
+[](int, char ** argv) {::free(argv);})
|
||||
kvm_close(kd);
|
||||
return res;
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
|
||||
kvm_close(kd);
|
||||
return {};
|
||||
}
|
||||
|
||||
#else
|
||||
#error "Platform not supported"
|
||||
filesystem::path cmd(boost::process::v2::pid_type, boost::system::error_code & ec)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, ENOTSUP, system_category());
|
||||
return "";
|
||||
}
|
||||
#endif
|
||||
|
||||
shell cmd(boost::process::v2::pid_type pid)
|
||||
|
||||
@@ -24,8 +24,11 @@
|
||||
#endif
|
||||
|
||||
#if (defined(__APPLE__) && defined(__MACH__))
|
||||
#include <sys/proc_info.h>
|
||||
#include <libproc.h>
|
||||
#include <TargetConditionals.h>
|
||||
#if !TARGET_OS_IOS
|
||||
#include <sys/proc_info.h>
|
||||
#include <libproc.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if (defined(BOOST_PROCESS_V2_WINDOWS) || defined(__linux__) || defined(__ANDROID__) || defined(__sun))
|
||||
@@ -46,8 +49,10 @@
|
||||
#endif
|
||||
|
||||
#if defined(__DragonFly__)
|
||||
#include <climits>
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_PROCESS_USE_STD_FS
|
||||
@@ -68,7 +73,7 @@ filesystem::path cwd(HANDLE proc, boost::system::error_code & ec)
|
||||
if (!buffer.empty())
|
||||
return filesystem::canonical(buffer, ec);
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return "";
|
||||
}
|
||||
|
||||
@@ -83,7 +88,7 @@ filesystem::path cwd(boost::process::v2::pid_type pid, boost::system::error_code
|
||||
};
|
||||
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)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
else
|
||||
return cwd(proc.get(), ec);
|
||||
return {};
|
||||
@@ -98,7 +103,7 @@ filesystem::path cwd(HANDLE proc)
|
||||
return res;
|
||||
}
|
||||
|
||||
#elif (defined(__APPLE__) && defined(__MACH__))
|
||||
#elif (defined(__APPLE__) && defined(__MACH__)) && !TARGET_OS_IOS
|
||||
|
||||
filesystem::path cwd(boost::process::v2::pid_type pid, boost::system::error_code & ec)
|
||||
{
|
||||
@@ -106,7 +111,7 @@ filesystem::path cwd(boost::process::v2::pid_type pid, boost::system::error_code
|
||||
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)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return "";
|
||||
}
|
||||
|
||||
@@ -141,10 +146,10 @@ filesystem::path cwd(boost::process::v2::pid_type pid, boost::system::error_code
|
||||
path = filesystem::canonical(kif.kf_path, ec);
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return path;
|
||||
}
|
||||
|
||||
@@ -152,55 +157,16 @@ filesystem::path cwd(boost::process::v2::pid_type pid, boost::system::error_code
|
||||
|
||||
filesystem::path cwd(boost::process::v2::pid_type pid, boost::system::error_code & ec)
|
||||
{
|
||||
/*
|
||||
filesystem::path path;
|
||||
// Official API (broken OS-level) - including code from DragonFly's fstat(1)
|
||||
// command line interface utility currently requires way too much code FWIW.
|
||||
std::size_t sz = 4, len = 0;
|
||||
char buffer[PATH_MAX];
|
||||
std::size_t sz = 4, len = sizeof(buffer);
|
||||
int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_CWD, pid};
|
||||
if (sysctl(mib, sz, nullptr, &len, nullptr, 0) == 0)
|
||||
if (sysctl(mib, sz, buffer, &len, nullptr, 0) == 0)
|
||||
{
|
||||
std::vector<char> vecbuff;
|
||||
vecbuff.resize(len);
|
||||
if (sysctl(mib, sz, &vecbuff[0], &len, nullptr, 0) == 0)
|
||||
{
|
||||
path = filesystem::canonical(&vecbuff[0], ec);
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
}
|
||||
path = filesystem::canonical(buffer, ec);
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return path;
|
||||
*/
|
||||
|
||||
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)
|
||||
if (pclose(fp) == -1)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return path;
|
||||
}
|
||||
|
||||
@@ -221,20 +187,24 @@ filesystem::path cwd(boost::process::v2::pid_type pid, boost::system::error_code
|
||||
{
|
||||
std::vector<char> vecbuff;
|
||||
vecbuff.resize(len);
|
||||
if (sysctl(mib, 4, &vecbuff[0], &len, nullptr, 0) == 0)
|
||||
if (sysctl(mib, sz, &vecbuff[0], &len, nullptr, 0) == 0)
|
||||
{
|
||||
path = filesystem::canonical(&vecbuff[0], ec);
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return path;
|
||||
}
|
||||
|
||||
#else
|
||||
#error "Platform not supported"
|
||||
filesystem::path cwd(boost::process::v2::pid_type pid, boost::system::error_code & ec)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, ENOTSUP, system_category());
|
||||
return "";
|
||||
}
|
||||
#endif
|
||||
|
||||
filesystem::path cwd(boost::process::v2::pid_type pid)
|
||||
|
||||
@@ -21,9 +21,12 @@
|
||||
#endif
|
||||
|
||||
#if (defined(__APPLE__) && defined(__MACH__))
|
||||
#include <sys/proc_info.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <libproc.h>
|
||||
#include <TargetConditionals.h>
|
||||
#if !TARGET_OS_IOS
|
||||
#include <sys/proc_info.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <libproc.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if (defined(__linux__) || defined(__ANDROID__))
|
||||
@@ -39,6 +42,13 @@
|
||||
#include <libprocstat.h>
|
||||
#endif
|
||||
|
||||
#if defined(__OpenBSD__)
|
||||
#include <sys/param.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <fcntl.h>
|
||||
#include <kvm.h>
|
||||
#endif
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
|
||||
namespace detail {
|
||||
@@ -95,7 +105,7 @@ const environment::char_type * dereference(native_env_iterator iterator)
|
||||
return iterator;
|
||||
}
|
||||
|
||||
#elif (defined(__APPLE___) || defined(__MACH__))
|
||||
#elif (defined(__APPLE___) || defined(__MACH__)) || defined(__OpenBSD__)
|
||||
|
||||
void native_env_handle_deleter::operator()(native_env_handle_type h) const
|
||||
{
|
||||
@@ -171,19 +181,19 @@ env_view env(HANDLE proc, boost::system::error_code & ec)
|
||||
|
||||
if (error)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, error, boost::system::system_category())
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, error, system_category());
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!ReadProcessMemory(proc, pbi.PebBaseAddress, &peb, sizeof(peb), &nRead))
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!ReadProcessMemory(proc, peb.ProcessParameters, &upp, sizeof(upp), &nRead))
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -194,7 +204,7 @@ env_view env(HANDLE proc, boost::system::error_code & ec)
|
||||
|
||||
if (!ReadProcessMemory(proc, buf, ev.handle_.get(), len, &nRead))
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -222,14 +232,14 @@ env_view env(boost::process::v2::pid_type pid, boost::system::error_code & ec)
|
||||
};
|
||||
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)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
else
|
||||
return env(proc.get(), ec);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
#elif (defined(__APPLE___) || defined(__MACH__))
|
||||
#elif (defined(__APPLE___) || defined(__MACH__)) && !TARGET_OS_IOS
|
||||
|
||||
env_view env(boost::process::v2::pid_type pid, boost::system::error_code & ec)
|
||||
{
|
||||
@@ -238,7 +248,7 @@ env_view env(boost::process::v2::pid_type pid, boost::system::error_code & ec)
|
||||
auto size = sizeof(argmax);
|
||||
if (sysctl(mib, 2, &argmax, &size, nullptr, 0) == -1)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -251,7 +261,7 @@ env_view env(boost::process::v2::pid_type pid, boost::system::error_code & ec)
|
||||
|
||||
if (sysctl(mib, 3, &*procargs.begin(), &size, nullptr, 0) != 0)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return {};
|
||||
}
|
||||
std::uint32_t nargs;
|
||||
@@ -309,7 +319,7 @@ env_view env(boost::process::v2::pid_type pid, boost::system::error_code & ec)
|
||||
auto r = ::read(f, buf.get() + size, 4096);
|
||||
if (r < 0)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
::close(f);
|
||||
return {};
|
||||
}
|
||||
@@ -376,21 +386,62 @@ env_view env(boost::process::v2::pid_type pid, boost::system::error_code & ec)
|
||||
ev.handle_.reset(eeo);
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
|
||||
}
|
||||
procstat_freeprocs(proc_stat, proc_info);
|
||||
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
procstat_close(proc_stat);
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return ev;
|
||||
}
|
||||
#elif defined(__OpenBSD__)
|
||||
env_view env(boost::process::v2::pid_type pid, boost::system::error_code & ec)
|
||||
{
|
||||
|
||||
std::vector<char> 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.get()) {BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return {};}
|
||||
if ((proc_info = kvm_getprocs(kd.get(), KERN_PROC_PID, pid, sizeof(struct kinfo_proc), &cntp)))
|
||||
{
|
||||
char **env = kvm_getenvv(kd.get(), proc_info, 0);
|
||||
if (env)
|
||||
{
|
||||
for (int i = 0; env[i] != nullptr; i++)
|
||||
{
|
||||
for (int j = 0; j < strlen(env[i]); j++)
|
||||
vec.push_back(env[i][j]);
|
||||
vec.push_back('\0');
|
||||
}
|
||||
vec.push_back('\0');
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
|
||||
env_view ev;
|
||||
ev.handle_.reset(new char[vec.size()]());
|
||||
std::copy(vec.begin(), vec.end(), ev.handle_.get());
|
||||
return ev;
|
||||
}
|
||||
#endif
|
||||
|
||||
env_view env(boost::process::v2::pid_type pid)
|
||||
|
||||
@@ -25,8 +25,11 @@
|
||||
#endif
|
||||
|
||||
#if (defined(__APPLE__) && defined(__MACH__))
|
||||
#include <sys/proc_info.h>
|
||||
#include <libproc.h>
|
||||
#include <TargetConditionals.h>
|
||||
#if !TARGET_OS_IOS
|
||||
#include <sys/proc_info.h>
|
||||
#include <libproc.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if (defined(BOOST_PROCESS_V2_WINDOWS) || defined(__linux__) || defined(__ANDROID__) || defined(__sun))
|
||||
@@ -80,7 +83,7 @@ filesystem::path exe(HANDLE proc, boost::system::error_code & ec)
|
||||
return filesystem::canonical(buffer, ec);
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
|
||||
return "";
|
||||
}
|
||||
@@ -106,14 +109,14 @@ filesystem::path exe(boost::process::v2::pid_type pid, boost::system::error_code
|
||||
};
|
||||
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)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
else
|
||||
return exe(proc.get(), ec);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
#elif (defined(__APPLE__) && defined(__MACH__))
|
||||
#elif (defined(__APPLE__) && defined(__MACH__)) && !TARGET_OS_IOS
|
||||
|
||||
filesystem::path exe(boost::process::v2::pid_type pid, boost::system::error_code & ec)
|
||||
{
|
||||
@@ -122,7 +125,7 @@ filesystem::path exe(boost::process::v2::pid_type pid, boost::system::error_code
|
||||
{
|
||||
return filesystem::canonical(buffer, ec);
|
||||
}
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return "";
|
||||
}
|
||||
|
||||
@@ -162,7 +165,7 @@ filesystem::path exe(boost::process::v2::pid_type pid, boost::system::error_code
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return "";
|
||||
}
|
||||
|
||||
@@ -170,12 +173,16 @@ filesystem::path exe(boost::process::v2::pid_type pid, boost::system::error_code
|
||||
|
||||
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())
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, ENOTSUP, system_category());
|
||||
return "";
|
||||
}
|
||||
|
||||
#else
|
||||
#error "Platform not supported"
|
||||
filesystem::path exe(boost::process::v2::pid_type pid, boost::system::error_code & ec)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, ENOTSUP, system_category());
|
||||
return "";
|
||||
}
|
||||
#endif
|
||||
|
||||
filesystem::path exe(boost::process::v2::pid_type pid)
|
||||
|
||||
@@ -16,14 +16,6 @@
|
||||
|
||||
#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
|
||||
@@ -51,19 +43,19 @@ std::wstring cwd_cmd_from_proc(HANDLE proc, int type, boost::system::error_code
|
||||
|
||||
if (error)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, error, boost::system::system_category())
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, error, system_category());
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!ReadProcessMemory(proc, pbi.PebBaseAddress, &peb, sizeof(peb), &nRead))
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!ReadProcessMemory(proc, peb.ProcessParameters, &upp, sizeof(upp), &nRead))
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -82,7 +74,7 @@ std::wstring cwd_cmd_from_proc(HANDLE proc, int type, boost::system::error_code
|
||||
|
||||
if (!ReadProcessMemory(proc, buf, &buffer[0], len, &nRead))
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -115,7 +107,7 @@ HANDLE open_process_with_debug_privilege(boost::process::v2::pid_type pid, boost
|
||||
if (!proc)
|
||||
proc = OpenProcess(PROCESS_ALL_ACCESS, false, pid);
|
||||
if (!proc)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return proc;
|
||||
}
|
||||
#endif
|
||||
|
||||
103
src/pid.cpp
103
src/pid.cpp
@@ -17,8 +17,11 @@
|
||||
#endif
|
||||
|
||||
#if (defined(__APPLE__) && defined(__MACH__))
|
||||
#include <sys/proc_info.h>
|
||||
#include <libproc.h>
|
||||
#include <TargetConditionals.h>
|
||||
#if !TARGET_OS_IOS
|
||||
#include <sys/proc_info.h>
|
||||
#include <libproc.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if (defined(__linux__) || defined(__ANDROID__))
|
||||
@@ -71,7 +74,7 @@ std::vector<pid_type> all_pids(boost::system::error_code & ec)
|
||||
HANDLE hp = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||
if (!hp)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return vec;
|
||||
}
|
||||
PROCESSENTRY32 pe;
|
||||
@@ -93,7 +96,7 @@ pid_type parent_pid(pid_type pid, boost::system::error_code & ec)
|
||||
HANDLE hp = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||
if (!hp)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return ppid;
|
||||
}
|
||||
PROCESSENTRY32 pe;
|
||||
@@ -120,7 +123,7 @@ std::vector<pid_type> child_pids(pid_type pid, boost::system::error_code & ec)
|
||||
HANDLE hp = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||
if (!hp)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return vec;
|
||||
}
|
||||
PROCESSENTRY32 pe;
|
||||
@@ -140,7 +143,7 @@ std::vector<pid_type> child_pids(pid_type pid, boost::system::error_code & ec)
|
||||
return vec;
|
||||
}
|
||||
|
||||
#elif (defined(__APPLE__) && defined(__MACH__))
|
||||
#elif (defined(__APPLE__) && defined(__MACH__)) && !TARGET_OS_IOS
|
||||
|
||||
std::vector<pid_type> all_pids(boost::system::error_code & ec)
|
||||
{
|
||||
@@ -149,7 +152,7 @@ std::vector<pid_type> all_pids(boost::system::error_code & ec)
|
||||
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)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return {};
|
||||
}
|
||||
vec.resize(sz);
|
||||
@@ -162,7 +165,7 @@ pid_type parent_pid(pid_type pid, boost::system::error_code & ec)
|
||||
proc_bsdinfo proc_info;
|
||||
if (proc_pidinfo(pid, PROC_PIDTBSDINFO, 0, &proc_info, sizeof(proc_info)) <= 0)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return ppid;
|
||||
}
|
||||
else
|
||||
@@ -177,7 +180,7 @@ std::vector<pid_type> child_pids(pid_type pid, boost::system::error_code & ec)
|
||||
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)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return {};
|
||||
}
|
||||
vec.resize(sz);
|
||||
@@ -192,7 +195,7 @@ std::vector<pid_type> all_pids(boost::system::error_code & ec)
|
||||
DIR *proc = opendir("/proc");
|
||||
if (!proc)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return vec;
|
||||
}
|
||||
struct dirent *ent = nullptr;
|
||||
@@ -215,9 +218,9 @@ pid_type parent_pid(pid_type pid, boost::system::error_code & ec)
|
||||
if (!stat)
|
||||
{
|
||||
if (errno == ENOENT)
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, ESRCH, system_category())
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, ESRCH, system_category());
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return ppid;
|
||||
}
|
||||
else
|
||||
@@ -242,7 +245,7 @@ pid_type parent_pid(pid_type pid, boost::system::error_code & ec)
|
||||
if (!token)
|
||||
{
|
||||
fclose(stat);
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return ppid;
|
||||
}
|
||||
}
|
||||
@@ -283,7 +286,7 @@ std::vector<pid_type> all_pids(boost::system::error_code & ec)
|
||||
free(proc_info);
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return vec;
|
||||
}
|
||||
|
||||
@@ -297,7 +300,7 @@ pid_type parent_pid(pid_type pid, boost::system::error_code & ec)
|
||||
free(proc_info);
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return ppid;
|
||||
}
|
||||
|
||||
@@ -319,7 +322,7 @@ std::vector<pid_type> child_pids(pid_type pid, boost::system::error_code & ec)
|
||||
free(proc_info);
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return vec;
|
||||
}
|
||||
|
||||
@@ -343,7 +346,7 @@ std::vector<pid_type> all_pids(boost::system::error_code & ec)
|
||||
std::unique_ptr<kvm_t, closer> kd{kvm_openfiles(nlistf, memf, nullptr, O_RDONLY, nullptr)};
|
||||
if (!kd)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return vec;
|
||||
}
|
||||
if ((proc_info = kvm_getprocs(kd.get(), KERN_PROC_ALL, 0, &cntp)))
|
||||
@@ -354,7 +357,7 @@ std::vector<pid_type> all_pids(boost::system::error_code & ec)
|
||||
vec.push_back(proc_info[i].kp_pid);
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return vec;
|
||||
}
|
||||
|
||||
@@ -376,7 +379,7 @@ pid_type parent_pid(pid_type pid, boost::system::error_code & ec)
|
||||
std::unique_ptr<kvm_t, closer> kd{kvm_openfiles(nlistf, memf, nullptr, O_RDONLY, nullptr)};
|
||||
if (!kd)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return ppid;
|
||||
}
|
||||
if ((proc_info = kvm_getprocs(kd.get(), KERN_PROC_PID, pid, &cntp)))
|
||||
@@ -387,7 +390,7 @@ pid_type parent_pid(pid_type pid, boost::system::error_code & ec)
|
||||
}
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return ppid;
|
||||
}
|
||||
|
||||
@@ -409,7 +412,7 @@ std::vector<pid_type> child_pids(pid_type pid, boost::system::error_code & ec)
|
||||
std::unique_ptr<kvm_t, closer> kd{kvm_openfiles(nlistf, memf, nullptr, O_RDONLY, nullptr)};
|
||||
if (!kd)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return vec;
|
||||
}
|
||||
if ((proc_info = kvm_getprocs(kd.get(), KERN_PROC_ALL, 0, &cntp)))
|
||||
@@ -424,7 +427,7 @@ std::vector<pid_type> child_pids(pid_type pid, boost::system::error_code & ec)
|
||||
}
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return vec;
|
||||
}
|
||||
|
||||
@@ -446,7 +449,7 @@ std::vector<pid_type> all_pids(boost::system::error_code & ec)
|
||||
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)
|
||||
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)))
|
||||
@@ -458,7 +461,7 @@ std::vector<pid_type> all_pids(boost::system::error_code & ec)
|
||||
}
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return vec;
|
||||
}
|
||||
|
||||
@@ -478,7 +481,7 @@ pid_type parent_pid(pid_type pid, boost::system::error_code & ec)
|
||||
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)
|
||||
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)))
|
||||
@@ -486,7 +489,7 @@ pid_type parent_pid(pid_type pid, boost::system::error_code & ec)
|
||||
ppid = proc_info->p_ppid;
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return ppid;
|
||||
}
|
||||
|
||||
@@ -506,7 +509,7 @@ std::vector<pid_type> child_pids(pid_type pid, boost::system::error_code & ec)
|
||||
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)
|
||||
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)))
|
||||
@@ -521,7 +524,7 @@ std::vector<pid_type> child_pids(pid_type pid, boost::system::error_code & ec)
|
||||
}
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return vec;
|
||||
}
|
||||
|
||||
@@ -543,7 +546,7 @@ std::vector<pid_type> all_pids(boost::system::error_code & ec)
|
||||
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)
|
||||
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)))
|
||||
@@ -551,14 +554,14 @@ std::vector<pid_type> all_pids(boost::system::error_code & ec)
|
||||
vec.reserve(cntp);
|
||||
for (int i = cntp - 1; i >= 0; i--)
|
||||
{
|
||||
if (proc_info[i].kp_pid >= 0)
|
||||
if (proc_info[i].p_pid >= 0)
|
||||
{
|
||||
vec.push_back(proc_info[i].kp_pid);
|
||||
vec.push_back(proc_info[i].p_pid);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return vec;
|
||||
}
|
||||
|
||||
@@ -578,7 +581,7 @@ pid_type parent_pid(pid_type pid, boost::system::error_code & ec)
|
||||
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)
|
||||
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)))
|
||||
@@ -586,7 +589,7 @@ pid_type parent_pid(pid_type pid, boost::system::error_code & ec)
|
||||
ppid = proc_info->p_ppid;
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return ppid;
|
||||
}
|
||||
|
||||
@@ -606,7 +609,7 @@ std::vector<pid_type> child_pids(pid_type pid, boost::system::error_code & ec)
|
||||
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)
|
||||
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)))
|
||||
@@ -621,7 +624,7 @@ std::vector<pid_type> child_pids(pid_type pid, boost::system::error_code & ec)
|
||||
}
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return vec;
|
||||
}
|
||||
|
||||
@@ -644,7 +647,7 @@ std::vector<pid_type> all_pids(boost::system::error_code & ec)
|
||||
std::unique_ptr<kvm_t, closer> kd{kvm_open(nullptr, nullptr, nullptr, O_RDONLY, nullptr)};
|
||||
if (!kd)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return vec;
|
||||
}
|
||||
while ((proc_info = kvm_nextproc(kd)))
|
||||
@@ -655,7 +658,7 @@ std::vector<pid_type> all_pids(boost::system::error_code & ec)
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -677,7 +680,7 @@ pid_type parent_pid(pid_type pid, boost::system::error_code & ec)
|
||||
std::unique_ptr<kvm_t, closer> kd{kvm_open(nullptr, nullptr, nullptr, O_RDONLY, nullptr)};
|
||||
if (!kd)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return ppid;
|
||||
}
|
||||
if ((proc_info = kvm_getproc(kd, pid)))
|
||||
@@ -685,7 +688,7 @@ pid_type parent_pid(pid_type pid, boost::system::error_code & ec)
|
||||
ppid = proc_info->p_ppid;
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return ppid;
|
||||
}
|
||||
|
||||
@@ -705,7 +708,7 @@ std::vector<pid_type> child_pids(pid_type pid, boost::system::error_code & ec)
|
||||
std::unique_ptr<kvm_t, closer> kd{kvm_open(nullptr, nullptr, nullptr, O_RDONLY, nullptr);
|
||||
if (!kd)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return vec;
|
||||
}
|
||||
while ((proc_info = kvm_nextproc(kd)))
|
||||
@@ -718,7 +721,7 @@ std::vector<pid_type> child_pids(pid_type pid, boost::system::error_code & ec)
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -727,7 +730,21 @@ std::vector<pid_type> child_pids(pid_type pid, boost::system::error_code & ec)
|
||||
}
|
||||
|
||||
#else
|
||||
#error "Platform not supported"
|
||||
std::vector<pid_type> all_pids(boost::system::error_code & ec)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, ENOTSUP, system_category());
|
||||
return {};
|
||||
}
|
||||
pid_type parent_pid(pid_type pid, boost::system::error_code & ec)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, ENOTSUP, system_category());
|
||||
return pid;
|
||||
}
|
||||
std::vector<pid_type> child_pids(pid_type, boost::system::error_code & ec)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, ENOTSUP, system_category());
|
||||
return {};
|
||||
}
|
||||
#endif
|
||||
|
||||
std::vector<pid_type> all_pids()
|
||||
|
||||
@@ -17,10 +17,9 @@
|
||||
// linux has close_range since 5.19
|
||||
|
||||
|
||||
#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
|
||||
#if defined(__FreeBSD__)
|
||||
|
||||
// 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
|
||||
@@ -45,7 +44,8 @@ int fdwalk(int (*func)(void *, int), void *cd);
|
||||
|
||||
#include <linux/version.h>
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,11,0) // kernel has close_range
|
||||
// kernel has close_range
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,9,0) && !defined(BOOST_PROCESS_V2_POSIX_FORCE_DISABLE_CLOSE_RANGE)
|
||||
|
||||
// version is included by stdlib.h #include <gnu/libc-version.h>
|
||||
#if (__GLIBC__ >= 2 && __GLIBC_MINOR__ >= 34) // glibc is compiled with close_range support
|
||||
@@ -219,4 +219,4 @@ void close_all(const std::vector<int> & whitelist, error_code & ec)
|
||||
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
#include <windows.h>
|
||||
#include <shellapi.h>
|
||||
#else
|
||||
#elif !defined(__OpenBSD__)
|
||||
#include <wordexp.h>
|
||||
#endif
|
||||
|
||||
@@ -30,7 +30,7 @@ BOOST_PROCESS_V2_DECL const error_category& get_shell_category()
|
||||
{
|
||||
return system_category();
|
||||
}
|
||||
#else
|
||||
#elif !defined(__OpenBSD__)
|
||||
|
||||
struct shell_category_t final : public error_category
|
||||
{
|
||||
@@ -38,7 +38,7 @@ struct shell_category_t final : public error_category
|
||||
|
||||
const char* name() const noexcept
|
||||
{
|
||||
return "process.v2.utf8";
|
||||
return "process.v2.shell";
|
||||
}
|
||||
std::string message(int value) const
|
||||
{
|
||||
@@ -66,6 +66,13 @@ BOOST_PROCESS_V2_DECL const error_category& get_shell_category()
|
||||
return instance;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
const error_category& get_shell_category()
|
||||
{
|
||||
return system_category();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined (BOOST_PROCESS_V2_WINDOWS)
|
||||
@@ -92,7 +99,7 @@ auto shell::args() const-> args_type
|
||||
return input_.c_str();
|
||||
}
|
||||
|
||||
#else
|
||||
#elif !defined(__OpenBSD__)
|
||||
|
||||
void shell::parse_()
|
||||
{
|
||||
@@ -135,6 +142,22 @@ auto shell::args() const -> args_type
|
||||
return const_cast<const char**>(argv());
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void shell::parse_()
|
||||
{
|
||||
error_code ec;
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, ENOTSUP, system_category());
|
||||
throw system_error(ec, "shell::parse");
|
||||
}
|
||||
|
||||
shell::~shell() = default;
|
||||
|
||||
auto shell::args() const -> args_type
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
@@ -9,25 +9,23 @@
|
||||
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
|
||||
import os ;
|
||||
|
||||
if [ os.name ] = NT
|
||||
{
|
||||
lib ws2_32 ;
|
||||
lib shell32 ;
|
||||
lib Advapi32 ;
|
||||
lib Ntdll ;
|
||||
}
|
||||
lib ws2_32 ;
|
||||
lib shell32 ;
|
||||
lib Advapi32 ;
|
||||
lib Ntdll ;
|
||||
|
||||
project : requirements
|
||||
<library>/boost/process//boost_process
|
||||
<define>BOOST_ASIO_NO_DEPRECATED
|
||||
<toolset>msvc:<define>_SCL_SECURE_NO_WARNINGS
|
||||
<toolset>msvc:<define>_CRT_SECURE_NO_DEPRECATE
|
||||
<toolset>msvc:<cxxflags>/bigobj
|
||||
<target-os>windows:<define>WIN32_LEAN_AND_MEAN
|
||||
<target-os>linux:<linkflags>-lpthread
|
||||
<target-os>freebsd:<linkflags>-lpthread
|
||||
<os>NT,<toolset>cw:<library>ws2_32
|
||||
<os>NT,<toolset>gcc:<library>ws2_32
|
||||
<library>/boost/test//included
|
||||
;
|
||||
|
||||
|
||||
@@ -35,16 +33,18 @@ project : requirements
|
||||
import testing ;
|
||||
|
||||
|
||||
alias program_options : /boost//program_options : <link>static ;
|
||||
alias filesystem : /boost//filesystem ;
|
||||
alias iostreams : /boost//iostreams ;
|
||||
alias system : /boost//system ;
|
||||
alias thread : /boost//thread ;
|
||||
alias coroutine : /boost//coroutine : <link>static ;
|
||||
alias program_options : usage-requirements <library>/boost/program_options//boost_program_options ;
|
||||
alias filesystem : usage-requirements <library>/boost/filesystem//boost_filesystem ;
|
||||
alias iostreams : usage-requirements <library>/boost/iostreams//boost_iostreams ;
|
||||
alias system : usage-requirements <library>/boost/system//boost_system ;
|
||||
alias thread : usage-requirements <library>/boost/thread//boost_thread ;
|
||||
alias scope_exit : usage-requirements <library>/boost/scope_exit//boost_scope_exit ;
|
||||
alias lambda : usage-requirements <library>/boost/lambda//boost_lambda ;
|
||||
alias chrono : usage-requirements <library>/boost/chrono//boost_chrono ;
|
||||
|
||||
lib multi_ref : multi_ref1.cpp multi_ref2.cpp system : <target-os>windows:<source>shell32 ;
|
||||
|
||||
exe sparring_partner : sparring_partner.cpp program_options system filesystem iostreams :
|
||||
exe sparring_partner : sparring_partner.cpp program_options system filesystem iostreams lambda :
|
||||
<warnings>off <target-os>windows:<source>shell32 <target-os>windows:<source>Ntdll
|
||||
;
|
||||
|
||||
@@ -100,15 +100,15 @@ test-suite with-valgrind :
|
||||
[ run env.cpp program_options system filesystem : [ test-options env ] : sparring_partner ]
|
||||
[ run group.cpp system thread filesystem : [ test-options group ] : sub_launch ]
|
||||
[ run group.cpp system thread filesystem : [ test-options group ] : sub_launch : <build>no <target-os>windows:<build>yes <define>BOOST_USE_WINDOWS_H=1 : group-windows-h ]
|
||||
[ run group_wait.cpp system thread filesystem : [ test-options group_wait ] : sparring_partner : <target-os>darwin:<build>no <target-os>freebsd:<build>no ]
|
||||
[ run group_wait.cpp system thread filesystem scope_exit : [ test-options group_wait ] : sparring_partner : <target-os>darwin:<build>no <target-os>freebsd:<build>no ]
|
||||
[ run limit_fd.cpp program_options system filesystem : [ test-options limit_fd ] : sparring_partner : <target-os>freebsd:<build>no ]
|
||||
[ run run_exe.cpp filesystem : : sparring_partner ]
|
||||
[ run run_exe_path.cpp filesystem : [ test-options run_exe_path ] : sparring_partner ]
|
||||
[ run search_path.cpp filesystem system : [ test-options search_path ] : : <target-os>windows:<source>shell32 ]
|
||||
[ run shell.cpp filesystem system : [ test-options shell ] : sparring_partner : <target-os>darwin:<build>no ]
|
||||
[ run shell_path.cpp filesystem system : [ test-options shell_path ] ]
|
||||
[ run system_test1.cpp filesystem system : [ test-options system_test1 ] : sparring_partner ]
|
||||
[ run system_test2.cpp filesystem system : [ test-options system_test2 ] : sparring_partner ]
|
||||
[ run system_test1.cpp filesystem system chrono : [ test-options system_test1 ] : sparring_partner ]
|
||||
[ run system_test2.cpp filesystem system chrono : [ test-options system_test2 ] : sparring_partner ]
|
||||
[ run spawn.cpp filesystem system : [ test-options spawn ] : sparring_partner ]
|
||||
[ run start_dir.cpp filesystem system : [ test-options start_dir ] : sparring_partner ]
|
||||
[ run terminate.cpp system filesystem : [ test-options terminate ] : sparring_partner : <target-os>freebsd:<build>no ]
|
||||
@@ -123,13 +123,10 @@ test-suite with-valgrind :
|
||||
: <dependency>bare ;
|
||||
|
||||
test-suite without-valgrind :
|
||||
[ run async_system_future.cpp filesystem system coroutine : [ test-options async_system_future ] : sparring_partner : <link>static <toolset>msvc:<cxxflags>/bigobj ]
|
||||
[ run async_system_stackful.cpp filesystem system coroutine : [ test-options async_system_stackful ] : sparring_partner : <link>static <toolset>msvc:<cxxflags>/bigobj ]
|
||||
[ run async_system_future.cpp filesystem system : [ test-options async_system_future ] : sparring_partner : <link>static <toolset>msvc:<cxxflags>/bigobj ]
|
||||
# [ run async_system_stackful.cpp filesystem system coroutine : [ test-options async_system_stackful ] : sparring_partner : <link>static <toolset>msvc:<cxxflags>/bigobj ]
|
||||
# [ run async_system_stackful_error.cpp filesystem system coroutine : [ test-options async_system_stackful_error ] : sparring_partner : <link>static <toolset>msvc:<cxxflags>/bigobj ]
|
||||
[ run async_system_stackful_except.cpp filesystem system coroutine : [ test-options async_system_stackful_except ] : sparring_partner : <link>static <toolset>msvc:<cxxflags>/bigobj ]
|
||||
[ run async_system_stackless.cpp filesystem system coroutine : [ test-options async_system_stackless ] : sparring_partner : <link>static <toolset>msvc:<cxxflags>/bigobj ]
|
||||
# [ run async_system_stackful_except.cpp filesystem system coroutine : [ test-options async_system_stackful_except ] : sparring_partner : <link>static <toolset>msvc:<cxxflags>/bigobj ]
|
||||
[ run async_system_stackless.cpp filesystem system : [ test-options async_system_stackless ] : sparring_partner : <link>static <toolset>msvc:<cxxflags>/bigobj ]
|
||||
[ run vfork.cpp system filesystem : [ test-options vfork ] : sparring_partner : <build>no <target-os>linux:<build>yes ]
|
||||
;
|
||||
|
||||
|
||||
alias v2-tests : v2//standalone v2//with_target ;
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
#include <boost/system/error_code.hpp>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/asio/deadline_timer.hpp>
|
||||
#include <boost/asio/steady_timer.hpp>
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -46,7 +46,7 @@ BOOST_AUTO_TEST_CASE(async_wait, *boost::unit_test::timeout(5))
|
||||
bool exit_called_for_c1 = false;
|
||||
int exit_code_c1 = 0;
|
||||
|
||||
boost::asio::deadline_timer timeout{io_context, boost::posix_time::seconds(2)};
|
||||
boost::asio::steady_timer timeout{io_context, std::chrono::seconds(2)};
|
||||
timeout.async_wait([&](boost::system::error_code ec){if (!ec) io_context.stop();});
|
||||
|
||||
bp::child c1(master_test_suite().argv[1],
|
||||
@@ -97,7 +97,7 @@ BOOST_AUTO_TEST_CASE(async_wait_sync_wait, *boost::unit_test::timeout(5))
|
||||
int exit_code = 0;
|
||||
std::error_code ec;
|
||||
|
||||
boost::asio::deadline_timer timeout{io_context, boost::posix_time::seconds(3)};
|
||||
boost::asio::steady_timer timeout{io_context, std::chrono::seconds(3)};
|
||||
timeout.async_wait([&](boost::system::error_code ec){if (!ec) io_context.stop();});
|
||||
|
||||
bp::child c1(
|
||||
@@ -140,10 +140,10 @@ BOOST_AUTO_TEST_CASE(async_wait_different_contexts, *boost::unit_test::timeout(1
|
||||
boost::asio::io_context io_context1;
|
||||
boost::asio::io_context io_context2;
|
||||
|
||||
boost::asio::deadline_timer timeout1{io_context1, boost::posix_time::seconds(2)};
|
||||
boost::asio::steady_timer timeout1{io_context1, std::chrono::seconds(2)};
|
||||
timeout1.async_wait([&](boost::system::error_code ec){if (!ec) io_context1.stop();});
|
||||
|
||||
boost::asio::deadline_timer timeout2{io_context2, boost::posix_time::seconds(7)};
|
||||
boost::asio::steady_timer timeout2{io_context2, std::chrono::seconds(7)};
|
||||
timeout2.async_wait([&](boost::system::error_code ec){if (!ec) io_context2.stop();});
|
||||
std::error_code ec;
|
||||
|
||||
@@ -208,7 +208,7 @@ BOOST_AUTO_TEST_CASE(async_wait_abort, *boost::unit_test::timeout(5))
|
||||
|
||||
std::error_code ec;
|
||||
|
||||
boost::asio::deadline_timer timeout{io_context, boost::posix_time::seconds(5)};
|
||||
boost::asio::steady_timer timeout{io_context, std::chrono::seconds(5)};
|
||||
timeout.async_wait([&](boost::system::error_code ec){if (!ec) io_context.stop();});
|
||||
|
||||
bool exit_called = false;
|
||||
@@ -245,7 +245,7 @@ BOOST_AUTO_TEST_CASE(async_future, *boost::unit_test::timeout(3))
|
||||
|
||||
boost::asio::io_context io_context;
|
||||
|
||||
boost::asio::deadline_timer timeout{io_context, boost::posix_time::seconds(2)};
|
||||
boost::asio::steady_timer timeout{io_context, std::chrono::seconds(2)};
|
||||
timeout.async_wait([&](boost::system::error_code ec){if (!ec) io_context.stop();});
|
||||
|
||||
std::error_code ec;
|
||||
@@ -278,7 +278,7 @@ BOOST_AUTO_TEST_CASE(async_out_stream, *boost::unit_test::timeout(5))
|
||||
|
||||
boost::asio::streambuf buf;
|
||||
|
||||
boost::asio::deadline_timer timeout{io_context, boost::posix_time::seconds(2)};
|
||||
boost::asio::steady_timer timeout{io_context, std::chrono::seconds(2)};
|
||||
timeout.async_wait([&](boost::system::error_code ec){if (!ec) io_context.stop();});
|
||||
|
||||
bp::child c(master_test_suite().argv[1],
|
||||
@@ -318,7 +318,7 @@ BOOST_AUTO_TEST_CASE(async_in_stream, *boost::unit_test::timeout(5))
|
||||
std::ostream ostr(&in_buf);
|
||||
ostr << "-string" << endl ;
|
||||
|
||||
boost::asio::deadline_timer timeout{io_context, boost::posix_time::seconds(2)};
|
||||
boost::asio::steady_timer timeout{io_context, std::chrono::seconds(2)};
|
||||
timeout.async_wait([&](boost::system::error_code ec){if (!ec) io_context.stop();});
|
||||
|
||||
bp::child c(
|
||||
@@ -355,7 +355,7 @@ BOOST_AUTO_TEST_CASE(async_error, *boost::unit_test::timeout(3))
|
||||
|
||||
boost::asio::io_context io_context;
|
||||
|
||||
boost::asio::deadline_timer timeout{io_context, boost::posix_time::seconds(2)};
|
||||
boost::asio::steady_timer timeout{io_context, std::chrono::seconds(2)};
|
||||
timeout.async_wait([&](boost::system::error_code ec){if (!ec) io_context.stop();});
|
||||
|
||||
bool exit_called = false;
|
||||
@@ -386,7 +386,7 @@ BOOST_AUTO_TEST_CASE(mixed_async, *boost::unit_test::timeout(5))
|
||||
|
||||
boost::asio::io_context io_context;
|
||||
|
||||
boost::asio::deadline_timer timeout{io_context, boost::posix_time::seconds(2)};
|
||||
boost::asio::steady_timer timeout{io_context, std::chrono::seconds(2)};
|
||||
timeout.async_wait([&](boost::system::error_code ec){if (!ec) io_context.stop();});
|
||||
|
||||
bool exit_called = false;
|
||||
|
||||
@@ -110,7 +110,7 @@ BOOST_AUTO_TEST_CASE(async_wait, *boost::unit_test::timeout(10))
|
||||
|
||||
boost::asio::io_context io_context;
|
||||
|
||||
boost::asio::deadline_timer timeout{io_context, boost::posix_time::seconds(3)};
|
||||
boost::asio::steady_timer timeout{io_context, std::chrono::seconds(3)};
|
||||
timeout.async_wait([&](boost::system::error_code ec){if (!ec) io_context.stop();});
|
||||
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#include <boost/chrono.hpp>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/asio/steady_timer.hpp>
|
||||
#include <boost/asio/deadline_timer.hpp>
|
||||
#include <boost/asio/steady_timer.hpp>
|
||||
|
||||
#include <boost/process/v1/error.hpp>
|
||||
#include <boost/process/v1/io.hpp>
|
||||
|
||||
@@ -53,7 +53,7 @@ BOOST_AUTO_TEST_CASE(async_wait, *boost::unit_test::timeout(4))
|
||||
std::error_code ec;
|
||||
bool called = false;
|
||||
|
||||
boost::asio::deadline_timer timeout{io_context, boost::posix_time::seconds(3)};
|
||||
boost::asio::steady_timer timeout{io_context, std::chrono::seconds(3)};
|
||||
timeout.async_wait([&](boost::system::error_code ec){if (!ec) io_context.stop();});
|
||||
|
||||
|
||||
|
||||
@@ -36,4 +36,14 @@ function(boost_process_v2_test_with_target name)
|
||||
endfunction()
|
||||
|
||||
boost_process_v2_test_with_target(process)
|
||||
boost_process_v2_test_with_target(ext)
|
||||
boost_process_v2_test_with_target(ext)
|
||||
|
||||
|
||||
add_executable(boost_process_v2_test_experimental_pty_target experimental/pty_target.cpp)
|
||||
target_link_libraries(boost_process_v2_test_experimental_pty_target PUBLIC Boost::process Boost::system)
|
||||
|
||||
add_executable(boost_process_v2_test_experimental_pty experimental/pty.cpp)
|
||||
target_link_libraries(boost_process_v2_test_experimental_pty Boost::process Boost::system Boost::filesystem boost_process_v2_test_impl)
|
||||
add_dependencies(boost_process_v2_test_experimental_pty boost_process_v2_test_experimental_pty_target)
|
||||
add_test(NAME boost_process_v2_test_experimental_pty COMMAND $<TARGET_FILE:boost_process_v2_test_experimental_pty>
|
||||
-- $<TARGET_FILE:boost_process_v2_test_experimental_pty_target>)
|
||||
@@ -4,19 +4,15 @@
|
||||
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
|
||||
import os ;
|
||||
|
||||
if [ os.name ] = NT
|
||||
{
|
||||
lib ws2_32 ;
|
||||
lib shell32 ;
|
||||
lib Advapi32 ;
|
||||
lib Ntdll ;
|
||||
lib user32 ;
|
||||
lib Bcrypt ;
|
||||
}
|
||||
lib ws2_32 ;
|
||||
lib shell32 ;
|
||||
lib Advapi32 ;
|
||||
lib Ntdll ;
|
||||
lib user32 ;
|
||||
lib Bcrypt ;
|
||||
|
||||
project : requirements
|
||||
<library>/boost/process//boost_process
|
||||
<define>BOOST_ASIO_NO_DEPRECATED
|
||||
<toolset>msvc:<define>_SCL_SECURE_NO_WARNINGS
|
||||
<toolset>msvc:<define>_CRT_SECURE_NO_DEPRECATE
|
||||
@@ -24,42 +20,54 @@ project : requirements
|
||||
<target-os>windows:<define>WIN32_LEAN_AND_MEAN
|
||||
<target-os>windows:<define>_WIN32_WINNT=0x0601
|
||||
<target-os>linux:<linkflags>-lpthread
|
||||
<target-os>freebsd:<linkflags>-lpthread
|
||||
<target-os>freebsd:<linkflags>-lutil
|
||||
<target-os>freebsd:<linkflags>-lkvm
|
||||
<target-os>freebsd:<linkflags>-lprocstat
|
||||
<target-os>bsd:<linkflags>-lpthread
|
||||
<target-os>bsd:<linkflags>-lkvm
|
||||
<target-os>netbsd:<linkflags>-lpthread
|
||||
<target-os>netbsd:<linkflags>-lkvm
|
||||
<target-os>openbsd:<linkflags>-lpthread
|
||||
<target-os>openbsd:<linkflags>-lkvm
|
||||
<target-os>solaris:<linkflags>-lpthread
|
||||
<target-os>solaris:<linkflags>-lkvm
|
||||
<os>NT,<toolset>cw:<library>ws2_32
|
||||
<os>NT,<toolset>gcc:<library>ws2_32
|
||||
<os>NT,<toolset>gcc:<library>Bcrypt
|
||||
<define>BOOST_PROCESS_V2_SEPARATE_COMPILATION=1
|
||||
<library>/boost/test//included
|
||||
;
|
||||
|
||||
import testing ;
|
||||
|
||||
alias filesystem : /boost//filesystem : <link>static ;
|
||||
|
||||
exe target : target.cpp :
|
||||
<warnings>off <target-os>windows:<source>shell32
|
||||
<target-os>windows:<source>Ntdll
|
||||
|
||||
;
|
||||
|
||||
local test_impl = test_impl.cpp /boost/process//boost_process /boost/test//boost_unit_test_framework ;
|
||||
|
||||
test-suite standalone :
|
||||
[ run utf8.cpp $(test_impl) ]
|
||||
[ run cstring_ref.cpp $(test_impl) ]
|
||||
[ run environment.cpp $(test_impl) ]
|
||||
[ run shell.cpp $(test_impl) ]
|
||||
;
|
||||
|
||||
test-suite with_target :
|
||||
[ run pid.cpp $(test_impl) : --log_level=all --catch_system_errors=no -- : target ]
|
||||
[ run process.cpp $(test_impl) : --log_level=all --catch_system_errors=no -- : target ]
|
||||
[ run windows.cpp $(test_impl) : --log_level=all --catch_system_errors=no -- : target : <build>no <target-os>windows:<build>yes <target-os>windows:<source>Advapi32 ]
|
||||
[ run ext.cpp $(test_impl) : --log_level=all --catch_system_errors=no -- : target : <target-os>darwin:<build>no ]
|
||||
;
|
||||
|
||||
exe experimental_pty_target : experimental/pty_target.cpp :
|
||||
<warnings>off <target-os>windows:<source>shell32
|
||||
<target-os>windows:<source>Ntdll
|
||||
;
|
||||
|
||||
lib test_impl : test_impl.cpp filesystem /boost//process :
|
||||
<define>BOOST_PROCESS_V2_SEPARATE_COMPILATION=1
|
||||
<define>BOOST_TEST_IGNORE_SIGCHLD=1
|
||||
<link>static
|
||||
;
|
||||
|
||||
test-suite standalone :
|
||||
[ run utf8.cpp test_impl ]
|
||||
[ run cstring_ref.cpp test_impl ]
|
||||
[ run environment.cpp test_impl ]
|
||||
[ run shell.cpp test_impl ]
|
||||
test-suite experimental :
|
||||
[ run experimental/pty.cpp $(test_impl) : --log_level=all --catch_system_errors=no -- : experimental_pty_target ]
|
||||
;
|
||||
|
||||
test-suite with_target :
|
||||
[ run pid.cpp test_impl : --log_level=all --catch_system_errors=no -- : target ]
|
||||
[ run process.cpp test_impl : --log_level=all --catch_system_errors=no -- : target ]
|
||||
[ run windows.cpp test_impl : --log_level=all --catch_system_errors=no -- : target : <build>no <target-os>windows:<build>yes <target-os>windows:<source>Advapi32 ]
|
||||
[ run ext.cpp test_impl : --log_level=all --catch_system_errors=no -- : target : <target-os>darwin:<build>no ]
|
||||
;
|
||||
|
||||
|
||||
364
test/v2/experimental/pty.cpp
Normal file
364
test/v2/experimental/pty.cpp
Normal file
@@ -0,0 +1,364 @@
|
||||
//
|
||||
// Copyright (c) 2024 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)
|
||||
//
|
||||
|
||||
|
||||
|
||||
|
||||
#include <boost/process/v2/experimental/pty.hpp>
|
||||
#include <boost/process/v2/process.hpp>
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include <boost/asio/coroutine.hpp>
|
||||
#include <boost/asio/read.hpp>
|
||||
#include <boost/asio/read_until.hpp>
|
||||
|
||||
#include <boost/asio/yield.hpp>
|
||||
|
||||
#if !defined(BOOST_PROCESS_V2_WINDOWS) || (NTDDI_VERSION >= 0x0A000006)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(sync_plain)
|
||||
{
|
||||
namespace bp2 = boost::process::v2;
|
||||
namespace net = boost::process::v2::net;
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
const auto pth = bp2::filesystem::absolute(master_test_suite().argv[1]);
|
||||
|
||||
boost::asio::io_context ctx;
|
||||
bp2::experimental::pty pt{ctx};
|
||||
bp2::process proc(ctx, pth, {}, pt);
|
||||
|
||||
|
||||
char buf[4];
|
||||
net::read(pt, net::buffer(buf));
|
||||
|
||||
std::string l1 = "Hello", l2 = ", ", l3 = "World!", l4 = "\n";
|
||||
|
||||
std::string read_buffer;
|
||||
read_buffer.resize(128);
|
||||
auto rb = net::buffer(read_buffer);
|
||||
|
||||
BOOST_CHECK_EQUAL(pt.write_some(net::buffer(l1)), 5);
|
||||
auto n = pt.read_some(rb);
|
||||
BOOST_CHECK_MESSAGE(n == 5, read_buffer.substr(0, n)); rb += n;
|
||||
|
||||
BOOST_CHECK_EQUAL(pt.write_some(net::buffer(l2)), 2);
|
||||
BOOST_CHECK_EQUAL(n = pt.read_some(rb), 2); rb += n;
|
||||
BOOST_CHECK_EQUAL(pt.write_some(net::buffer(l3)), 6);
|
||||
BOOST_CHECK_EQUAL(n = pt.read_some(rb), 6); rb += n;
|
||||
BOOST_CHECK_EQUAL(pt.write_some(net::buffer(l4)), 1);
|
||||
BOOST_CHECK_EQUAL(n = pt.read_some(rb), 2); rb += n;
|
||||
|
||||
n = read_buffer.size() - rb.size();
|
||||
|
||||
BOOST_CHECK_EQUAL(read_buffer.substr(0, n), "HELLO, WORLD!\r\n");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(async_plain)
|
||||
{
|
||||
namespace bp2 = boost::process::v2;
|
||||
namespace net = boost::process::v2::net;
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
const auto pth = bp2::filesystem::absolute(master_test_suite().argv[1]);
|
||||
|
||||
boost::asio::io_context ctx;
|
||||
bp2::experimental::pty pt{ctx};
|
||||
bp2::process proc(ctx, pth, {"--async"}, pt);
|
||||
|
||||
|
||||
char buf[4];
|
||||
net::read(pt, net::buffer(buf));
|
||||
|
||||
|
||||
struct op : net::coroutine
|
||||
{
|
||||
bp2::experimental::pty &pt;
|
||||
bp2::process &proc;
|
||||
|
||||
op(bp2::experimental::pty &pt, bp2::process &proc) : pt(pt), proc(proc) {}
|
||||
|
||||
std::string read_buffer = std::string(64, ' ');
|
||||
net::mutable_buffer rb = net::buffer(read_buffer);
|
||||
std::string l1 = "Hello", l2 = ", ", l3 = "World!", l4 = "\n";
|
||||
|
||||
|
||||
void operator()(bp2::error_code ec, std::size_t n)
|
||||
{
|
||||
BOOST_REQUIRE_MESSAGE(!ec, ec.message());
|
||||
reenter(this)
|
||||
{
|
||||
yield pt.async_write_some(net::buffer(l1), *this);
|
||||
BOOST_CHECK_EQUAL(n, 5);
|
||||
yield pt.async_read_some(rb, *this);
|
||||
BOOST_CHECK_EQUAL(n, 5); rb += n;
|
||||
|
||||
yield pt.async_write_some(net::buffer(l2), *this);
|
||||
BOOST_CHECK_EQUAL(n, 2);
|
||||
yield pt.async_read_some(rb, *this);
|
||||
BOOST_CHECK_EQUAL(n, 2);
|
||||
rb += n;
|
||||
yield pt.async_write_some(net::buffer(l3), *this);
|
||||
BOOST_CHECK_EQUAL(n, 6);
|
||||
yield pt.async_read_some(rb, *this);
|
||||
BOOST_CHECK_EQUAL(n, 6); rb += n;
|
||||
yield pt.async_write_some(net::buffer(l4), *this);
|
||||
BOOST_CHECK_EQUAL(n, 1);
|
||||
yield pt.async_read_some(rb, *this);
|
||||
BOOST_CHECK_EQUAL(n, 2); rb += n;
|
||||
|
||||
n = read_buffer.size() - rb.size();
|
||||
BOOST_CHECK_EQUAL(read_buffer.substr(0, n), "HELLO, WORLD!\r\n");
|
||||
|
||||
proc.terminate();
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
op{pt, proc}({}, 0u);
|
||||
ctx.run();
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(sync_echo)
|
||||
{
|
||||
namespace bp2 = boost::process::v2;
|
||||
namespace net = boost::process::v2::net;
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
const auto pth = bp2::filesystem::absolute(master_test_suite().argv[1]);
|
||||
|
||||
boost::asio::io_context ctx;
|
||||
bp2::experimental::pty pt{ctx};
|
||||
bp2::process proc(ctx, pth, {"--echo"}, pt);
|
||||
|
||||
|
||||
char buf[4];
|
||||
net::read(pt, net::buffer(buf));
|
||||
|
||||
std::string l1 = "Hello", l2 = ", ", l3 = "World!", l4 = "\n";
|
||||
|
||||
std::string read_buffer;
|
||||
read_buffer.resize(64);
|
||||
auto rb = net::buffer(read_buffer);
|
||||
|
||||
BOOST_CHECK_EQUAL(pt.write_some(net::buffer(l1)), 5);
|
||||
|
||||
auto n = net::read(pt, net::buffer(rb, 10));
|
||||
BOOST_CHECK_EQUAL(n, 10);
|
||||
rb += n;
|
||||
|
||||
BOOST_CHECK_EQUAL(pt.write_some(net::buffer(l2)), 2);
|
||||
BOOST_CHECK_EQUAL(n = net::read(pt, net::buffer(rb, 4)), 4); rb += n;
|
||||
BOOST_CHECK_EQUAL(pt.write_some(net::buffer(l3)), 6);
|
||||
BOOST_CHECK_EQUAL(n = net::read(pt, net::buffer(rb, 12)), 12); rb += n;
|
||||
BOOST_CHECK_EQUAL(pt.write_some(net::buffer(l4)), 1);
|
||||
BOOST_CHECK_EQUAL(n = net::read(pt, net::buffer(rb, 4)), 4); rb += n;
|
||||
|
||||
n = read_buffer.size() - rb.size();
|
||||
|
||||
BOOST_CHECK_EQUAL(read_buffer.substr(0, n), "HelloHELLO, , World!WORLD!^J\r\n");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(async_echo)
|
||||
{
|
||||
namespace bp2 = boost::process::v2;
|
||||
namespace net = boost::process::v2::net;
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
const auto pth = bp2::filesystem::absolute(master_test_suite().argv[1]);
|
||||
|
||||
boost::asio::io_context ctx;
|
||||
bp2::experimental::pty pt{ctx};
|
||||
bp2::process proc(ctx, pth, {"--async", "--echo"}, pt);
|
||||
|
||||
char buf[4];
|
||||
net::read(pt, net::buffer(buf));
|
||||
|
||||
|
||||
struct op : net::coroutine
|
||||
{
|
||||
bp2::experimental::pty &pt;
|
||||
bp2::process &proc;
|
||||
|
||||
op(bp2::experimental::pty &pt, bp2::process &proc) : pt(pt), proc(proc) {}
|
||||
|
||||
std::string read_buffer = std::string(64, ' ');
|
||||
net::mutable_buffer rb = net::buffer(read_buffer);
|
||||
std::string l1 = "Hello", l2 = ", ", l3 = "World!", l4 = "\n";
|
||||
|
||||
|
||||
void operator()(bp2::error_code ec, std::size_t n)
|
||||
{
|
||||
BOOST_REQUIRE_MESSAGE(!ec, ec.message());
|
||||
reenter(this)
|
||||
{
|
||||
yield pt.async_write_some(net::buffer(l1), *this);
|
||||
BOOST_CHECK_EQUAL(n, 5);
|
||||
yield net::async_read(pt, net::buffer(rb, 10), *this);
|
||||
BOOST_CHECK_EQUAL(n, 10); rb += n;
|
||||
|
||||
yield pt.async_write_some(net::buffer(l2), *this);
|
||||
BOOST_CHECK_EQUAL(n, 2);
|
||||
yield net::async_read(pt, net::buffer(rb, 4), *this);
|
||||
BOOST_CHECK_EQUAL(n, 4);
|
||||
rb += n;
|
||||
yield pt.async_write_some(net::buffer(l3), *this);
|
||||
BOOST_CHECK_EQUAL(n, 6);
|
||||
yield net::async_read(pt, net::buffer(rb, 12), *this);
|
||||
BOOST_CHECK_EQUAL(n, 12); rb += n;
|
||||
yield pt.async_write_some(net::buffer(l4), *this);
|
||||
BOOST_CHECK_EQUAL(n, 1);
|
||||
yield net::async_read(pt, net::buffer(rb, 4), *this);
|
||||
BOOST_CHECK_EQUAL(n, 4); rb += n;
|
||||
|
||||
n = read_buffer.size() - rb.size();
|
||||
BOOST_CHECK_EQUAL(read_buffer.substr(0, n), "HelloHELLO, , World!WORLD!^J\r\n");
|
||||
|
||||
proc.terminate();
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
op{pt, proc}({}, 0u);
|
||||
ctx.run();
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(async_line)
|
||||
{
|
||||
namespace bp2 = boost::process::v2;
|
||||
namespace net = boost::process::v2::net;
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
const auto pth = bp2::filesystem::absolute(master_test_suite().argv[1]);
|
||||
|
||||
boost::asio::io_context ctx;
|
||||
bp2::experimental::pty pt{ctx};
|
||||
bp2::process proc(ctx, pth, {"--async", "--line"}, pt);
|
||||
|
||||
|
||||
char buf[4];
|
||||
net::read(pt, net::buffer(buf));
|
||||
|
||||
|
||||
std::size_t read = 0u;
|
||||
std::string read_buffer;
|
||||
net::async_read_until(
|
||||
pt, net::dynamic_buffer(read_buffer), '\n',
|
||||
[&](bp2::error_code ec, std::size_t n)
|
||||
{
|
||||
BOOST_CHECK_EQUAL(read_buffer.substr(0, n), "HELLO, WORLD!\r\n");
|
||||
read = n;
|
||||
});
|
||||
|
||||
struct op : net::coroutine
|
||||
{
|
||||
bp2::experimental::pty &pt;
|
||||
std::size_t & read;
|
||||
|
||||
op(bp2::experimental::pty &pt, std::size_t & read) : pt(pt), read(read) {}
|
||||
|
||||
std::string l1 = "Hello", l2 = ", ", l3 = "World!", l4 = "\n";
|
||||
|
||||
|
||||
void operator()(bp2::error_code ec, std::size_t n)
|
||||
{
|
||||
BOOST_REQUIRE_MESSAGE(!ec, ec.message());
|
||||
reenter(this)
|
||||
{
|
||||
yield pt.async_write_some(net::buffer(l1), *this);
|
||||
BOOST_CHECK_EQUAL(n, 5);
|
||||
BOOST_CHECK_EQUAL(read, 0);
|
||||
yield pt.async_write_some(net::buffer(l2), *this);
|
||||
BOOST_CHECK_EQUAL(n, 2);
|
||||
BOOST_CHECK_EQUAL(read, 0);
|
||||
yield pt.async_write_some(net::buffer(l3), *this);
|
||||
BOOST_CHECK_EQUAL(n, 6);
|
||||
BOOST_CHECK_EQUAL(read, 0);
|
||||
yield pt.async_write_some(net::buffer(l4), *this);
|
||||
BOOST_CHECK_EQUAL(n, 1);
|
||||
BOOST_CHECK_EQUAL(read, 0);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
op{pt, read}({}, 0u);
|
||||
ctx.run();
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(sync_line_echo)
|
||||
{
|
||||
namespace bp2 = boost::process::v2;
|
||||
namespace net = boost::process::v2::net;
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
const auto pth = bp2::filesystem::absolute(master_test_suite().argv[1]);
|
||||
|
||||
boost::asio::io_context ctx;
|
||||
bp2::experimental::pty pt{ctx};
|
||||
bp2::process proc(ctx, pth, {"--line", "--echo"}, pt);
|
||||
|
||||
|
||||
char buf[4];
|
||||
net::read(pt, net::buffer(buf));
|
||||
|
||||
std::string l1 = "Hello", l2 = ", ", l3 = "World!", l4 = "\n";
|
||||
|
||||
std::string read_buffer;
|
||||
read_buffer.resize(64);
|
||||
auto rb = net::buffer(read_buffer);
|
||||
|
||||
BOOST_CHECK_EQUAL(pt.write_some(net::buffer(l1)), 5);
|
||||
auto n = pt.read_some(rb);
|
||||
BOOST_CHECK_EQUAL(n, 5); rb += n;
|
||||
|
||||
BOOST_CHECK_EQUAL(pt.write_some(net::buffer(l2)), 2);
|
||||
BOOST_CHECK_EQUAL(n = pt.read_some(rb), 2); rb += n;
|
||||
BOOST_CHECK_EQUAL(pt.write_some(net::buffer(l3)), 6);
|
||||
BOOST_CHECK_EQUAL(n = pt.read_some(rb), 6); rb += n;
|
||||
BOOST_CHECK_EQUAL(pt.write_some(net::buffer(l4)), 1);
|
||||
BOOST_CHECK_EQUAL(n = pt.read_some(rb), 2); rb += n;
|
||||
|
||||
|
||||
rb += pt.read_some(rb);
|
||||
n = read_buffer.size() - rb.size();
|
||||
|
||||
BOOST_CHECK_EQUAL(read_buffer.substr(0, n), "Hello, World!\r\nHELLO, WORLD!\r\n");
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(resize)
|
||||
{
|
||||
namespace bp2 = boost::process::v2;
|
||||
namespace net = boost::process::v2::net;
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
const auto pth = bp2::filesystem::absolute(master_test_suite().argv[1]);
|
||||
|
||||
boost::asio::io_context ctx;
|
||||
bp2::experimental::pty pt{ctx};
|
||||
|
||||
bp2::experimental::console_size_t cs{100, 40};
|
||||
pt.open(cs);
|
||||
|
||||
bp2::process proc(ctx, pth, {"--wait-resize"}, pt);
|
||||
|
||||
|
||||
char buf[4];
|
||||
net::read(pt, net::buffer(buf));
|
||||
|
||||
std::string line;
|
||||
auto n = net::read_until(pt, net::dynamic_buffer(line), '\n');
|
||||
BOOST_CHECK_EQUAL(line, "cols=100 rows=40\r\n");
|
||||
|
||||
line.clear();
|
||||
|
||||
cs.columns = 85;
|
||||
cs.rows = 35;
|
||||
pt.resize(cs);
|
||||
|
||||
n = net::read_until(pt, net::dynamic_buffer(line), '\n');
|
||||
BOOST_CHECK_EQUAL(line, "cols=85 rows=35\r\n");
|
||||
}
|
||||
|
||||
#endif
|
||||
119
test/v2/experimental/pty_target.cpp
Normal file
119
test/v2/experimental/pty_target.cpp
Normal file
@@ -0,0 +1,119 @@
|
||||
//
|
||||
// Copyright (c) 2024 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)
|
||||
//
|
||||
|
||||
#include <boost/process/v2/experimental/stream.hpp>
|
||||
|
||||
#include <boost/algorithm/string/case_conv.hpp>
|
||||
|
||||
#include <boost/asio/coroutine.hpp>
|
||||
#include <boost/asio/post.hpp>
|
||||
#include <boost/asio/write.hpp>
|
||||
#include <boost/asio/yield.hpp>
|
||||
|
||||
|
||||
namespace net = boost::asio;
|
||||
namespace bp = boost::process::v2;
|
||||
|
||||
char buf[512];
|
||||
|
||||
bool async_check = false;
|
||||
|
||||
struct async_op : net::coroutine
|
||||
{
|
||||
bp::experimental::basic_stream<net::io_context::executor_type> &in, &out;
|
||||
|
||||
async_op(bp::experimental::basic_stream<net::io_context::executor_type> &in,
|
||||
bp::experimental::basic_stream<net::io_context::executor_type> &out) : in(in), out(out) {}
|
||||
void operator()(bp::error_code ec = {}, std::size_t n = {})
|
||||
{
|
||||
if (ec)
|
||||
return;
|
||||
reenter(this)
|
||||
{
|
||||
while (in.is_open())
|
||||
{
|
||||
async_check = false;
|
||||
net::post(in.get_executor(), []{async_check=true;});
|
||||
yield in.async_read_some(net::buffer(buf), *this);
|
||||
assert(async_check);
|
||||
boost::algorithm::to_upper(buf);
|
||||
yield net::async_write(out, net::buffer(buf, n), *this);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
try
|
||||
{
|
||||
net::io_context ctx;
|
||||
|
||||
auto in = bp::experimental::open_stdin(ctx.get_executor());
|
||||
assert(in.is_pty());
|
||||
//assert(in.echo());
|
||||
//assert(in.line());
|
||||
|
||||
std::vector<std::string> args{argv + 1, argv + argc};
|
||||
|
||||
const bool async = std::find(args.begin(), args.end(), "--async") != args.end();
|
||||
const bool stder = std::find(args.begin(), args.end(), "--stderr") != args.end();
|
||||
const bool echo = std::find(args.begin(), args.end(), "--echo") != args.end();
|
||||
const bool line = std::find(args.begin(), args.end(), "--line") != args.end();
|
||||
const bool wait = std::find(args.begin(), args.end(), "--wait-resize") != args.end();
|
||||
|
||||
auto out = stder ? bp::experimental::open_stderr(ctx.get_executor())
|
||||
: bp::experimental::open_stdout(ctx.get_executor());
|
||||
in.set_echo(echo);
|
||||
in.set_line(line);
|
||||
|
||||
assert(in.echo() == echo);
|
||||
assert(in.line() == line);
|
||||
|
||||
net::write(out, net::buffer("sync", 4));
|
||||
|
||||
if (wait)
|
||||
{
|
||||
|
||||
in.async_wait_for_size_change(
|
||||
[&](bp::error_code ec, bp::experimental::console_size_t cs)
|
||||
{
|
||||
assert(!ec);
|
||||
printf("cols=%d rows=%d\n", cs.columns, cs.rows);
|
||||
});
|
||||
|
||||
net::post(ctx, [&]{
|
||||
const auto sz = in.console_size();
|
||||
printf("cols=%d rows=%d\n", sz.columns, sz.rows);
|
||||
});
|
||||
ctx.run();
|
||||
}
|
||||
else if (async)
|
||||
{
|
||||
net::post(ctx, async_op{in, out});
|
||||
ctx.run();
|
||||
}
|
||||
else
|
||||
{
|
||||
char buf[512];
|
||||
auto f = fopen("./test.txt", "w");
|
||||
while (in.is_open())
|
||||
{
|
||||
auto n = in.read_some(net::buffer(buf));
|
||||
boost::algorithm::to_upper(buf);
|
||||
fwrite(buf, 1u, n, f);
|
||||
fflush(f);
|
||||
net::write(out, net::buffer(buf, n));
|
||||
}
|
||||
}
|
||||
|
||||
return 0u;
|
||||
}
|
||||
catch(boost::system::system_error & se)
|
||||
{
|
||||
fprintf(stderr, "Pty-Target exception: %s(%d): %s\n", se.code().location().file_name(), se.code().location().line(), se.what());
|
||||
return 1;
|
||||
}
|
||||
@@ -9,9 +9,6 @@
|
||||
#define BOOST_ALL_NO_LIB 1
|
||||
#endif // !defined(BOOST_ALL_NO_LIB)
|
||||
|
||||
#if defined(BOOST_FILESYSTEM_DYN_LINK)
|
||||
#undef BOOST_FILESYSTEM_DYN_LINK
|
||||
#endif
|
||||
#define BOOST_TEST_IGNORE_SIGCHLD 1
|
||||
|
||||
#if true //defined(BOOST_POSIX_API)
|
||||
@@ -34,6 +31,7 @@
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <boost/asio/connect_pipe.hpp>
|
||||
#include <boost/asio/cancel_after.hpp>
|
||||
#include <boost/asio/detached.hpp>
|
||||
#include <boost/asio/readable_pipe.hpp>
|
||||
#include <boost/asio/read.hpp>
|
||||
@@ -55,9 +53,9 @@ BOOST_AUTO_TEST_CASE(exit_code_sync)
|
||||
{
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
const auto pth = master_test_suite().argv[1];
|
||||
|
||||
|
||||
boost::asio::io_context ctx;
|
||||
|
||||
|
||||
BOOST_CHECK_EQUAL(bpv::process(ctx, pth, {"exit-code", "0"}).wait(), 0);
|
||||
BOOST_CHECK_EQUAL(bpv::execute(bpv::process(ctx, pth, {"exit-code", "1"})), 1);
|
||||
std::vector<std::string> args = {"exit-code", "2"};
|
||||
@@ -85,7 +83,7 @@ BOOST_AUTO_TEST_CASE(exit_code_async)
|
||||
|
||||
int called = 0;
|
||||
printf("Setting up processes\n");
|
||||
|
||||
|
||||
bpv::process proc1(ctx, pth, {"exit-code", "0"});
|
||||
bpv::process proc3(ctx, pth, {"exit-code", "2"});
|
||||
bpv::process proc4(ctx, pth, {"exit-code", "42"});
|
||||
@@ -200,7 +198,7 @@ BOOST_AUTO_TEST_CASE(print_args_out)
|
||||
{
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
const auto pth = master_test_suite().argv[1];
|
||||
|
||||
|
||||
asio::io_context ctx;
|
||||
|
||||
asio::readable_pipe rp{ctx};
|
||||
@@ -296,7 +294,7 @@ BOOST_AUTO_TEST_CASE(echo_file)
|
||||
{
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
const auto pth = master_test_suite().argv[1];
|
||||
|
||||
|
||||
asio::io_context ctx;
|
||||
|
||||
asio::readable_pipe rp{ctx};
|
||||
@@ -476,7 +474,7 @@ BOOST_AUTO_TEST_CASE(environment)
|
||||
|
||||
sub_env.push_back("FOOBAR=FOO-BAR");
|
||||
BOOST_CHECK_EQUAL("FOO-BAR", read_env("FOOBAR", bpv::process_environment{sub_env}));
|
||||
|
||||
|
||||
sub_env.push_back("XYZ=ZYX");
|
||||
auto itr = std::find_if(sub_env.begin(), sub_env.end(), [](const bpv::environment::key_value_pair & kv) {return kv.key() == bpv::environment::key("PATH");});
|
||||
path += static_cast<char>(bpv::environment::delimiter);
|
||||
@@ -511,7 +509,7 @@ BOOST_AUTO_TEST_CASE(exit_code_as_error)
|
||||
bpv::process proc3(ctx, pth, {"sleep", "2000"});
|
||||
|
||||
int called = 0;
|
||||
|
||||
|
||||
proc3.terminate();
|
||||
|
||||
|
||||
@@ -642,6 +640,30 @@ BOOST_AUTO_TEST_CASE(async_request_exit)
|
||||
ctx.run();
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(async_cancel_wait)
|
||||
{
|
||||
asio::io_context ctx;
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
const auto pth = bpv::filesystem::absolute(master_test_suite().argv[1]);
|
||||
|
||||
bpv::process proc(ctx, pth, {"sleep", "1000"});
|
||||
|
||||
asio::steady_timer tim{ctx, std::chrono::milliseconds(250)};
|
||||
asio::cancellation_signal sig;
|
||||
|
||||
// check that the async_wait gets properly cancelled
|
||||
proc.async_wait(asio::cancel_after(std::chrono::milliseconds(100),
|
||||
[&](boost::system::error_code ec, int)
|
||||
{
|
||||
BOOST_CHECK(ec == asio::error::operation_aborted);
|
||||
BOOST_CHECK(proc.running());
|
||||
if (proc.running())
|
||||
proc.terminate();
|
||||
}));
|
||||
|
||||
ctx.run();
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END();
|
||||
|
||||
|
||||
@@ -5,4 +5,4 @@
|
||||
|
||||
#define BOOST_TEST_IGNORE_SIGCHLD
|
||||
#define BOOST_TEST_MODULE process_v2_test
|
||||
#include <boost/test/included/unit_test.hpp>
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
@@ -9,10 +9,6 @@
|
||||
#define BOOST_ALL_NO_LIB 1
|
||||
#endif // !defined(BOOST_ALL_NO_LIB)
|
||||
|
||||
#if defined(BOOST_FILESYSTEM_DYN_LINK)
|
||||
#undef BOOST_FILESYSTEM_DYN_LINK
|
||||
#endif
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include <boost/process/v2/process.hpp>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user