├── .circleci └── config.yml ├── .drone.star ├── .drone ├── drone.bat └── drone.sh ├── .gitattributes ├── .github └── workflows │ └── ci.yml ├── .gitignore ├── .travis.yml ├── CMakeLists.txt ├── README.md ├── build.jam ├── build └── Jamfile ├── doc ├── Jamfile.jam ├── acknowledgements.adoc ├── configuration.adoc ├── env.adoc ├── images │ ├── plantuml.txt │ ├── posix_exec_err.svg │ ├── posix_fork_err.svg │ ├── posix_success.svg │ └── windows_exec.svg ├── index.adoc ├── launcher.adoc ├── quickstart.adoc ├── reference │ ├── bind_launcher.adoc │ ├── cstring_ref.adoc │ ├── default_launcher.adoc │ ├── environment.adoc │ ├── error.adoc │ ├── execute.adoc │ ├── exit_code.adoc │ ├── ext.adoc │ ├── pid.adoc │ ├── popen.adoc │ ├── posix │ │ └── bind_fd.adoc │ ├── process.adoc │ ├── process_handle.adoc │ ├── shell.adoc │ ├── start_dir.adoc │ ├── stdio.adoc │ └── windows │ │ ├── creation_flags.adoc │ │ └── show_window.adoc ├── start_dir.adoc ├── stdio.adoc └── version2.adoc ├── example ├── Jamfile.jam ├── env.cpp ├── intro.cpp ├── intro_popen.cpp ├── quickstart.cpp ├── start_dir.cpp └── stdio.cpp ├── filter_section_warning.py ├── include └── boost │ ├── process.hpp │ └── process │ ├── bind_launcher.hpp │ ├── cstring_ref.hpp │ ├── default_launcher.hpp │ ├── environment.hpp │ ├── error.hpp │ ├── execute.hpp │ ├── exit_code.hpp │ ├── ext.hpp │ ├── ext │ ├── cmd.hpp │ ├── cwd.hpp │ ├── env.hpp │ └── exe.hpp │ ├── pid.hpp │ ├── popen.hpp │ ├── posix │ ├── bind_fd.hpp │ ├── default_launcher.hpp │ ├── fork_and_forget_launcher.hpp │ ├── pdfork_launcher.hpp │ └── vfork_launcher.hpp │ ├── process.hpp │ ├── process_handle.hpp │ ├── shell.hpp │ ├── start_dir.hpp │ ├── stdio.hpp │ ├── v1 │ ├── args.hpp │ ├── async.hpp │ ├── async_pipe.hpp │ ├── async_system.hpp │ ├── child.hpp │ ├── cmd.hpp │ ├── detail │ │ ├── async_handler.hpp │ │ ├── basic_cmd.hpp │ │ ├── child_decl.hpp │ │ ├── config.hpp │ │ ├── execute_impl.hpp │ │ ├── handler.hpp │ │ ├── handler_base.hpp │ │ ├── on_exit.hpp │ │ ├── posix │ │ │ ├── asio_fwd.hpp │ │ │ ├── async_handler.hpp │ │ │ ├── async_in.hpp │ │ │ ├── async_out.hpp │ │ │ ├── async_pipe.hpp │ │ │ ├── basic_cmd.hpp │ │ │ ├── basic_pipe.hpp │ │ │ ├── child_handle.hpp │ │ │ ├── close_in.hpp │ │ │ ├── close_out.hpp │ │ │ ├── cmd.hpp │ │ │ ├── compare_handles.hpp │ │ │ ├── env_init.hpp │ │ │ ├── environment.hpp │ │ │ ├── exe.hpp │ │ │ ├── executor.hpp │ │ │ ├── fd.hpp │ │ │ ├── file_descriptor.hpp │ │ │ ├── file_in.hpp │ │ │ ├── file_out.hpp │ │ │ ├── group_handle.hpp │ │ │ ├── group_ref.hpp │ │ │ ├── handler.hpp │ │ │ ├── handles.hpp │ │ │ ├── io_context_ref.hpp │ │ │ ├── is_running.hpp │ │ │ ├── null_in.hpp │ │ │ ├── null_out.hpp │ │ │ ├── on_exit.hpp │ │ │ ├── pipe_in.hpp │ │ │ ├── pipe_out.hpp │ │ │ ├── search_path.hpp │ │ │ ├── shell_path.hpp │ │ │ ├── sigchld_service.hpp │ │ │ ├── signal.hpp │ │ │ ├── start_dir.hpp │ │ │ ├── terminate.hpp │ │ │ ├── use_vfork.hpp │ │ │ ├── wait_for_exit.hpp │ │ │ └── wait_group.hpp │ │ ├── throw_on_error.hpp │ │ ├── traits.hpp │ │ ├── traits │ │ │ ├── async.hpp │ │ │ ├── cmd_or_exe.hpp │ │ │ ├── decl.hpp │ │ │ ├── env.hpp │ │ │ ├── error.hpp │ │ │ ├── group.hpp │ │ │ └── wchar_t.hpp │ │ ├── used_handles.hpp │ │ └── windows │ │ │ ├── asio_fwd.hpp │ │ │ ├── async_handler.hpp │ │ │ ├── async_in.hpp │ │ │ ├── async_out.hpp │ │ │ ├── async_pipe.hpp │ │ │ ├── basic_cmd.hpp │ │ │ ├── basic_pipe.hpp │ │ │ ├── child_handle.hpp │ │ │ ├── close_in.hpp │ │ │ ├── close_out.hpp │ │ │ ├── cmd.hpp │ │ │ ├── compare_handles.hpp │ │ │ ├── env_init.hpp │ │ │ ├── environment.hpp │ │ │ ├── executor.hpp │ │ │ ├── file_descriptor.hpp │ │ │ ├── file_in.hpp │ │ │ ├── file_out.hpp │ │ │ ├── group_handle.hpp │ │ │ ├── group_ref.hpp │ │ │ ├── handle_workaround.hpp │ │ │ ├── handler.hpp │ │ │ ├── handles.hpp │ │ │ ├── io_context_ref.hpp │ │ │ ├── is_running.hpp │ │ │ ├── job_workaround.hpp │ │ │ ├── locale.hpp │ │ │ ├── null_in.hpp │ │ │ ├── null_out.hpp │ │ │ ├── on_exit.hpp │ │ │ ├── pipe_in.hpp │ │ │ ├── pipe_out.hpp │ │ │ ├── search_path.hpp │ │ │ ├── shell_path.hpp │ │ │ ├── show_window.hpp │ │ │ ├── start_dir.hpp │ │ │ ├── terminate.hpp │ │ │ ├── wait_for_exit.hpp │ │ │ └── wait_group.hpp │ ├── env.hpp │ ├── environment.hpp │ ├── error.hpp │ ├── exception.hpp │ ├── exe.hpp │ ├── extend.hpp │ ├── filesystem.hpp │ ├── group.hpp │ ├── handles.hpp │ ├── io.hpp │ ├── locale.hpp │ ├── pipe.hpp │ ├── posix.hpp │ ├── search_path.hpp │ ├── shell.hpp │ ├── spawn.hpp │ ├── start_dir.hpp │ ├── system.hpp │ └── windows.hpp │ ├── v2 │ ├── bind_launcher.hpp │ ├── cstring_ref.hpp │ ├── default_launcher.hpp │ ├── detail │ │ ├── config.hpp │ │ ├── environment_posix.hpp │ │ ├── environment_win.hpp │ │ ├── last_error.hpp │ │ ├── process_handle_fd.hpp │ │ ├── process_handle_fd_or_signal.hpp │ │ ├── process_handle_signal.hpp │ │ ├── process_handle_windows.hpp │ │ ├── throw_error.hpp │ │ ├── throw_exception.hpp │ │ └── utf8.hpp │ ├── environment.hpp │ ├── error.hpp │ ├── execute.hpp │ ├── exit_code.hpp │ ├── ext.hpp │ ├── ext │ │ ├── cmd.hpp │ │ ├── cwd.hpp │ │ ├── detail │ │ │ └── proc_info.hpp │ │ ├── env.hpp │ │ └── exe.hpp │ ├── pid.hpp │ ├── popen.hpp │ ├── posix │ │ ├── bind_fd.hpp │ │ ├── default_launcher.hpp │ │ ├── detail │ │ │ └── close_handles.hpp │ │ ├── fork_and_forget_launcher.hpp │ │ ├── pdfork_launcher.hpp │ │ ├── pipe_fork_launcher.hpp │ │ └── vfork_launcher.hpp │ ├── process.hpp │ ├── process_handle.hpp │ ├── shell.hpp │ ├── start_dir.hpp │ ├── stdio.hpp │ └── windows │ │ ├── as_user_launcher.hpp │ │ ├── creation_flags.hpp │ │ ├── default_launcher.hpp │ │ ├── show_window.hpp │ │ ├── with_logon_launcher.hpp │ │ └── with_token_launcher.hpp │ └── windows │ ├── as_user_launcher.hpp │ ├── creation_flags.hpp │ ├── default_launcher.hpp │ ├── show_window.hpp │ ├── with_logon_launcher.hpp │ └── with_token_launcher.hpp ├── index.html ├── meta └── libraries.json ├── src ├── detail │ ├── environment_posix.cpp │ ├── environment_win.cpp │ ├── last_error.cpp │ ├── process_handle_windows.cpp │ ├── throw_error.cpp │ └── utf8.cpp ├── environment.cpp ├── error.cpp ├── ext │ ├── cmd.cpp │ ├── cwd.cpp │ ├── env.cpp │ ├── exe.cpp │ └── proc_info.cpp ├── pid.cpp ├── posix │ └── close_handles.cpp ├── shell.cpp └── windows │ └── default_launcher.cpp └── test ├── CMakeLists.txt ├── Jamfile.jam ├── appveyor.yml ├── v1 ├── CMakeLists.txt ├── Jamfile.jam ├── args_cmd.cpp ├── args_handling.cpp ├── asio_no_deprecated.cpp ├── async.cpp ├── async_fut.cpp ├── async_pipe.cpp ├── async_system_fail.cpp ├── async_system_future.cpp ├── async_system_stackful.cpp ├── async_system_stackful_error.cpp ├── async_system_stackful_except.cpp ├── async_system_stackless.cpp ├── bind_stderr.cpp ├── bind_stdin.cpp ├── bind_stdin_stdout.cpp ├── bind_stdout.cpp ├── bind_stdout_stderr.cpp ├── close_stderr.cpp ├── close_stdin.cpp ├── close_stdout.cpp ├── cmd_test.cpp ├── env.cpp ├── environment.cpp ├── error.cpp ├── exit_argc.cpp ├── exit_code.cpp ├── extensions.cpp ├── group.cpp ├── group_wait.cpp ├── limit_fd.cpp ├── multi_ref1.cpp ├── multi_ref2.cpp ├── no_ansi_apps.cpp ├── on_exit.cpp ├── on_exit2.cpp ├── on_exit3.cpp ├── pipe.cpp ├── pipe_fwd.cpp ├── posix_specific.cpp ├── run_exe.cpp ├── run_exe_path.cpp ├── search_path.cpp ├── shell.cpp ├── shell_path.cpp ├── sparring_partner.cpp ├── spawn.cpp ├── spawn_fail.cpp ├── start_dir.cpp ├── sub_launcher.cpp ├── system_test1.cpp ├── system_test2.cpp ├── terminate.cpp ├── test-file ├── throw_on_error.cpp ├── vfork.cpp ├── wait.cpp ├── wait_for.cpp ├── wargs_cmd.cpp └── windows_specific.cpp └── v2 ├── CMakeLists.txt ├── Jamfile.jam ├── cstring_ref.cpp ├── environment.cpp ├── ext.cpp ├── pid.cpp ├── process.cpp ├── shell.cpp ├── target.cpp ├── test_impl.cpp ├── utf8.cpp └── windows.cpp /.drone/drone.bat: -------------------------------------------------------------------------------- 1 | @ECHO ON 2 | setlocal enabledelayedexpansion 3 | 4 | if "%DRONE_JOB_BUILDTYPE%" == "boost" ( 5 | 6 | echo '==================================> INSTALL' 7 | 8 | git clone https://github.com/boostorg/boost-ci.git boost-ci-cloned --depth 1 9 | cp -prf boost-ci-cloned/ci . 10 | rm -rf boost-ci-cloned 11 | 12 | REM source ci/travis/install.sh 13 | REM The contents of install.sh below: 14 | 15 | for /F %%i in ("%DRONE_REPO%") do @set SELF=%%~nxi 16 | SET BOOST_CI_TARGET_BRANCH=%DRONE_COMMIT_BRANCH% 17 | SET BOOST_CI_SRC_FOLDER=%cd% 18 | 19 | call ci\common_install.bat 20 | 21 | echo '==================================> COMPILE' 22 | 23 | REM set B2_TARGETS=libs/!SELF!/test libs/!SELF!/example 24 | set B2_TARGETS=libs/!SELF!/test 25 | 26 | cd !BOOST_ROOT! 27 | call bootstrap.bat 28 | b2 headers 29 | b2 --debug-configuration variant=%VARIANT% cxxstd=%CXXSTD% define=%DEFINE% address-model=%ADDRESS_MODEL% toolset=%TOOLSET% --verbose-test libs/!SELF!/test libs/!SELF!/example -j3 30 | ) else if "%DRONE_JOB_BUILDTYPE%" == "standalone-windows" ( 31 | 32 | REM not used 33 | 34 | ) -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Compiled Dynamic libraries 8 | *.so 9 | *.dylib 10 | *.dll 11 | 12 | # Compiled Static libraries 13 | *.lai 14 | *.la 15 | *.a 16 | *.lib 17 | 18 | # Executables 19 | *.exe 20 | *.out 21 | *.app 22 | /bin 23 | /*/bin 24 | /doc/autodoc.xml 25 | /doc/html 26 | /sparring_log.txt 27 | /.cproject 28 | /.project 29 | /Doxyfile 30 | 31 | /notes.cpp 32 | /notes_p.txt 33 | .settings 34 | .DS_Store 35 | 36 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Generated by `boostdep --cmake process` 2 | # Copyright 2020 Peter Dimov 3 | # Distributed under the Boost Software License, Version 1.0. 4 | # https://www.boost.org/LICENSE_1_0.txt 5 | 6 | cmake_minimum_required(VERSION 3.5...3.16) 7 | 8 | project(boost_process VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX) 9 | 10 | option(BOOST_PROCESS_USE_STD_FS "Use std::filesystem instead of Boost.Filesystem" OFF) 11 | 12 | add_library(boost_process 13 | src/detail/environment_posix.cpp 14 | src/detail/environment_win.cpp 15 | src/detail/last_error.cpp 16 | src/detail/process_handle_windows.cpp 17 | src/detail/throw_error.cpp 18 | src/detail/utf8.cpp 19 | src/ext/cmd.cpp 20 | src/ext/cwd.cpp 21 | src/ext/env.cpp 22 | src/ext/exe.cpp 23 | src/ext/proc_info.cpp 24 | src/posix/close_handles.cpp 25 | src/windows/default_launcher.cpp 26 | src/environment.cpp 27 | src/error.cpp 28 | src/pid.cpp 29 | src/shell.cpp) 30 | 31 | add_library(Boost::process ALIAS boost_process) 32 | 33 | target_include_directories(boost_process PUBLIC include) 34 | target_link_libraries(boost_process 35 | PUBLIC 36 | Boost::algorithm 37 | Boost::asio 38 | Boost::config 39 | Boost::core 40 | Boost::fusion 41 | Boost::iterator 42 | Boost::move 43 | Boost::optional 44 | Boost::system 45 | Boost::tokenizer 46 | Boost::type_index 47 | Boost::winapi 48 | ) 49 | 50 | target_compile_definitions(boost_process 51 | PRIVATE BOOST_PROCESS_SOURCE=1 52 | ) 53 | 54 | if(BOOST_PROCESS_USE_STD_FS) 55 | target_compile_definitions(boost_process PUBLIC BOOST_PROCESS_USE_STD_FS) 56 | target_compile_features(boost_process PUBLIC cxx_std_17) 57 | else() 58 | target_link_libraries(boost_process PUBLIC Boost::filesystem) 59 | endif() 60 | 61 | if(WIN32) 62 | target_link_libraries(boost_process PUBLIC ntdll shell32 advapi32 user32 ws2_32) 63 | endif() 64 | 65 | if(BUILD_SHARED_LIBS) 66 | target_compile_definitions(boost_process PUBLIC BOOST_PROCESS_DYN_LINK) 67 | else() 68 | target_compile_definitions(boost_process PUBLIC BOOST_PROCESS_STATIC_LINK) 69 | endif() 70 | 71 | if(BUILD_TESTING AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/CMakeLists.txt") 72 | add_subdirectory(test) 73 | endif() 74 | 75 | -------------------------------------------------------------------------------- /build.jam: -------------------------------------------------------------------------------- 1 | # Copyright René Ferdinand Rivera Morell 2024 2 | # Distributed under the Boost Software License, Version 1.0. 3 | # (See accompanying file LICENSE_1_0.txt or copy at 4 | # http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | require-b2 5.2 ; 7 | 8 | import feature : feature ; 9 | 10 | feature boost.process.fs : boost std : optional propagated ; 11 | feature boost.process.disable-close-range : on off : optional ; 12 | 13 | constant boost_dependencies : 14 | /boost/algorithm//boost_algorithm 15 | /boost/asio//boost_asio 16 | /boost/assert//boost_assert 17 | /boost/config//boost_config 18 | /boost/core//boost_core 19 | /boost/fusion//boost_fusion 20 | /boost/io//boost_io 21 | /boost/iterator//boost_iterator 22 | /boost/move//boost_move 23 | /boost/optional//boost_optional 24 | /boost/system//boost_system 25 | /boost/throw_exception//boost_throw_exception 26 | /boost/tokenizer//boost_tokenizer 27 | /boost/type_index//boost_type_index 28 | /boost/type_traits//boost_type_traits 29 | /boost/utility//boost_utility 30 | /boost/winapi//boost_winapi ; 31 | 32 | project /boost/process 33 | : common-requirements 34 | include 35 | : default-build 36 | boost 37 | ; 38 | 39 | explicit 40 | [ alias boost_process : build//boost_process ] 41 | [ alias all : boost_process example example/v2 test ] 42 | ; 43 | 44 | call-if : boost-library process 45 | : install boost_process 46 | ; 47 | 48 | -------------------------------------------------------------------------------- /build/Jamfile: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2024 Klemens D. Morgenstern 2 | # 3 | # Distributed under the Boost Software License, Version 1.0. (See accompanying 4 | # file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | import os ; 7 | import feature ; 8 | import-search /boost/config/checks ; 9 | import config : requires ; 10 | 11 | project : requirements 12 | BOOST_ASIO_NO_DEPRECATED 13 | msvc:_SCL_SECURE_NO_WARNINGS 14 | msvc:_CRT_SECURE_NO_DEPRECATE 15 | msvc:/bigobj 16 | windows:WIN32_LEAN_AND_MEAN 17 | linux:-lpthread 18 | : source-location ../src 19 | : common-requirements 20 | $(boost_dependencies) 21 | std:BOOST_PROCESS_USE_STD_FS=1 22 | ; 23 | 24 | alias process_sources 25 | : detail/environment_posix.cpp 26 | detail/environment_win.cpp 27 | detail/last_error.cpp 28 | detail/process_handle_windows.cpp 29 | detail/throw_error.cpp 30 | detail/utf8.cpp 31 | ext/cmd.cpp 32 | ext/cwd.cpp 33 | ext/env.cpp 34 | ext/exe.cpp 35 | ext/proc_info.cpp 36 | posix/close_handles.cpp 37 | windows/default_launcher.cpp 38 | environment.cpp 39 | error.cpp 40 | pid.cpp 41 | shell.cpp 42 | ; 43 | 44 | lib shell32 ; 45 | lib advapi32 ; 46 | lib ntdll ; 47 | lib user32 ; 48 | lib ws2_32 ; 49 | 50 | lib kvm ; 51 | lib procstat ; 52 | 53 | lib boost_process 54 | : process_sources 55 | : requirements BOOST_PROCESS_SOURCE=1 56 | shared:BOOST_PROCESS_DYN_LINK=1 57 | boost:/boost/filesystem//boost_filesystem 58 | on:BOOST_PROCESS_V2_POSIX_FORCE_DISABLE_CLOSE_RANGE=1 59 | windows:shell32 60 | windows:user32 61 | windows:ntdll 62 | windows:advapi32 63 | windows:ws2_32 64 | bsd:kvm 65 | freebsd:kvm 66 | freebsd:procstat 67 | netbsd:kvm 68 | openbsd:kvm 69 | solaris:kvm 70 | : usage-requirements 71 | shared:BOOST_PROCESS_DYN_LINK=1 72 | boost:/boost/filesystem//boost_filesystem 73 | ; 74 | -------------------------------------------------------------------------------- /doc/Jamfile.jam: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Klemens D. Morgenstern 2 | # Distributed under the Boost Software License, Version 1.0. 3 | # https://www.boost.org/LICENSE_1_0.txt 4 | 5 | import asciidoctor ; 6 | 7 | html index.html : index.adoc ; 8 | 9 | install html_ : index.html : html ; 10 | 11 | pdf process.pdf : index.adoc ; 12 | explicit process.pdf ; 13 | 14 | install pdf_ : process.pdf : pdf ; 15 | explicit pdf_ ; 16 | 17 | install images 18 | : 19 | images/posix_exec_err.svg 20 | images/posix_fork_err.svg 21 | images/posix_success.svg 22 | images/windows_exec.svg 23 | : 24 | html/images 25 | ; 26 | 27 | alias boostdoc ; 28 | explicit boostdoc ; 29 | alias boostrelease : html_ ; 30 | explicit boostrelease ; 31 | 32 | -------------------------------------------------------------------------------- /doc/acknowledgements.adoc: -------------------------------------------------------------------------------- 1 | = Acknowledgements 2 | 3 | The first Boost.Process draft was created in 2006. A lof of people have worked on various drafts since then. Especially Merino Vidal, Ilya Sokolov and Felipe Tanus spent a lot of time working on early drafts. They influenced Boost.Process over the years and wrote code which, to various extents, is still around in the library today. 4 | 5 | The design of earlier versions of Boost.Process was not always satisfying. In 2011 Jeff Flinn proposed the executor and initializer concepts Boost.Process is based on today. Without Jeff's idea the overall design of Boost.Process would not look like it does today. 6 | 7 | A special thank you goes to [http://www.intra2net.com/(Intra2net AG) (especially Thomas Jarosch) who sponsored a project to support the development of Boost.Process. It was this sponsorship which made it possible to create a new Boost.Process version in 2012. 8 | 9 | Great thanks also goes to Boris Schaeling, who despite having boost.process rejected, went on to work on it and maintained it up until this day and participated in the development of the current version. 10 | 11 | Many Thanks, to [https://github.com/time-killer-games](Samuel Venable) for contributing the <> functionality and all the research that went into it. 12 | 13 | 14 | -------------------------------------------------------------------------------- /doc/configuration.adoc: -------------------------------------------------------------------------------- 1 | = Configuration 2 | 3 | Boost process v2 can be configured in the following ways: 4 | 5 | [cols="1,1"] 6 | |=== 7 | | Macro | Description 8 | 9 | | `BOOST_PROCESS_V2_STANDALONE` | Build boost.process for standalone asio 10 | | `BOOST_PROCESS_USE_STD_FS` | Use std::filesystem instead of boost::filesystem 11 | | `BOOST_PROCESS_V2_POSIX_FORCE_DISABLE_CLOSE_RANGE` | Disable usage of `close_range`. 12 | -------------------------------------------------------------------------------- /doc/env.adoc: -------------------------------------------------------------------------------- 1 | == Environment 2 | 3 | The `environment` namespace provides all sorts of facilities to query and manipulate the environment of the current process. 4 | 5 | The api should be straight forward, but one oddity that needs to be pointed out is, that environment names 6 | are not case sensitive on windows. The key_traits class implements the proper traits depending on the current system. 7 | 8 | Additionally, environment can be lists separated by `:` or `;`; `environment::value` and 9 | `environment::value_view` can be used to iterate those. 10 | 11 | Beyond that, the requirements on an environment are a low as possible; 12 | an environment is either a list of strings or a list of string-pairs. It is however recommended to use the environment types, 13 | as to have the right value comparisons. 14 | 15 | To note is the `find_executable` functions, which searches in an environment for an executable. 16 | 17 | .example/env.cpp:19-28 18 | [source,cpp] 19 | ---- 20 | include::../example/env.cpp[tag=current_env] 21 | ---- 22 | 23 | == Subprocess environment 24 | 25 | The subprocess environment assignment follows the same constraints: 26 | 27 | .example/env.cpp:34-42 28 | [source,cpp,ident=0] 29 | ---- 30 | include::../example/env.cpp[tag=subprocess_env] 31 | ---- 32 | -------------------------------------------------------------------------------- /doc/index.adoc: -------------------------------------------------------------------------------- 1 | = boost.process 2 | Klemens Morgenstern 3 | Version 2.0, 19.11.2024 4 | :source-highlighter: rouge 5 | :toc: left 6 | :toclevels: 4 7 | :icons: font 8 | :idprefix: 9 | :docinfo: private-footer 10 | :source-highlighter: rouge 11 | :source-language: c++ 12 | :example-caption: Example 13 | 14 | :imagesdir: ./images 15 | 16 | :leveloffset: +1 17 | 18 | include::quickstart.adoc[] 19 | include::launcher.adoc[] 20 | 21 | = Initializers 22 | 23 | include::start_dir.adoc[] 24 | include::stdio.adoc[] 25 | include::env.adoc[] 26 | 27 | = Reference 28 | 29 | 30 | include::reference/bind_launcher.adoc[] 31 | include::reference/cstring_ref.adoc[] 32 | include::reference/default_launcher.adoc[] 33 | include::reference/environment.adoc[] 34 | include::reference/error.adoc[] 35 | include::reference/execute.adoc[] 36 | include::reference/exit_code.adoc[] 37 | include::reference/ext.adoc[] 38 | include::reference/pid.adoc[] 39 | include::reference/popen.adoc[] 40 | include::reference/process.adoc[] 41 | include::reference/process_handle.adoc[] 42 | include::reference/shell.adoc[] 43 | include::reference/start_dir.adoc[] 44 | include::reference/stdio.adoc[] 45 | include::reference/ext.adoc[] 46 | include::reference/posix/bind_fd.adoc[] 47 | include::reference/windows/creation_flags.adoc[] 48 | include::reference/windows/show_window.adoc[] 49 | 50 | include::version2.adoc[] 51 | include::acknowledgements.adoc[] -------------------------------------------------------------------------------- /doc/reference/bind_launcher.adoc: -------------------------------------------------------------------------------- 1 | == `bind_launcher.hpp` 2 | 3 | The `bind_launcher` utlitities allow on the fly construction of a launcher with bound initializers. 4 | 5 | [source,cpp] 6 | ---- 7 | // Creates a new launcher with the bound initializer. 8 | template 9 | auto bind_launcher(Launcher && launcher, Init && ... init); 10 | 11 | // Calls bind_launcher with the default_launcher as the first parameter. 12 | // The new launcher with bound parameters 13 | template 14 | auto bind_default_launcher(Init && ... init); 15 | ---- 16 | 17 | -------------------------------------------------------------------------------- /doc/reference/cstring_ref.adoc: -------------------------------------------------------------------------------- 1 | == `cstring_ref.hpp` 2 | 3 | The `cstring_ref` is a string-view like type that holds a null-terminated string. -------------------------------------------------------------------------------- /doc/reference/default_launcher.adoc: -------------------------------------------------------------------------------- 1 | == `default_launcher.hpp` 2 | [#default_launcher] 3 | 4 | The `default_launcher` is the standard way of creating a process. 5 | 6 | [source,cpp] 7 | ---- 8 | asio::io_context ctx; 9 | process proc(ctx.get_executor(), "test", {}); 10 | // equivalent to 11 | process prod = default_launcher()(ctx.get_executor(), "test", {}); 12 | ---- 13 | 14 | It has four overloads: 15 | 16 | [source,cpp] 17 | ---- 18 | (ExecutionContext &, filesystem::path, Args && args, Inits && ... inits) -> basic_process 19 | (Executor &, filesystem::path, Args && args, Inits && ... inits) -> basic_process; 20 | (ExecutionContext &, error_code&, filesystem::path, Args && args, Inits && ... inits) -> basic_process;` 21 | (Executor &, error_code&, filesystem::path, Args && args, Inits && ... inits) -> basic_process 22 | ---- 23 | -------------------------------------------------------------------------------- /doc/reference/error.adoc: -------------------------------------------------------------------------------- 1 | == `error.hpp` 2 | [#error] 3 | 4 | The error header provides two error categories: 5 | 6 | [source,cpp] 7 | ---- 8 | // Errors used for utf8 <-> UCS-2 conversions. 9 | enum utf8_conv_error 10 | { 11 | insufficient_buffer = 1, 12 | invalid_character, 13 | }; 14 | 15 | extern const error_category& get_utf8_category(); 16 | static const error_category& utf8_category = get_utf8_category(); 17 | 18 | extern const error_category& get_exit_code_category(); 19 | 20 | /// An error category that can be used to interpret exit codes of subprocesses. 21 | static const error_category& exit_code_category = get_exit_code_category(); 22 | 23 | } 24 | ---- 25 | 26 | The `get_exit_code_category` can be used as follows: 27 | 28 | [source,cpp] 29 | ---- 30 | void run_my_process(filesystem::path pt, error_code & ec) 31 | { 32 | process proc(pt, {}); 33 | proc.wait(); 34 | ec.assign(proc.native_exit_code(), error::get_exit_code_category()); 35 | } 36 | ---- -------------------------------------------------------------------------------- /doc/reference/execute.adoc: -------------------------------------------------------------------------------- 1 | 2 | == `execute.hpp` 3 | [#execute] 4 | 5 | The execute header provides two error categories: 6 | 7 | [source,cpp] 8 | ---- 9 | 10 | // Run a process and wait for it to complete. 11 | template int execute(basic_process proc); 12 | template int execute(basic_process proc, error_code & ec) 13 | 14 | // Execute a process asynchronously 15 | template> 18 | auto async_execute(basic_process proc, 19 | WaitHandler && handler = net::default_completion_token_t()); 20 | ---- 21 | 22 | The `async_execute` function asynchronously for a process to complete. 23 | 24 | Cancelling the execution will signal the child process to exit 25 | with the following interpretations: 26 | 27 | - `cancellation_type::total` -> interrupt 28 | - `cancellation_type::partial` -> request_exit 29 | - `cancellation_type::terminal` -> terminate 30 | 31 | It is to note that `async_execute` will use the lowest selected cancellation 32 | type. A subprocess might ignore anything not terminal. 33 | 34 | -------------------------------------------------------------------------------- /doc/reference/exit_code.adoc: -------------------------------------------------------------------------------- 1 | == `exit_code.hpp` 2 | [#exit_code] 3 | 4 | The exit code header provides portable handles for exit codes. 5 | 6 | [source,cpp] 7 | ---- 8 | // The native exit-code type, usually an integral value 9 | /* The OS may have a value different from `int` to represent 10 | * the exit codes of subprocesses. It might also 11 | * contain additional information. 12 | */ 13 | typedef implementation_defined native_exit_code_type; 14 | 15 | 16 | // Check if the native exit code indicates the process is still running 17 | bool process_is_running(native_exit_code_type code); 18 | 19 | // Obtain the portable part of the exit code, i.e. what the subprocess has returned from main. 20 | int evaluate_exit_code(native_exit_code_type code); 21 | 22 | // Helper to subsume an exit-code into an error_code if there's no actual error isn't set. 23 | error_code check_exit_code( 24 | error_code &ec, native_exit_code_type native_code, 25 | const error_category & category = error::get_exit_code_category()); 26 | ---- 27 | 28 | 29 | The `check_exit_code` can be used like this: 30 | 31 | [source,cpp] 32 | ---- 33 | 34 | process proc{co_await this_coro::executor, "exit", {"1"}}; 35 | 36 | co_await proc.async_wait( 37 | asio::deferred( 38 | [&proc](error_code ec, int) 39 | { 40 | return asio::deferred.values( 41 | check_exit_code(ec, proc.native_exit_code()) 42 | ); 43 | ---- 44 | -------------------------------------------------------------------------------- /doc/reference/ext.adoc: -------------------------------------------------------------------------------- 1 | == `ext` 2 | 3 | The headers in `process/ext` provides features to obtain information about third part processes. 4 | 5 | [source,cpp] 6 | ---- 7 | // Get the cmd line used to launche the process 8 | template 9 | shell cmd(basic_process_handle & handle, error_code & ec); 10 | template 11 | shell cmd(basic_process_handle & handle); 12 | shell cmd(pid_type pid, error_code & ec); 13 | shell cmd(pid_type pid); 14 | 15 | 16 | // Get the current working directory of the process. 17 | template 18 | filesystem::path cwd(basic_process_handle & handle, error_code & ec); 19 | template 20 | filesystem::path cwd(basic_process_handle & handle) 21 | filesystem::path cwd(pid_type pid, error_code & ec); 22 | filesystem::path cwd(pid_type pid); 23 | 24 | 25 | // Get the current environment of the process. 26 | template 27 | env_view cwd(basic_process_handle & handle, error_code & ec); 28 | template 29 | env_view cwd(basic_process_handle & handle) 30 | env_view env(pid_type pid, error_code & ec); 31 | env_view env(pid_type pid); 32 | 33 | 34 | // Get the executable of the process. 35 | template 36 | filesystem::path exe(basic_process_handle & handle, error_code & ec); 37 | template 38 | filesystem::path exe(basic_process_handle & handle) 39 | filesystem::path exe(pid_type pid, error_code & ec); 40 | filesystem::path exe(pid_type pid); 41 | ---- 42 | 43 | WARNING: The function may fail with "operation_not_supported" on some niche platforms. 44 | 45 | NOTE: On windows overloads taking a `HANDLE` are also available. 46 | 47 | -------------------------------------------------------------------------------- /doc/reference/pid.adoc: -------------------------------------------------------------------------------- 1 | == `pid.hpp` 2 | [#pid] 3 | 4 | [source,cpp] 5 | ---- 6 | //An integral type representing a process id. 7 | typedef implementation_defined pid_type; 8 | 9 | // Get the process id of the current process. 10 | pid_type current_pid(); 11 | 12 | // List all available pids. 13 | std::vector all_pids(boost::system::error_code & ec); 14 | std::vector all_pids(); 15 | 16 | // return parent pid of pid. 17 | pid_type parent_pid(pid_type pid, boost::system::error_code & ec); 18 | pid_type parent_pid(pid_type pid); 19 | 20 | // return child pids of pid. 21 | std::vector child_pids(pid_type pid, boost::system::error_code & ec); 22 | std::vector child_pids(pid_type pid); 23 | ---- 24 | -------------------------------------------------------------------------------- /doc/reference/posix/bind_fd.adoc: -------------------------------------------------------------------------------- 1 | == `posix/bind_fd.hpp` 2 | 3 | `bind_fd` is a utility class to bind a file descriptor to an explicit file descriptor for the child process. 4 | 5 | [source,cpp] 6 | ---- 7 | struct bind_fd 8 | { 9 | // Inherit file descriptor with the same value. 10 | /* 11 | * This will pass descriptor 42 as 42 to the child process: 12 | * @code 13 | * process p{"test", {}, posix::bind_fd(42)}; 14 | * @endcode 15 | */ 16 | bind_fd(int target); 17 | 18 | // Inherit an asio io-object as a given file descriptor to the child process. 19 | /* 20 | * This will pass the tcp::socket, as 42 to the child process: 21 | * @code 22 | * extern tcp::socket sock; 23 | * process p{"test", {}, posix::bind_fd(42, sock)}; 24 | * @endcode 25 | */ 26 | 27 | template 28 | bind_fd(int target, Stream && str); 29 | 30 | // Inherit a `FILE` as a given file descriptor to the child process. 31 | /* This will pass the given `FILE*`, as 42 to the child process: 32 | 33 | process p{"test", {}, posix::bind_fd(42, stderr)}; 34 | 35 | */ 36 | bind_fd(int target, FILE * f); 37 | 38 | // Inherit a file descriptor with as a different value. 39 | /* This will pass 24 as 42 to the child process: 40 | 41 | process p{"test", {}, posix::bind_fd(42, 24)}; 42 | 43 | */ 44 | bind_fd(int target, int fd): 45 | 46 | // Inherit a null device as a set descriptor. 47 | /* This will a null device as 42 to the child process: 48 | 49 | process p{"test", {}, posix::bind_fd(42, nullptr)}; 50 | 51 | */ 52 | bind_fd(int target, std::nullptr_t); 53 | 54 | // Inherit a newly opened-file as a set descriptor. 55 | /* This will pass a descriptor to "extra-output.txt" as 42 to the child process: 56 | 57 | process p{"test", {}, posix::bind_fd(42, "extra-output.txt")}; 58 | 59 | */ 60 | bind_fd(int target, const filesystem::path & pth, int flags = O_RDWR | O_CREAT); 61 | 62 | }; 63 | ---- 64 | 65 | Using `bind_fd` can be used to inherit file descriptors explicitly, because no unused one will be. 66 | 67 | [source,cpp] 68 | ---- 69 | 70 | ---- 71 | -------------------------------------------------------------------------------- /doc/reference/shell.adoc: -------------------------------------------------------------------------------- 1 | == `shell.hpp` 2 | [#shell] 3 | 4 | This utility class parses command lines into tokens 5 | and allows users to execute processes based on textual inputs. 6 | 7 | In v1, this was possible directly when starting a process, 8 | but has been removed based on the security risks associated with this. 9 | 10 | By making the shell parsing explicitly, it encourages 11 | a user to run a sanity check on the executable before launching it. 12 | 13 | .Example 14 | [source,cpp] 15 | ---- 16 | asio::io_context ctx; 17 | 18 | auto cmd = shell("my-app --help"); 19 | auto exe = cmd.exe(); 20 | check_if_malicious(exe); 21 | 22 | process proc{ctx, exe, cmd.args()}; 23 | 24 | ---- 25 | 26 | [source,cpp] 27 | ---- 28 | /// Utility to parse commands 29 | struct shell 30 | { 31 | shell() = default; 32 | template 33 | shell(basic_string_view input); 34 | 35 | shell(basic_cstring_ref input); 36 | shell(const shell &) = delete; 37 | shell(shell && lhs) noexcept; 38 | shell& operator=(const shell &) = delete; 39 | shell& operator=(shell && lhs) noexcept; 40 | 41 | 42 | // the length of the parsed shell, including the executable 43 | int argc() const ; 44 | char_type** argv() const; 45 | 46 | char_type** begin() const; 47 | char_type** end() const; 48 | 49 | bool empty() const; 50 | std::size_t size() const; 51 | 52 | // Native representation of the arguments to be used - excluding the executable 53 | args_type args() const; 54 | template 55 | filesystem::path exe(Environment && env = environment::current()) const; 56 | }; 57 | ---- -------------------------------------------------------------------------------- /doc/reference/start_dir.adoc: -------------------------------------------------------------------------------- 1 | == `start_dir.hpp` 2 | [#start_dir] 3 | 4 | 5 | [source,cpp] 6 | ---- 7 | /// Initializer for the starting directory of a subprocess to be launched. 8 | struct process_start_dir 9 | { 10 | filesystem::path start_dir; 11 | 12 | process_start_dir(filesystem::path start_dir); 13 | { 14 | } 15 | }; 16 | ---- -------------------------------------------------------------------------------- /doc/reference/stdio.adoc: -------------------------------------------------------------------------------- 1 | == `stdio.hpp` 2 | [#stdio] 3 | 4 | The initializer for the stdio of a subprocess 5 | The subprocess stdio initializer has three members: 6 | 7 | - in for stdin 8 | - out for stdout 9 | - err for stderr 10 | 11 | If the initializer is present all three will be set for the subprocess. 12 | By default they will inherit the stdio handles from the parent process. 13 | This means that this will forward stdio to the subprocess: 14 | 15 | [source,cpp] 16 | ---- 17 | asio::io_context ctx; 18 | v2::process proc(ctx, "/bin/bash", {}, v2::process_stdio{}); 19 | ---- 20 | 21 | No constructors are provided in order to support designated initializers 22 | in later version of C++. 23 | 24 | [source,cpp] 25 | ---- 26 | asio::io_context ctx; 27 | 28 | /// C++17 29 | v2::process proc17(ctx, "/bin/bash", {}, v2::process_stdio{.stderr=nullptr}); 30 | /// C++11 & C++14 31 | v2::process proc17(ctx, "/bin/bash", {}, v2::process_stdio{ {}, {}, nullptr}); 32 | ---- 33 | 34 | Valid initializers for any stdio are: 35 | 36 | - `std::nullptr_t` assigning a null-device 37 | - `FILE*` any open file, including `stdin`, `stdout` and `stderr` 38 | - a filesystem::path, which will open a readable or writable depending on the direction of the stream 39 | - `native_handle` any native file handle (`HANDLE` on windows) or file descriptor (`int` on posix) 40 | - any io-object with a .native_handle() function that is compatible with the above. E.g. a asio::ip::tcp::socket 41 | - an asio::basic_writeable_pipe for stdin or asio::basic_readable_pipe for stderr/stdout. 42 | 43 | 44 | 45 | 46 | [source,cpp] 47 | ---- 48 | /// The initializer for the stdio of a subprocess 49 | struct process_stdio 50 | { 51 | __implementation_defined__ in; 52 | __implementation_defined__ out; 53 | __implementation_defined__ err; 54 | }; 55 | ---- -------------------------------------------------------------------------------- /doc/reference/windows/creation_flags.adoc: -------------------------------------------------------------------------------- 1 | == `windows/creation_flags.hpp` 2 | 3 | Creation flags allows explicitly setting `dwFlags` 4 | 5 | [source,cpp] 6 | ---- 7 | // An initializer to add to the dwFlags in the startup-info 8 | template 9 | struct process_creation_flags; 10 | 11 | // A flag to create a new process group. Necessary to allow interrupts for the subprocess. 12 | constexpr static process_creation_flags create_new_process_group; 13 | 14 | // Breakaway from the current job object. 15 | constexpr static process_creation_flags create_breakaway_from_job; 16 | // Allocate a new console. 17 | constexpr static process_creation_flags create_new_console; 18 | 19 | ---- 20 | 21 | 22 | The flags can be used like this: 23 | 24 | [source,cpp] 25 | ---- 26 | process p{"C:\\not-a-virus.exe", {}, process::windows::create_new_console}; 27 | ---- -------------------------------------------------------------------------------- /doc/reference/windows/show_window.adoc: -------------------------------------------------------------------------------- 1 | == `windows/show_window.hpp` 2 | 3 | Creation flags allows explicitly setting `wShowWindow` options 4 | 5 | [source,cpp] 6 | ---- 7 | /// A templated initializer to set wShowWindow flags. 8 | template 9 | struct process_show_window; 10 | 11 | //Hides the window and activates another window. 12 | constexpr static process_show_window show_window_hide; 13 | //Activates the window and displays it as a maximized window. 14 | constexpr static process_show_window show_window_maximized; 15 | //Activates the window and displays it as a minimized window. 16 | constexpr static process_show_window show_window_minimized; 17 | //Displays the window as a minimized window. This value is similar to `minimized`, except the window is not activated. 18 | constexpr static process_show_window show_window_minimized_not_active; 19 | //Displays a window in its most recent size and position. This value is similar to show_normal`, except that the window is not activated. 20 | constexpr static process_show_window show_window_not_active; 21 | //Activates and displays a window. If the window is minimized or maximized, the system restores it to its original size and position. An application should specify this flag when displaying the window for the first time. 22 | constexpr static process_show_window show_window_normal; 23 | 24 | ---- 25 | 26 | 27 | The flags can be used like this: 28 | 29 | [source,cpp] 30 | ---- 31 | process p{"C:\\not-a-virus.exe", {}, process::windows::show_window_minimized}; 32 | ---- -------------------------------------------------------------------------------- /doc/start_dir.adoc: -------------------------------------------------------------------------------- 1 | == `process_start_dir` 2 | 3 | The easier initializer to use is `process_start_dir`: 4 | 5 | .example/start_dir.cpp:17-20 6 | [source,cpp,indent=0] 7 | ---- 8 | include::../example/start_dir.cpp[tag=start_dir] 9 | ---- 10 | 11 | This will run `ls` in the folder `/home` instead of the current folder. 12 | 13 | WARNING: If your path is relative, it may fail on posix, because the directory is changed before a call to execve. -------------------------------------------------------------------------------- /doc/stdio.adoc: -------------------------------------------------------------------------------- 1 | = stdio 2 | 3 | When using io with a subprocess, all three standard streams (stdin, stdout, stderr) get set for the child-process. 4 | The default setting is to inherit the parent process. 5 | 6 | This feature meant to be flexible, which is why there is little checking on the arguments assigned to one of those streams. 7 | 8 | == Pipes 9 | 10 | asio pipes can be used for io. When using in process_stdio they will get 11 | automatically connected and the other side will get assigned to the child process: 12 | 13 | .example/stdio.cpp:20-29 14 | [source,cpp,indent=0] 15 | ---- 16 | include::../example/stdio.cpp[tag=readable_pipe] 17 | ---- 18 | 19 | readable pipes can be assigned to `out` and `err`, while writable_pipes can be assigned to `in`. 20 | 21 | == `FILE*` 22 | 23 | `FILE*` can also be used for either side; this allows the `stdin`, `stderr`, `stdout` macros to be used: 24 | 25 | .example/stdio.cpp:35-38 26 | [source,cpp] 27 | ---- 28 | include::../example/stdio.cpp[tag=file] 29 | ---- 30 | 31 | == `nullptr` 32 | 33 | `nullptr` may be used to set a given stream to be opened on the null-device (`/dev/null` on posix, `NUL` on windows). 34 | This is used to ignore output or give only EOF as input. 35 | 36 | .example/stdio.cpp:43-46 37 | [source,cpp] 38 | ---- 39 | include::../example/stdio.cpp[tag=null] 40 | ---- 41 | 42 | == `native_handle` 43 | 44 | A native handle can be used as well, which means an `int` on posix or a `HANDLE` on windows. 45 | Furthermore, any object that has a `native_handle` function which returns a valid type for a stdio stream. 46 | 47 | E.g. a domain socket on linux. 48 | 49 | .example/stdio.cpp:52-57 50 | [source,cpp] 51 | ---- 52 | include::../example/stdio.cpp[tag=native_handle] 53 | ---- 54 | 55 | == popen 56 | 57 | Additionally, process v2 provides a `popen` class. 58 | It starts a process and connects pipes for stdin and stdout, so that the popen object can be used as a stream. 59 | 60 | .example/stdio.cpp:63-66 61 | [source,cpp] 62 | ---- 63 | include::../example/stdio.cpp[tag=popen] 64 | ---- 65 | 66 | -------------------------------------------------------------------------------- /example/Jamfile.jam: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2022 Klemens Morgenstern 2 | # 3 | # Distributed under the Boost Software License, Version 1.0. (See accompanying 4 | # file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | project : requirements 7 | msvc:_SCL_SECURE_NO_WARNINGS 8 | windows:WIN32_LEAN_AND_MEAN 9 | static 10 | ; 11 | 12 | import testing ; 13 | 14 | exe intro : intro.cpp /boost//process : boost ; 15 | exe intro_popen : intro_popen.cpp /boost//process : boost ; 16 | exe quickstart : quickstart.cpp /boost//process : boost ; 17 | exe env : env.cpp /boost//process : boost ; 18 | exe start_dir : start_dir.cpp /boost//process : boost ; 19 | exe stdio : stdio.cpp /boost//process : boost ; 20 | -------------------------------------------------------------------------------- /example/env.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2006, 2007 Julio M. Merino Vidal 2 | // Copyright (c) 2008 Ilya Sokolov, Boris Schaeling 3 | // Copyright (c) 2009 Boris Schaeling 4 | // Copyright (c) 2010 Felipe Tanus, Boris Schaeling 5 | // Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling 6 | // 7 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 8 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 9 | 10 | #include 11 | #include 12 | 13 | using namespace boost::process; 14 | namespace asio = boost::asio; 15 | 16 | int main() 17 | { 18 | { // tag::current_env[] 19 | // search in the current environment 20 | auto exe = environment::find_executable("g++"); 21 | 22 | std::unordered_map my_env = 23 | { 24 | {"SECRET", "THIS_IS_A_TEST"}, 25 | {"PATH", {"/bin", "/usr/bin"}} 26 | }; 27 | 28 | auto other_exe = environment::find_executable("g++", my_env); 29 | //end::current_env[] 30 | } 31 | 32 | { 33 | // tag::subprocess_env[] 34 | asio::io_context ctx; 35 | std::unordered_map my_env = 36 | { 37 | {"SECRET", "THIS_IS_A_TEST"}, 38 | {"PATH", {"/bin", "/usr/bin"}} 39 | }; 40 | auto exe = environment::find_executable("g++", my_env); 41 | process proc(ctx, exe, {"main.cpp"}, process_environment(my_env)); 42 | process pro2(ctx, exe, {"test.cpp"}, process_environment(my_env)); 43 | // end::subprocess_env[] 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /example/intro.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022 Klemens Morgenstern 2 | // 3 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 4 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | //[intro 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | 16 | namespace proc = boost::process; 17 | namespace asio = boost::asio; 18 | 19 | 20 | int main() 21 | { 22 | asio::io_context ctx; 23 | asio::readable_pipe p{ctx}; 24 | 25 | const auto exe = proc::environment::find_executable("gcc"); 26 | 27 | proc::process c{ctx, exe, {"--version"}, proc::process_stdio{nullptr, p}}; 28 | 29 | std::string line; 30 | boost::system::error_code ec; 31 | 32 | auto sz = asio::read(p, asio::dynamic_buffer(line), ec); 33 | assert(ec == asio::error::eof); 34 | 35 | std::cout << "Gcc version: '" << line << "'" << std::endl; 36 | 37 | c.wait(); 38 | return c.exit_code(); 39 | } 40 | //] 41 | -------------------------------------------------------------------------------- /example/intro_popen.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022Klemens Morgenstern 2 | // 3 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 4 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | #include 7 | 8 | //[intro 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | 18 | namespace proc = boost::process; 19 | namespace asio = boost::asio; 20 | 21 | 22 | int main() 23 | { 24 | asio::io_context ctx; 25 | const auto exe = proc::environment::find_executable("gcc"); 26 | proc::popen c{ctx, exe, {"--version"}}; 27 | 28 | std::string line; 29 | boost::system::error_code ec; 30 | 31 | auto sz = asio::read(c, asio::dynamic_buffer(line), ec); 32 | assert(ec == asio::error::eof); 33 | 34 | boost::ignore_unused(sz); 35 | 36 | std::cout << "Gcc version: '" << line << "'" << std::endl; 37 | 38 | c.wait(); 39 | return c.exit_code(); 40 | } 41 | //] 42 | -------------------------------------------------------------------------------- /example/quickstart.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace asio = boost::asio; 5 | using boost::process::process; 6 | 7 | 8 | int main(int /*argv*/, char ** /*argv*/) 9 | { 10 | asio::io_context ctx; 11 | { 12 | //tag::cp[] 13 | // process(asio::any_io_executor, filesystem::path, range args, AdditionalInitializers...) 14 | process proc(ctx.get_executor(), // <1> 15 | "/usr/bin/cp", // <2> 16 | {"source.txt", "target.txt"} // <3> 17 | ); // <4> 18 | //end::cp[] 19 | } 20 | { 21 | //tag::ls[] 22 | process proc(ctx, "/bin/ls", {}); 23 | assert(proc.wait() == 0); 24 | //end::ls[] 25 | } 26 | { 27 | //tag::terminate[] 28 | process proc(ctx, "/bin/totally-not-a-virus", {}); 29 | proc.terminate(); 30 | //end::terminate[] 31 | } 32 | { 33 | //tag::request_exit[] 34 | process proc(ctx, "/bin/bash", {}); 35 | proc.request_exit(); 36 | proc.wait(); 37 | //end::request_exit[] 38 | } 39 | { 40 | //tag::interrupt[] 41 | process proc(ctx, "/usr/bin/addr2line", {}); 42 | proc.interrupt(); 43 | proc.wait(); 44 | //end::interrupt[] 45 | } 46 | { 47 | //tag::execute[] 48 | assert(execute(process(ctx, "/bin/ls", {})) == 0); 49 | //end::execute[] 50 | } 51 | { 52 | //tag::async_execute[] 53 | async_execute(process(ctx, "/usr/bin/g++", {"hello_world.cpp"})) 54 | (asio::cancel_after(std::chrono::seconds(10), asio::cancellation_type::partial)) // <1> 55 | (asio::cancel_after(std::chrono::seconds(10), asio::cancellation_type::terminal)) //<2> 56 | (asio::detached); 57 | //end::async_execute[] 58 | ctx.run(); 59 | } 60 | return 0; 61 | } 62 | 63 | 64 | -------------------------------------------------------------------------------- /example/start_dir.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2006, 2007 Julio M. Merino Vidal 2 | // Copyright (c) 2008 Ilya Sokolov, Boris Schaeling 3 | // Copyright (c) 2009 Boris Schaeling 4 | // Copyright (c) 2010 Felipe Tanus, Boris Schaeling 5 | // Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling 6 | // 7 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 8 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 9 | 10 | #include 11 | 12 | using namespace boost::process; 13 | namespace asio = boost::asio; 14 | 15 | int main() 16 | { 17 | // tag::start_dir[] 18 | asio::io_context ctx; 19 | process ls(ctx.get_executor(), "/ls", {}, process_start_dir("/home")); 20 | ls.wait(); 21 | // end::start_dir[] 22 | } 23 | -------------------------------------------------------------------------------- /example/stdio.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2006, 2007 Julio M. Merino Vidal 2 | // Copyright (c) 2008 Ilya Sokolov, Boris Schaeling 3 | // Copyright (c) 2009 Boris Schaeling 4 | // Copyright (c) 2010 Felipe Tanus, Boris Schaeling 5 | // Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling 6 | // 7 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 8 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 9 | 10 | #include 11 | #include 12 | 13 | using namespace boost::process; 14 | namespace asio = boost::asio; 15 | 16 | int main(int argc, char *argv[]) 17 | { 18 | { 19 | //tag::readable_pipe[] 20 | asio::io_context ctx; 21 | asio::readable_pipe rp{ctx}; 22 | 23 | process proc(ctx, "/usr/bin/g++", {"--version"}, process_stdio{{ /* in to default */}, rp, { /* err to default */ }}); 24 | std::string output; 25 | 26 | boost::system::error_code ec; 27 | asio::read(rp, asio::dynamic_buffer(output), ec); 28 | assert(!ec || (ec == asio::error::eof)); 29 | proc.wait(); 30 | //end::readable_pipe[] 31 | } 32 | 33 | { 34 | //tag::file[] 35 | asio::io_context ctx; 36 | // forward both stderr & stdout to stdout of the parent process 37 | process proc(ctx, "/usr/bin/g++", {"--version"}, process_stdio{{ /* in to default */}, stdout, stdout}); 38 | proc.wait(); 39 | //end::file[] 40 | } 41 | { 42 | //tag::null[] 43 | asio::io_context ctx; 44 | // forward stderr to /dev/null or NUL 45 | process proc(ctx, "/usr/bin/g++", {"--version"}, process_stdio{{ /* in to default */}, {}, nullptr}); 46 | proc.wait(); 47 | //end::null[] 48 | } 49 | #if defined(BOOST_POSIX_API) 50 | { 51 | //tag::native_handle[] 52 | asio::io_context ctx; 53 | // ignore stderr 54 | asio::local::stream_protocol::socket sock{ctx}, other{ctx}; 55 | asio::local::connect_pair(sock, other); 56 | process proc(ctx, "~/not-a-virus", {}, process_stdio{sock, sock, nullptr}); 57 | proc.wait(); 58 | //end::native_handle[] 59 | } 60 | #endif 61 | { 62 | //tag::popen[] 63 | asio::io_context ctx; 64 | boost::process::popen proc(ctx, "/usr/bin/addr2line", {argv[0]}); 65 | asio::write(proc, asio::buffer("main\n")); 66 | std::string line; 67 | asio::read_until(proc, asio::dynamic_buffer(line), '\n'); 68 | //end::popen[] 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /filter_section_warning.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # 3 | 4 | import sys 5 | 6 | for line in sys.stdin: 7 | # If line is a 'noisy' warning, don't print it or the following two lines. 8 | if ('warning: section' in line and 'is deprecated' in line 9 | or 'note: change section name to' in line): 10 | next(sys.stdin) 11 | next(sys.stdin) 12 | else: 13 | sys.stdout.write(line) 14 | sys.stdout.flush() -------------------------------------------------------------------------------- /include/boost/process.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2006, 2007 Julio M. Merino Vidal 2 | // Copyright (c) 2008 Ilya Sokolov, Boris Schaeling 3 | // Copyright (c) 2009 Boris Schaeling 4 | // Copyright (c) 2010 Felipe Tanus, Boris Schaeling 5 | // Copyright (c) 2011 Jeff Flinn, Boris Schaeling 6 | // Copyright (c) 2012 Boris Schaeling 7 | // Copyright (c) 2016 Klemens D. Morgenstern 8 | // 9 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 10 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 11 | 12 | #ifndef BOOST_PROCESS_HPP 13 | #define BOOST_PROCESS_HPP 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /include/boost/process/bind_launcher.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /include/boost/process/cstring_ref.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /include/boost/process/default_launcher.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /include/boost/process/environment.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /include/boost/process/error.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /include/boost/process/execute.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /include/boost/process/exit_code.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /include/boost/process/ext.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /include/boost/process/ext/cmd.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /include/boost/process/ext/cwd.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /include/boost/process/ext/env.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /include/boost/process/ext/exe.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /include/boost/process/pid.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /include/boost/process/popen.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /include/boost/process/posix/bind_fd.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /include/boost/process/posix/default_launcher.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /include/boost/process/posix/fork_and_forget_launcher.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /include/boost/process/posix/pdfork_launcher.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /include/boost/process/posix/vfork_launcher.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /include/boost/process/process.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /include/boost/process/process_handle.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /include/boost/process/shell.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /include/boost/process/start_dir.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /include/boost/process/stdio.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /include/boost/process/v1/detail/handler.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 Klemens D. Morgenstern 2 | // 3 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 4 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | 7 | #ifndef BOOST_PROCESS_DETAIL_HANDLER_HPP_ 8 | #define BOOST_PROCESS_DETAIL_HANDLER_HPP_ 9 | 10 | #include 11 | 12 | #if defined(BOOST_POSIX_API) 13 | #include 14 | #elif defined(BOOST_WINDOWS_API) 15 | #include 16 | #endif 17 | 18 | 19 | namespace boost { namespace process { BOOST_PROCESS_V1_INLINE namespace v1 { namespace detail { 20 | 21 | //extended handler base. 22 | typedef api::handler_base_ext handler; 23 | 24 | 25 | template 26 | struct on_setup_ : handler 27 | { 28 | explicit on_setup_(Handler handler) : handler_(handler) {} 29 | 30 | template 31 | void on_setup(Executor &e) 32 | { 33 | handler_(e); 34 | } 35 | private: 36 | Handler handler_; 37 | }; 38 | 39 | template 40 | struct on_error_ : handler 41 | { 42 | explicit on_error_(Handler handler) : handler_(handler) {} 43 | 44 | template 45 | void on_error(Executor &e, const std::error_code &ec) 46 | { 47 | handler_(e, ec); 48 | } 49 | private: 50 | Handler handler_; 51 | }; 52 | 53 | template 54 | struct on_success_ : handler 55 | { 56 | explicit on_success_(Handler handler) : handler_(handler) {} 57 | 58 | template 59 | void on_success(Executor &e) 60 | { 61 | handler_(e); 62 | } 63 | private: 64 | Handler handler_; 65 | }; 66 | 67 | } 68 | 69 | 70 | 71 | }}} 72 | 73 | #endif /* BOOST_PROCESS_DETAIL_HANDLER_HPP_ */ 74 | -------------------------------------------------------------------------------- /include/boost/process/v1/detail/handler_base.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2006, 2007 Julio M. Merino Vidal 2 | // Copyright (c) 2008 Ilya Sokolov, Boris Schaeling 3 | // Copyright (c) 2009 Boris Schaeling 4 | // Copyright (c) 2010 Felipe Tanus, Boris Schaeling 5 | // Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling 6 | // Copyright (c) 2016 Klemens D. Morgenstern 7 | // 8 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 9 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 10 | 11 | #ifndef BOOST_PROCESS_DETAIL_HANDLER_BASE_HPP 12 | #define BOOST_PROCESS_DETAIL_HANDLER_BASE_HPP 13 | 14 | #include 15 | #include 16 | 17 | namespace boost { namespace process { BOOST_PROCESS_V1_INLINE namespace v1 { namespace detail { 18 | 19 | template