diff --git a/doc/env.adoc b/doc/env.adoc index d00bb7cf..8421c9fb 100644 --- a/doc/env.adoc +++ b/doc/env.adoc @@ -14,33 +14,18 @@ as to have the right value comparisons. To note is the `find_executable` functions, which searches in an environment for an executable. +.example/env.cpp:19-28 [source,cpp] ---- -// search in the current environment -auto exe = environment::find_executable("g++"); - -std::unordered_map my_env = - { - {"SECRET", "THIS_IS_A_TEST"}, - {"PATH", {"/bin", "/usr/bin"}} - }; - -auto other_exe = environment::find_executable("g++", my_env); +include::../example/env.cpp[tag=current_env] ---- == Subprocess environment The subprocess environment assignment follows the same constraints: -[source,cpp] +.example/env.cpp:34-42 +[source,cpp,ident=0] ---- -asio::io_context ctx; -std::unordered_map my_env = - { - {"SECRET", "THIS_IS_A_TEST"}, - {"PATH", {"/bin", "/usr/bin"}} - }; -auto exe = find_executable("g++"); -process proc(ctx, exe, {"main.cpp"}, process_environment(my_env)); -process pro2(ctx, exe, {"test.cpp"}, process_environment(my_env)); +include::../example/env.cpp[tag=subprocess_env] ---- diff --git a/doc/quickstart.adoc b/doc/quickstart.adoc index f3ddf9ee..dbf00777 100644 --- a/doc/quickstart.adoc +++ b/doc/quickstart.adoc @@ -7,14 +7,10 @@ A process needs four things to be launched: * a list of arguments * a variadic set of initializers -[source,cpp] +.example/quickstart.cpp:13-17 +[source,cpp,indent=0] ---- -// process(asio::any_io_executor, filesystem::path, range args, AdditionalInitializers...) -asio::io_context ctx; -process proc(ctx.get_executor(), // <1> - "/usr/bin/cp", // <2> - {"source.txt", "target.txt"} // <3> - ); // <4> +include::../example/quickstart.cpp[tag=cp] ---- <1> The executor for the process handle <2> The Path to the executable @@ -33,10 +29,10 @@ A process that completed will deliver an exit-code, which can be obtained by calling `.exit_code` on the exited process and which is also returned from `.wait()`. -[source,cpp] +.example/quickstart.cpp:22-23 +[source,cpp, indent=0] ---- -process proc("/bin/ls", {}); -assert(proc.wait() == 0); +include::../example/quickstart.cpp[tag=ls] ---- The normal exit-code is what the subprocess returned from `main`; @@ -54,32 +50,30 @@ The parent process can signal the subprocess demanding certain actions. `.terminate` will cause the subprocess to exit immediately (`SIGKILL` on posix). This is the only reliable & portable way to end a subprocess. -[source,cpp] +.example/quickstart.cpp:28-29 +[source,cpp,indent=0] ---- -process proc("/bin/totally-not-a-virus", {}); -proc.terminate(); +include::../example/quickstart.cpp[tag=terminate] ---- `.request_exit` will ask the subprocess to shutdown (`SIGTERM` on posix), which the subprocess might ignore. +.example/quickstart.cpp:34-36 [source,cpp] ---- -process proc("/bin/bash", {}); -proc.request_exit(); -proc.wait(); +include::../example/quickstart.cpp[tag=request_exit] ---- `.interrupt` will send an SIGINT to the subprocess, which a subprocess might -interpret as a signal to shutdown. +interpret as a signal for shutdown. WARNING: interrupt requires the initializer `windows::create_new_process_group` to be set on windows +.example/quickstart.cpp:41-43 [source,cpp] ---- -process proc("/usr/bin/addr2line", {}); -proc.request_exit(); -proc.wait(); +include::../example/quickstart.cpp[tag=interrupt] ---- [endsect] @@ -88,9 +82,10 @@ proc.wait(); Process v2 provides `execute` and `async_execute` functions that can be used for managed executions. +.example/quickstart.cpp:48 [source,cpp] ---- -assert(execute(process("/bin/ls", {}) == 0)); +include::../example/quickstart.cpp[tag=execute] ---- The async version supports cancellation and will forward cancellation types as follows: @@ -99,14 +94,10 @@ The async version supports cancellation and will forward cancellation types as f - `asio::cancellation_type::partial` -> request_exit - `asio::cancellation_type::terminal` -> terminate +.example/quickstart.cpp:53-56 [source,cpp] ---- -asio::awaitable compile() -{ - co_await async_execute(process("/usr/bin/g++", {"hello_world.cpp"})) - (asio::cancel_after(std::chrono::seconds(10, asio::cancellation_type::partial)) // <1> - (asio::cancel_after(std::chrono::seconds(10, asio::cancellation_type::terminal)); //<2> -} +include::../example/quickstart.cpp[tag=async_execute] ---- <1> After 10 seconds send a request_exit. <2> After 20 seconds terminate diff --git a/doc/start_dir.adoc b/doc/start_dir.adoc index c37ee256..27f4bd6d 100644 --- a/doc/start_dir.adoc +++ b/doc/start_dir.adoc @@ -2,11 +2,10 @@ The easier initializer to use is `process_start_dir`: -[source,cpp] +.example/start_dir.cpp:17-20 +[source,cpp,indent=0] ---- -asio::io_context ctx; -process ls(ctx.get_executor(), "/ls", {}, process_start_dir("/home")); -ls.wait(); +include::../example/start_dir.cpp[tag=start_dir] ---- This will run `ls` in the folder `/home` instead of the current folder. diff --git a/doc/stdio.adoc b/doc/stdio.adoc index bd2b2dc9..e0f0f7dc 100644 --- a/doc/stdio.adoc +++ b/doc/stdio.adoc @@ -10,18 +10,10 @@ This feature meant to be flexible, which is why there is little checking on the asio pipes can be used for io. When using in process_stdio they will get automatically connected and the other side will get assigned to the child process: -[source,cpp] +.example/stdio.cpp:20-29 +[source,cpp,indent=0] ---- -asio::io_context ctx; -asio::readable_pipe rp{ctx}; - -process proc(ctx, "/usr/bin/g++", {"--version"}, process_stdio{{ /* in to default */}, rp, { /* err to default */ }}); -std::string output; - -system::error_code ec; -rp.read(asio::dynamic_buffer(output), ec); -assert(ec == asio::eof); -proc.wait(); +include::../example/stdio.cpp[tag=readable_pipe] ---- readable pipes can be assigned to `out` an `err`, while writable_pipes can be assigned to `in`. @@ -30,12 +22,10 @@ readable pipes can be assigned to `out` an `err`, while writable_pipes can be as `FILE*` can also be used for either side; this allows the `stdin`, `stderr`, `stdout` macros to be used: +.example/stdio.cpp:35-38 [source,cpp] ---- -asio::io_context ctx; -// forward both stderr & stdout to stdout of the parent process -process proc(ctx, "/usr/bin/g++", {"--version"}, process_stdio{{ /* in to default */}, stdout, stdout}); -proc.wait(); +include::../example/stdio.cpp[tag=file] ---- == `nullptr` @@ -43,12 +33,10 @@ proc.wait(); `nullptr` may be used to set a given stream to be opened on the null-device (`/dev/null` on posix, `NUL` on windows). This is used to ignore output or give only EOF as input. +.example/stdio.cpp:43-46 [source,cpp] ---- -asio::io_context ctx; -// ignore stderr -process proc(ctx, "/usr/bin/g++", {"--version"}, process_stdio{{ /* in to default */}, {}, nullptr}); -proc.wait(); +include::../example/stdio.cpp[tag=null] ---- == `native_handle` @@ -56,14 +44,10 @@ proc.wait(); A native handle can be used as well, which means an `int` on posix or a `HANDLE` on windows. Furthermore, any object that has a `native_handle` returning that native handle type is valid, too. +.example/stdio.cpp:51-56 [source,cpp] ---- -asio::io_context ctx; -// ignore stderr -asio::ip::tcp::socket sock{ctx}; -connect_my_socket(sock); -process proc(ctx, "~/not-a-virus", {}, process_stdio{sock, sock, nullptr}); -proc.wait(); +include::../example/stdio.cpp[tag=native_handle] ---- == popen @@ -71,11 +55,9 @@ proc.wait(); Additionally, process v2 provides a `popen` class. It starts a process and connects pipes for stdin and stdout, so that the popen object can be used as a stream. +.example/stdio.cpp:61-64 [source,cpp] ---- -popen proc(executor, "/usr/bin/addr2line, {argv[0]}); -asio::write(proc, asio::buffer("main\n")); -std::string line; -asio::read_until(proc, asio::dynamic_buffer(line), '\n'); +include::../example/stdio.cpp[tag=popen] ---- diff --git a/doc/version2.adoc b/doc/version2.adoc index 726ecc33..7667705d 100644 --- a/doc/version2.adoc +++ b/doc/version2.adoc @@ -32,7 +32,7 @@ For process v2, the interfaces is simple: ---- extern std::unordered_map my_env; extern asio::io_context ctx; -process proc(ctx, "./test", {"--help"}, process_io{nullptr, {}, {}}, process_environment(my_env)); +process proc(ctx, "./test", {"--help"}, process_stdio{nullptr, {}, {}}, process_environment(my_env)); ---- Every initializer addresses one logical component (e.g. stdio) instead of multiple ones accumulating. @@ -49,8 +49,6 @@ Windows has provided `HANDLE`s for processes all along. Unless the OS doesn't support it, process v2 will use file descriptors and handles to implement waiting for processes. - - == Full asio integration Process v1 aimed to make asio optional, but synchronous IO with subprocesses usually means one is begging diff --git a/example/Jamfile.jam b/example/Jamfile.jam index 5ec31f04..b837a8e0 100644 --- a/example/Jamfile.jam +++ b/example/Jamfile.jam @@ -1,28 +1,19 @@ -# Copyright (c) 2006, 2007 Julio M. Merino Vidal -# Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -# Copyright (c) 2009 Boris Schaeling -# Copyright (c) 2010 Felipe Tanus, Boris Schaeling -# Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +# Copyright (c) 2022 Klemens Morgenstern # # Distributed under the Boost Software License, Version 1.0. (See accompanying # file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) project : requirements - /boost/process//boost_process msvc:_SCL_SECURE_NO_WARNINGS windows:WIN32_LEAN_AND_MEAN + static ; import testing ; -compile args.cpp ; -compile async_io.cpp ; -compile env.cpp ; -compile error_handling.cpp ; -compile io.cpp ; -compile posix.cpp : no linux:yes ; -compile start_dir.cpp ; -compile sync_io.cpp ; -compile terminate.cpp ; -compile wait.cpp ; -compile windows.cpp : no windows:yes ; +exe intro : intro.cpp /boost//process : boost ; +exe intro_popen : intro_popen.cpp /boost//process : boost ; +exe quickstart : quickstart.cpp /boost//process : boost ; +exe env : env.cpp /boost//process : boost ; +exe start_dir : start_dir.cpp /boost//process : boost ; +exe stdio : stdio.cpp /boost//process : boost ; diff --git a/example/args.cpp b/example/args.cpp deleted file mode 100644 index efad00d1..00000000 --- a/example/args.cpp +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling -// -// 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 -#include -#include - -namespace bp = boost::process; - -int main() -{ - bp::child c("test.exe", "--foo", "/bar"); - - //or explicit - - bp::child c2( - bp::exe="test.exe", - bp::args={"--foo", "/bar"} - ); - - c.wait(); - c2.wait(); -} diff --git a/example/async_io.cpp b/example/async_io.cpp deleted file mode 100644 index 6ac18de7..00000000 --- a/example/async_io.cpp +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling -// -// 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 -#include -#include -#include - -namespace bp = boost::process; - -int main() -{ - boost::asio::io_context ios; - boost::asio::streambuf buffer; - - - bp::child c( - "test.exe", - bp::std_out > buffer, - ios - ); - - ios.run(); -} diff --git a/example/env.cpp b/example/env.cpp index cb9a609b..5242b5d1 100644 --- a/example/env.cpp +++ b/example/env.cpp @@ -9,16 +9,37 @@ #include -namespace bp = boost::process; +using namespace boost::process; +namespace asio = boost::asio; int main() { - bp::environment my_env = boost::this_process::environment(); + { + // tag::current_env[] + // search in the current environment + auto exe = environment::find_executable("g++"); - my_env["PATH"] += "/foo"; - bp::system("test.exe", my_env); + std::unordered_map my_env = + { + {"SECRET", "THIS_IS_A_TEST"}, + {"PATH", {"/bin", "/usr/bin"}} + }; + auto other_exe = environment::find_executable("g++", my_env); + //end::current_env[] + } - - bp::system("test.exe", bp::env["PATH"]+="/bar"); + { + // tag::subprocess_env[] + asio::io_context ctx; + std::unordered_map my_env = + { + {"SECRET", "THIS_IS_A_TEST"}, + {"PATH", {"/bin", "/usr/bin"}} + }; + auto exe = environment::find_executable("g++", my_env); + process proc(ctx, exe, {"main.cpp"}, process_environment(my_env)); + process pro2(ctx, exe, {"test.cpp"}, process_environment(my_env)); + // end::subprocess_env[] + } } diff --git a/example/error_handling.cpp b/example/error_handling.cpp deleted file mode 100644 index 1a0dad00..00000000 --- a/example/error_handling.cpp +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling -// -// 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 -#include - -namespace bp = boost::process; - -int main() -{ - - std::error_code ec; - bp::child c1("test.exe", ec); - - - bp::child c2("test.exe", bp::ignore_error); - -} diff --git a/example/intro.cpp b/example/intro.cpp index 85e65c29..a8097c9c 100644 --- a/example/intro.cpp +++ b/example/intro.cpp @@ -1,8 +1,4 @@ -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// Copyright (c) 2022 Klemens Morgenstern // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -10,21 +6,35 @@ //[intro #include +#include +#include +#include + #include #include -using namespace boost::process; +namespace proc = boost::process; +namespace asio = boost::asio; + int main() { - ipstream pipe_stream; - child c("gcc --version", std_out > pipe_stream); + asio::io_context ctx; + asio::readable_pipe p{ctx}; + + const auto exe = proc::environment::find_executable("gcc"); + + proc::process c{ctx, exe, {"--version"}, proc::process_stdio{nullptr, p}}; std::string line; + boost::system::error_code ec; - while (pipe_stream && std::getline(pipe_stream, line) && !line.empty()) - std::cerr << line << std::endl; + auto sz = asio::read(p, asio::dynamic_buffer(line), ec); + assert(ec == asio::error::eof); + + std::cout << "Gcc version: '" << line << "'" << std::endl; c.wait(); + return c.exit_code(); } //] diff --git a/example/v2/intro_popen.cpp b/example/intro_popen.cpp similarity index 82% rename from example/v2/intro_popen.cpp rename to example/intro_popen.cpp index 001f0bfb..bb1d1f7c 100644 --- a/example/v2/intro_popen.cpp +++ b/example/intro_popen.cpp @@ -3,8 +3,10 @@ // 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 + //[intro -#include +#include #include #include @@ -13,7 +15,7 @@ #include #include -namespace proc = boost::process::v2; +namespace proc = boost::process; namespace asio = boost::asio; @@ -29,8 +31,11 @@ int main() auto sz = asio::read(c, asio::dynamic_buffer(line), ec); assert(ec == asio::error::eof); + boost::ignore_unused(sz); + std::cout << "Gcc version: '" << line << "'" << std::endl; c.wait(); + return c.exit_code(); } //] diff --git a/example/io.cpp b/example/io.cpp deleted file mode 100644 index 7b5142da..00000000 --- a/example/io.cpp +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling -// -// 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 -#include - -namespace bp = boost::process; - -int main() -{ - // - bp::system( - "test.exe", - bp::std_out > stdout, //forward - bp::std_err.close(), //close - bp::std_in < bp::null //null in - ); - - boost::process::v1::filesystem::path p = "input.txt"; - - bp::system( - "test.exe", - (bp::std_out & bp::std_err) > "output.txt", //redirect both to one file - bp::std_in < p //read input from file - ); - - { - bp::opstream p1; - bp::ipstream p2; - bp::system( - "test.exe", - bp::std_out > p2, - bp::std_in < p1 - ); - p1 << "my_text"; - int i = 0; - p2 >> i; - - } - { - boost::asio::io_context io_context; - bp::async_pipe p1(io_context); - bp::async_pipe p2(io_context); - bp::system( - "test.exe", - bp::std_out > p2, - bp::std_in < p1, - io_context, - bp::on_exit([&](int exit, const std::error_code& ec_in) - { - p1.async_close(); - p2.async_close(); - }) - ); - std::vector in_buf; - std::string value = "my_string"; - boost::asio::async_write(p1, boost::asio::buffer(value), []( const boost::system::error_code&, std::size_t){}); - boost::asio::async_read (p2, boost::asio::buffer(in_buf), []( const boost::system::error_code&, std::size_t){}); - } - { - boost::asio::io_context io_context; - std::vector in_buf; - std::string value = "my_string"; - bp::system( - "test.exe", - bp::std_out > bp::buffer(in_buf), - bp::std_in < bp::buffer(value) - ); - } - - { - boost::asio::io_context io_context; - std::future> in_buf; - std::future write_fut; - std::string value = "my_string"; - bp::system( - "test.exe", - bp::std_out > in_buf, - bp::std_in < bp::buffer(value) > write_fut - ); - - write_fut.get(); - in_buf.get(); - } -} diff --git a/example/posix.cpp b/example/posix.cpp deleted file mode 100644 index e822af76..00000000 --- a/example/posix.cpp +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling -// -// 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 -#include -#include -#include -#include -#include -#include - -namespace bp = boost::process; - -int main() -{ - - //duplicate our pipe descriptor into literal position 4 - bp::pipe p; - bp::system("test", bp::posix::fd.bind(4, p.native_sink())); - - - //close file-descriptor from explicit integral value - bp::system("test", bp::posix::fd.close(STDIN_FILENO)); - - //close file-descriptors from explicit integral values - bp::system("test", bp::posix::fd.close({STDIN_FILENO, STDOUT_FILENO})); - - //add custom handlers - const char *env[2] = { 0 }; - env[0] = "LANG=de"; - bp::system("test", - bp::extend::on_setup([env](auto &e) { e.env = const_cast(env); }), - bp::extend::on_fork_error([](auto&, const std::error_code & ec) - { std::cerr << errno << std::endl; }), - bp::extend::on_exec_setup([](auto&) - { ::chroot("/new/root/directory/"); }), - bp::extend::on_exec_error([](auto&, const std::error_code & ec) - { std::ofstream ofs("log.txt"); if (ofs) ofs << errno; }) - ); - -} diff --git a/example/quickstart.cpp b/example/quickstart.cpp new file mode 100644 index 00000000..d3383f1c --- /dev/null +++ b/example/quickstart.cpp @@ -0,0 +1,63 @@ +#include +#include + +namespace asio = boost::asio; +using boost::process::process; + + +int main(int /*argv*/, char ** /*argv*/) +{ + asio::io_context ctx; + { + //tag::cp[] + // process(asio::any_io_executor, filesystem::path, range args, AdditionalInitializers...) + process proc(ctx.get_executor(), // <1> + "/usr/bin/cp", // <2> + {"source.txt", "target.txt"} // <3> + ); // <4> + //end::cp[] + } + { + //tag::ls[] + process proc(ctx, "/bin/ls", {}); + assert(proc.wait() == 0); + //end::ls[] + } + { + //tag::terminate[] + process proc(ctx, "/bin/totally-not-a-virus", {}); + proc.terminate(); + //end::terminate[] + } + { + //tag::request_exit[] + process proc(ctx, "/bin/bash", {}); + proc.request_exit(); + proc.wait(); + //end::request_exit[] + } + { + //tag::interrupt[] + process proc(ctx, "/usr/bin/addr2line", {}); + proc.interrupt(); + proc.wait(); + //end::interrupt[] + } + { + //tag::execute[] + assert(execute(process(ctx, "/bin/ls", {})) == 0); + //end::execute[] + } + { + //tag::async_execute[] + async_execute(process(ctx, "/usr/bin/g++", {"hello_world.cpp"})) + (asio::cancel_after(std::chrono::seconds(10), asio::cancellation_type::partial)) // <1> + (asio::cancel_after(std::chrono::seconds(10), asio::cancellation_type::terminal)) //<2> + (asio::detached); + //end::async_execute[] + ctx.run(); + } + return 0; +} + + diff --git a/example/start_dir.cpp b/example/start_dir.cpp index fa7ae764..300f91ac 100644 --- a/example/start_dir.cpp +++ b/example/start_dir.cpp @@ -8,20 +8,15 @@ // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #include -#include -namespace bp = boost::process; +using namespace boost::process; +namespace asio = boost::asio; int main() { - bp::system( - "test.exe", - bp::start_dir="../foo" - ); - - boost::process::v1::filesystem::path exe = "test.exe"; - bp::system( - boost::process::v1::filesystem::absolute(exe), - bp::start_dir="../foo" - ); + // tag::start_dir[] + asio::io_context ctx; + process ls(ctx.get_executor(), "/ls", {}, process_start_dir("/home")); + ls.wait(); + // end::start_dir[] } diff --git a/example/stdio.cpp b/example/stdio.cpp new file mode 100644 index 00000000..97a2bf42 --- /dev/null +++ b/example/stdio.cpp @@ -0,0 +1,68 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// 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 +#include + +using namespace boost::process; +namespace asio = boost::asio; + +int main(int argc, char *argv[]) +{ + { + //tag::readable_pipe[] + asio::io_context ctx; + asio::readable_pipe rp{ctx}; + + process proc(ctx, "/usr/bin/g++", {"--version"}, process_stdio{{ /* in to default */}, rp, { /* err to default */ }}); + std::string output; + + boost::system::error_code ec; + asio::read(rp, asio::dynamic_buffer(output), ec); + assert(!ec || (ec == asio::error::eof)); + proc.wait(); + //end::readable_pipe[] + } + + { + //tag::file[] + asio::io_context ctx; + // forward both stderr & stdout to stdout of the parent process + process proc(ctx, "/usr/bin/g++", {"--version"}, process_stdio{{ /* in to default */}, stdout, stdout}); + proc.wait(); + //end::file[] + } + { + //tag::null[] + asio::io_context ctx; + // forward stderr to /dev/null or NUL + process proc(ctx, "/usr/bin/g++", {"--version"}, process_stdio{{ /* in to default */}, {}, nullptr}); + proc.wait(); + //end::null[] + } + { + //tag::native_handle[] + asio::io_context ctx; + // ignore stderr + asio::local::stream_protocol::socket sock{ctx}, other{ctx}; + asio::local::connect_pair(sock, other); + process proc(ctx, "~/not-a-virus", {}, process_stdio{sock, sock, nullptr}); + proc.wait(); + //end::native_handle[] + } + { + //tag::popen[] + asio::io_context ctx; + boost::process::popen proc(ctx, "/usr/bin/addr2line", {argv[0]}); + asio::write(proc, asio::buffer("main\n")); + std::string line; + asio::read_until(proc, asio::dynamic_buffer(line), '\n'); + //end::popen[] + } +} diff --git a/example/sync_io.cpp b/example/sync_io.cpp deleted file mode 100644 index a861e7ab..00000000 --- a/example/sync_io.cpp +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling -// -// 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 -#include - -namespace bp = boost::process; - -int main() -{ - bp::ipstream p; - - bp::child c( - "test.exe", - bp::std_out > p - ); - - std::string s; - std::getline(p, s); - - c.wait(); -} diff --git a/example/terminate.cpp b/example/terminate.cpp deleted file mode 100644 index 7de2d830..00000000 --- a/example/terminate.cpp +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling -// -// 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 - -namespace bp = boost::process; - -int main() -{ - bp::child c("test.exe"); - c.terminate(); -} diff --git a/example/v2/Jamfile.jam b/example/v2/Jamfile.jam deleted file mode 100644 index 450fdc21..00000000 --- a/example/v2/Jamfile.jam +++ /dev/null @@ -1,15 +0,0 @@ -# Copyright (c) 2022 Klemens Morgenstern -# -# Distributed under the Boost Software License, Version 1.0. (See accompanying -# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -project : requirements - msvc:_SCL_SECURE_NO_WARNINGS - windows:WIN32_LEAN_AND_MEAN - static -; - -import testing ; - -exe intro : intro.cpp ; -exe intro_popen : intro_popen.cpp : boost ; diff --git a/example/v2/intro.cpp b/example/v2/intro.cpp deleted file mode 100644 index 2e0f2363..00000000 --- a/example/v2/intro.cpp +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) 2022 Klemens Morgenstern -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -//[intro -#include - -#include -#include -#include - -#include -#include - -namespace proc = boost::process::v2; -namespace asio = boost::asio; - - -int main() -{ - asio::io_context ctx; - asio::readable_pipe p{ctx}; - - const auto exe = proc::environment::find_executable("gcc"); - - proc::process c{ctx, exe, {"--version"}, proc::process_stdio{nullptr, p}}; - - std::string line; - boost::system::error_code ec; - - auto sz = asio::read(p, asio::dynamic_buffer(line), ec); - assert(ec == asio::error::eof); - - std::cout << "Gcc version: '" << line << "'" << std::endl; - - c.wait(); -} -//] diff --git a/example/wait.cpp b/example/wait.cpp deleted file mode 100644 index 9ebb5314..00000000 --- a/example/wait.cpp +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling -// -// 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 -#include - -namespace bp = boost::process; - -int main() -{ - { - bp::child c("test.exe"); - c.wait(); - auto exit_code = c.exit_code(); - } - - { - boost::asio::io_context io_context; - - bp::child c( - "test.exe", - io_context, - bp::on_exit([&](int exit, const std::error_code& ec_in){}) - ); - - io_context.run(); - } -} diff --git a/example/windows.cpp b/example/windows.cpp deleted file mode 100644 index 93b4f62c..00000000 --- a/example/windows.cpp +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling -// -// 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 -#include -#include -#include - -#include - -namespace bp = boost::process; - -int main() -{ - bp::system("test.exe", - bp::windows::show); - - - bp::system("test.exe", - bp::extend::on_setup([](auto &e) - { e.startup_info.dwFlags = STARTF_RUNFULLSCREEN; }), - bp::extend::on_error([](auto&, const std::error_code & ec) - { std::cerr << ec.message() << std::endl; }) - ); -}