2
0
mirror of https://github.com/boostorg/process.git synced 2026-01-20 16:52:14 +00:00

Compare commits

..

159 Commits

Author SHA1 Message Date
Klemens David Morgenstern
6abce365c5 started on asio_no_deprecated.cpp 2018-03-11 20:57:18 +01:00
Klemens Morgenstern
8e8d36772e Merge pull request #151 from amerry/is-running-fixes
is_running fixes
2018-02-26 13:53:41 +01:00
Alex Merry
ec04919825 Rename tests to reflect what they do 2018-02-22 14:32:54 +00:00
Alex Merry
6625999765 Check the "still running" status code does not clash with WIFSIGNALED
This makes the static_assert reflect the actual assumptions in the code.
2018-02-22 14:31:22 +00:00
Alex Merry
0d3688aca5 Ignore stopped processes
is_running should only concern itself with terminated processes, not
stopped processes (which might be continued later).
2018-02-22 14:12:46 +00:00
Klemens Morgenstern
40be786c43 Merge pull request #150 from amerry/async-exit-status
Return the same exit status in the async handler as the sync method
2018-02-22 13:43:06 +01:00
Klemens Morgenstern
d4a0444223 Merge pull request #147 from amerry/args
Always set arguments on POSIX
2018-02-22 13:05:33 +01:00
Klemens Morgenstern
f99cfe77f4 Merge pull request #148 from pepsiman/patch-1
Fix grammar in tutorial
2018-02-22 12:59:52 +01:00
Alex Merry
ed32531369 Return the same exit status in the async handler as the sync method
Previously, if the process terminated via a signal on posix, the async
handler would provide an exit status of 0.
2018-02-22 11:53:42 +00:00
Malcolm Parsons
751af041cd Fix grammar in tutorial 2018-02-22 10:29:59 +00:00
Alex Merry
a0ceebd59f Fix copyright headers
Insofar as there are copyrights on these changes, they are owned by my
employer, as I'm doing this on company time.
2018-02-22 09:02:02 +00:00
Klemens Morgenstern
b0b37f2ce6 Merge pull request #146 from amerry/test-for-sigchld-fix
Add unit tests for async exit watching with multiple io_contexts
2018-02-21 17:50:27 +01:00
Alex Merry
cf1f904ae2 Fix compilation on MSVC 2018-02-21 15:53:46 +00:00
Alex Merry
8aaf53d76d Always set arguments on POSIX
Explicitly specifying an executable (either with boost::filesystem::path
or boost::process::exe) and no arguments causes NULL to be passed as the
argument list.

Not only is this unexpected behaviour for the child process (which
doesn't even have argv[0]), it is not portable across UNIX systems. From
the execve(2) man page on Linux:

"On Linux, either argv or envp can be specified as NULL, which has the
same effect as specifying these arguments as a pointer to a list
containing a single NULL pointer.  Do not take advantage of this
misfeature!  It is nonstandard and nonportable:  on  most other UNIX
systems doing this will result in an error (EFAULT)."
2018-02-21 15:43:32 +00:00
Alex Merry
76c03ded89 Add unit tests for async exit watching with multiple io_contexts
These tests fail without the commit "Only reap children we are watching
for when handling SIGCHLD" applied, and succeed with it applied.
2018-02-21 15:13:28 +00:00
Klemens Morgenstern
e6fa19b4c5 Merge pull request #145 from amerry/async-wait-fix
Only reap children we are watching for when handling SIGCHLD
2018-02-20 19:53:54 +01:00
Alex Merry
92ee239891 Only reap children we are watching for when handling SIGCHLD
There may be other io_context instances with child instances, and child
instances with no associated io_context. If we pass 0 to ::waitpid(), we
will reap their processes as well, without updating the state of the
corresponding child instance.

Instead, we call `::waitpid` once for each child we are watching for.
This has some amount of overhead (multiple system calls), but ensures
correct behaviour (providing nothing other than an asio::signal_set is
watching for SIGCHLD).
2018-02-20 14:32:33 +00:00
Klemens Morgenstern
c37e2a7524 Merge pull request #142 from cls/search_path_returns_dir
Fix search_path not to return directories on POSIX
2018-02-14 15:41:58 +01:00
Connor Lane Smith
a610fe74ff Fix search_path not to return directories on POSIX 2018-02-14 13:56:34 +00:00
Klemens Morgenstern
ea49952da2 Merge pull request #141 from markus-t314/fix_issue139
Fix: Inconsistent behaviour in various overloaded functions/methods #139
2018-02-09 21:15:19 +01:00
Markus Tillinger
a55946eb5d Fix: Inconsistent behaviour in various overloaded functions/methods #139
Removed duplicated code in overloaded functions.
Replaced system_clock with steady_clock.
2018-02-08 21:49:49 +01:00
Klemens David Morgenstern
60302c0017 Merge branch 'develop' of github.com:klemens-morgenstern/boost-process into develop 2018-02-06 20:20:18 +01:00
Klemens David Morgenstern
08eaf8b7a1 added BOOST_NO_ANSI_APIS support, closes #26 2018-02-06 20:20:02 +01:00
Klemens Morgenstern
cc70ec9362 Update pipe_in.hpp 2018-02-06 10:29:16 +01:00
Klemens Morgenstern
b58ecc7c9d Update async_in.hpp 2018-02-06 10:27:16 +01:00
Klemens Morgenstern
668cbcdaf4 Update windows.hpp 2018-02-06 10:23:02 +01:00
Klemens David Morgenstern
6d7cbd0989 closes #83 2018-02-06 00:32:55 +01:00
Klemens David Morgenstern
0764f788a6 typo fix 2018-02-06 00:24:45 +01:00
Klemens David Morgenstern
2b95dd7011 Merge branch 'develop' of github.com:klemens-morgenstern/boost-process into develop 2018-02-06 00:08:26 +01:00
Klemens David Morgenstern
ae380c30ad added CREATE_NO_WINDOW flags, closes #129 2018-02-06 00:07:35 +01:00
Klemens Morgenstern
d2265890bd Merge pull request #138 from markus-t314/consistent_wait_handling
Fixed inconsistent posix-wait-handling
2018-02-05 23:42:04 +01:00
Klemens Morgenstern
831d49c1b3 Merge pull request #137 from markus-t314/fix_issue136
Fix: [posix] inconsistent exit status when child received signal #136
2018-02-05 23:38:59 +01:00
Klemens Morgenstern
6935c53510 Merge pull request #132 from egorpugin/patch-1
Fix initialization of atomic var. This fixes mingw build.
2018-02-05 23:34:11 +01:00
Klemens David Morgenstern
f30d90a179 Merge remote-tracking branch 'remotes/boostorg/develop' into develop 2018-02-05 23:32:17 +01:00
Klemens Morgenstern
55cfcecfb8 Merge pull request #27 from adrianimboden/develop
fix use of uninitalized variable
2018-02-05 23:16:21 +01:00
Klemens Morgenstern
233f46a2cb Merge pull request #30 from cinghiale/patch-1
update the code snippets to reflect the doc
2018-02-05 23:15:15 +01:00
Markus Tillinger
342554b3d8 Fixed inconsistent posix-wait-handling
Refactored: Removed duplicated code
Made wait_until compatible with steady_clock
2018-02-03 22:11:37 +01:00
Markus Tillinger
7aa812a0e1 Fix: [posix] inconsistent exit status when child received signal #136 2018-02-03 17:47:14 +01:00
Klemens David Morgenstern
a411f06dc4 Merge remote-tracking branch 'remotes/origin/master' into develop
# Conflicts:
#	test/Jamfile.jam
#	test/async_system_stackless.cpp
2018-02-02 22:37:32 +01:00
Klemens David Morgenstern
d085262076 added /bigobj flag for msvc 2018-02-02 22:14:42 +01:00
Klemens David Morgenstern
0396740467 splitted up the async_system tests 2018-02-02 21:52:14 +01:00
Klemens Morgenstern
0fd7de9481 Merge pull request #134 from hrayrbabajanyan/patch-1
eval_exit_status would return 0 in case if the child received SIBABRT
2018-02-01 20:44:00 +01:00
hrayrbabajanyan
ba790dad0a eval_exit_status would return 0 in case if the child received SIBABRT 2018-02-01 02:53:24 +04:00
David Mugnai
f2e8776965 update the code snippets to reflect the doc 2018-01-23 23:35:54 +01:00
Adrian Imboden
444d5eb702 fix use of uninitalized variable 2018-01-06 13:36:42 +01:00
Egor Pugin
3e12e989ab Fix initialization of atomic var. This fixes mingw build. 2018-01-06 14:04:32 +03:00
klemens-morgenstern
917030c3cd Merge branch 'develop' 2017-11-11 01:02:31 +01:00
Klemens Morgenstern
faf848bd8b Merge pull request #125 from ca-l-eb/fixes
Fix async_pipe reassignment and child_decl
2017-11-05 15:39:13 -05:00
Caleb Dechant
d78c7901b3 Revert async_pipe dtor to original 2017-11-05 11:48:20 -08:00
Klemens Morgenstern
09e98d8746 Merge pull request #122 from egorpugin/develop
Fix multithreaded async pipes creation.
2017-11-05 13:47:56 -05:00
Egor Pugin
ab6e5b54ec Rename to io_context 2017-11-05 20:21:49 +03:00
Egor Pugin
b268e0e1fb Change atomic var to size_t. 2017-11-05 17:28:42 +03:00
Caleb Dechant
996f4b357c Fix child_decl's move constructor
The _terminated field is now copied from the moved child.
2017-11-04 17:25:00 -07:00
Caleb Dechant
8ce3e760dc Fix async_pipe move assignment and destructor
Simplify async_pipe's move assignment so it now properly closes the old
pipe handles by swapping the asio stream_descriptors.

Reassigning async_pipes previously raised exceptions complaining about
EBADF or EEXIST. I think the ::close calls in the destructor and the
move assignment were not closing the pipe correctly.
2017-11-04 17:22:15 -07:00
klemens-morgenstern
6e60928b1f Merge branch 'develop' of github.com:boostorg/process into develop 2017-11-03 00:14:23 +01:00
Klemens Morgenstern
e27baa7628 Merge pull request #24 from ca-l-eb/fix-terminate
Fix move assignment for child_decl
2017-11-02 19:13:17 -04:00
Caleb Dechant
337a6e3e83 Fix move assignment for child
_terminate field is now copied from the move assingment operator on
child. This fixes the issue that a child process could previously only
be terminated() once (even after reassignment).
2017-11-02 16:03:05 -07:00
klemens-morgenstern
bbfc334c93 split up the async_system test 2017-10-28 13:04:01 +02:00
klemens-morgenstern
1a9fa2cc2c Merge branch 'develop' 2017-10-28 12:09:36 +02:00
klemens-morgenstern
1296e02372 Merge branch 'develop' of github.com:klemens-morgenstern/boost-process into develop 2017-10-25 18:49:13 +02:00
klemens-morgenstern
585104605e removed variadic arg in test 2017-10-25 18:48:55 +02:00
Klemens Morgenstern
d0c07b7c63 Update windows_specific.cpp 2017-10-25 12:20:00 +02:00
Klemens Morgenstern
7c9ce7f8b9 Update exit_code.cpp 2017-10-25 10:55:40 +02:00
Klemens Morgenstern
c388f24d6e Update windows_specific.cpp 2017-10-25 10:53:46 +02:00
klemens-morgenstern
b1f50e953b some additions attempted fixes for the windows part 2017-10-25 09:07:23 +02:00
klemens-morgenstern
852d8f3d9d renamed windows/io_service_ref.hpp 2017-10-24 23:54:58 +02:00
klemens-morgenstern
2c026e43a8 removed constness for gcc 4.8 2017-10-24 23:17:42 +02:00
klemens-morgenstern
51396227a0 renamed native() to native_handle() 2017-10-24 23:15:53 +02:00
klemens-morgenstern
75d3049199 Merge branch 'develop' of github.com:klemens-morgenstern/boost-process into develop 2017-10-24 22:36:48 +02:00
Klemens Morgenstern
3d9a8b2353 Merge pull request #22 from Lastique/update_winapi
Update Boost.WinAPI usage to the new location and namespace
2017-10-24 16:35:40 -04:00
Klemens Morgenstern
8097c2e07a Merge pull request #19 from chriskohlhoff/asio-updates-1
Updates to compile against latest asio.
2017-10-24 16:34:06 -04:00
Andrey Semashev
d9231d466c Updated Boost.WinAPI usage to the new location and namespace. 2017-10-24 23:27:56 +03:00
Christopher Kohlhoff
153e05eac0 Updates to compile against latest asio. 2017-10-23 21:23:44 +11:00
Klemens Morgenstern
883b6ac937 Merge pull request #15 from ganboing/develop
fix uninitialized variable and close(-1) behavior
2017-10-22 15:41:53 -04:00
Klemens Morgenstern
764fff1f65 Merge pull request #17 from gevorgvoskanyan/search_path_unused_var
remove unused variable in boost::process::detail::posix::search_path()
2017-10-22 15:35:58 -04:00
Klemens Morgenstern
16ff42290a Merge pull request #16 from gevorgvoskanyan/doc_typos
Some typo fixes
2017-10-22 15:35:43 -04:00
Gevorg Voskanyan
6adf1bf545 fix param path comment for search_path() 2017-10-22 23:20:02 +04:00
Gevorg Voskanyan
126659f2f9 remove unused variable in boost::process::detail::posix::search_path() 2017-10-22 22:50:45 +04:00
Gevorg Voskanyan
90adf118ac s/a environment/an environment 2017-10-22 22:30:24 +04:00
Gevorg Voskanyan
63952fa2a6 s/seperated/separated 2017-10-22 22:20:27 +04:00
Bo Gan
2f00162817 fix uninitialized variable and close(-1) behavior 2017-09-12 12:37:20 -07:00
Klemens Morgenstern
28b402eed1 Merge pull request #120 from klemens-morgenstern/vfork-check-fix
Updated vfork check
2017-08-29 13:22:32 -04:00
Egor Pugin
3f12d82e00 Rename io service. 2017-08-29 14:38:23 +03:00
Egor Pugin
e01c1e0d37 Rename test. 2017-08-29 14:34:35 +03:00
Egor Pugin
c2602e86e9 Make counter 64 bits. 2017-08-29 14:20:51 +03:00
Egor Pugin
e2a2a57820 Fix multithreaded async pipes creation. 2017-08-29 14:19:21 +03:00
Klemens Morgenstern
547c04fc1f Updated vfork check 2017-08-22 22:02:48 +02:00
Klemens Morgenstern
6ab2ed1723 Merge pull request #119 from klemens-morgenstern/fix_for_118
Strange typo fix
2017-08-22 15:50:58 -04:00
Klemens Morgenstern
79e26878b1 Strange typo fix
Trying to fix #118
2017-08-22 18:24:53 +02:00
Klemens Morgenstern
d15e7be16a Merge pull request #117 from sehe/develop
fix `rdbuf()` implementation on pipe
2017-08-22 15:40:57 +02:00
sehe
3ab038fc0f fix rdbuf() implementation on pipe 2017-08-22 09:56:44 +02:00
Klemens Morgenstern
66989a25f2 Update wait_group.hpp 2017-08-02 22:23:09 +02:00
klemens-morgenstern
c748fff766 Merge branch 'master' of github.com:boostorg/process 2017-08-02 21:59:29 +02:00
Klemens Morgenstern
4772a08f89 Merge pull request #113 from klemens-morgenstern/develop
1.65 bugfixes
2017-08-02 21:58:22 +02:00
klemens-morgenstern
054d7980ab hopefully closes #106 2017-08-02 21:08:33 +02:00
Klemens Morgenstern
4c6b0fff2a Merge pull request #115 from klemens-morgenstern/sigchld_service
Sigchld service
2017-08-02 13:50:09 +02:00
Klemens Morgenstern
449eef0b98 Update async.hpp 2017-08-02 09:37:06 +02:00
Klemens Morgenstern
3992965359 Update extend.qbk 2017-08-02 09:36:53 +02:00
Klemens Morgenstern
264b517b38 Update async.hpp 2017-08-02 09:35:41 +02:00
Klemens Morgenstern
71c2fad8ce Update extend.qbk 2017-08-02 09:33:36 +02:00
Klemens Morgenstern
5b45fad163 Update wait.cpp
removed double wait
2017-08-02 09:27:38 +02:00
Klemens Morgenstern
e899189bf4 Update on_exit3.cpp
typo fix
2017-08-02 09:25:39 +02:00
klemens-morgenstern
241883c9e4 changed to use only one signal 2017-08-02 08:34:53 +02:00
klemens-morgenstern
aeee4e5dbb windows wait_for fix 2017-08-02 08:31:30 +02:00
Klemens David Morgenstern
e08e095fd1 WEXITSTATUS fix 2017-08-02 01:52:58 -04:00
Klemens David Morgenstern
da34b4020d Trying to get the sigchld-service to work 2017-08-01 18:41:55 -04:00
Klemens David Morgenstern
99001ccb50 Fixed wait_for & wait_until, closes #11 2017-08-01 18:00:44 -04:00
klemens-morgenstern
f402f48138 started on sigchld_service.hpp 2017-08-01 20:58:09 +02:00
klemens-morgenstern
1960360099 typo fixes 2017-08-01 20:07:22 +02:00
klemens-morgenstern
83019b5f70 started on the wait for fix for posix 2017-08-01 19:35:55 +02:00
klemens-morgenstern
76418ca191 added wait_for and wait_until tests 2017-08-01 19:17:28 +02:00
klemens-morgenstern
f02e72304f seperated test-suites into valgrind / no-valgrind 2017-08-01 19:05:40 +02:00
klemens-morgenstern
4850ae493f Merge branch 'develop' of github.com:klemens-morgenstern/boost-process into develop 2017-07-31 22:32:29 +02:00
Klemens Morgenstern
77aecb43b8 Merge pull request #14 from jschueller/lowercase-windows-header
lowercase win32 header to fix cross-compilation
2017-07-31 22:31:37 +02:00
Julien Schueller
66e576806f lowercase win32 header to fix cross-compilation 2017-07-31 22:27:39 +02:00
Klemens Morgenstern
15445fd2bf Merge pull request #110 from thomasschaub/develop
Respect WIFSIGNALED in all relevant places
2017-07-25 20:27:13 +02:00
Klemens Morgenstern
6f49261c6e Merge pull request #111 from thomasschaub/feature/avoid-reencoding-on-windows
Avoid string charset conversion
2017-07-25 20:24:15 +02:00
Thomas Schaub
062b26e046 Avoid string charset conversion 2017-07-25 18:12:13 +02:00
Thomas Schaub
bb0fe86292 Respect WIFSIGNALED in all relevant places
Was only respected for one `waitpid` call
2017-07-25 18:01:53 +02:00
Klemens Morgenstern
a3d3a98d5b Merge pull request #13 from egorpugin/develop
Set correct access rights. Fix windows build.
2017-07-24 07:23:23 +02:00
Egor Pugin
950f16fe42 Merge branch 'develop' of github.com-egorpugin:egorpugin/process into develop 2017-07-24 00:48:37 +03:00
Egor Pugin
225b322e56 Fix windows build. 2017-07-24 00:47:48 +03:00
Egor Pugin
3e31d43d61 Fix access rights. 2017-07-24 00:27:17 +03:00
Klemens Morgenstern
085adc07ec Merge pull request #12 from egorpugin/develop
Fix incorrect on_exit() callback called on any child exited.
2017-07-23 23:18:39 +02:00
Klemens Morgenstern
6aaefedf25 Merge pull request #11 from thomasschaub/develop
Respect WIFSIGNALED
2017-07-23 23:18:16 +02:00
Egor Pugin
8df9c467e5 Fix incorrect on_exit() callback called on any child exited. 2017-07-24 00:10:30 +03:00
Thomas Schaub
529d09f43b Respect WIFSIGNALED 2017-07-19 12:00:44 +02:00
klemens-morgenstern
ce2a06f3a6 closes #102 2017-06-03 10:29:45 +02:00
Klemens Morgenstern
93a077e911 Merge pull request #10 from triccardi-systran/typos
Fix some typos.
2017-05-22 11:24:35 +02:00
Thomas Riccardi
9ed2ebef27 Fix some typos. 2017-05-22 11:14:29 +02:00
klemens-morgenstern
7882bad799 updated readme 2017-05-10 15:00:55 +02:00
Klemens Morgenstern
92e1e04ae4 Merge pull request #9 from cdglove/restore_wargs_tests
Restore wargs tests
2017-05-10 14:59:31 +02:00
Chris Glover
cf19c451fa Remove returns that were disabling wargs tests. 2017-05-10 08:51:31 -04:00
klemens-morgenstern
74dd6570e3 small fixes, closes #97 2017-05-07 12:44:38 +02:00
klemens-morgenstern
826177a12e Merge branch 'develop' of github.com:boostorg/process into develop
# Conflicts:
#	include/boost/process/detail/windows/search_path.hpp
2017-05-01 10:56:24 +02:00
Klemens Morgenstern
6712c54827 Merge pull request #8 from tabe/throw_last_error-const_char
Overloading boost::process::detail::throw_last_error() for Xcode's clang++
2017-05-01 10:54:32 +02:00
Takeshi Abe
6a64b9e0bd Allow const char * as throw_last_error()'s argument 2017-05-01 17:29:35 +09:00
klemens-morgenstern
34377ecad0 typo fixes 2017-04-25 21:02:16 +02:00
klemens-morgenstern
ae2b0a9024 removed tabs 2017-04-23 19:16:39 +02:00
klemens-morgenstern
712ebf772b changed search_path to use PATHEXT on windows, closes #91 2017-04-23 19:14:18 +02:00
klemens-morgenstern
7a99be71d3 tab fix 2017-04-23 17:46:18 +02:00
klemens-morgenstern
210efd8dc5 Merge branch 'async-pipe-fix' into develop 2017-04-23 17:43:42 +02:00
klemens-morgenstern
ed15395f6d fixed example error, closes #87 2017-04-23 17:42:02 +02:00
klemens-morgenstern
05443af621 readme fix 2017-04-23 17:30:36 +02:00
klemens-morgenstern
a25665aeff removed merge error 2017-04-23 17:29:12 +02:00
klemens-morgenstern
ee4428c226 Merge branch 'whitespaces' into develop
# Conflicts:
#	include/boost/process/io.hpp
2017-04-23 17:28:35 +02:00
klemens-morgenstern
74814e46c1 closes #90 2017-04-23 15:09:39 +02:00
klemens-morgenstern
f27898cdcd yml branch selection fix 2017-04-23 15:05:41 +02:00
klemens-morgenstern
007dd97486 added pid_t typedef, closes #82 2017-04-23 15:03:50 +02:00
klemens-morgenstern
f0082aa797 closes #89 2017-04-23 14:54:46 +02:00
klemens-morgenstern
ba14d9f870 Normalize all the line endings 2017-04-23 14:48:16 +02:00
klemens-morgenstern
684f9bcf11 added .git attributes, see #88 2017-04-23 14:41:26 +02:00
Klemens Morgenstern
51735a5640 Merge pull request #86 from ForNeVeR/patch-1
README: update markdown
2017-04-06 08:53:09 +02:00
Friedrich von Never
d6b242c54a README: update markdown 2017-04-06 11:46:24 +07:00
Klemens Morgenstern
9daf3b4717 Merge pull request #80 from klemens-morgenstern/env_fix
Updated environment reset on windows
2017-03-19 18:36:51 +01:00
klemens-morgenstern
9cab8d455a Updated environment reset on windows 2017-03-19 18:04:38 +01:00
Klemens Morgenstern
f1bd81d56e Merge pull request #79 from ChrisKitching/moreWarnings
Fix some more warnings...
2017-03-17 19:13:24 +01:00
Chris Kitching
28dc0c8830 Repair more Wunused warnings 2017-03-17 17:39:33 +00:00
Chris Kitching
7e217fe012 Stop using mixed line-endings... 2017-03-17 17:39:05 +00:00
140 changed files with 7597 additions and 6897 deletions

96
.gitattributes vendored Normal file
View File

@@ -0,0 +1,96 @@
* text=auto !eol svneol=native#text/plain
*.gitattributes text svneol=native#text/plain
# Scriptish formats
*.bat text svneol=native#text/plain
*.bsh text svneol=native#text/x-beanshell
*.cgi text svneol=native#text/plain
*.cmd text svneol=native#text/plain
*.js text svneol=native#text/javascript
*.php text svneol=native#text/x-php
*.pl text svneol=native#text/x-perl
*.pm text svneol=native#text/x-perl
*.py text svneol=native#text/x-python
*.sh eol=lf svneol=LF#text/x-sh
configure eol=lf svneol=LF#text/x-sh
# Image formats
*.bmp binary svneol=unset#image/bmp
*.gif binary svneol=unset#image/gif
*.ico binary svneol=unset#image/ico
*.jpeg binary svneol=unset#image/jpeg
*.jpg binary svneol=unset#image/jpeg
*.png binary svneol=unset#image/png
*.tif binary svneol=unset#image/tiff
*.tiff binary svneol=unset#image/tiff
*.svg text svneol=native#image/svg%2Bxml
# Data formats
*.pdf binary svneol=unset#application/pdf
*.avi binary svneol=unset#video/avi
*.doc binary svneol=unset#application/msword
*.dsp text svneol=crlf#text/plain
*.dsw text svneol=crlf#text/plain
*.eps binary svneol=unset#application/postscript
*.gz binary svneol=unset#application/gzip
*.mov binary svneol=unset#video/quicktime
*.mp3 binary svneol=unset#audio/mpeg
*.ppt binary svneol=unset#application/vnd.ms-powerpoint
*.ps binary svneol=unset#application/postscript
*.psd binary svneol=unset#application/photoshop
*.rdf binary svneol=unset#text/rdf
*.rss text svneol=unset#text/xml
*.rtf binary svneol=unset#text/rtf
*.sln text svneol=native#text/plain
*.swf binary svneol=unset#application/x-shockwave-flash
*.tgz binary svneol=unset#application/gzip
*.vcproj text svneol=native#text/xml
*.vcxproj text svneol=native#text/xml
*.vsprops text svneol=native#text/xml
*.wav binary svneol=unset#audio/wav
*.xls binary svneol=unset#application/vnd.ms-excel
*.zip binary svneol=unset#application/zip
# Text formats
.htaccess text svneol=native#text/plain
*.bbk text svneol=native#text/xml
*.cmake text svneol=native#text/plain
*.css text svneol=native#text/css
*.dtd text svneol=native#text/xml
*.htm text svneol=native#text/html
*.html text svneol=native#text/html
*.ini text svneol=native#text/plain
*.log text svneol=native#text/plain
*.mak text svneol=native#text/plain
*.qbk text svneol=native#text/plain
*.rst text svneol=native#text/plain
*.sql text svneol=native#text/x-sql
*.txt text svneol=native#text/plain
*.xhtml text svneol=native#text/xhtml%2Bxml
*.xml text svneol=native#text/xml
*.xsd text svneol=native#text/xml
*.xsl text svneol=native#text/xml
*.xslt text svneol=native#text/xml
*.xul text svneol=native#text/xul
*.yml text svneol=native#text/plain
boost-no-inspect text svneol=native#text/plain
CHANGES text svneol=native#text/plain
COPYING text svneol=native#text/plain
INSTALL text svneol=native#text/plain
Jamfile text svneol=native#text/plain
Jamroot text svneol=native#text/plain
Jamfile.v2 text svneol=native#text/plain
Jamrules text svneol=native#text/plain
Makefile* text svneol=native#text/plain
README text svneol=native#text/plain
TODO text svneol=native#text/plain
# Code formats
*.c text svneol=native#text/plain
*.cpp text svneol=native#text/plain
*.h text svneol=native#text/plain
*.hpp text svneol=native#text/plain
*.ipp text svneol=native#text/plain
*.tpp text svneol=native#text/plain
*.jam text svneol=native#text/plain
*.java text svneol=native#text/plain

View File

@@ -65,7 +65,7 @@ before_install:
- BOOST=$HOME/boost-local
- git init $BOOST
- cd $BOOST
- if [ $(BRANCH_TO_TEST) = "master" ]; then
- if [ $BRANCH_TO_TEST = "master" ]; then
BOOST_BRANCH=master;
else BOOST_BRANCH=develop; fi
- git remote add --no-tags -t $BOOST_BRANCH origin https://github.com/boostorg/boost.git
@@ -89,8 +89,8 @@ before_install:
script:
# `--coverage` flags required to generate coverage info for Coveralls
- ../../../b2 address-model=64 architecture=x86 testing.launcher=valgrind valgrind=on toolset=$TOOLSET cxxflags="--coverage -DBOOST_TRAVISCI_BUILD -std=$CXX_STANDARD" linkflags="--coverage" -sBOOST_BUILD_PATH=.
- ../../../b2 vfork address-model=64 architecture=x86 toolset=$TOOLSET cxxflags="--coverage -DBOOST_TRAVISCI_BUILD -std=$CXX_STANDARD" linkflags="--coverage" -sBOOST_BUILD_PATH=.
- ../../../b2 with-valgrind address-model=64 architecture=x86 testing.launcher=valgrind valgrind=on toolset=$TOOLSET cxxflags="--coverage -DBOOST_TRAVISCI_BUILD -std=$CXX_STANDARD" linkflags="--coverage" -sBOOST_BUILD_PATH=.
- ../../../b2 without-valgrind address-model=64 architecture=x86 toolset=$TOOLSET cxxflags="--coverage -DBOOST_TRAVISCI_BUILD -std=$CXX_STANDARD" linkflags="--coverage" -sBOOST_BUILD_PATH=.
after_success:
# Copying Coveralls data to a separate folder
- mkdir -p $TRAVIS_BUILD_DIR/coverals

View File

@@ -1,13 +1,13 @@
#[Boost Process (Boost.Process)](https://github.com/klemens-morgenstern/boost-process)
# [Boost Process (Boost.Process)](https://github.com/klemens-morgenstern/boost-process)
Boost.process is not yet part of the [Boost C++ Libraries](http://github.com/boostorg), but will probably be released in boost 1.64. It is a library for comfortable management of processes.
Boost.process is a library for comfortable management of processes, released with boost 1.64.0.
### Test results
Branches | Build | Tests coverage |
----------------|-------------- | -------------- |
Develop: | [![Build Status](https://travis-ci.org/klemens-morgenstern/boost-process.svg?branch=develop)](https://travis-ci.org/klemens-morgenstern/boost-process) [![Build status](https://ci.appveyor.com/api/projects/status/peup7e6m0e1bb5ba?svg=true)](https://ci.appveyor.com/project/klemens-morgenstern/boost-process) | [![Coverage Status](https://coveralls.io/repos/github/klemens-morgenstern/boost-process/badge.svg?branch=develop)](https://coveralls.io/github/klemens-morgenstern/boost-process?branch=develop) |
Master: | [![Build Status](https://travis-ci.org/klemens-morgenstern/boost-process.svg?branch=master)] (https://travis-ci.org/klemens-morgenstern/boost-process) [![Build status](https://ci.appveyor.com/api/projects/status/peup7e6m0e1bb5ba/branch/master?svg=true)](https://ci.appveyor.com/project/klemens-morgenstern/boost-process/branch/master) | [![Coverage Status](https://coveralls.io/repos/github/klemens-morgenstern/boost-process/badge.svg?branch=master)](https://coveralls.io/github/klemens-morgenstern/boost-process?branch=master) |
Master: | [![Build Status](https://travis-ci.org/klemens-morgenstern/boost-process.svg?branch=master)](https://travis-ci.org/klemens-morgenstern/boost-process) [![Build status](https://ci.appveyor.com/api/projects/status/peup7e6m0e1bb5ba/branch/master?svg=true)](https://ci.appveyor.com/project/klemens-morgenstern/boost-process/branch/master) | [![Coverage Status](https://coveralls.io/repos/github/klemens-morgenstern/boost-process/badge.svg?branch=master)](https://coveralls.io/github/klemens-morgenstern/boost-process?branch=master) |
[Open Issues](https://github.com/klemens-morgenstern/boost-process/issues)
@@ -21,4 +21,4 @@ Distributed under the [Boost Software License, Version 1.0](http://www.boost.org
### Dependency
This library requires boost 1.63. Since this is not released yet you can clone the winapi module from [here](https://github.com/boostorg/winapi) to get it to work on windows.
This library requires boost 1.64 with which it is released.

View File

@@ -50,7 +50,7 @@ which also have file-like names, but are in a different scope than the actual fi
[section:process Processes]
A process is an independently executable entity, which is different from a thread, in that it has it's own resources.
A process is an independently executable entity, which is different from a thread, in that it has its own resources.
Those include memory and hardware resources.
Every process is identified by a unique number[footnote it is unique as long as the process is active], called the process identification digit, `pid`.

View File

@@ -103,12 +103,11 @@ struct async_foo : __handler__, __require_io_service__
tempalte<typename Executor>
void on_setup(Executor & exec)
{
__io_service__ & ios = __get_io_service__(exec.seq); //gives us a reference and a compiler error if not present.
io_service & ios = __get_io_service__(exec.seq); //gives us a reference and a compiler error if not present.
//do something with ios
}
};
```
[note Inheriting [globalref boost::process::extend::require_io_service require_io_service] is necessary, so [funcref boost::process::system system] provides one.]
Additionally the handler can provide a function that is invoked when the child process exits. This is done through __async_handler__.
@@ -134,6 +133,8 @@ struct async_bar : __handler, __async_handler__
[caution `on_exit_handler` does not default and is always required when [classref boost::process::extend::async_handler async_handler] is inherited. ]
[caution `on_exit_handler` uses `boost::asio::signal_set` to listen for SIGCHLD on posix. The application must not also register a signal handler for SIGCHLD using functions such as `signal()` or `sigaction()` (but using `boost::asio::signal_set` is fine). ]
[endsect]
[section:error Error handling]
@@ -208,4 +209,4 @@ way to implement systems-specific code without using the preprocessor.
[endsect]
[endsect]
[endsect]

View File

@@ -1,87 +1,87 @@
[section:faq Frequently Asked Questions]
[section:faq Frequently Asked Questions]
[section:dead_lock Why does this produce a deadlock?]
[section:dead_lock Why does this produce a deadlock?]
Now let's revisit our c++filt example and we will put in an obvious mistake.
This might however be not as obvious for more complex applications.
Now let's revisit our c++filt example and we will put in an obvious mistake.
This might however be not as obvious for more complex applications.
```
vector<string> demangle(vector<string> in)
{
ipstream is;
opstream os;
child c("c++filt", std_out > is, std_in < os);
vector<string> data;
for (auto & elem : data)
{
string line;
getline(is, line);
os << elem;
}
}
```
We switched the read and write operation up, so that's causing a dead-lock.
This locks immediately. This is because `c++filt` expects input, before
outputting any data. The launching process on the other hand wait's for it's output.
```
vector<string> demangle(vector<string> in)
{
ipstream is;
opstream os;
child c("c++filt", std_out > is, std_in < os);
vector<string> data;
for (auto & elem : data)
{
string line;
getline(is, line);
os << elem;
}
}
```
We switched the read and write operation up, so that's causing a dead-lock.
This locks immediately. This is because `c++filt` expects input, before
outputting any data. The launching process on the other hand waits for its output.
[endsect]
[endsect]
[section:closep Why does the pipe not close?]
[section:closep Why does the pipe not close?]
Now for another example, which might look correct, let's consider you want
to use `ls` to read the current directory.
Now for another example, which might look correct, let's consider you want
to use `ls` to read the current directory.
```
ipstream is;
child c("ls", std_out > is);
```
ipstream is;
child c("ls", std_out > is);
std::string file;
while (is >> file)
cout << "File: " << file << endl;
```
std::string file;
while (is >> file)
cout << "File: " << file << endl;
```
This will also deadlock, because the pipe does not close when the subprocess exits.
So the `ipstream` will still look for data even though the process has ended.
This will also deadlock, because the pipe does not close when the subprocess exits.
So the `ipstream` will still look for data even though the process has ended.
[note It is not possible to use automatically pipe-closing in this library, because
a pipe might be a file-handle (as for async pipes on windows).]
[note It is not possible to use automatically pipe-closing in this library, because
a pipe might be a file-handle (as for async pipes on windows).]
But, since pipes are buffered, you might get incomplete data if you do this:
But, since pipes are buffered, you might get incomplete data if you do this:
```
ipstream is;
child c("ls", std_out > is);
```
ipstream is;
child c("ls", std_out > is);
std::string file;
while (c.running())
{
is >> file;
cout << "File: " << file << endl;
}
```
std::string file;
while (c.running())
{
is >> file;
cout << "File: " << file << endl;
}
```
It is therefore highly recommended that you use the asynchronous api if you are
not absolutely sure how the output will look.
It is therefore highly recommended that you use the asynchronous api if you are
not absolutely sure how the output will look.
[endsect]
[endsect]
[section:wchar_t When will the codecvt be used?]
[section:wchar_t When will the codecvt be used?]
Since windows does not use UTF-8 it is sometimes unavoidable to use the `wchar_t` version of the WinApi.
To keep this library consistent it provides `wchar_t` support on posix also.
Since windows does not use UTF-8 it is sometimes unavoidable to use the `wchar_t` version of the WinApi.
To keep this library consistent it provides `wchar_t` support on posix also.
Since the posix api is purely `char` every `wchar_t` based type will be converted into `char`.
Since the posix api is purely `char` every `wchar_t` based type will be converted into `char`.
Windows on the other hand is more selective; the default is to use `char`,
but if any parameter requires `wchar_t`, everything will be converted to `wchar_t`.
This also includes `boost::filesystem::path`. Additionally, if the system does not provide
the `char` api (as is the case with Windows CE) everything will also be converted.
Windows on the other hand is more selective; the default is to use `char`,
but if any parameter requires `wchar_t`, everything will be converted to `wchar_t`.
This also includes `boost::filesystem::path`. Additionally, if the system does not provide
the `char` api (as is the case with Windows CE) everything will also be converted.
[endsect]
[endsect]
[endsect]

View File

@@ -81,7 +81,7 @@ So as a first step, we'll use the `exe-args` style.
int result = bp::system("/usr/bin/g++", "main.cpp");
```
With that sytax we still have "g++" hard-coded, so let's assume we get the string
With that syntax we still have "g++" hard-coded, so let's assume we get the string
from an external source as `boost::filesystem::path`, we can do this too.
```
@@ -104,13 +104,13 @@ This also includes to add a file suffix on windows, such as `.exe` or `.bat`.]
[section:launch_mode Launch functions]
Given that in our example used the [funcref boost::process::system system] function,
our program will wait until the child process is completed. This maybe unwanted,
Given that our example used the [funcref boost::process::system system] function,
our program will wait until the child process is completed. This may be unwanted,
especially since compiling can take a while.
In order to avoid that, boost.process provides several ways to launch a process.
Besides the already mentioned [funcref boost::process::system system] function and it's
asynchronous version [funcref boost::process::async_system async_system],
Besides the already mentioned [funcref boost::process::system system] function and its
asynchronous version [funcref boost::process::async_system async_system],
we can also use the [funcref boost::process::spawn spawn] function or the
[classref boost::process::child child] class.
@@ -151,10 +151,10 @@ This can be avoided by calling __detach__ beforehand]
Until now, we have assumed that everything works out, but it is not impossible,
that "g++" is not present. That will cause the launch of the process to fail.
The default behaviour of all functions is to throw an
The default behaviour of all functions is to throw a
[@http://en.cppreference.com/w/cpp/error/system_error std::system_error] on failure.
As with many other functions in this library, passing an [@http://en.cppreference.com/w/cpp/error/error_code std::error_code]
will change the behaviour, so that instead of throwing an exception, the error will be a assigned to the error code.
will change the behaviour, so that instead of throwing an exception, the error will be assigned to the error code.
```
std::error_code ec;
@@ -200,7 +200,7 @@ wrap around the [classref boost::process::pipe pipe] and provide an implementati
std::vector<std::string> read_outline(std::string & file)
{
bp::ipstream is; //reading pipe-stream
bp::child c(bp::search_patk("nm"), file, bp::std_out > is);
bp::child c(bp::search_path("nm"), file, bp::std_out > is);
std::vector<std::string> data;
std::string line;
@@ -278,7 +278,7 @@ With [@http://www.boost.org/doc/libs/release/libs/asio/ boost.asio] this is what
```
io_service ios;
std::vector<char> buf;
std::vector<char> buf(4096);
bp::async_pipe ap(ios);
@@ -288,7 +288,6 @@ asio_async_read(ap, asio_buffer(buf),
[](const boost::system::error_code &ec, std::size_t size){});
ios.run();
c.wait();
int result = c.exit_code();
```
@@ -302,7 +301,6 @@ std::vector<char> buf;
bp::child c(bp::search_path("g++"), "main.cpp", bp::std_out > asio_buffer(buf), ios);
ios.run();
c.wait();
int result = c.exit_code();
```
@@ -342,10 +340,10 @@ it will not terminate all the child processes of the child unless you use a grou
The two main reasons to use groups are:
# Being able two terminate child processes of the child process
# Being able to terminate child processes of the child process
# Grouping several processes into one, just so they can be terminated at once
If we have program like `make`, which does launch it's own child processes,
If we have program like `make`, which does launch its own child processes,
a call of child_terminate might not suffice. I.e. if we have a makefile launching `gcc`
and use the following code, the `gcc` process will still run afterwards:
@@ -388,7 +386,7 @@ void f()
```
In the example, it will wait for both processes at the end of the function unless
an exception occures. I.e. if an exception is thrown, the group will be terminated.
an exception occurs. I.e. if an exception is thrown, the group will be terminated.
Please see the [headerref boost/process/group.hpp reference] for more information.
@@ -405,7 +403,7 @@ auto env = boost::this_process::environment();
//add a variable to the current environment
env["VALUE_1"] = "foo";
//copy it into a environment seperate to the one of this process
//copy it into an environment separate to the one of this process
bp::environment env_ = env;
//append two values to a variable in the new env
env_["VALUE_2"] += {"bar1", "bar2"};

View File

@@ -16,7 +16,7 @@ namespace bp = boost::process;
int main()
{
boost::asio::io_service ios;
boost::asio::io_context ios;
boost::asio::streambuf buffer;

View File

@@ -44,14 +44,14 @@ int main()
}
{
boost::asio::io_service io_service;
bp::async_pipe p1(io_service);
bp::async_pipe p2(io_service);
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_service,
io_context,
bp::on_exit([&](int exit, const std::error_code& ec_in)
{
p1.async_close();
@@ -64,7 +64,7 @@ int main()
boost::asio::async_read (p2, boost::asio::buffer(in_buf), []( const boost::system::error_code&, std::size_t){});
}
{
boost::asio::io_service io_service;
boost::asio::io_context io_context;
std::vector<char> in_buf;
std::string value = "my_string";
bp::system(
@@ -75,7 +75,7 @@ int main()
}
{
boost::asio::io_service io_service;
boost::asio::io_context io_context;
std::future<std::vector<char>> in_buf;
std::future<void> write_fut;
std::string value = "my_string";

View File

@@ -21,14 +21,14 @@ int main()
}
{
boost::asio::io_service io_service;
boost::asio::io_context io_context;
bp::child c(
"test.exe",
io_service,
io_context,
bp::on_exit([&](int exit, const std::error_code& ec_in){})
);
io_service.run();
io_context.run();
}
}

View File

@@ -7,7 +7,7 @@
The header which provides the basic asynchrounous features.
It provides the on_exit property, which allows callbacks when the process exits.
It also implements the necessary traits for passing an boost::asio::io_service,
It also implements the necessary traits for passing an boost::asio::io_context,
which is needed for asynchronous communication.
It also pulls the [boost::asio::buffer](http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/buffer.html)
@@ -32,20 +32,20 @@ namespace boost {
#include <boost/process/detail/traits.hpp>
#include <boost/process/detail/on_exit.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/streambuf.hpp>
#include <boost/asio/buffer.hpp>
#include <type_traits>
#include <boost/fusion/iterator/deref.hpp>
#if defined(BOOST_POSIX_API)
#include <boost/process/detail/posix/io_service_ref.hpp>
#include <boost/process/detail/posix/io_context_ref.hpp>
#include <boost/process/detail/posix/async_in.hpp>
#include <boost/process/detail/posix/async_out.hpp>
#include <boost/process/detail/posix/on_exit.hpp>
#elif defined(BOOST_WINDOWS_API)
#include <boost/process/detail/windows/io_service_ref.hpp>
#include <boost/process/detail/windows/io_context_ref.hpp>
#include <boost/process/detail/windows/async_in.hpp>
#include <boost/process/detail/windows/async_out.hpp>
#include <boost/process/detail/windows/on_exit.hpp>
@@ -56,25 +56,25 @@ namespace boost { namespace process { namespace detail {
struct async_tag;
template<typename T>
struct is_io_service : std::false_type {};
struct is_io_context : std::false_type {};
template<>
struct is_io_service<api::io_service_ref> : std::true_type {};
struct is_io_context<api::io_context_ref> : std::true_type {};
template<typename Tuple>
inline asio::io_service& get_io_service(const Tuple & tup)
inline asio::io_context& get_io_context(const Tuple & tup)
{
auto& ref = *boost::fusion::find_if<is_io_service<boost::mpl::_>>(tup);
auto& ref = *boost::fusion::find_if<is_io_context<boost::mpl::_>>(tup);
return ref.get();
}
struct async_builder
{
boost::asio::io_service * ios;
boost::asio::io_context * ios;
void operator()(boost::asio::io_service & ios_) {this->ios = &ios_;};
void operator()(boost::asio::io_context & ios_) {this->ios = &ios_;};
typedef api::io_service_ref result_type;
api::io_service_ref get_initializer() {return api::io_service_ref (*ios);};
typedef api::io_context_ref result_type;
api::io_context_ref get_initializer() {return api::io_context_ref (*ios);};
};
@@ -90,7 +90,7 @@ using ::boost::asio::buffer;
#if defined(BOOST_PROCESS_DOXYGEN)
/** When an io_service is passed, the on_exit property can be used, to be notified
/** When an io_context is passed, the on_exit property can be used, to be notified
when the child process exits.
@@ -107,7 +107,7 @@ with `function` being a callable object with the signature `(int, const std::err
\par Example
\code{.cpp}
io_service ios;
io_context ios;
child c("ls", on_exit=[](int exit, const std::error_code& ec_in){});
@@ -117,8 +117,10 @@ chlid c2("ls", on_exit=exit_code);
\endcode
\note The handler is not invoked when the launch fails.
\warning When used \ref ignore_error it might gte invoked on error.
\warning When used \ref ignore_error it might get invoked on error.
\warning `on_exit` uses `boost::asio::signal_set` to listen for `SIGCHLD` on posix, and so has the
same restrictions as that class (do not register a handler for `SIGCHLD` except by using
`boost::asio::signal_set`).
*/
constexpr static ::boost::process::detail::on_exit_ on_exit{};
#endif

View File

@@ -48,31 +48,31 @@ public:
typedef platform_specific handle_type;
/** Construct a new async_pipe, does automatically open the pipe.
* Initializes source and sink with the same io_service.
* Initializes source and sink with the same io_context.
* @note Windows creates a named pipe here, where the name is automatically generated.
*/
inline async_pipe(boost::asio::io_service & ios);
inline async_pipe(boost::asio::io_context & ios);
/** Construct a new async_pipe, does automatically open the pipe.
* @note Windows creates a named pipe here, where the name is automatically generated.
*/
inline async_pipe(boost::asio::io_service & ios_source,
boost::asio::io_service & ios_sink);
inline async_pipe(boost::asio::io_context & ios_source,
boost::asio::io_context & ios_sink);
/** Construct a new async_pipe, does automatically open.
* Initializes source and sink with the same io_service.
* Initializes source and sink with the same io_context.
*
* @note Windows restricts possible names.
*/
inline async_pipe(boost::asio::io_service & ios, const std::string & name);
inline async_pipe(boost::asio::io_context & ios, const std::string & name);
/** Construct a new async_pipe, does automatically open.
*
* @note Windows restricts possible names.
*/
inline async_pipe(boost::asio::io_service & ios_source,
boost::asio::io_service & ios_sink, const std::string & name);
inline async_pipe(boost::asio::io_context & ios_source,
boost::asio::io_context & ios_sink, const std::string & name);
/** Copy-Constructor of the async pipe.
* @note Windows requires a named pipe for this, if a the wrong type is used an exception is thrown.
@@ -89,15 +89,15 @@ public:
*
*/
template<class CharT, class Traits = std::char_traits<CharT>>
explicit async_pipe(boost::asio::io_service & ios, const basic_pipe<CharT, Traits> & p);
explicit async_pipe(boost::asio::io_context & ios, const basic_pipe<CharT, Traits> & p);
/** Construct the async-pipe from a pipe, with two different io_service objects.
/** Construct the async-pipe from a pipe, with two different io_context objects.
* @note Windows requires a named pipe for this, if a the wrong type is used an exception is thrown.
*
*/
template<class CharT, class Traits = std::char_traits<CharT>>
explicit async_pipe(boost::asio::io_service & ios_source,
boost::asio::io_service & ios_sink,
explicit async_pipe(boost::asio::io_context & ios_source,
boost::asio::io_context & ios_sink,
const basic_pipe<CharT, Traits> & p);
@@ -189,15 +189,15 @@ public:
///Get the asio handle of the pipe source. Qualified as rvalue
handle_type && source() &&;
/// Move the source out of this class and change the io_service. Qualified as rvalue. \attention Will always move.
handle_type source(::boost::asio::io_service& ios) &&;
/// Move the sink out of this class and change the io_service. Qualified as rvalue. \attention Will always move
handle_type sink (::boost::asio::io_service& ios) &&;
/// Move the source out of this class and change the io_context. Qualified as rvalue. \attention Will always move.
handle_type source(::boost::asio::io_context& ios) &&;
/// Move the sink out of this class and change the io_context. Qualified as rvalue. \attention Will always move
handle_type sink (::boost::asio::io_context& ios) &&;
/// Copy the source out of this class and change the io_service. \attention Will always copy.
handle_type source(::boost::asio::io_service& ios) const &;
/// Copy the sink out of this class and change the io_service. \attention Will always copy
handle_type sink (::boost::asio::io_service& ios) const &;
/// Copy the source out of this class and change the io_context. \attention Will always copy.
handle_type source(::boost::asio::io_context& ios) const &;
/// Copy the sink out of this class and change the io_context. \attention Will always copy
handle_type sink (::boost::asio::io_context& ios) const &;

View File

@@ -40,8 +40,8 @@ namespace detail
template<typename ExitHandler>
struct async_system_handler : ::boost::process::detail::api::async_handler
{
boost::asio::io_service & ios;
boost::asio::detail::async_result_init<
boost::asio::io_context & ios;
boost::asio::async_completion<
ExitHandler, void(boost::system::error_code, int)> init;
#if defined(BOOST_POSIX_API)
@@ -50,8 +50,8 @@ struct async_system_handler : ::boost::process::detail::api::async_handler
template<typename ExitHandler_>
async_system_handler(
boost::asio::io_service & ios,
ExitHandler_ && exit_handler) : ios(ios), init(std::forward<ExitHandler_>(exit_handler))
boost::asio::io_context & ios,
ExitHandler_ && exit_handler) : ios(ios), init(exit_handler)
{
}
@@ -63,7 +63,7 @@ struct async_system_handler : ::boost::process::detail::api::async_handler
#if defined(BOOST_POSIX_API)
errored = true;
#endif
auto & h = init.handler;
auto & h = init.completion_handler;
ios.post(
[h, ec]() mutable
{
@@ -84,7 +84,7 @@ struct async_system_handler : ::boost::process::detail::api::async_handler
if (errored)
return [](int exit_code, const std::error_code & ec){};
#endif
auto & h = init.handler;
auto & h = init.completion_handler;
return [h](int exit_code, const std::error_code & ec) mutable
{
h(boost::system::error_code(ec.value(), boost::system::system_category()), exit_code);
@@ -106,7 +106,7 @@ but is similar to the asynchronous functions in [boost.asio](http://www.boost.or
It uses [asio::async_result](http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/async_result.html) to determine
the return value (from the second parameter, `exit_handler`).
\param ios A reference to an [io_service](http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference.html)
\param ios A reference to an [io_context](http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference.html)
\param exit_handler The exit-handler for the signature `void(boost::system::error_code, int)`
\note This function does not allow custom error handling, since those are done through the `exit_handler`.
@@ -115,12 +115,12 @@ the return value (from the second parameter, `exit_handler`).
#if defined(BOOST_PROCESS_DOXYGEN)
template<typename ExitHandler, typename ...Args>
inline boost::process::detail::dummy
async_system(boost::asio::io_service & ios, ExitHandler && exit_handler, Args && ...args);
async_system(boost::asio::io_context & ios, ExitHandler && exit_handler, Args && ...args);
#endif
template<typename ExitHandler, typename ...Args>
inline BOOST_ASIO_INITFN_RESULT_TYPE(ExitHandler, void (boost::system::error_code, int))
async_system(boost::asio::io_service & ios, ExitHandler && exit_handler, Args && ...args)
async_system(boost::asio::io_context & ios, ExitHandler && exit_handler, Args && ...args)
{
detail::async_system_handler<ExitHandler> async_h{ios, std::forward<ExitHandler>(exit_handler)};

View File

@@ -35,6 +35,9 @@ child::child(Args&&...args)
: child(::boost::process::detail::execute_impl(std::forward<Args>(args)...)) {}
///Typedef for the type of an pid_t
typedef ::boost::process::detail::api::pid_t pid_t;
#if defined(BOOST_PROCESS_DOXYGEN)
/** The main class to hold a child process. It is simliar to [std::thread](http://en.cppreference.com/w/cpp/thread/thread),
* in that it has a join and detach function.

View File

@@ -1,122 +1,122 @@
// 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) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// 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) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PROCESS_DETAIL_CMD_LINE_HPP
#define BOOST_PROCESS_DETAIL_CMD_LINE_HPP
#ifndef BOOST_PROCESS_DETAIL_CMD_LINE_HPP
#define BOOST_PROCESS_DETAIL_CMD_LINE_HPP
#include <boost/detail/winapi/config.hpp>
#include <boost/process/detail/config.hpp>
#include <boost/process/detail/handler_base.hpp>
#include <boost/process/detail/traits/cmd_or_exe.hpp>
#include <boost/process/detail/traits/wchar_t.hpp>
#include <boost/winapi/config.hpp>
#include <boost/process/detail/config.hpp>
#include <boost/process/detail/handler_base.hpp>
#include <boost/process/detail/traits/cmd_or_exe.hpp>
#include <boost/process/detail/traits/wchar_t.hpp>
#if defined(BOOST_POSIX_API)
#include <boost/process/detail/posix/cmd.hpp>
#elif defined(BOOST_WINDOWS_API)
#include <boost/process/detail/windows/cmd.hpp>
#endif
#if defined(BOOST_POSIX_API)
#include <boost/process/detail/posix/cmd.hpp>
#elif defined(BOOST_WINDOWS_API)
#include <boost/process/detail/windows/cmd.hpp>
#endif
/** \file boost/process/cmd.hpp
*
* This header provides the \xmlonly <globalname alt="boost::process::cmd">cmd</globalname>\endxmlonly property.
*
\xmlonly
<programlisting>
namespace boost {
namespace process {
<emphasis>unspecified</emphasis> <globalname alt="boost::process::cmd">cmd</globalname>;
}
}
</programlisting>
\endxmlonly
*/
/** \file boost/process/cmd.hpp
*
* This header provides the \xmlonly <globalname alt="boost::process::cmd">cmd</globalname>\endxmlonly property.
*
\xmlonly
<programlisting>
namespace boost {
namespace process {
<emphasis>unspecified</emphasis> <globalname alt="boost::process::cmd">cmd</globalname>;
}
}
</programlisting>
\endxmlonly
*/
namespace boost { namespace process { namespace detail {
namespace boost { namespace process { namespace detail {
struct cmd_
{
constexpr cmd_() {}
struct cmd_
{
constexpr cmd_() {}
template<typename Char>
inline api::cmd_setter_<Char> operator()(const Char *s) const
{
return api::cmd_setter_<Char>(s);
}
template<typename Char>
inline api::cmd_setter_<Char> operator= (const Char *s) const
{
return api::cmd_setter_<Char>(s);
}
template<typename Char>
inline api::cmd_setter_<Char> operator()(const Char *s) const
{
return api::cmd_setter_<Char>(s);
}
template<typename Char>
inline api::cmd_setter_<Char> operator= (const Char *s) const
{
return api::cmd_setter_<Char>(s);
}
template<typename Char>
inline api::cmd_setter_<Char> operator()(const std::basic_string<Char> &s) const
{
return api::cmd_setter_<Char>(s);
}
template<typename Char>
inline api::cmd_setter_<Char> operator= (const std::basic_string<Char> &s) const
{
return api::cmd_setter_<Char>(s);
}
};
template<typename Char>
inline api::cmd_setter_<Char> operator()(const std::basic_string<Char> &s) const
{
return api::cmd_setter_<Char>(s);
}
template<typename Char>
inline api::cmd_setter_<Char> operator= (const std::basic_string<Char> &s) const
{
return api::cmd_setter_<Char>(s);
}
};
template<> struct is_wchar_t<api::cmd_setter_<wchar_t>> : std::true_type {};
template<> struct is_wchar_t<api::cmd_setter_<wchar_t>> : std::true_type {};
template<>
struct char_converter<char, api::cmd_setter_<wchar_t>>
{
static api::cmd_setter_<char> conv(const api::cmd_setter_<wchar_t> & in)
{
return { ::boost::process::detail::convert(in.str()) };
}
};
template<>
struct char_converter<char, api::cmd_setter_<wchar_t>>
{
static api::cmd_setter_<char> conv(const api::cmd_setter_<wchar_t> & in)
{
return { ::boost::process::detail::convert(in.str()) };
}
};
template<>
struct char_converter<wchar_t, api::cmd_setter_<char>>
{
static api::cmd_setter_<wchar_t> conv(const api::cmd_setter_<char> & in)
{
return { ::boost::process::detail::convert(in.str()) };
}
};
template<>
struct char_converter<wchar_t, api::cmd_setter_<char>>
{
static api::cmd_setter_<wchar_t> conv(const api::cmd_setter_<char> & in)
{
return { ::boost::process::detail::convert(in.str()) };
}
};
}
}
/** The cmd property allows to explicitly set commands for the execution.
/** The cmd property allows to explicitly set commands for the execution.
The overload form applies when only one string is passed to a launching function.
The string will be internally parsed and split at spaces.
The overload form applies when only one string is passed to a launching function.
The string will be internally parsed and split at spaces.
The following expressions are valid, with `value` being either a C-String or
a `std::basic_string` with `char` or `wchar_t`.
The following expressions are valid, with `value` being either a C-String or
a `std::basic_string` with `char` or `wchar_t`.
\code{.cpp}
cmd="value";
cmd(value);
\endcode
\code{.cpp}
cmd="value";
cmd(value);
\endcode
The property can only be used for assignments.
The property can only be used for assignments.
*/
constexpr static ::boost::process::detail::cmd_ cmd;
*/
constexpr static ::boost::process::detail::cmd_ cmd;
}}
}}
#endif
#endif

View File

@@ -27,37 +27,37 @@ namespace detail {
#if defined(BOOST_POSIX_API)
using ::boost::process::detail::posix::is_async_handler;
using ::boost::process::detail::posix::does_require_io_service;
using ::boost::process::detail::posix::does_require_io_context;
#else
using ::boost::process::detail::windows::is_async_handler;
using ::boost::process::detail::windows::does_require_io_service;
using ::boost::process::detail::windows::does_require_io_context;
#endif
template<typename ...Args>
struct has_io_service;
struct has_io_context;
template<typename T, typename ...Args>
struct has_io_service<T, Args...>
struct has_io_context<T, Args...>
{
typedef typename has_io_service<Args...>::type next;
typedef typename has_io_context<Args...>::type next;
typedef typename std::is_same<
typename std::remove_reference<T>::type,
boost::asio::io_service>::type is_ios;
boost::asio::io_context>::type is_ios;
typedef typename std::conditional<is_ios::value,
std::true_type,
next>::type type;
};
template<typename T>
struct has_io_service<T>
struct has_io_context<T>
{
typedef typename std::is_same<
typename std::remove_reference<T>::type,
boost::asio::io_service>::type type;
boost::asio::io_context>::type type;
};
template<typename ...Args>
using has_io_service_t = typename has_io_service<Args...>::type;
using has_io_context_t = typename has_io_context<Args...>::type;
template<typename ...Args>
struct has_async_handler;
@@ -79,34 +79,34 @@ struct has_async_handler<T>
};
template<typename ...Args>
struct needs_io_service;
struct needs_io_context;
template<typename T, typename ...Args>
struct needs_io_service<T, Args...>
struct needs_io_context<T, Args...>
{
typedef typename needs_io_service<Args...>::type next;
typedef typename does_require_io_service<T>::type is_ios;
typedef typename needs_io_context<Args...>::type next;
typedef typename does_require_io_context<T>::type is_ios;
typedef typename std::conditional<is_ios::value,
std::true_type,
next>::type type;
};
template<typename T>
struct needs_io_service<T>
struct needs_io_context<T>
{
typedef typename does_require_io_service<T>::type type;
typedef typename does_require_io_context<T>::type type;
};
template<typename ...Args>
boost::asio::io_service &get_io_service_var(boost::asio::io_service & f, Args&...)
boost::asio::io_context &get_io_context_var(boost::asio::io_context & f, Args&...)
{
return f;
}
template<typename First, typename ...Args>
boost::asio::io_service &get_io_service_var(First&, Args&...args)
boost::asio::io_context &get_io_context_var(First&, Args&...args)
{
return get_io_service_var(args...);
return get_io_context_var(args...);
}
}

View File

@@ -1,292 +1,292 @@
// Copyright (c) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Copyright (c) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PROCESS_DETAIL_BASIC_CMD_HPP_
#define BOOST_PROCESS_DETAIL_BASIC_CMD_HPP_
#ifndef BOOST_PROCESS_DETAIL_BASIC_CMD_HPP_
#define BOOST_PROCESS_DETAIL_BASIC_CMD_HPP_
#include <boost/process/detail/config.hpp>
#include <boost/process/detail/config.hpp>
#include <boost/process/detail/handler_base.hpp>
#include <boost/process/detail/traits/cmd_or_exe.hpp>
#include <boost/process/detail/traits/wchar_t.hpp>
#include <boost/process/detail/handler_base.hpp>
#include <boost/process/detail/traits/cmd_or_exe.hpp>
#include <boost/process/detail/traits/wchar_t.hpp>
#if defined( BOOST_WINDOWS_API )
#include <boost/process/detail/windows/basic_cmd.hpp>
#include <boost/process/detail/windows/cmd.hpp>
#elif defined( BOOST_POSIX_API )
#include <boost/process/detail/posix/basic_cmd.hpp>
#include <boost/process/detail/posix/cmd.hpp>
#endif
#if defined( BOOST_WINDOWS_API )
#include <boost/process/detail/windows/basic_cmd.hpp>
#include <boost/process/detail/windows/cmd.hpp>
#elif defined( BOOST_POSIX_API )
#include <boost/process/detail/posix/basic_cmd.hpp>
#include <boost/process/detail/posix/cmd.hpp>
#endif
#include <boost/process/shell.hpp>
#include <boost/process/shell.hpp>
#include <iterator>
#include <iterator>
namespace boost { namespace process { namespace detail {
namespace boost { namespace process { namespace detail {
template<typename Char>
struct exe_setter_
{
typedef Char value_type;
typedef std::basic_string<Char> string_type;
template<typename Char>
struct exe_setter_
{
typedef Char value_type;
typedef std::basic_string<Char> string_type;
string_type exe_;
exe_setter_(string_type && str) : exe_(std::move(str)) {}
exe_setter_(const string_type & str) : exe_(str) {}
};
string_type exe_;
exe_setter_(string_type && str) : exe_(std::move(str)) {}
exe_setter_(const string_type & str) : exe_(str) {}
};
template<> struct is_wchar_t<exe_setter_<wchar_t>> : std::true_type {};
template<> struct is_wchar_t<exe_setter_<wchar_t>> : std::true_type {};
template<>
struct char_converter<char, exe_setter_<wchar_t>>
{
static exe_setter_<char> conv(const exe_setter_<wchar_t> & in)
{
return {::boost::process::detail::convert(in.exe_)};
}
};
template<>
struct char_converter<char, exe_setter_<wchar_t>>
{
static exe_setter_<char> conv(const exe_setter_<wchar_t> & in)
{
return {::boost::process::detail::convert(in.exe_)};
}
};
template<>
struct char_converter<wchar_t, exe_setter_<char>>
{
static exe_setter_<wchar_t> conv(const exe_setter_<char> & in)
{
return {::boost::process::detail::convert(in.exe_)};
}
};
template<>
struct char_converter<wchar_t, exe_setter_<char>>
{
static exe_setter_<wchar_t> conv(const exe_setter_<char> & in)
{
return {::boost::process::detail::convert(in.exe_)};
}
};
template <typename Char, bool Append >
struct arg_setter_
{
using value_type = Char;
using string_type = std::basic_string<value_type>;
std::vector<string_type> _args;
template <typename Char, bool Append >
struct arg_setter_
{
using value_type = Char;
using string_type = std::basic_string<value_type>;
std::vector<string_type> _args;
typedef typename std::vector<string_type>::iterator iterator;
typedef typename std::vector<string_type>::const_iterator const_iterator;
typedef typename std::vector<string_type>::iterator iterator;
typedef typename std::vector<string_type>::const_iterator const_iterator;
template<typename Iterator>
arg_setter_(Iterator && begin, Iterator && end) : _args(begin, end) {}
template<typename Iterator>
arg_setter_(Iterator && begin, Iterator && end) : _args(begin, end) {}
template<typename Range>
arg_setter_(Range && str) :
_args(std::begin(str),
std::end(str)) {}
template<typename Range>
arg_setter_(Range && str) :
_args(std::begin(str),
std::end(str)) {}
iterator begin() {return _args.begin();}
iterator end() {return _args.end();}
const_iterator begin() const {return _args.begin();}
const_iterator end() const {return _args.end();}
arg_setter_(string_type & str) : _args{{str}} {}
arg_setter_(string_type && s) : _args({std::move(s)}) {}
arg_setter_(const string_type & s) : _args({s}) {}
arg_setter_(const value_type* s) : _args({std::move(s)}) {}
iterator begin() {return _args.begin();}
iterator end() {return _args.end();}
const_iterator begin() const {return _args.begin();}
const_iterator end() const {return _args.end();}
arg_setter_(string_type & str) : _args{{str}} {}
arg_setter_(string_type && s) : _args({std::move(s)}) {}
arg_setter_(const string_type & s) : _args({s}) {}
arg_setter_(const value_type* s) : _args({std::move(s)}) {}
template<std::size_t Size>
arg_setter_(const value_type (&s) [Size]) : _args({s}) {}
};
template<std::size_t Size>
arg_setter_(const value_type (&s) [Size]) : _args({s}) {}
};
template<> struct is_wchar_t<arg_setter_<wchar_t, true >> : std::true_type {};
template<> struct is_wchar_t<arg_setter_<wchar_t, false>> : std::true_type {};
template<> struct is_wchar_t<arg_setter_<wchar_t, true >> : std::true_type {};
template<> struct is_wchar_t<arg_setter_<wchar_t, false>> : std::true_type {};
template<>
struct char_converter<char, arg_setter_<wchar_t, true>>
{
static arg_setter_<char, true> conv(const arg_setter_<wchar_t, true> & in)
{
std::vector<std::string> vec(in._args.size());
std::transform(in._args.begin(), in._args.end(), vec.begin(),
[](const std::wstring & ws)
{
return ::boost::process::detail::convert(ws);
});
return {vec};
}
};
template<>
struct char_converter<char, arg_setter_<wchar_t, true>>
{
static arg_setter_<char, true> conv(const arg_setter_<wchar_t, true> & in)
{
std::vector<std::string> vec(in._args.size());
std::transform(in._args.begin(), in._args.end(), vec.begin(),
[](const std::wstring & ws)
{
return ::boost::process::detail::convert(ws);
});
return {vec};
}
};
template<>
struct char_converter<wchar_t, arg_setter_<char, true>>
{
static arg_setter_<wchar_t, true> conv(const arg_setter_<char, true> & in)
{
std::vector<std::wstring> vec(in._args.size());
std::transform(in._args.begin(), in._args.end(), vec.begin(),
[](const std::string & ws)
{
return ::boost::process::detail::convert(ws);
});
template<>
struct char_converter<wchar_t, arg_setter_<char, true>>
{
static arg_setter_<wchar_t, true> conv(const arg_setter_<char, true> & in)
{
std::vector<std::wstring> vec(in._args.size());
std::transform(in._args.begin(), in._args.end(), vec.begin(),
[](const std::string & ws)
{
return ::boost::process::detail::convert(ws);
});
return {vec};
}
};
return {vec};
}
};
template<>
struct char_converter<char, arg_setter_<wchar_t, false>>
{
static arg_setter_<char, false> conv(const arg_setter_<wchar_t, false> & in)
{
std::vector<std::string> vec(in._args.size());
std::transform(in._args.begin(), in._args.end(), vec.begin(),
[](const std::wstring & ws)
{
return ::boost::process::detail::convert(ws);
});
return {vec}; }
};
template<>
struct char_converter<char, arg_setter_<wchar_t, false>>
{
static arg_setter_<char, false> conv(const arg_setter_<wchar_t, false> & in)
{
std::vector<std::string> vec(in._args.size());
std::transform(in._args.begin(), in._args.end(), vec.begin(),
[](const std::wstring & ws)
{
return ::boost::process::detail::convert(ws);
});
return {vec}; }
};
template<>
struct char_converter<wchar_t, arg_setter_<char, false>>
{
static arg_setter_<wchar_t, false> conv(const arg_setter_<char, false> & in)
{
std::vector<std::wstring> vec(in._args.size());
std::transform(in._args.begin(), in._args.end(), vec.begin(),
[](const std::string & ws)
{
return ::boost::process::detail::convert(ws);
});
return {vec};
}
};
template<>
struct char_converter<wchar_t, arg_setter_<char, false>>
{
static arg_setter_<wchar_t, false> conv(const arg_setter_<char, false> & in)
{
std::vector<std::wstring> vec(in._args.size());
std::transform(in._args.begin(), in._args.end(), vec.begin(),
[](const std::string & ws)
{
return ::boost::process::detail::convert(ws);
});
return {vec};
}
};
using api::exe_cmd_init;
using api::exe_cmd_init;
template<typename Char>
struct exe_builder
{
//set by path, because that will not be interpreted as a cmd
bool not_cmd = false;
bool shell = false;
using string_type = std::basic_string<Char>;
string_type exe;
std::vector<string_type> args;
template<typename Char>
struct exe_builder
{
//set by path, because that will not be interpreted as a cmd
bool not_cmd = false;
bool shell = false;
using string_type = std::basic_string<Char>;
string_type exe;
std::vector<string_type> args;
void operator()(const boost::filesystem::path & data)
{
not_cmd = true;
if (exe.empty())
exe = data.native();
else
args.push_back(data.native());
}
void operator()(const boost::filesystem::path & data)
{
not_cmd = true;
if (exe.empty())
exe = data.native();
else
args.push_back(data.native());
}
void operator()(const string_type & data)
{
if (exe.empty())
exe = data;
else
args.push_back(data);
}
void operator()(const Char* data)
{
if (exe.empty())
exe = data;
else
args.push_back(data);
}
void operator()(shell_) {shell = true;}
void operator()(std::vector<string_type> && data)
{
if (data.empty())
return;
void operator()(const string_type & data)
{
if (exe.empty())
exe = data;
else
args.push_back(data);
}
void operator()(const Char* data)
{
if (exe.empty())
exe = data;
else
args.push_back(data);
}
void operator()(shell_) {shell = true;}
void operator()(std::vector<string_type> && data)
{
if (data.empty())
return;
auto itr = std::make_move_iterator(data.begin());
auto end = std::make_move_iterator(data.end());
auto itr = std::make_move_iterator(data.begin());
auto end = std::make_move_iterator(data.end());
if (exe.empty())
{
exe = *itr;
itr++;
}
args.insert(args.end(), itr, end);
}
if (exe.empty())
{
exe = *itr;
itr++;
}
args.insert(args.end(), itr, end);
}
void operator()(const std::vector<string_type> & data)
{
if (data.empty())
return;
void operator()(const std::vector<string_type> & data)
{
if (data.empty())
return;
auto itr = data.begin();
auto end = data.end();
auto itr = data.begin();
auto end = data.end();
if (exe.empty())
{
exe = *itr;
itr++;
}
args.insert(args.end(), itr, end);
}
void operator()(exe_setter_<Char> && data)
{
not_cmd = true;
exe = std::move(data.exe_);
}
void operator()(const exe_setter_<Char> & data)
{
not_cmd = true;
exe = data.exe_;
}
void operator()(arg_setter_<Char, false> && data)
{
args.assign(
std::make_move_iterator(data._args.begin()),
std::make_move_iterator(data._args.end()));
}
void operator()(arg_setter_<Char, true> && data)
{
args.insert(args.end(),
std::make_move_iterator(data._args.begin()),
std::make_move_iterator(data._args.end()));
}
void operator()(const arg_setter_<Char, false> & data)
{
args.assign(data._args.begin(), data._args.end());
}
void operator()(const arg_setter_<Char, true> & data)
{
args.insert(args.end(), data._args.begin(), data._args.end());
}
if (exe.empty())
{
exe = *itr;
itr++;
}
args.insert(args.end(), itr, end);
}
void operator()(exe_setter_<Char> && data)
{
not_cmd = true;
exe = std::move(data.exe_);
}
void operator()(const exe_setter_<Char> & data)
{
not_cmd = true;
exe = data.exe_;
}
void operator()(arg_setter_<Char, false> && data)
{
args.assign(
std::make_move_iterator(data._args.begin()),
std::make_move_iterator(data._args.end()));
}
void operator()(arg_setter_<Char, true> && data)
{
args.insert(args.end(),
std::make_move_iterator(data._args.begin()),
std::make_move_iterator(data._args.end()));
}
void operator()(const arg_setter_<Char, false> & data)
{
args.assign(data._args.begin(), data._args.end());
}
void operator()(const arg_setter_<Char, true> & data)
{
args.insert(args.end(), data._args.begin(), data._args.end());
}
api::exe_cmd_init<Char> get_initializer()
{
if (not_cmd || !args.empty())
{
if (shell)
return api::exe_cmd_init<Char>::exe_args_shell(std::move(exe), std::move(args));
else
return api::exe_cmd_init<Char>::exe_args(std::move(exe), std::move(args));
}
else
if (shell)
return api::exe_cmd_init<Char>::cmd_shell(std::move(exe));
else
return api::exe_cmd_init<Char>::cmd(std::move(exe));
api::exe_cmd_init<Char> get_initializer()
{
if (not_cmd || !args.empty())
{
if (shell)
return api::exe_cmd_init<Char>::exe_args_shell(std::move(exe), std::move(args));
else
return api::exe_cmd_init<Char>::exe_args(std::move(exe), std::move(args));
}
else
if (shell)
return api::exe_cmd_init<Char>::cmd_shell(std::move(exe));
else
return api::exe_cmd_init<Char>::cmd(std::move(exe));
}
typedef api::exe_cmd_init<Char> result_type;
};
}
typedef api::exe_cmd_init<Char> result_type;
};
template<>
struct initializer_builder<cmd_or_exe_tag<char>>
{
typedef exe_builder<char> type;
};
template<>
struct initializer_builder<cmd_or_exe_tag<char>>
{
typedef exe_builder<char> type;
};
template<>
struct initializer_builder<cmd_or_exe_tag<wchar_t>>
{
typedef exe_builder<wchar_t> type;
};
template<>
struct initializer_builder<cmd_or_exe_tag<wchar_t>>
{
typedef exe_builder<wchar_t> type;
};
}}}
}}}
#endif /* BOOST_PROCESS_DETAIL_EXE_BUILDER_HPP_ */
#endif /* BOOST_PROCESS_DETAIL_EXE_BUILDER_HPP_ */

View File

@@ -65,7 +65,8 @@ public:
child(child && lhs) noexcept
: _child_handle(std::move(lhs._child_handle)),
_exit_status(std::move(lhs._exit_status)),
_attached (lhs._attached)
_attached (lhs._attached),
_terminated (lhs._terminated)
{
lhs._attached = false;
}
@@ -79,6 +80,7 @@ public:
_child_handle= std::move(lhs._child_handle);
_exit_status = std::move(lhs._exit_status);
_attached = lhs._attached;
_terminated = lhs._terminated;
lhs._attached = false;
return *this;
};
@@ -101,72 +103,52 @@ public:
bool running()
{
if (valid() && !_exited())
{
int code;
auto res = boost::process::detail::api::is_running(_child_handle, code);
if (!res && !_exited())
_exit_status->store(code);
return res;
}
return false;
std::error_code ec;
bool b = running(ec);
boost::process::detail::throw_error(ec, "running error");
return b;
}
void terminate()
{
if (valid() && running())
boost::process::detail::api::terminate(_child_handle);
_terminated = true;
std::error_code ec;
terminate(ec);
boost::process::detail::throw_error(ec, "terminate error");
}
void wait()
{
if (!_exited() && valid())
{
int exit_code = 0;
boost::process::detail::api::wait(_child_handle, exit_code);
_exit_status->store(exit_code);
}
std::error_code ec;
wait(ec);
boost::process::detail::throw_error(ec, "wait error");
}
template< class Rep, class Period >
bool wait_for (const std::chrono::duration<Rep, Period>& rel_time)
bool wait_for (const std::chrono::duration<Rep, Period>& rel_time)
{
if (!_exited())
{
int exit_code = 0;
auto b = boost::process::detail::api::wait_for(_child_handle, exit_code, rel_time);
if (!b)
return false;
_exit_status->store(exit_code);
}
return true;
std::error_code ec;
bool b = wait_for(rel_time, ec);
boost::process::detail::throw_error(ec, "wait_for error");
return b;
}
template< class Clock, class Duration >
bool wait_until(const std::chrono::time_point<Clock, Duration>& timeout_time )
{
if (!_exited())
{
int exit_code = 0;
auto b = boost::process::detail::api::wait_until(_child_handle, exit_code, timeout_time);
if (!b)
return false;
_exit_status->store(exit_code);
}
return true;
std::error_code ec;
bool b = wait_until(timeout_time, ec);
boost::process::detail::throw_error(ec, "wait_until error");
return b;
}
bool running(std::error_code & ec) noexcept
{
if (valid() && !_exited())
{
int code;
auto res = boost::process::detail::api::is_running(_child_handle, code, ec);
int exit_code = 0;
auto res = boost::process::detail::api::is_running(_child_handle, exit_code, ec);
if (!res && !_exited())
_exit_status->store(code);
_exit_status->store(exit_code);
return res;
}
@@ -192,17 +174,9 @@ public:
}
template< class Rep, class Period >
bool wait_for (const std::chrono::duration<Rep, Period>& rel_time, std::error_code & ec) noexcept
bool wait_for (const std::chrono::duration<Rep, Period>& rel_time, std::error_code & ec) noexcept
{
if (!_exited())
{
int exit_code = 0;
auto b = boost::process::detail::api::wait_for(_child_handle, exit_code, rel_time, ec);
if (!b)
return false;
_exit_status->store(exit_code);
}
return true;
return wait_until(std::chrono::steady_clock::now() + rel_time, ec);
}
template< class Clock, class Duration >

View File

@@ -31,7 +31,7 @@
extern char **environ;
#endif
#elif defined(BOOST_WINDOWS_API)
#include <boost/detail/winapi/get_last_error.hpp>
#include <boost/winapi/get_last_error.hpp>
#else
#error "System API not supported by boost.process"
#endif
@@ -53,7 +53,7 @@ inline std::error_code get_last_error() noexcept
}
//copied from linux spec.
#if defined (__USE_XOPEN_EXTENDED) && !defined (__USE_XOPEN2K8) || defined( __USE_BSD)
#if (_XOPEN_SOURCE >= 500 || _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED) && !(_POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700)
#define BOOST_POSIX_HAS_VFORK 1
#endif
@@ -63,7 +63,7 @@ namespace api = windows;
inline std::error_code get_last_error() noexcept
{
return std::error_code(::boost::detail::winapi::GetLastError(), std::system_category());
return std::error_code(::boost::winapi::GetLastError(), std::system_category());
}
#endif
@@ -72,11 +72,27 @@ inline void throw_last_error(const std::string & msg)
throw process_error(get_last_error(), msg);
}
inline void throw_last_error(const char * msg)
{
throw process_error(get_last_error(), msg);
}
inline void throw_last_error()
{
throw process_error(get_last_error());
}
inline void throw_error(const std::error_code& ec)
{
if (ec)
throw process_error(ec);
}
inline void throw_error(const std::error_code& ec, const char* msg)
{
if (ec)
throw process_error(ec, msg);
}
template<typename Char> constexpr Char null_char();
template<> constexpr char null_char<char> (){return '\0';}

View File

@@ -1,75 +1,75 @@
// Copyright (c) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Copyright (c) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PROCESS_DETAIL_HANDLER_HPP_
#define BOOST_PROCESS_DETAIL_HANDLER_HPP_
#ifndef BOOST_PROCESS_DETAIL_HANDLER_HPP_
#define BOOST_PROCESS_DETAIL_HANDLER_HPP_
#include <boost/process/detail/config.hpp>
#include <boost/process/detail/config.hpp>
#if defined(BOOST_POSIX_API)
#include <boost/process/detail/posix/handler.hpp>
#elif defined(BOOST_WINDOWS_API)
#include <boost/process/detail/windows/handler.hpp>
#endif
#if defined(BOOST_POSIX_API)
#include <boost/process/detail/posix/handler.hpp>
#elif defined(BOOST_WINDOWS_API)
#include <boost/process/detail/windows/handler.hpp>
#endif
namespace boost { namespace process { namespace detail {
namespace boost { namespace process { namespace detail {
//extended handler base.
typedef api::handler_base_ext handler;
//extended handler base.
typedef api::handler_base_ext handler;
template <class Handler>
struct on_setup_ : handler
{
explicit on_setup_(Handler handler) : handler_(handler) {}
template <class Handler>
struct on_setup_ : handler
{
explicit on_setup_(Handler handler) : handler_(handler) {}
template <class Executor>
void on_setup(Executor &e)
{
handler_(e);
}
private:
Handler handler_;
};
template <class Executor>
void on_setup(Executor &e)
{
handler_(e);
}
private:
Handler handler_;
};
template <class Handler>
struct on_error_ : handler
{
explicit on_error_(Handler handler) : handler_(handler) {}
template <class Handler>
struct on_error_ : handler
{
explicit on_error_(Handler handler) : handler_(handler) {}
template <class Executor>
void on_error(Executor &e, const std::error_code &ec)
{
handler_(e, ec);
}
private:
Handler handler_;
};
template <class Executor>
void on_error(Executor &e, const std::error_code &ec)
{
handler_(e, ec);
}
private:
Handler handler_;
};
template <class Handler>
struct on_success_ : handler
{
explicit on_success_(Handler handler) : handler_(handler) {}
template <class Handler>
struct on_success_ : handler
{
explicit on_success_(Handler handler) : handler_(handler) {}
template <class Executor>
void on_success(Executor &e)
{
handler_(e);
}
private:
Handler handler_;
};
template <class Executor>
void on_success(Executor &e)
{
handler_(e);
}
private:
Handler handler_;
};
}
}
}}
}}
#endif /* BOOST_PROCESS_DETAIL_HANDLER_HPP_ */
#endif /* BOOST_PROCESS_DETAIL_HANDLER_HPP_ */

View File

@@ -20,34 +20,33 @@ template<typename Allocator>
class basic_streambuf;
typedef basic_streambuf<std::allocator<char>> streambuf;
class io_service;
class io_context;
#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
class signal_set_service;
template <typename SignalSetService>
class basic_signal_set;
typedef basic_signal_set<signal_set_service> signal_set;
#else /* defined(BOOST_ASIO_ENABLE_OLD_SERVICES) */
class signal_set;
#endif /* defined(BOOST_ASIO_ENABLE_OLD_SERVICES) */
template <typename Handler>
class basic_yield_context;
namespace posix {
#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
class stream_descriptor_service;
template <typename StreamDesscriptorService>
class basic_stream_descriptor;
typedef basic_stream_descriptor<stream_descriptor_service> stream_descriptor;
class object_handle_service;
template <typename ObjectHandleService>
class basic_object_handle;
typedef basic_object_handle<object_handle_service> object_handle;
#else /* defined(BOOST_ASIO_ENABLE_OLD_SERVICES) */
class stream_descriptor;
#endif /* defined(BOOST_ASIO_ENABLE_OLD_SERVICES) */
} //posix
} //asio

View File

@@ -1,40 +1,40 @@
// Copyright (c) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Copyright (c) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PROCESS_POSIX_ASYNC_HANDLER_HPP_
#define BOOST_PROCESS_POSIX_ASYNC_HANDLER_HPP_
#ifndef BOOST_PROCESS_POSIX_ASYNC_HANDLER_HPP_
#define BOOST_PROCESS_POSIX_ASYNC_HANDLER_HPP_
#include <boost/process/detail/posix/handler.hpp>
#include <type_traits>
#include <boost/process/detail/posix/handler.hpp>
#include <type_traits>
namespace boost { namespace process { namespace detail { namespace posix {
namespace boost { namespace process { namespace detail { namespace posix {
struct require_io_service {};
struct require_io_context {};
struct async_handler : handler_base_ext, require_io_service
{
};
struct async_handler : handler_base_ext, require_io_context
{
};
template<typename T>
struct is_async_handler : std::is_base_of<async_handler, T> {};
template<typename T>
struct is_async_handler<T&> : std::is_base_of<async_handler, T> {};
template<typename T>
struct is_async_handler<const T&> : std::is_base_of<async_handler, T> {};
template<typename T>
struct is_async_handler : std::is_base_of<async_handler, T> {};
template<typename T>
struct is_async_handler<T&> : std::is_base_of<async_handler, T> {};
template<typename T>
struct is_async_handler<const T&> : std::is_base_of<async_handler, T> {};
template<typename T>
struct does_require_io_service : std::is_base_of<require_io_service, T> {};
template<typename T>
struct does_require_io_context : std::is_base_of<require_io_context, T> {};
template<typename T>
struct does_require_io_service<T&> : std::is_base_of<require_io_service, T> {};
template<typename T>
struct does_require_io_context<T&> : std::is_base_of<require_io_context, T> {};
template<typename T>
struct does_require_io_service<const T&> : std::is_base_of<require_io_service, T> {};
template<typename T>
struct does_require_io_context<const T&> : std::is_base_of<require_io_context, T> {};
}}}}
}}}}
#endif /* BOOST_PROCESS_WINDOWS_ASYNC_HANDLER_HPP_ */
#endif /* BOOST_PROCESS_WINDOWS_ASYNC_HANDLER_HPP_ */

View File

@@ -1,95 +1,97 @@
// 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)
// 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)
#ifndef BOOST_PROCESS_DETAIL_POSIX_ASYNC_IN_HPP
#define BOOST_PROCESS_DETAIL_POSIX_ASYNC_IN_HPP
#ifndef BOOST_PROCESS_DETAIL_POSIX_ASYNC_IN_HPP
#define BOOST_PROCESS_DETAIL_POSIX_ASYNC_IN_HPP
#include <boost/process/detail/handler_base.hpp>
#include <boost/process/detail/posix/async_handler.hpp>
#include <boost/asio/write.hpp>
#include <boost/process/async_pipe.hpp>
#include <memory>
#include <future>
#include <boost/process/detail/handler_base.hpp>
#include <boost/process/detail/posix/async_handler.hpp>
#include <boost/asio/write.hpp>
#include <boost/process/async_pipe.hpp>
#include <memory>
#include <future>
namespace boost { namespace process { namespace detail { namespace posix {
namespace boost { namespace process { namespace detail { namespace posix {
template<typename Buffer>
struct async_in_buffer : ::boost::process::detail::posix::handler_base_ext,
::boost::process::detail::posix::require_io_service
{
Buffer & buf;
template<typename Buffer>
struct async_in_buffer : ::boost::process::detail::posix::handler_base_ext,
::boost::process::detail::posix::require_io_context
{
Buffer & buf;
std::shared_ptr<std::promise<void>> promise;
async_in_buffer operator>(std::future<void> & fut)
{
promise = std::make_shared<std::promise<void>>();
fut = promise->get_future(); return std::move(*this);
}
std::shared_ptr<std::promise<void>> promise;
async_in_buffer operator>(std::future<void> & fut)
{
promise = std::make_shared<std::promise<void>>();
fut = promise->get_future(); return std::move(*this);
}
std::shared_ptr<boost::process::async_pipe> pipe;
std::shared_ptr<boost::process::async_pipe> pipe;
async_in_buffer(Buffer & buf) : buf(buf)
{
}
template <typename Executor>
inline void on_success(Executor &exec)
{
auto pipe = this->pipe;
if (this->promise)
{
auto promise = this->promise;
async_in_buffer(Buffer & buf) : buf(buf)
{
}
template <typename Executor>
inline void on_success(Executor &exec)
{
auto pipe = this->pipe;
if (this->promise)
{
auto promise = this->promise;
boost::asio::async_write(*pipe, buf,
[pipe, promise](const boost::system::error_code & ec, std::size_t)
{
if (ec && (ec.value() != EBADF) && (ec.value() != EPERM) && (ec.value() != ENOENT))
{
std::error_code e(ec.value(), std::system_category());
promise->set_exception(std::make_exception_ptr(process_error(e)));
}
else
promise->set_value();
});
}
else
boost::asio::async_write(*pipe, buf,
[pipe](const boost::system::error_code&ec, std::size_t size){});
boost::asio::async_write(*pipe, buf,
[pipe, promise](const boost::system::error_code & ec, std::size_t)
{
if (ec && (ec.value() != EBADF) && (ec.value() != EPERM) && (ec.value() != ENOENT))
{
std::error_code e(ec.value(), std::system_category());
promise->set_exception(std::make_exception_ptr(process_error(e)));
}
else
promise->set_value();
});
}
else
boost::asio::async_write(*pipe, buf,
[pipe](const boost::system::error_code&ec, std::size_t size){});
std::move(*pipe).source().close();
std::move(*pipe).source().close();
this->pipe = nullptr;
}
this->pipe = nullptr;
}
template<typename Executor>
void on_error(Executor &, const std::error_code &) const
{
std::move(*pipe).source().close();
}
template<typename Executor>
void on_error(Executor &, const std::error_code &) const
{
std::move(*pipe).source().close();
}
template<typename Executor>
void on_setup(Executor & exec)
{
pipe = std::make_shared<boost::process::async_pipe>(get_io_service(exec.seq));
}
template<typename Executor>
void on_setup(Executor & exec)
{
pipe = std::make_shared<boost::process::async_pipe>(get_io_context(exec.seq));
}
template <typename Executor>
void on_exec_setup(Executor &exec)
{
if (::dup2(pipe->native_source(), STDIN_FILENO) == -1)
exec.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
template <typename Executor>
void on_exec_setup(Executor &exec)
{
if (::dup2(pipe->native_source(), STDIN_FILENO) == -1)
exec.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
::close(pipe->native_source());
}
};
if (pipe->native_source() != STDIN_FILENO)
::close(pipe->native_source());
::close(pipe->native_sink());
}
};
}}}}
}}}}
#endif
#endif

View File

@@ -1,170 +1,173 @@
// 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)
// 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)
#ifndef BOOST_PROCESS_DETAIL_POSIX_ASYNC_OUT_HPP
#define BOOST_PROCESS_DETAIL_POSIX_ASYNC_OUT_HPP
#ifndef BOOST_PROCESS_DETAIL_POSIX_ASYNC_OUT_HPP
#define BOOST_PROCESS_DETAIL_POSIX_ASYNC_OUT_HPP
#include <boost/process/detail/posix/handler.hpp>
#include <boost/asio/posix/stream_descriptor.hpp>
#include <boost/asio/read.hpp>
#include <boost/process/async_pipe.hpp>
#include <istream>
#include <memory>
#include <exception>
#include <future>
#include <boost/process/detail/posix/handler.hpp>
#include <boost/asio/posix/stream_descriptor.hpp>
#include <boost/asio/read.hpp>
#include <boost/process/async_pipe.hpp>
#include <istream>
#include <memory>
#include <exception>
#include <future>
namespace boost { namespace process { namespace detail { namespace posix {
namespace boost { namespace process { namespace detail { namespace posix {
inline int apply_out_handles(int handle, std::integral_constant<int, 1>, std::integral_constant<int, -1>)
{
return ::dup2(handle, STDOUT_FILENO);
}
inline int apply_out_handles(int handle, std::integral_constant<int, 1>, std::integral_constant<int, -1>)
{
return ::dup2(handle, STDOUT_FILENO);
}
inline int apply_out_handles(int handle, std::integral_constant<int, 2>, std::integral_constant<int, -1>)
{
return ::dup2(handle, STDERR_FILENO);
}
inline int apply_out_handles(int handle, std::integral_constant<int, 2>, std::integral_constant<int, -1>)
{
return ::dup2(handle, STDERR_FILENO);
}
inline int apply_out_handles(int handle, std::integral_constant<int, 1>, std::integral_constant<int, 2>)
{
if (::dup2(handle, STDOUT_FILENO) == -1)
return -1;
if (::dup2(handle, STDERR_FILENO) == -1)
return -1;
inline int apply_out_handles(int handle, std::integral_constant<int, 1>, std::integral_constant<int, 2>)
{
if (::dup2(handle, STDOUT_FILENO) == -1)
return -1;
if (::dup2(handle, STDERR_FILENO) == -1)
return -1;
return 0;
}
return 0;
}
template<int p1, int p2, typename Buffer>
struct async_out_buffer : ::boost::process::detail::posix::handler_base_ext,
::boost::process::detail::posix::require_io_service
{
Buffer & buf;
template<int p1, int p2, typename Buffer>
struct async_out_buffer : ::boost::process::detail::posix::handler_base_ext,
::boost::process::detail::posix::require_io_context
{
Buffer & buf;
std::shared_ptr<boost::process::async_pipe> pipe;
std::shared_ptr<boost::process::async_pipe> pipe;
async_out_buffer(Buffer & buf) : buf(buf)
{
}
async_out_buffer(Buffer & buf) : buf(buf)
{
}
template <typename Executor>
inline void on_success(Executor &exec)
{
auto pipe = this->pipe;
boost::asio::async_read(*pipe, buf,
[pipe](const boost::system::error_code&, std::size_t size){});
template <typename Executor>
inline void on_success(Executor &exec)
{
auto pipe = this->pipe;
boost::asio::async_read(*pipe, buf,
[pipe](const boost::system::error_code&, std::size_t size){});
this->pipe = nullptr;
std::move(*pipe).sink().close();
}
this->pipe = nullptr;
std::move(*pipe).sink().close();
}
template<typename Executor>
void on_error(Executor &, const std::error_code &) const
{
std::move(*pipe).sink().close();
}
template<typename Executor>
void on_error(Executor &, const std::error_code &) const
{
std::move(*pipe).sink().close();
}
template<typename Executor>
void on_setup(Executor & exec)
{
pipe = std::make_shared<boost::process::async_pipe>(get_io_service(exec.seq));
}
template<typename Executor>
void on_setup(Executor & exec)
{
pipe = std::make_shared<boost::process::async_pipe>(get_io_context(exec.seq));
}
template <typename Executor>
void on_exec_setup(Executor &exec)
{
int res = apply_out_handles(pipe->native_sink(),
std::integral_constant<int, p1>(), std::integral_constant<int, p2>());
if (res == -1)
exec.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
template <typename Executor>
void on_exec_setup(Executor &exec)
{
int res = apply_out_handles(pipe->native_sink(),
std::integral_constant<int, p1>(), std::integral_constant<int, p2>());
if (res == -1)
exec.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
::close(pipe->native_sink());
}
};
::close(pipe->native_sink());
::close(pipe->native_source());
}
};
template<int p1, int p2, typename Type>
struct async_out_future : ::boost::process::detail::posix::handler_base_ext,
::boost::process::detail::posix::require_io_service
{
std::shared_ptr<std::promise<Type>> promise = std::make_shared<std::promise<Type>>();
template<int p1, int p2, typename Type>
struct async_out_future : ::boost::process::detail::posix::handler_base_ext,
::boost::process::detail::posix::require_io_context
{
std::shared_ptr<std::promise<Type>> promise = std::make_shared<std::promise<Type>>();
std::shared_ptr<boost::asio::streambuf> buffer = std::make_shared<boost::asio::streambuf>();
std::shared_ptr<boost::asio::streambuf> buffer = std::make_shared<boost::asio::streambuf>();
std::shared_ptr<boost::process::async_pipe> pipe;
std::shared_ptr<boost::process::async_pipe> pipe;
async_out_future(std::future<Type> & fut)
{
fut = promise->get_future();
}
template <typename Executor>
inline void on_success(Executor &exec)
{
auto pipe = this->pipe;
async_out_future(std::future<Type> & fut)
{
fut = promise->get_future();
}
template <typename Executor>
inline void on_success(Executor &exec)
{
auto pipe = this->pipe;
auto buffer = this->buffer;
auto promise = this->promise;
auto buffer = this->buffer;
auto promise = this->promise;
boost::asio::async_read(*pipe, *buffer,
[pipe, buffer, promise](const boost::system::error_code& ec, std::size_t size)
{
if (ec && (ec.value() != ENOENT))
{
std::error_code e(ec.value(), std::system_category());
promise->set_exception(std::make_exception_ptr(process_error(e)));
}
else
{
std::istream is (buffer.get());
Type arg;
arg.resize(buffer->size());
is.read(&*arg.begin(), buffer->size());
promise->set_value(std::move(arg));
}
});
boost::asio::async_read(*pipe, *buffer,
[pipe, buffer, promise](const boost::system::error_code& ec, std::size_t size)
{
if (ec && (ec.value() != ENOENT))
{
std::error_code e(ec.value(), std::system_category());
promise->set_exception(std::make_exception_ptr(process_error(e)));
}
else
{
std::istream is (buffer.get());
Type arg;
arg.resize(buffer->size());
is.read(&*arg.begin(), buffer->size());
promise->set_value(std::move(arg));
}
});
std::move(*pipe).sink().close();
this->pipe = nullptr;
}
std::move(*pipe).sink().close();
this->pipe = nullptr;
}
template<typename Executor>
void on_error(Executor &, const std::error_code &) const
{
std::move(*pipe).sink().close();
}
template<typename Executor>
void on_error(Executor &, const std::error_code &) const
{
std::move(*pipe).sink().close();
}
template<typename Executor>
void on_setup(Executor & exec)
{
pipe = std::make_shared<boost::process::async_pipe>(get_io_service(exec.seq));
}
template<typename Executor>
void on_setup(Executor & exec)
{
pipe = std::make_shared<boost::process::async_pipe>(get_io_context(exec.seq));
}
template <typename Executor>
void on_exec_setup(Executor &exec)
{
template <typename Executor>
void on_exec_setup(Executor &exec)
{
int res = apply_out_handles(pipe->native_sink(),
std::integral_constant<int, p1>(), std::integral_constant<int, p2>());
if (res == -1)
exec.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
int res = apply_out_handles(pipe->native_sink(),
std::integral_constant<int, p1>(), std::integral_constant<int, p2>());
if (res == -1)
exec.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
::close(pipe->native_sink());
}
::close(pipe->native_sink());
::close(pipe->native_source());
}
};
};
}}}}
}}}}
#endif
#endif

View File

@@ -11,6 +11,7 @@
#include <boost/asio/posix/stream_descriptor.hpp>
#include <system_error>
#include <string>
#include <utility>
namespace boost { namespace process { namespace detail { namespace posix {
@@ -22,10 +23,10 @@ public:
typedef int native_handle_type;
typedef ::boost::asio::posix::stream_descriptor handle_type;
inline async_pipe(boost::asio::io_service & ios) : async_pipe(ios, ios) {}
inline async_pipe(boost::asio::io_context & ios) : async_pipe(ios, ios) {}
inline async_pipe(boost::asio::io_service & ios_source,
boost::asio::io_service & ios_sink) : _source(ios_source), _sink(ios_sink)
inline async_pipe(boost::asio::io_context & ios_source,
boost::asio::io_context & ios_sink) : _source(ios_source), _sink(ios_sink)
{
int fds[2];
if (::pipe(fds) == -1)
@@ -34,11 +35,11 @@ public:
_source.assign(fds[0]);
_sink .assign(fds[1]);
};
inline async_pipe(boost::asio::io_service & ios, const std::string & name)
inline async_pipe(boost::asio::io_context & ios, const std::string & name)
: async_pipe(ios, ios, name) {}
inline async_pipe(boost::asio::io_service & ios_source,
boost::asio::io_service & io_sink, const std::string & name);
inline async_pipe(boost::asio::io_context & ios_source,
boost::asio::io_context & io_sink, const std::string & name);
inline async_pipe(const async_pipe& lhs);
async_pipe(async_pipe&& lhs) : _source(std::move(lhs._source)), _sink(std::move(lhs._sink))
{
@@ -47,15 +48,15 @@ public:
}
template<class CharT, class Traits = std::char_traits<CharT>>
explicit async_pipe(::boost::asio::io_service & ios_source,
::boost::asio::io_service & ios_sink,
explicit async_pipe(::boost::asio::io_context & ios_source,
::boost::asio::io_context & ios_sink,
const basic_pipe<CharT, Traits> & p)
: _source(ios_source, p.native_source()), _sink(ios_sink, p.native_sink())
{
}
template<class CharT, class Traits = std::char_traits<CharT>>
explicit async_pipe(boost::asio::io_service & ios, const basic_pipe<CharT, Traits> & p)
explicit async_pipe(boost::asio::io_context & ios, const basic_pipe<CharT, Traits> & p)
: async_pipe(ios, ios, p)
{
}
@@ -68,10 +69,10 @@ public:
~async_pipe()
{
if (_sink .native() != -1)
::close(_sink.native());
if (_source.native() != -1)
::close(_source.native());
if (_sink .native_handle() != -1)
::close(_sink.native_handle());
if (_source.native_handle() != -1)
::close(_source.native_handle());
}
template<class CharT, class Traits = std::char_traits<CharT>>
@@ -108,9 +109,9 @@ public:
void async_close()
{
if (_sink.is_open())
_sink.get_io_service(). post([this]{_sink.close();});
_sink.get_io_context(). post([this]{_sink.close();});
if (_source.is_open())
_source.get_io_service().post([this]{_source.close();});
_source.get_io_context().post([this]{_source.close();});
}
template<typename MutableBufferSequence>
@@ -124,8 +125,8 @@ public:
return _sink.write_some(buffers);
}
native_handle_type native_source() const {return const_cast<boost::asio::posix::stream_descriptor&>(_source).native();}
native_handle_type native_sink () const {return const_cast<boost::asio::posix::stream_descriptor&>(_sink ).native();}
native_handle_type native_source() const {return const_cast<boost::asio::posix::stream_descriptor&>(_source).native_handle();}
native_handle_type native_sink () const {return const_cast<boost::asio::posix::stream_descriptor&>(_sink ).native_handle();}
template<typename MutableBufferSequence,
typename ReadHandler>
@@ -156,32 +157,32 @@ public:
handle_type && sink() && { return std::move(_sink); }
handle_type && source()&& { return std::move(_source); }
handle_type source(::boost::asio::io_service& ios) &&
handle_type source(::boost::asio::io_context& ios) &&
{
::boost::asio::posix::stream_descriptor stolen(ios, _source.release());
return stolen;
}
handle_type sink (::boost::asio::io_service& ios) &&
handle_type sink (::boost::asio::io_context& ios) &&
{
::boost::asio::posix::stream_descriptor stolen(ios, _sink.release());
return stolen;
}
handle_type source(::boost::asio::io_service& ios) const &
handle_type source(::boost::asio::io_context& ios) const &
{
auto source_in = const_cast<::boost::asio::posix::stream_descriptor &>(_source).native();
auto source_in = const_cast<::boost::asio::posix::stream_descriptor &>(_source).native_handle();
return ::boost::asio::posix::stream_descriptor(ios, ::dup(source_in));
}
handle_type sink (::boost::asio::io_service& ios) const &
handle_type sink (::boost::asio::io_context& ios) const &
{
auto sink_in = const_cast<::boost::asio::posix::stream_descriptor &>(_sink).native();
auto sink_in = const_cast<::boost::asio::posix::stream_descriptor &>(_sink).native_handle();
return ::boost::asio::posix::stream_descriptor(ios, ::dup(sink_in));
}
};
async_pipe::async_pipe(boost::asio::io_service & ios_source,
boost::asio::io_service & ios_sink,
async_pipe::async_pipe(boost::asio::io_context & ios_source,
boost::asio::io_context & ios_sink,
const std::string & name) : _source(ios_source), _sink(ios_sink)
{
auto fifo = mkfifo(name.c_str(), 0666 );
@@ -205,19 +206,19 @@ async_pipe::async_pipe(boost::asio::io_service & ios_source,
}
async_pipe::async_pipe(const async_pipe & p) :
_source(const_cast<async_pipe&>(p)._source.get_io_service()),
_sink( const_cast<async_pipe&>(p)._sink.get_io_service())
_source(const_cast<async_pipe&>(p)._source.get_io_context()),
_sink( const_cast<async_pipe&>(p)._sink.get_io_context())
{
//cannot get the handle from a const object.
auto source_in = const_cast<::boost::asio::posix::stream_descriptor &>(_source).native();
auto sink_in = const_cast<::boost::asio::posix::stream_descriptor &>(_sink).native();
auto source_in = const_cast<::boost::asio::posix::stream_descriptor &>(_source).native_handle();
auto sink_in = const_cast<::boost::asio::posix::stream_descriptor &>(_sink).native_handle();
if (source_in == -1)
_source.assign(-1);
else
{
_source.assign(::dup(source_in));
if (_source.native()== -1)
if (_source.native_handle()== -1)
::boost::process::detail::throw_last_error("dup()");
}
@@ -226,7 +227,7 @@ async_pipe::async_pipe(const async_pipe & p) :
else
{
_sink.assign(::dup(sink_in));
if (_sink.native() == -1)
if (_sink.native_handle() == -1)
::boost::process::detail::throw_last_error("dup()");
}
}
@@ -237,8 +238,8 @@ async_pipe& async_pipe::operator=(const async_pipe & p)
int sink;
//cannot get the handle from a const object.
auto source_in = const_cast<::boost::asio::posix::stream_descriptor &>(_source).native();
auto sink_in = const_cast<::boost::asio::posix::stream_descriptor &>(_sink).native();
auto source_in = const_cast<::boost::asio::posix::stream_descriptor &>(_source).native_handle();
auto sink_in = const_cast<::boost::asio::posix::stream_descriptor &>(_sink).native_handle();
if (source_in == -1)
source = -1;
else
@@ -264,16 +265,8 @@ async_pipe& async_pipe::operator=(const async_pipe & p)
async_pipe& async_pipe::operator=(async_pipe && lhs)
{
if (_source.native_handle() == -1)
::close(_source.native());
if (_sink.native_handle() == -1)
::close(_sink.native());
_source.assign(lhs._source.native_handle());
_sink .assign(lhs._sink .native_handle());
lhs._source.assign(-1);
lhs._sink .assign(-1);
std::swap(_source, lhs._source);
std::swap(_sink, lhs._sink);
return *this;
}
@@ -284,8 +277,8 @@ async_pipe::operator basic_pipe<CharT, Traits>() const
int sink;
//cannot get the handle from a const object.
auto source_in = const_cast<::boost::asio::posix::stream_descriptor &>(_source).native();
auto sink_in = const_cast<::boost::asio::posix::stream_descriptor &>(_sink).native();
auto source_in = const_cast<::boost::asio::posix::stream_descriptor &>(_source).native_handle();
auto sink_in = const_cast<::boost::asio::posix::stream_descriptor &>(_sink).native_handle();
if (source_in == -1)

View File

@@ -118,12 +118,8 @@ struct exe_cmd_init<char> : boost::process::detail::api::handler_base_ext
else
exec.exe = &exe.front();
if (!args.empty())
{
cmd_impl = make_cmd();
exec.cmd_line = cmd_impl.data();
}
cmd_impl = make_cmd();
exec.cmd_line = cmd_impl.data();
}
static exe_cmd_init exe_args(std::string && exe, std::vector<std::string> && args) {return exe_cmd_init(std::move(exe), std::move(args));}
static exe_cmd_init cmd (std::string && cmd)
@@ -163,8 +159,10 @@ std::vector<char*> exe_cmd_init<char>::make_cmd()
if (!exe.empty())
vec.push_back(&exe.front());
for (auto & v : args)
vec.push_back(&v.front());
if (!args.empty()) {
for (auto & v : args)
vec.push_back(&v.front());
}
vec.push_back(nullptr);

View File

@@ -29,7 +29,7 @@ class basic_pipe
int _sink = -1;
public:
explicit basic_pipe(int source, int sink) : _source(source), _sink(sink) {}
explicit basic_pipe(int source, int sink, const std::string & name) : _source(source), _sink(sink) {}
explicit basic_pipe(int source, int sink, const std::string&) : _source(source), _sink(sink) {}
typedef CharT char_type ;
typedef Traits traits_type;
typedef typename Traits::int_type int_type ;
@@ -105,8 +105,10 @@ public:
void close()
{
::close(_source);
::close(_sink);
if (_source != -1)
::close(_source);
if (_sink != -1)
::close(_sink);
_source = -1;
_sink = -1;
}

View File

@@ -44,7 +44,7 @@ struct child_handle
return pid;
}
bool in_group() const {return true;}
bool in_group(std::error_code &ec) const noexcept {return true;}
bool in_group(std::error_code&) const noexcept {return true;}
typedef int process_handle_t;
process_handle_t process_handle() const { return pid; }

View File

@@ -1,322 +1,322 @@
// Copyright (c) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Copyright (c) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PROCESS_DETAIL_POSIX_ENVIRONMENT_HPP_
#define BOOST_PROCESS_DETAIL_POSIX_ENVIRONMENT_HPP_
#ifndef BOOST_PROCESS_DETAIL_POSIX_ENVIRONMENT_HPP_
#define BOOST_PROCESS_DETAIL_POSIX_ENVIRONMENT_HPP_
#include <string>
#include <vector>
#include <unordered_map>
#include <boost/process/detail/config.hpp>
#include <algorithm>
#include <cstdlib>
#include <boost/process/locale.hpp>
#include <string>
#include <vector>
#include <unordered_map>
#include <boost/process/detail/config.hpp>
#include <algorithm>
#include <cstdlib>
#include <boost/process/locale.hpp>
namespace boost { namespace process { namespace detail { namespace posix {
namespace boost { namespace process { namespace detail { namespace posix {
template<typename Char>
class native_environment_impl
{
static std::vector<std::basic_string<Char>> _load()
{
std::vector<std::basic_string<Char>> val;
auto p = environ;
while (*p != nullptr)
{
std::string str = *p;
val.push_back(::boost::process::detail::convert(str));
p++;
}
return val;
}
static std::vector<Char*> _load_var(std::vector<std::basic_string<Char>> & vec)
{
std::vector<Char*> val;
val.resize(vec.size() + 1);
std::transform(vec.begin(), vec.end(), val.begin(),
[](std::basic_string<Char> & str)
{
return &str.front();
});
val.back() = nullptr;
return val;
}
std::vector<std::basic_string<Char>> _buffer = _load();
std::vector<Char*> _impl = _load_var(_buffer);
public:
using char_type = Char;
using pointer_type = const char_type*;
using string_type = std::basic_string<char_type>;
using native_handle_type = char_type **;
template<typename Char>
class native_environment_impl
{
static std::vector<std::basic_string<Char>> _load()
{
std::vector<std::basic_string<Char>> val;
auto p = environ;
while (*p != nullptr)
{
std::string str = *p;
val.push_back(::boost::process::detail::convert(str));
p++;
}
return val;
}
static std::vector<Char*> _load_var(std::vector<std::basic_string<Char>> & vec)
{
std::vector<Char*> val;
val.resize(vec.size() + 1);
std::transform(vec.begin(), vec.end(), val.begin(),
[](std::basic_string<Char> & str)
{
return &str.front();
});
val.back() = nullptr;
return val;
}
std::vector<std::basic_string<Char>> _buffer = _load();
std::vector<Char*> _impl = _load_var(_buffer);
public:
using char_type = Char;
using pointer_type = const char_type*;
using string_type = std::basic_string<char_type>;
using native_handle_type = char_type **;
void reload()
{
_buffer = _load();
_impl = _load_var(_buffer);
}
void reload()
{
_buffer = _load();
_impl = _load_var(_buffer);
}
string_type get(const pointer_type id) { return get(string_type(id)); }
void set(const pointer_type id, const pointer_type value)
{
set(string_type(id), string_type(value));
}
void reset(const pointer_type id) { reset(string_type(id)); }
string_type get(const pointer_type id) { return get(string_type(id)); }
void set(const pointer_type id, const pointer_type value)
{
set(string_type(id), string_type(value));
}
void reset(const pointer_type id) { reset(string_type(id)); }
string_type get(const string_type & id)
{
std::string id_c = ::boost::process::detail::convert(id);
std::string g = ::getenv(id_c.c_str());
return ::boost::process::detail::convert(g.c_str());
}
void set(const string_type & id, const string_type & value)
{
std::string id_c = ::boost::process::detail::convert(id.c_str());
std::string value_c = ::boost::process::detail::convert(value.c_str());
auto res = ::setenv(id_c.c_str(), value_c.c_str(), true);
if (res != 0)
boost::process::detail::throw_last_error();
}
void reset(const string_type & id)
{
std::string id_c = ::boost::process::detail::convert(id.c_str());
auto res = ::unsetenv(id_c.c_str());
if (res != 0)
::boost::process::detail::throw_last_error();
}
string_type get(const string_type & id)
{
std::string id_c = ::boost::process::detail::convert(id);
std::string g = ::getenv(id_c.c_str());
return ::boost::process::detail::convert(g.c_str());
}
void set(const string_type & id, const string_type & value)
{
std::string id_c = ::boost::process::detail::convert(id.c_str());
std::string value_c = ::boost::process::detail::convert(value.c_str());
auto res = ::setenv(id_c.c_str(), value_c.c_str(), true);
if (res != 0)
boost::process::detail::throw_last_error();
}
void reset(const string_type & id)
{
std::string id_c = ::boost::process::detail::convert(id.c_str());
auto res = ::unsetenv(id_c.c_str());
if (res != 0)
::boost::process::detail::throw_last_error();
}
native_environment_impl() = default;
native_environment_impl(const native_environment_impl& ) = delete;
native_environment_impl(native_environment_impl && ) = default;
native_environment_impl & operator=(const native_environment_impl& ) = delete;
native_environment_impl & operator=(native_environment_impl && ) = default;
native_handle_type _env_impl = _impl.data();
native_environment_impl() = default;
native_environment_impl(const native_environment_impl& ) = delete;
native_environment_impl(native_environment_impl && ) = default;
native_environment_impl & operator=(const native_environment_impl& ) = delete;
native_environment_impl & operator=(native_environment_impl && ) = default;
native_handle_type _env_impl = _impl.data();
native_handle_type native_handle() const {return environ;}
};
native_handle_type native_handle() const {return environ;}
};
template<>
class native_environment_impl<char>
{
public:
using char_type = char;
using pointer_type = const char_type*;
using string_type = std::basic_string<char_type>;
using native_handle_type = char_type **;
template<>
class native_environment_impl<char>
{
public:
using char_type = char;
using pointer_type = const char_type*;
using string_type = std::basic_string<char_type>;
using native_handle_type = char_type **;
void reload() {this->_env_impl = ::environ;}
void reload() {this->_env_impl = ::environ;}
string_type get(const pointer_type id) { return getenv(id); }
void set(const pointer_type id, const pointer_type value)
{
auto res = ::setenv(id, value, 1);
if (res != 0)
boost::process::detail::throw_last_error();
reload();
}
void reset(const pointer_type id)
{
auto res = ::unsetenv(id);
if (res != 0)
boost::process::detail::throw_last_error();
reload();
}
string_type get(const pointer_type id) { return getenv(id); }
void set(const pointer_type id, const pointer_type value)
{
auto res = ::setenv(id, value, 1);
if (res != 0)
boost::process::detail::throw_last_error();
reload();
}
void reset(const pointer_type id)
{
auto res = ::unsetenv(id);
if (res != 0)
boost::process::detail::throw_last_error();
reload();
}
string_type get(const string_type & id) {return get(id.c_str());}
void set(const string_type & id, const string_type & value) {set(id.c_str(), value.c_str()); }
void reset(const string_type & id) {reset(id.c_str());}
string_type get(const string_type & id) {return get(id.c_str());}
void set(const string_type & id, const string_type & value) {set(id.c_str(), value.c_str()); }
void reset(const string_type & id) {reset(id.c_str());}
native_environment_impl() = default;
native_environment_impl(const native_environment_impl& ) = delete;
native_environment_impl(native_environment_impl && ) = default;
native_environment_impl & operator=(const native_environment_impl& ) = delete;
native_environment_impl & operator=(native_environment_impl && ) = default;
native_handle_type _env_impl = environ;
native_environment_impl() = default;
native_environment_impl(const native_environment_impl& ) = delete;
native_environment_impl(native_environment_impl && ) = default;
native_environment_impl & operator=(const native_environment_impl& ) = delete;
native_environment_impl & operator=(native_environment_impl && ) = default;
native_handle_type _env_impl = environ;
native_handle_type native_handle() const {return ::environ;}
};
native_handle_type native_handle() const {return ::environ;}
};
template<typename Char>
struct basic_environment_impl
{
std::vector<std::basic_string<Char>> _data {};
static std::vector<Char*> _load_var(std::vector<std::basic_string<Char>> & data);
std::vector<Char*> _env_arr{_load_var(_data)};
public:
using char_type = Char;
using pointer_type = const char_type*;
using string_type = std::basic_string<char_type>;
using native_handle_type = Char**;
void reload()
{
_env_arr = _load_var(_data);
_env_impl = _env_arr.data();
}
template<typename Char>
struct basic_environment_impl
{
std::vector<std::basic_string<Char>> _data {};
static std::vector<Char*> _load_var(std::vector<std::basic_string<Char>> & data);
std::vector<Char*> _env_arr{_load_var(_data)};
public:
using char_type = Char;
using pointer_type = const char_type*;
using string_type = std::basic_string<char_type>;
using native_handle_type = Char**;
void reload()
{
_env_arr = _load_var(_data);
_env_impl = _env_arr.data();
}
string_type get(const pointer_type id) {return get(string_type(id));}
void set(const pointer_type id, const pointer_type value) {set(string_type(id), value);}
void reset(const pointer_type id) {reset(string_type(id));}
string_type get(const pointer_type id) {return get(string_type(id));}
void set(const pointer_type id, const pointer_type value) {set(string_type(id), value);}
void reset(const pointer_type id) {reset(string_type(id));}
string_type get(const string_type & id);
void set(const string_type & id, const string_type & value);
void reset(const string_type & id);
string_type get(const string_type & id);
void set(const string_type & id, const string_type & value);
void reset(const string_type & id);
basic_environment_impl(const native_environment_impl<Char> & nei);
basic_environment_impl() = default;
basic_environment_impl(const basic_environment_impl& rhs)
: _data(rhs._data)
{
basic_environment_impl(const native_environment_impl<Char> & nei);
basic_environment_impl() = default;
basic_environment_impl(const basic_environment_impl& rhs)
: _data(rhs._data)
{
}
basic_environment_impl(basic_environment_impl && ) = default;
basic_environment_impl & operator=(const basic_environment_impl& rhs)
{
_data = rhs._data;
_env_arr = _load_var(_data);
_env_impl = &*_env_arr.begin();
return *this;
}
basic_environment_impl & operator=(basic_environment_impl && ) = default;
}
basic_environment_impl(basic_environment_impl && ) = default;
basic_environment_impl & operator=(const basic_environment_impl& rhs)
{
_data = rhs._data;
_env_arr = _load_var(_data);
_env_impl = &*_env_arr.begin();
return *this;
}
basic_environment_impl & operator=(basic_environment_impl && ) = default;
template<typename CharR>
explicit inline basic_environment_impl(
const basic_environment_impl<CharR>& rhs,
const ::boost::process::codecvt_type & cv = ::boost::process::codecvt())
: _data(rhs._data.size())
{
std::transform(rhs._data.begin(), rhs._data.end(), _data.begin(),
[&](const std::basic_string<CharR> & st)
{
return ::boost::process::detail::convert(st, cv);
}
template<typename CharR>
explicit inline basic_environment_impl(
const basic_environment_impl<CharR>& rhs,
const ::boost::process::codecvt_type & cv = ::boost::process::codecvt())
: _data(rhs._data.size())
{
std::transform(rhs._data.begin(), rhs._data.end(), _data.begin(),
[&](const std::basic_string<CharR> & st)
{
return ::boost::process::detail::convert(st, cv);
}
);
reload();
}
);
reload();
}
template<typename CharR>
basic_environment_impl & operator=(const basic_environment_impl<CharR>& rhs)
{
_data = ::boost::process::detail::convert(rhs._data);
_env_arr = _load_var(&*_data.begin());
_env_impl = &*_env_arr.begin();
return *this;
}
template<typename CharR>
basic_environment_impl & operator=(const basic_environment_impl<CharR>& rhs)
{
_data = ::boost::process::detail::convert(rhs._data);
_env_arr = _load_var(&*_data.begin());
_env_impl = &*_env_arr.begin();
return *this;
}
Char ** _env_impl = &*_env_arr.data();
Char ** _env_impl = &*_env_arr.data();
native_handle_type native_handle() const {return &_data.front();}
};
native_handle_type native_handle() const {return &_data.front();}
};
template<typename Char>
basic_environment_impl<Char>::basic_environment_impl(const native_environment_impl<Char> & nei)
{
auto beg = nei.native_handle();
template<typename Char>
basic_environment_impl<Char>::basic_environment_impl(const native_environment_impl<Char> & nei)
{
auto beg = nei.native_handle();
auto end = beg;
while (*end != nullptr)
end++;
this->_data.assign(beg, end);
reload();
}
auto end = beg;
while (*end != nullptr)
end++;
this->_data.assign(beg, end);
reload();
}
template<typename Char>
inline auto basic_environment_impl<Char>::get(const string_type &id) -> string_type
{
auto itr = std::find_if(_data.begin(), _data.end(),
[&](const string_type & st)
{
if (st.size() <= id.size())
return false;
return std::equal(id.begin(), id.end(), st.begin()) && (st[id.size()] == equal_sign<Char>());
}
);
template<typename Char>
inline auto basic_environment_impl<Char>::get(const string_type &id) -> string_type
{
auto itr = std::find_if(_data.begin(), _data.end(),
[&](const string_type & st)
{
if (st.size() <= id.size())
return false;
return std::equal(id.begin(), id.end(), st.begin()) && (st[id.size()] == equal_sign<Char>());
}
);
if (itr == _data.end())
{
return "";
}
else return
itr->data() + id.size(); //id=Thingy -> +2 points to T
}
if (itr == _data.end())
{
return "";
}
else return
itr->data() + id.size(); //id=Thingy -> +2 points to T
}
template<typename Char>
inline void basic_environment_impl<Char>::set(const string_type &id, const string_type &value)
{
auto itr = std::find_if(_data.begin(), _data.end(),
[&](const string_type & st)
{
if (st.size() <= id.size())
return false;
return std::equal(id.begin(), id.end(), st.begin()) && (st[id.size()] == equal_sign<Char>());
}
);
template<typename Char>
inline void basic_environment_impl<Char>::set(const string_type &id, const string_type &value)
{
auto itr = std::find_if(_data.begin(), _data.end(),
[&](const string_type & st)
{
if (st.size() <= id.size())
return false;
return std::equal(id.begin(), id.end(), st.begin()) && (st[id.size()] == equal_sign<Char>());
}
);
if (itr != _data.end())
*itr = id + equal_sign<Char>() + value;
else
_data.push_back(id + equal_sign<Char>() + value);
if (itr != _data.end())
*itr = id + equal_sign<Char>() + value;
else
_data.push_back(id + equal_sign<Char>() + value);
reload();
}
reload();
}
template<typename Char>
inline void basic_environment_impl<Char>::reset(const string_type &id)
{
auto itr = std::find_if(_data.begin(), _data.end(),
[&](const string_type & st)
{
if (st.size() <= id.size())
return false;
return std::equal(id.begin(), id.end(), st.begin()) && (st[id.size()] == equal_sign<Char>());
}
);
if (itr != _data.end())
{
_data.erase(itr);//and remove it
}
reload();
template<typename Char>
inline void basic_environment_impl<Char>::reset(const string_type &id)
{
auto itr = std::find_if(_data.begin(), _data.end(),
[&](const string_type & st)
{
if (st.size() <= id.size())
return false;
return std::equal(id.begin(), id.end(), st.begin()) && (st[id.size()] == equal_sign<Char>());
}
);
if (itr != _data.end())
{
_data.erase(itr);//and remove it
}
reload();
}
}
template<typename Char>
std::vector<Char*> basic_environment_impl<Char>::_load_var(std::vector<std::basic_string<Char>> & data)
{
std::vector<Char*> ret;
ret.reserve(data.size() +1);
template<typename Char>
std::vector<Char*> basic_environment_impl<Char>::_load_var(std::vector<std::basic_string<Char>> & data)
{
std::vector<Char*> ret;
ret.reserve(data.size() +1);
for (auto & val : data)
ret.push_back(&val.front());
for (auto & val : data)
ret.push_back(&val.front());
ret.push_back(nullptr);
return ret;
}
ret.push_back(nullptr);
return ret;
}
template<typename T> constexpr T env_seperator();
template<> constexpr char env_seperator() {return ':'; }
template<> constexpr wchar_t env_seperator() {return L':'; }
template<typename T> constexpr T env_seperator();
template<> constexpr char env_seperator() {return ':'; }
template<> constexpr wchar_t env_seperator() {return L':'; }
typedef int native_handle_t;
typedef int native_handle_t;
inline int get_id() {return getpid(); }
inline int native_handle() {return getpid(); }
inline int get_id() {return getpid(); }
inline int native_handle() {return getpid(); }
}
}
}
}
}
}
}
}
#endif /* BOOST_PROCESS_DETAIL_WINDOWS_ENV_STORAGE_HPP_ */
#endif /* BOOST_PROCESS_DETAIL_WINDOWS_ENV_STORAGE_HPP_ */

View File

@@ -180,7 +180,7 @@ template<typename Sequence>
class executor
{
template<typename HasHandler, typename UseVFork>
void internal_error_handle(const std::error_code &ec, const char* msg, HasHandler, boost::mpl::true_, UseVFork) {}
void internal_error_handle(const std::error_code&, const char*, HasHandler, boost::mpl::true_, UseVFork) {}
int _pipe_sink = -1;
@@ -233,7 +233,8 @@ class executor
void check_error(boost::mpl::true_) {};
void check_error(boost::mpl::false_)
{
throw process_error(_ec, _msg);
if (_ec)
throw process_error(_ec, _msg);
}
typedef typename ::boost::process::detail::has_error_handler<Sequence>::type has_error_handler;

View File

@@ -1,76 +1,76 @@
// Copyright (c) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Copyright (c) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PROCESS_DETAIL_POSIX_FILE_DESCRIPTOR_HPP_
#define BOOST_PROCESS_DETAIL_POSIX_FILE_DESCRIPTOR_HPP_
#ifndef BOOST_PROCESS_DETAIL_POSIX_FILE_DESCRIPTOR_HPP_
#define BOOST_PROCESS_DETAIL_POSIX_FILE_DESCRIPTOR_HPP_
#include <fcntl.h>
#include <string>
#include <boost/filesystem/path.hpp>
#include <fcntl.h>
#include <string>
#include <boost/filesystem/path.hpp>
namespace boost { namespace process { namespace detail { namespace posix {
namespace boost { namespace process { namespace detail { namespace posix {
struct file_descriptor
{
enum mode_t
{
read = 1,
write = 2,
read_write = 3
};
struct file_descriptor
{
enum mode_t
{
read = 1,
write = 2,
read_write = 3
};
file_descriptor() = default;
explicit file_descriptor(const boost::filesystem::path& p, mode_t mode = read_write)
: file_descriptor(p.native(), mode)
{
}
file_descriptor() = default;
explicit file_descriptor(const boost::filesystem::path& p, mode_t mode = read_write)
: file_descriptor(p.native(), mode)
{
}
explicit file_descriptor(const std::string & path , mode_t mode = read_write)
: file_descriptor(path.c_str(), mode) {}
explicit file_descriptor(const std::string & path , mode_t mode = read_write)
: file_descriptor(path.c_str(), mode) {}
explicit file_descriptor(const char* path, mode_t mode = read_write)
: _handle(create_file(path, mode))
{
explicit file_descriptor(const char* path, mode_t mode = read_write)
: _handle(create_file(path, mode))
{
}
}
file_descriptor(const file_descriptor & ) = delete;
file_descriptor(file_descriptor && ) = default;
file_descriptor(const file_descriptor & ) = delete;
file_descriptor(file_descriptor && ) = default;
file_descriptor& operator=(const file_descriptor & ) = delete;
file_descriptor& operator=(file_descriptor && ) = default;
file_descriptor& operator=(const file_descriptor & ) = delete;
file_descriptor& operator=(file_descriptor && ) = default;
~file_descriptor()
{
if (_handle != -1)
::close(_handle);
}
~file_descriptor()
{
if (_handle != -1)
::close(_handle);
}
int handle() const { return _handle;}
int handle() const { return _handle;}
private:
static int create_file(const char* name, mode_t mode )
{
switch(mode)
{
case read:
return ::open(name, O_RDONLY);
case write:
return ::open(name, O_WRONLY | O_CREAT, 0660);
case read_write:
return ::open(name, O_RDWR | O_CREAT, 0660);
default:
return -1;
}
}
private:
static int create_file(const char* name, mode_t mode )
{
switch(mode)
{
case read:
return ::open(name, O_RDONLY);
case write:
return ::open(name, O_WRONLY | O_CREAT, 0660);
case read_write:
return ::open(name, O_RDWR | O_CREAT, 0660);
default:
return -1;
}
}
int _handle = -1;
};
int _handle = -1;
};
}}}}
}}}}
#endif /* BOOST_PROCESS_DETAIL_WINDOWS_FILE_DESCRIPTOR_HPP_ */
#endif /* BOOST_PROCESS_DETAIL_WINDOWS_FILE_DESCRIPTOR_HPP_ */

View File

@@ -1,40 +1,40 @@
// 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)
// 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)
#ifndef BOOST_PROCESS_DETAIL_POSIX_FILE_IN_HPP
#define BOOST_PROCESS_DETAIL_POSIX_FILE_IN_HPP
#ifndef BOOST_PROCESS_DETAIL_POSIX_FILE_IN_HPP
#define BOOST_PROCESS_DETAIL_POSIX_FILE_IN_HPP
#include <boost/process/pipe.hpp>
#include <boost/process/detail/posix/handler.hpp>
#include <boost/process/detail/posix/file_descriptor.hpp>
#include <cstdio>
#include <unistd.h>
#include <boost/process/pipe.hpp>
#include <boost/process/detail/posix/handler.hpp>
#include <boost/process/detail/posix/file_descriptor.hpp>
#include <cstdio>
#include <unistd.h>
namespace boost { namespace process { namespace detail { namespace posix {
namespace boost { namespace process { namespace detail { namespace posix {
struct file_in : handler_base_ext
{
file_descriptor file;
int handle = file.handle();
struct file_in : handler_base_ext
{
file_descriptor file;
int handle = file.handle();
template<typename T>
file_in(T&& t) : file(std::forward<T>(t)) {}
file_in(FILE * f) : handle(fileno(f)) {}
template<typename T>
file_in(T&& t) : file(std::forward<T>(t)) {}
file_in(FILE * f) : handle(fileno(f)) {}
template <class WindowsExecutor>
void on_exec_setup(WindowsExecutor &e) const
{
if (::dup2(handle, STDIN_FILENO) == -1)
e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
}
};
template <class WindowsExecutor>
void on_exec_setup(WindowsExecutor &e) const
{
if (::dup2(handle, STDIN_FILENO) == -1)
e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
}
};
}}}}
}}}}
#endif
#endif

View File

@@ -1,65 +1,65 @@
// 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) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// 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) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PROCESS_POSIX_FILE_OUT_HPP
#define BOOST_PROCESS_POSIX_FILE_OUT_HPP
#ifndef BOOST_PROCESS_POSIX_FILE_OUT_HPP
#define BOOST_PROCESS_POSIX_FILE_OUT_HPP
#include <boost/process/detail/posix/handler.hpp>
#include <boost/process/detail/posix/file_descriptor.hpp>
#include <boost/process/detail/posix/handler.hpp>
#include <boost/process/detail/posix/file_descriptor.hpp>
#include <unistd.h>
namespace boost { namespace process { namespace detail { namespace posix {
#include <unistd.h>
namespace boost { namespace process { namespace detail { namespace posix {
template<int p1, int p2>
struct file_out : handler_base_ext
{
file_descriptor file;
int handle = file.handle();
template<int p1, int p2>
struct file_out : handler_base_ext
{
file_descriptor file;
int handle = file.handle();
template<typename T>
file_out(T&& t) : file(std::forward<T>(t), file_descriptor::write), handle(file.handle()) {}
file_out(FILE * f) : handle(fileno(f)) {}
template<typename T>
file_out(T&& t) : file(std::forward<T>(t), file_descriptor::write), handle(file.handle()) {}
file_out(FILE * f) : handle(fileno(f)) {}
template <typename Executor>
void on_exec_setup(Executor &e) const;
};
template <typename Executor>
void on_exec_setup(Executor &e) const;
};
template<>
template<typename Executor>
void file_out<1,-1>::on_exec_setup(Executor &e) const
{
if (::dup2(handle, STDOUT_FILENO) == -1)
e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
}
template<>
template<typename Executor>
void file_out<1,-1>::on_exec_setup(Executor &e) const
{
if (::dup2(handle, STDOUT_FILENO) == -1)
e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
}
template<>
template<typename Executor>
void file_out<2,-1>::on_exec_setup(Executor &e) const
{
if (::dup2(handle, STDERR_FILENO) == -1)
e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
}
template<>
template<typename Executor>
void file_out<2,-1>::on_exec_setup(Executor &e) const
{
if (::dup2(handle, STDERR_FILENO) == -1)
e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
}
template<>
template<typename Executor>
void file_out<1,2>::on_exec_setup(Executor &e) const
{
if (::dup2(handle, STDOUT_FILENO) == -1)
e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
template<>
template<typename Executor>
void file_out<1,2>::on_exec_setup(Executor &e) const
{
if (::dup2(handle, STDOUT_FILENO) == -1)
e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
if (::dup2(handle, STDERR_FILENO) == -1)
e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
if (::dup2(handle, STDERR_FILENO) == -1)
e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
}
}
}}}}
}}}}
#endif
#endif

View File

@@ -6,14 +6,13 @@
#ifndef BOOST_PROCESS_DETAIL_POSIX_GROUP_HPP_
#define BOOST_PROCESS_DETAIL_POSIX_GROUP_HPP_
#include <boost/process/detail/config.hpp>
#include <boost/process/detail/posix/child_handle.hpp>
#include <system_error>
#include <unistd.h>
namespace boost { namespace process { namespace detail { namespace posix {
struct group_handle
{
pid_t grp = -1;
@@ -26,7 +25,6 @@ struct group_handle
{
}
group_handle() = default;
~group_handle() = default;
@@ -38,7 +36,6 @@ struct group_handle
group_handle &operator=(const group_handle & c) = delete;
group_handle &operator=(group_handle && c)
{
grp = c.grp;
c.grp = -1;
return *this;
@@ -62,23 +59,14 @@ struct group_handle
bool has(handle_t proc, std::error_code & ec) noexcept
{
return ::getpgid(proc) == grp;
}
bool valid() const
{
return grp != -1;
}
};
inline void terminate(group_handle &p)
{
if (::killpg(p.grp, SIGKILL) == -1)
boost::process::detail::throw_last_error("killpg(2) failed");
p.grp = -1;
}
inline void terminate(group_handle &p, std::error_code &ec) noexcept
{
if (::killpg(p.grp, SIGKILL) == -1)
@@ -89,15 +77,18 @@ inline void terminate(group_handle &p, std::error_code &ec) noexcept
p.grp = -1;
}
inline void terminate(group_handle &p)
{
std::error_code ec;
terminate(p, ec);
boost::process::detail::throw_error(ec, "killpg(2) failed in terminate");
}
inline bool in_group()
{
return true;
}
}}}}
#endif /* BOOST_PROCESS_DETAIL_WINDOWS_GROUP_HPP_ */

View File

@@ -28,7 +28,7 @@ struct group_ref : handler_base_ext
{}
template <class Executor>
void on_exec_setup(Executor& exec) const
void on_exec_setup(Executor&) const
{
if (grp.grp == -1)
::setpgid(0, 0);

View File

@@ -1,74 +1,74 @@
// Copyright (c) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Copyright (c) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PROCESS_DETAIL_POSIX_HANDLER_HPP_
#define BOOST_PROCESS_DETAIL_POSIX_HANDLER_HPP_
#ifndef BOOST_PROCESS_DETAIL_POSIX_HANDLER_HPP_
#define BOOST_PROCESS_DETAIL_POSIX_HANDLER_HPP_
#include <boost/process/detail/handler_base.hpp>
#include <boost/process/detail/handler_base.hpp>
namespace boost { namespace process { namespace detail { namespace posix {
namespace boost { namespace process { namespace detail { namespace posix {
//does not extend anything.
struct handler_base_ext : handler_base
{
template<typename Executor>
void on_fork_error (Executor &, const std::error_code&) const {}
//does not extend anything.
struct handler_base_ext : handler_base
{
template<typename Executor>
void on_fork_error (Executor &, const std::error_code&) const {}
template<typename Executor>
void on_exec_setup (Executor &) const {}
template<typename Executor>
void on_exec_setup (Executor &) const {}
template<typename Executor>
void on_exec_error (Executor &, const std::error_code&) const {}
};
template<typename Executor>
void on_exec_error (Executor &, const std::error_code&) const {}
};
template <class Handler>
struct on_fork_error_ : handler_base_ext
{
explicit on_fork_error_(Handler handler) : handler_(handler) {}
template <class Handler>
struct on_fork_error_ : handler_base_ext
{
explicit on_fork_error_(Handler handler) : handler_(handler) {}
template <class Executor>
void on_fork_error(Executor &e, const std::error_code &ec) const
{
handler_(e, ec);
}
private:
Handler handler_;
};
template <class Executor>
void on_fork_error(Executor &e, const std::error_code &ec) const
{
handler_(e, ec);
}
private:
Handler handler_;
};
template <class Handler>
struct on_exec_setup_ : handler_base_ext
{
explicit on_exec_setup_(Handler handler) : handler_(handler) {}
template <class Handler>
struct on_exec_setup_ : handler_base_ext
{
explicit on_exec_setup_(Handler handler) : handler_(handler) {}
template <class Executor>
void on_exec_setup(Executor &e) const
{
handler_(e);
}
private:
Handler handler_;
};
template <class Executor>
void on_exec_setup(Executor &e) const
{
handler_(e);
}
private:
Handler handler_;
};
template <class Handler>
struct on_exec_error_ : handler_base_ext
{
explicit on_exec_error_(Handler handler) : handler_(handler) {}
template <class Handler>
struct on_exec_error_ : handler_base_ext
{
explicit on_exec_error_(Handler handler) : handler_(handler) {}
template <class Executor>
void on_exec_error(Executor &e, const std::error_code &ec) const
{
handler_(e, ec);
}
private:
Handler handler_;
};
template <class Executor>
void on_exec_error(Executor &e, const std::error_code &ec) const
{
handler_(e, ec);
}
private:
Handler handler_;
};
}}}}
}}}}
#endif /* BOOST_PROCESS_DETAIL_POSIX_HANDLER_HPP_ */
#endif /* BOOST_PROCESS_DETAIL_POSIX_HANDLER_HPP_ */

View File

@@ -1,155 +1,115 @@
// Copyright (c) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Copyright (c) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PROCESS_POSIX_IO_SERVICE_REF_HPP_
#define BOOST_PROCESS_POSIX_IO_SERVICE_REF_HPP_
#ifndef BOOST_PROCESS_POSIX_IO_CONTEXT_REF_HPP_
#define BOOST_PROCESS_POSIX_IO_CONTEXT_REF_HPP_
#include <boost/process/detail/posix/handler.hpp>
#include <boost/process/detail/posix/async_handler.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/asio/signal_set.hpp>
#include <boost/process/detail/posix/handler.hpp>
#include <boost/process/detail/posix/async_handler.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/fusion/algorithm/iteration/for_each.hpp>
#include <boost/fusion/algorithm/transformation/filter_if.hpp>
#include <boost/fusion/algorithm/transformation/transform.hpp>
#include <boost/fusion/view/transform_view.hpp>
#include <boost/fusion/container/vector/convert.hpp>
#include <boost/fusion/algorithm/iteration/for_each.hpp>
#include <boost/fusion/algorithm/transformation/filter_if.hpp>
#include <boost/fusion/algorithm/transformation/transform.hpp>
#include <boost/fusion/view/transform_view.hpp>
#include <boost/fusion/container/vector/convert.hpp>
#include <functional>
#include <type_traits>
#include <memory>
#include <vector>
#include <sys/wait.h>
#include <boost/process/detail/posix/sigchld_service.hpp>
#include <boost/process/detail/posix/is_running.hpp>
namespace boost { namespace process { namespace detail { namespace posix {
#include <functional>
#include <type_traits>
#include <memory>
#include <vector>
#include <sys/wait.h>
template<typename Executor>
struct on_exit_handler_transformer
{
Executor & exec;
on_exit_handler_transformer(Executor & exec) : exec(exec) {}
template<typename Sig>
struct result;
namespace boost { namespace process { namespace detail { namespace posix {
template<typename T>
struct result<on_exit_handler_transformer<Executor>(T&)>
{
typedef typename T::on_exit_handler_t type;
};
template<typename Executor>
struct on_exit_handler_transformer
{
Executor & exec;
on_exit_handler_transformer(Executor & exec) : exec(exec) {}
template<typename Sig>
struct result;
template<typename T>
auto operator()(T& t) const -> typename T::on_exit_handler_t
{
return t.on_exit_handler(exec);
}
};
template<typename T>
struct result<on_exit_handler_transformer<Executor>(T&)>
{
typedef typename T::on_exit_handler_t type;
};
template<typename Executor>
struct async_handler_collector
{
Executor & exec;
std::vector<std::function<void(int, const std::error_code & ec)>> &handlers;
template<typename T>
auto operator()(T& t) const -> typename T::on_exit_handler_t
{
return t.on_exit_handler(exec);
}
};
template<typename Executor>
struct async_handler_collector
{
Executor & exec;
std::vector<std::function<void(int, const std::error_code & ec)>> &handlers;
async_handler_collector(Executor & exec,
std::vector<std::function<void(int, const std::error_code & ec)>> &handlers)
: exec(exec), handlers(handlers) {}
async_handler_collector(Executor & exec,
std::vector<std::function<void(int, const std::error_code & ec)>> &handlers)
: exec(exec), handlers(handlers) {}
template<typename T>
void operator()(T & t) const
{
handlers.push_back(t.on_exit_handler(exec));
};
};
template<typename T>
void operator()(T & t) const
{
handlers.push_back(t.on_exit_handler(exec));
};
};
//Also set's up waiting for the exit, so it can close async stuff.
struct io_service_ref : handler_base_ext
{
io_service_ref(boost::asio::io_service & ios) : ios(ios)
{
//Also set's up waiting for the exit, so it can close async stuff.
struct io_context_ref : handler_base_ext
{
io_context_ref(boost::asio::io_context & ios) : ios(ios)
{
}
boost::asio::io_service &get() {return ios;};
}
boost::asio::io_context &get() {return ios;};
template <class Executor>
void on_success(Executor& exec)
{
//must be on the heap so I can move it into the lambda.
auto asyncs = boost::fusion::filter_if<
is_async_handler<
typename std::remove_reference< boost::mpl::_ > ::type
>>(exec.seq);
boost::asio::signal_set *signal_p = nullptr;
//ok, check if there are actually any.
if (boost::fusion::empty(asyncs))
return;
template <class Executor>
void on_setup(Executor& exec)
{
//must be on the heap so I can move it into the lambda.
auto asyncs = boost::fusion::filter_if<
is_async_handler<
typename std::remove_reference< boost::mpl::_ > ::type
>>(exec.seq);
std::vector<std::function<void(int, const std::error_code & ec)>> funcs;
funcs.reserve(boost::fusion::size(asyncs));
boost::fusion::for_each(asyncs, async_handler_collector<Executor>(exec, funcs));
//ok, check if there are actually any.
if (boost::fusion::empty(asyncs))
return;
auto & es = exec.exit_status;
std::vector<std::function<void(int, const std::error_code & ec)>> funcs;
funcs.reserve(boost::fusion::size(asyncs));
boost::fusion::for_each(asyncs, async_handler_collector<Executor>(exec, funcs));
auto wh = [funcs, es](int val, const std::error_code & ec)
{
es->store(val);
for (auto & func : funcs)
func(::boost::process::detail::posix::eval_exit_status(val), ec);
};
wait_handler wh(std::move(funcs), ios, exec.exit_status);
sigchld_service.async_wait(exec.pid, std::move(wh));
}
signal_p = wh.signal_.get();
signal_p->async_wait(std::move(wh));
private:
boost::asio::io_context &ios;
boost::process::detail::posix::sigchld_service &sigchld_service = boost::asio::use_service<boost::process::detail::posix::sigchld_service>(ios);
};
}
}}}}
template <class Executor>
void on_error(Executor & exec, const std::error_code & ec) const
{
if (signal_p != nullptr)
{
boost::system::error_code ec;
signal_p->cancel(ec);
}
}
struct wait_handler
{
std::shared_ptr<boost::asio::signal_set> signal_;
std::vector<std::function<void(int, const std::error_code & ec)>> funcs;
std::shared_ptr<std::atomic<int>> exit_status;
wait_handler(const wait_handler & ) = default;
wait_handler(wait_handler && ) = default;
wait_handler(
std::vector<std::function<void(int, const std::error_code & ec)>> && funcs,
boost::asio::io_service & ios,
const std::shared_ptr<std::atomic<int>> &exit_status)
: signal_(new boost::asio::signal_set(ios, SIGCHLD)),
funcs(std::move(funcs)),
exit_status(exit_status)
{
}
void operator()(const boost::system::error_code & ec_in, int /*signal*/)
{
if (ec_in.value() == boost::asio::error::operation_aborted)
return;
int status;
::wait(&status);
std::error_code ec(ec_in.value(), std::system_category());
int val = WEXITSTATUS(status);
exit_status->store(status);
for (auto & func : funcs)
func(val, ec);
}
};
private:
boost::asio::io_service &ios;
};
}}}}
#endif /* BOOST_PROCESS_WINDOWS_IO_SERVICE_REF_HPP_ */
#endif /* BOOST_PROCESS_WINDOWS_IO_CONTEXT_REF_HPP_ */

View File

@@ -13,37 +13,22 @@
namespace boost { namespace process { namespace detail { namespace posix {
// Use the "stopped" state (WIFSTOPPED) to indicate "not terminated".
// This bit arrangement of status codes is not guaranteed by POSIX, but (according to comments in
// the glibc <bits/waitstatus.h> header) is the same across systems in practice.
constexpr int still_active = 0x7F;
static_assert(!WIFEXITED(still_active), "Internal Error");
static_assert(!WIFEXITED(still_active) && !WIFSIGNALED(still_active), "Internal Error");
inline bool is_running(const child_handle &p, int & exit_code)
inline bool is_running(int code)
{
int status;
auto ret = ::waitpid(p.pid, &status, WNOHANG|WUNTRACED);
if (ret == -1)
{
if (errno != ECHILD) //because it no child is running, than this one isn't either, obviously.
::boost::process::detail::throw_last_error("is_running error");
return false;
}
else if (ret == 0)
return true;
else //exited
{
if (WIFEXITED(status))
exit_code = status;
return false;
}
return !WIFEXITED(code) && !WIFSIGNALED(code);
}
inline bool is_running(const child_handle &p, int & exit_code, std::error_code &ec) noexcept
{
int status;
auto ret = ::waitpid(p.pid, &status, WNOHANG|WUNTRACED);
auto ret = ::waitpid(p.pid, &status, WNOHANG);
if (ret == -1)
{
if (errno != ECHILD) //because it no child is running, than this one isn't either, obviously.
@@ -55,22 +40,36 @@ inline bool is_running(const child_handle &p, int & exit_code, std::error_code &
else
{
ec.clear();
if (WIFEXITED(status))
if (!is_running(status))
exit_code = status;
return false;
}
}
inline bool is_running(int code)
inline bool is_running(const child_handle &p, int & exit_code)
{
return !WIFEXITED(code);
std::error_code ec;
bool b = is_running(p, exit_code, ec);
boost::process::detail::throw_error(ec, "waitpid(2) failed in is_running");
return b;
}
inline int eval_exit_status(int code)
{
return WEXITSTATUS(code);
if (WIFEXITED(code))
{
return WEXITSTATUS(code);
}
else if (WIFSIGNALED(code))
{
return WTERMSIG(code);
}
else
{
return code;
}
}
}}}}

View File

@@ -1,35 +1,35 @@
// 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)
// 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)
#ifndef BOOST_PROCESS_DETAIL_POSIX_NULL_IN_HPP
#define BOOST_PROCESS_DETAIL_POSIX_NULL_IN_HPP
#ifndef BOOST_PROCESS_DETAIL_POSIX_NULL_IN_HPP
#define BOOST_PROCESS_DETAIL_POSIX_NULL_IN_HPP
#include <boost/process/pipe.hpp>
#include <boost/process/detail/posix/handler.hpp>
#include <boost/process/detail/posix/file_descriptor.hpp>
#include <unistd.h>
#include <boost/process/pipe.hpp>
#include <boost/process/detail/posix/handler.hpp>
#include <boost/process/detail/posix/file_descriptor.hpp>
#include <unistd.h>
namespace boost { namespace process { namespace detail { namespace posix {
namespace boost { namespace process { namespace detail { namespace posix {
struct null_in : handler_base_ext
{
file_descriptor source{"/dev/null", file_descriptor::read};
struct null_in : handler_base_ext
{
file_descriptor source{"/dev/null", file_descriptor::read};
public:
template <class Executor>
void on_exec_setup(Executor &e) const
{
if (::dup2(source.handle(), STDIN_FILENO) == -1)
e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
}
};
public:
template <class Executor>
void on_exec_setup(Executor &e) const
{
if (::dup2(source.handle(), STDIN_FILENO) == -1)
e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
}
};
}}}}
}}}}
#endif
#endif

View File

@@ -1,58 +1,58 @@
// 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) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// 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) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PROCESS_POSIX_PIPE_OUT_HPP
#define BOOST_PROCESS_POSIX_PIPE_OUT_HPP
#ifndef BOOST_PROCESS_POSIX_PIPE_OUT_HPP
#define BOOST_PROCESS_POSIX_PIPE_OUT_HPP
#include <boost/process/detail/posix/handler.hpp>
#include <boost/process/detail/posix/file_descriptor.hpp>
#include <boost/process/detail/posix/handler.hpp>
#include <boost/process/detail/posix/file_descriptor.hpp>
#include <unistd.h>
namespace boost { namespace process { namespace detail { namespace posix {
#include <unistd.h>
namespace boost { namespace process { namespace detail { namespace posix {
template<int p1, int p2>
struct null_out : handler_base_ext
{
file_descriptor sink{"/dev/null", file_descriptor::write};
template <typename Executor>
void on_exec_setup(Executor &e) const;
};
template<int p1, int p2>
struct null_out : handler_base_ext
{
file_descriptor sink{"/dev/null", file_descriptor::write};
template <typename Executor>
void on_exec_setup(Executor &e) const;
};
template<>
template<typename Executor>
void null_out<1,-1>::on_exec_setup(Executor &e) const
{
if (::dup2(sink.handle(), STDOUT_FILENO) == -1)
e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
}
template<>
template<typename Executor>
void null_out<1,-1>::on_exec_setup(Executor &e) const
{
if (::dup2(sink.handle(), STDOUT_FILENO) == -1)
e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
}
template<>
template<typename Executor>
void null_out<2,-1>::on_exec_setup(Executor &e) const
{
if (::dup2(sink.handle(), STDERR_FILENO) == -1)
e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
}
template<>
template<typename Executor>
void null_out<2,-1>::on_exec_setup(Executor &e) const
{
if (::dup2(sink.handle(), STDERR_FILENO) == -1)
e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
}
template<>
template<typename Executor>
void null_out<1,2>::on_exec_setup(Executor &e) const
{
if (::dup2(sink.handle(), STDOUT_FILENO) == -1)
e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
template<>
template<typename Executor>
void null_out<1,2>::on_exec_setup(Executor &e) const
{
if (::dup2(sink.handle(), STDOUT_FILENO) == -1)
e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
if (::dup2(sink.handle(), STDERR_FILENO) == -1)
e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
}
if (::dup2(sink.handle(), STDERR_FILENO) == -1)
e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
}
}}}}
}}}}
#endif
#endif

View File

@@ -1,35 +1,35 @@
// Copyright (c) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Copyright (c) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PROCESS_POSIX_ON_EXIT_HPP_
#define BOOST_PROCESS_POSIX_ON_EXIT_HPP_
#ifndef BOOST_PROCESS_POSIX_ON_EXIT_HPP_
#define BOOST_PROCESS_POSIX_ON_EXIT_HPP_
#include <boost/process/detail/config.hpp>
#include <boost/process/detail/handler_base.hpp>
#include <boost/process/detail/posix/async_handler.hpp>
#include <system_error>
#include <functional>
#include <boost/process/detail/config.hpp>
#include <boost/process/detail/handler_base.hpp>
#include <boost/process/detail/posix/async_handler.hpp>
#include <system_error>
#include <functional>
namespace boost { namespace process { namespace detail { namespace posix {
namespace boost { namespace process { namespace detail { namespace posix {
struct on_exit_ : boost::process::detail::posix::async_handler
{
std::function<void(int, const std::error_code&)> handler;
on_exit_(const std::function<void(int, const std::error_code&)> & handler) : handler(handler)
{
struct on_exit_ : boost::process::detail::posix::async_handler
{
std::function<void(int, const std::error_code&)> handler;
on_exit_(const std::function<void(int, const std::error_code&)> & handler) : handler(handler)
{
}
}
template<typename Executor>
std::function<void(int, const std::error_code&)> on_exit_handler(Executor & exec)
{
return handler;
template<typename Executor>
std::function<void(int, const std::error_code&)> on_exit_handler(Executor&)
{
return handler;
};
};
};
};
}}}}
#endif /* BOOST_PROCESS_POSIX_ON_EXIT_HPP_ */
}}}}
#endif /* BOOST_PROCESS_POSIX_ON_EXIT_HPP_ */

View File

@@ -1,90 +1,90 @@
// 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)
// 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)
#ifndef BOOST_PROCESS_POSIX_PIPE_IN_HPP
#define BOOST_PROCESS_POSIX_PIPE_IN_HPP
#ifndef BOOST_PROCESS_POSIX_PIPE_IN_HPP
#define BOOST_PROCESS_POSIX_PIPE_IN_HPP
#include <boost/process/pipe.hpp>
#include <boost/process/detail/posix/handler.hpp>
#include <unistd.h>
#include <boost/process/pipe.hpp>
#include <boost/process/detail/posix/handler.hpp>
#include <unistd.h>
namespace boost { namespace process { namespace detail { namespace posix {
namespace boost { namespace process { namespace detail { namespace posix {
struct pipe_in : handler_base_ext
{
int source;
int sink; //opposite end
struct pipe_in : handler_base_ext
{
int source;
int sink; //opposite end
pipe_in(int sink, int source) : source(source), sink(sink) {}
pipe_in(int sink, int source) : source(source), sink(sink) {}
template<typename T>
pipe_in(T & p) : source(p.native_source()), sink(p.native_sink())
{
p.assign_source(-1);
}
template<typename T>
pipe_in(T & p) : source(p.native_source()), sink(p.native_sink())
{
p.assign_source(-1);
}
template<typename Executor>
void on_error(Executor &, const std::error_code &) const
{
::close(source);
}
template<typename Executor>
void on_error(Executor &, const std::error_code &) const
{
::close(source);
}
template<typename Executor>
void on_success(Executor &) const
{
::close(source);
}
template<typename Executor>
void on_success(Executor &) const
{
::close(source);
}
template <class Executor>
void on_exec_setup(Executor &e) const
{
if (::dup2(source, STDIN_FILENO) == -1)
e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
::close(source);
::close(sink);
}
template <class Executor>
void on_exec_setup(Executor &e) const
{
if (::dup2(source, STDIN_FILENO) == -1)
e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
::close(source);
::close(sink);
}
};
};
class async_pipe;
class async_pipe;
struct async_pipe_in : public pipe_in
{
async_pipe &pipe;
struct async_pipe_in : public pipe_in
{
async_pipe &pipe;
template<typename AsyncPipe>
async_pipe_in(AsyncPipe & p) : pipe_in(p.native_sink(), p.native_source()), pipe(p)
{
}
template<typename AsyncPipe>
async_pipe_in(AsyncPipe & p) : pipe_in(p.native_sink(), p.native_source()), pipe(p)
{
}
template<typename Pipe, typename Executor>
static void close(Pipe & pipe, Executor &)
{
boost::system::error_code ec;
std::move(pipe).source().close(ec);
}
template<typename Pipe, typename Executor>
static void close(Pipe & pipe, Executor &)
{
boost::system::error_code ec;
std::move(pipe).source().close(ec);
}
template<typename Executor>
void on_error(Executor & exec, const std::error_code &)
{
close(pipe, exec);
}
template<typename Executor>
void on_error(Executor & exec, const std::error_code &)
{
close(pipe, exec);
}
template<typename Executor>
void on_success(Executor &exec)
{
close(pipe, exec);
}
};
template<typename Executor>
void on_success(Executor &exec)
{
close(pipe, exec);
}
};
}}}}
}}}}
#endif
#endif

View File

@@ -1,116 +1,116 @@
// 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) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// 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) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PROCESS_DETAIL_POSIX_PIPE_OUT_HPP
#define BOOST_PROCESS_DETAIL_POSIX_PIPE_OUT_HPP
#ifndef BOOST_PROCESS_DETAIL_POSIX_PIPE_OUT_HPP
#define BOOST_PROCESS_DETAIL_POSIX_PIPE_OUT_HPP
#include <boost/process/pipe.hpp>
#include <boost/process/detail/posix/handler.hpp>
#include <unistd.h>
#include <boost/process/pipe.hpp>
#include <boost/process/detail/posix/handler.hpp>
#include <unistd.h>
namespace boost { namespace process { namespace detail { namespace posix {
namespace boost { namespace process { namespace detail { namespace posix {
template<int p1, int p2>
struct pipe_out : handler_base_ext
{
int sink;
int source; //opposite end
template<int p1, int p2>
struct pipe_out : handler_base_ext
{
int sink;
int source; //opposite end
pipe_out(int sink, int source) : sink(sink), source(source) {}
pipe_out(int sink, int source) : sink(sink), source(source) {}
template<typename T>
pipe_out(T & p) : sink(p.native_sink()), source(p.native_source())
{
p.assign_sink(-1);
}
template<typename T>
pipe_out(T & p) : sink(p.native_sink()), source(p.native_source())
{
p.assign_sink(-1);
}
template<typename Executor>
void on_error(Executor &, const std::error_code &) const
{
::close(sink);
}
template<typename Executor>
void on_error(Executor &, const std::error_code &) const
{
::close(sink);
}
template<typename Executor>
void on_success(Executor &) const
{
::close(sink);
}
template<typename Executor>
void on_success(Executor &) const
{
::close(sink);
}
template <typename Executor>
void on_exec_setup(Executor &e) const;
};
template <typename Executor>
void on_exec_setup(Executor &e) const;
};
template<>
template<typename Executor>
void pipe_out<1,-1>::on_exec_setup(Executor &e) const
{
if (::dup2(sink, STDOUT_FILENO) == -1)
e.set_error(::boost::process::detail::get_last_error(), "dup3() failed");
::close(sink);
::close(source);
}
template<>
template<typename Executor>
void pipe_out<1,-1>::on_exec_setup(Executor &e) const
{
if (::dup2(sink, STDOUT_FILENO) == -1)
e.set_error(::boost::process::detail::get_last_error(), "dup3() failed");
::close(sink);
::close(source);
}
template<>
template<typename Executor>
void pipe_out<2,-1>::on_exec_setup(Executor &e) const
{
if (::dup2(sink, STDERR_FILENO) == -1)
e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
::close(sink);
::close(source);
}
template<>
template<typename Executor>
void pipe_out<2,-1>::on_exec_setup(Executor &e) const
{
if (::dup2(sink, STDERR_FILENO) == -1)
e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
::close(sink);
::close(source);
}
template<>
template<typename Executor>
void pipe_out<1,2>::on_exec_setup(Executor &e) const
{
if (::dup2(sink, STDOUT_FILENO) == -1)
e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
if (::dup2(sink, STDERR_FILENO) == -1)
e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
::close(sink);
::close(source);
}
template<>
template<typename Executor>
void pipe_out<1,2>::on_exec_setup(Executor &e) const
{
if (::dup2(sink, STDOUT_FILENO) == -1)
e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
if (::dup2(sink, STDERR_FILENO) == -1)
e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
::close(sink);
::close(source);
}
class async_pipe;
class async_pipe;
template<int p1, int p2>
struct async_pipe_out : public pipe_out<p1, p2>
{
async_pipe &pipe;
template<typename AsyncPipe>
async_pipe_out(AsyncPipe & p) : pipe_out<p1, p2>(p.native_sink(), p.native_source()), pipe(p)
{
}
template<int p1, int p2>
struct async_pipe_out : public pipe_out<p1, p2>
{
async_pipe &pipe;
template<typename AsyncPipe>
async_pipe_out(AsyncPipe & p) : pipe_out<p1, p2>(p.native_sink(), p.native_source()), pipe(p)
{
}
template<typename Pipe, typename Executor>
static void close(Pipe & pipe, Executor &)
{
boost::system::error_code ec;
std::move(pipe).sink().close(ec);
}
template<typename Pipe, typename Executor>
static void close(Pipe & pipe, Executor &)
{
boost::system::error_code ec;
std::move(pipe).sink().close(ec);
}
template<typename Executor>
void on_error(Executor & exec, const std::error_code &)
{
close(pipe, exec);
}
template<typename Executor>
void on_error(Executor & exec, const std::error_code &)
{
close(pipe, exec);
}
template<typename Executor>
void on_success(Executor &exec)
{
close(pipe, exec);
}
};
template<typename Executor>
void on_success(Executor &exec)
{
close(pipe, exec);
}
};
}}}}
}}}}
#endif
#endif

View File

@@ -24,11 +24,12 @@ inline boost::filesystem::path search_path(
const boost::filesystem::path &filename,
const std::vector<boost::filesystem::path> &path)
{
std::string result;
for (const boost::filesystem::path & pp : path)
{
auto p = pp / filename;
if (!::access(p.c_str(), X_OK))
boost::system::error_code ec;
bool file = boost::filesystem::is_regular_file(p, ec);
if (!ec && file && ::access(p.c_str(), X_OK) == 0)
return p;
}
return "";

View File

@@ -0,0 +1,122 @@
// Copyright (c) 2017 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PROCESS_DETAIL_POSIX_SIGCHLD_SERVICE_HPP_
#define BOOST_PROCESS_DETAIL_POSIX_SIGCHLD_SERVICE_HPP_
#include <boost/asio/signal_set.hpp>
#include <boost/asio/strand.hpp>
#include <boost/optional.hpp>
#include <signal.h>
#include <functional>
#include <sys/wait.h>
namespace boost { namespace process { namespace detail { namespace posix {
class sigchld_service : public boost::asio::detail::service_base<sigchld_service>
{
boost::asio::io_context::strand _strand{get_io_context()};
boost::asio::signal_set _signal_set{get_io_context(), SIGCHLD};
std::vector<std::pair<::pid_t, std::function<void(int, std::error_code)>>> _receivers;
inline void _handle_signal(const boost::system::error_code & ec);
public:
sigchld_service(boost::asio::io_context & io_context)
: boost::asio::detail::service_base<sigchld_service>(io_context)
{
}
template <typename SignalHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(SignalHandler,
void (int, std::error_code))
async_wait(::pid_t pid, SignalHandler && handler)
{
boost::asio::async_completion<
SignalHandler, void(boost::system::error_code)> init{handler};
auto & h = init.completion_handler;
_strand.post(
[this, pid, h]
{
if (_receivers.empty())
_signal_set.async_wait(
[this](const boost::system::error_code & ec, int)
{
_strand.post([this,ec]{this->_handle_signal(ec);});
});
_receivers.emplace_back(pid, h);
});
return init.result.get();
}
void shutdown_service() override
{
_receivers.clear();
}
void cancel()
{
_signal_set.cancel();
}
void cancel(boost::system::error_code & ec)
{
_signal_set.cancel(ec);
}
};
void sigchld_service::_handle_signal(const boost::system::error_code & ec)
{
std::error_code ec_{ec.value(), std::system_category()};
if (ec_)
{
for (auto & r : _receivers)
r.second(-1, ec_);
return;
}
for (auto & r : _receivers) {
int status;
int pid = ::waitpid(r.first, &status, WNOHANG);
if (pid < 0) {
// error (eg: the process no longer exists)
r.second(-1, get_last_error());
r.first = 0; // mark for deletion
} else if (pid == r.first) {
r.second(status, ec_);
r.first = 0; // mark for deletion
}
// otherwise the process is still around
}
_receivers.erase(std::remove_if(_receivers.begin(), _receivers.end(),
[](const std::pair<::pid_t, std::function<void(int, std::error_code)>> & p)
{
return p.first == 0;
}),
_receivers.end());
if (!_receivers.empty())
{
_signal_set.async_wait(
[this](const boost::system::error_code & ec, int)
{
_strand.post([ec]{});
this->_handle_signal(ec);
});
}
}
}
}
}
}
#endif

View File

@@ -19,15 +19,6 @@
namespace boost { namespace process { namespace detail { namespace posix {
inline void terminate(const child_handle &p)
{
if (::kill(p.pid, SIGKILL) == -1)
boost::process::detail::throw_last_error("kill(2) failed");
int status;
::waitpid(p.pid, &status, 0); //just to clean it up
}
inline void terminate(const child_handle &p, std::error_code &ec) noexcept
{
if (::kill(p.pid, SIGKILL) == -1)
@@ -39,6 +30,13 @@ inline void terminate(const child_handle &p, std::error_code &ec) noexcept
::waitpid(p.pid, &status, 0); //just to clean it up
}
inline void terminate(const child_handle &p)
{
std::error_code ec;
terminate(p, ec);
boost::process::detail::throw_error(ec, "kill(2) failed");
}
}}}}
#endif

View File

@@ -15,23 +15,10 @@
#include <system_error>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
namespace boost { namespace process { namespace detail { namespace posix {
inline void wait(const child_handle &p, int & exit_code)
{
pid_t ret;
int status;
do
{
ret = ::waitpid(p.pid, &status, 0);
} while (((ret == -1) && (errno == EINTR)) || (ret != -1 && !WIFEXITED(status)));
if (ret == -1)
boost::process::detail::throw_last_error("waitpid(2) failed");
exit_code = status;
}
inline void wait(const child_handle &p, int & exit_code, std::error_code &ec) noexcept
{
pid_t ret;
@@ -41,8 +28,8 @@ inline void wait(const child_handle &p, int & exit_code, std::error_code &ec) no
{
ret = ::waitpid(p.pid, &status, 0);
}
while (((ret == -1) && (errno == EINTR)) || (ret != -1 && !WIFEXITED(status)));
while (((ret == -1) && (errno == EINTR)) || (ret != -1 && !WIFEXITED(status) && !WIFSIGNALED(status)));
if (ret == -1)
ec = boost::process::detail::get_last_error();
else
@@ -50,45 +37,63 @@ inline void wait(const child_handle &p, int & exit_code, std::error_code &ec) no
ec.clear();
exit_code = status;
}
}
template< class Rep, class Period >
inline bool wait_for(
inline void wait(const child_handle &p, int & exit_code) noexcept
{
std::error_code ec;
wait(p, exit_code, ec);
boost::process::detail::throw_error(ec, "waitpid(2) failed in wait");
}
template< class Clock, class Duration >
inline bool wait_until(
const child_handle &p,
int & exit_code,
const std::chrono::duration<Rep, Period>& rel_time)
const std::chrono::time_point<Clock, Duration>& time_out,
std::error_code & ec) noexcept
{
pid_t ret;
int status;
auto start = std::chrono::system_clock::now();
auto time_out = start + rel_time;
bool timed_out;
bool time_out_occured = false;
do
{
ret = ::waitpid(p.pid, &status, WUNTRACED | WNOHANG);
if (std::chrono::system_clock::now() >= time_out)
ret = ::waitpid(p.pid, &status, WNOHANG);
if (ret == 0)
{
time_out_occured = true;
break;
timed_out = Clock::now() >= time_out;
if (timed_out)
return false;
}
}
while (((ret == -1) && errno == EINTR) ||
((ret != -1) && !WIFEXITED(status)));
}
while ((ret == 0) ||
(((ret == -1) && errno == EINTR) ||
((ret != -1) && !WIFEXITED(status) && !WIFSIGNALED(status))));
if (ret == -1)
boost::process::detail::throw_last_error("waitpid(2) failed");
exit_code = status;
ec = boost::process::detail::get_last_error();
else
{
ec.clear();
exit_code = status;
}
return !time_out_occured;
return true;
}
template< class Clock, class Duration >
inline bool wait_until(
const child_handle &p,
int & exit_code,
const std::chrono::time_point<Clock, Duration>& time_out) noexcept
{
std::error_code ec;
bool b = wait_until(p, exit_code, time_out, ec);
boost::process::detail::throw_error(ec, "waitpid(2) failed in wait_until");
return b;
}
template< class Rep, class Period >
inline bool wait_for(
@@ -97,107 +102,19 @@ inline bool wait_for(
const std::chrono::duration<Rep, Period>& rel_time,
std::error_code & ec) noexcept
{
pid_t ret;
int status;
auto start = std::chrono::system_clock::now();
auto time_out = start + rel_time;
bool time_out_occured = false;
do
{
ret = ::waitpid(p.pid, &status, WUNTRACED | WNOHANG);
if (std::chrono::system_clock::now() >= time_out)
{
time_out_occured = true;
break;
}
}
while (((ret == -1) && errno == EINTR) ||
((ret != -1) && !WIFEXITED(status)));
if (ret == -1)
ec = boost::process::detail::get_last_error();
else
{
ec.clear();
exit_code = status;
}
return !time_out_occured;
return wait_until(p, exit_code, std::chrono::steady_clock::now() + rel_time, ec);
}
template< class Rep, class Period >
inline bool wait_until(
inline bool wait_for(
const child_handle &p,
int & exit_code,
const std::chrono::duration<Rep, Period>& time_out)
const std::chrono::duration<Rep, Period>& rel_time) noexcept
{
pid_t ret;
int status;
bool time_out_occured = false;
do
{
ret = ::waitpid(p.pid, &status, WUNTRACED | WNOHANG);
if (std::chrono::system_clock::now() >= time_out)
{
time_out_occured = true;
break;
}
}
while (((ret == -1) && errno == EINTR) ||
((ret != -1) && !WIFEXITED(status)));
if (ret == -1)
boost::process::detail::throw_last_error("waitpid(2) failed");
exit_code = status;
return !time_out_occured;
}
template< class Rep, class Period >
inline bool wait_until(
const child_handle &p,
int & exit_code,
const std::chrono::duration<Rep, Period>& time_out,
std::error_code & ec) noexcept
{
pid_t ret;
int status;
bool time_out_occured = false;
do
{
ret = ::waitpid(p.pid, &status, WUNTRACED | WNOHANG);
if (std::chrono::system_clock::now() >= time_out)
{
time_out_occured = true;
break;
}
}
while (((ret == -1) && errno == EINTR) ||
((ret != -1) && !WIFEXITED(status)));
if (ret == -1)
ec = boost::process::detail::get_last_error();
else
{
ec.clear();
exit_code = status;
}
return !time_out_occured;
std::error_code ec;
bool b = wait_for(p, exit_code, rel_time, ec);
boost::process::detail::throw_error(ec, "waitpid(2) failed in wait_for");
return b;
}
}}}}

View File

@@ -12,24 +12,13 @@
#include <boost/process/detail/config.hpp>
#include <boost/process/detail/posix/group_handle.hpp>
#include <chrono>
#include <system_error>
#include <sys/types.h>
#include <sys/wait.h>
namespace boost { namespace process { namespace detail { namespace posix {
inline void wait(const group_handle &p)
{
pid_t ret;
int status;
do
{
ret = ::waitpid(-p.grp, &status, 0);
} while (((ret == -1) && (errno == EINTR)) || (ret != -1 && !WIFEXITED(status)));
if (ret == -1)
boost::process::detail::throw_last_error("waitpid(2) failed");
}
inline void wait(const group_handle &p, std::error_code &ec) noexcept
{
pid_t ret;
@@ -39,151 +28,83 @@ inline void wait(const group_handle &p, std::error_code &ec) noexcept
{
ret = ::waitpid(-p.grp, &status, 0);
}
while (((ret == -1) && (errno == EINTR)) || (ret != -1 && !WIFEXITED(status)));
while (((ret == -1) && (errno == EINTR)) || (ret != -1 && !WIFEXITED(status) && !WIFSIGNALED(status)));
if (ret == -1)
ec = boost::process::detail::get_last_error();
else
ec.clear();
}
inline void wait(const group_handle &p) noexcept
{
std::error_code ec;
wait(p, ec);
boost::process::detail::throw_error(ec, "waitpid(2) failed in wait");
}
template< class Clock, class Duration >
inline bool wait_until(
const group_handle &p,
const std::chrono::time_point<Clock, Duration>& time_out,
std::error_code & ec) noexcept
{
pid_t ret;
int status;
bool timed_out;
do
{
ret = ::waitpid(-p.grp, &status, WNOHANG);
if (ret == 0)
{
timed_out = Clock::now() >= time_out;
if (timed_out)
return false;
}
}
while ((ret == 0) ||
(((ret == -1) && errno == EINTR) ||
((ret != -1) && !WIFEXITED(status) && !WIFSIGNALED(status))));
if (ret == -1)
ec = boost::process::detail::get_last_error();
else
ec.clear();
return true;
}
template< class Rep, class Period >
inline bool wait_for(
template< class Clock, class Duration >
inline bool wait_until(
const group_handle &p,
const std::chrono::duration<Rep, Period>& rel_time)
const std::chrono::time_point<Clock, Duration>& time_out) noexcept
{
pid_t ret;
int status;
auto start = std::chrono::system_clock::now();
auto time_out = start + rel_time;
bool time_out_occured = false;
do
{
ret = ::waitpid(-p.grp, &status, WUNTRACED | WNOHANG);
if (std::chrono::system_clock::now() >= time_out)
{
time_out_occured = true;
break;
}
}
while (((ret == -1) && errno == EINTR) ||
((ret != -1) && !WIFEXITED(status)));
if (ret == -1)
boost::process::detail::throw_last_error("waitpid(2) failed");
return !time_out_occured;
std::error_code ec;
bool b = wait_until(p, time_out, ec);
boost::process::detail::throw_error(ec, "waitpid(2) failed in wait_until");
return b;
}
template< class Rep, class Period >
inline bool wait_for(
const group_handle &p,
const std::chrono::duration<Rep, Period>& rel_time,
std::error_code & ec) noexcept
{
pid_t ret;
int status;
auto start = std::chrono::system_clock::now();
auto time_out = start + rel_time;
bool time_out_occured = false;
do
{
ret = ::waitpid(-p.grp, &status, WUNTRACED | WNOHANG);
if (std::chrono::system_clock::now() >= time_out)
{
time_out_occured = true;
break;
}
}
while (((ret == -1) && errno == EINTR) ||
((ret != -1) && !WIFEXITED(status)));
if (ret == -1)
ec = boost::process::detail::get_last_error();
else
ec.clear();
return !time_out_occured;
return wait_until(p, std::chrono::steady_clock::now() + rel_time, ec);
}
template< class Rep, class Period >
inline bool wait_until(
inline bool wait_for(
const group_handle &p,
const std::chrono::duration<Rep, Period>& time_out)
const std::chrono::duration<Rep, Period>& rel_time) noexcept
{
pid_t ret;
int status;
auto start = std::chrono::system_clock::now();
bool time_out_occured = false;
do
{
ret = ::waitpid(-p.grp, &status, WUNTRACED | WNOHANG);
if (std::chrono::system_clock::now() >= time_out)
{
time_out_occured = true;
break;
}
}
while (((ret == -1) && errno == EINTR) ||
((ret != -1) && !WIFEXITED(status)));
if (ret == -1)
boost::process::detail::throw_last_error("waitpid(2) failed");
return !time_out_occured;
}
template< class Rep, class Period >
inline bool wait_until(
const group_handle &p,
const std::chrono::duration<Rep, Period>& time_out,
std::error_code & ec) noexcept
{
pid_t ret;
int status;
auto start = std::chrono::system_clock::now();
bool time_out_occured = false;
do
{
ret = ::waitpid(-p.grp, &status, WUNTRACED | WNOHANG);
if (std::chrono::system_clock::now() >= time_out)
{
time_out_occured = true;
break;
}
}
while (((ret == -1) && errno == EINTR) ||
((ret != -1) && !WIFEXITED(status)));
if (ret == -1)
ec = boost::process::detail::get_last_error();
else
ec.clear();
return !time_out_occured;
std::error_code ec;
bool b = wait_for(p, rel_time, ec);
boost::process::detail::throw_error(ec, "waitpid(2) failed in wait_for");
return b;
}
}}}}

View File

@@ -1,17 +1,17 @@
// Copyright (c) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Copyright (c) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PROCESS_TRAITS_HPP_
#define BOOST_PROCESS_TRAITS_HPP_
#ifndef BOOST_PROCESS_TRAITS_HPP_
#define BOOST_PROCESS_TRAITS_HPP_
#include <boost/process/detail/traits/decl.hpp>
#include <boost/process/detail/traits/async.hpp>
#include <boost/process/detail/traits/cmd_or_exe.hpp>
#include <boost/process/detail/traits/env.hpp>
#include <boost/process/detail/traits/error.hpp>
#include <boost/process/detail/traits/wchar_t.hpp>
#include <boost/process/detail/traits/decl.hpp>
#include <boost/process/detail/traits/async.hpp>
#include <boost/process/detail/traits/cmd_or_exe.hpp>
#include <boost/process/detail/traits/env.hpp>
#include <boost/process/detail/traits/error.hpp>
#include <boost/process/detail/traits/wchar_t.hpp>
#endif /* BOOST_PROCESS_TRAITS_HPP_ */
#endif /* BOOST_PROCESS_TRAITS_HPP_ */

View File

@@ -1,34 +1,34 @@
// Copyright (c) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Copyright (c) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PROCESS_DETAIL_TRAITS_ASYNC_HPP_
#define BOOST_PROCESS_DETAIL_TRAITS_ASYNC_HPP_
#ifndef BOOST_PROCESS_DETAIL_TRAITS_ASYNC_HPP_
#define BOOST_PROCESS_DETAIL_TRAITS_ASYNC_HPP_
#include <boost/process/detail/config.hpp>
#include <boost/process/detail/traits/decl.hpp>
#include <boost/process/detail/config.hpp>
#include <boost/process/detail/traits/decl.hpp>
namespace boost { namespace asio {
namespace boost { namespace asio {
class io_service;
}}
class io_context;
}}
namespace boost { namespace process { namespace detail {
namespace boost { namespace process { namespace detail {
struct async_tag {};
struct async_tag {};
template<>
struct initializer_builder<async_tag>;
template<>
struct initializer_builder<async_tag>;
template<> struct initializer_tag<::boost::asio::io_service> { typedef async_tag type;};
template<> struct initializer_tag<::boost::asio::io_context> { typedef async_tag type;};
}}}
}}}
#endif /* BOOST_PROCESS_DETAIL_HANDLER_HPP_ */
#endif /* BOOST_PROCESS_DETAIL_HANDLER_HPP_ */

View File

@@ -1,85 +1,85 @@
// Copyright (c) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Copyright (c) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PROCESS_DETAIL_TRAITS_CMD_OR_EXE_HPP_
#define BOOST_PROCESS_DETAIL_TRAITS_CMD_OR_EXE_HPP_
#ifndef BOOST_PROCESS_DETAIL_TRAITS_CMD_OR_EXE_HPP_
#define BOOST_PROCESS_DETAIL_TRAITS_CMD_OR_EXE_HPP_
#include <string>
#include <vector>
#include <type_traits>
#include <initializer_list>
#include <boost/filesystem/path.hpp>
#include <boost/process/detail/traits/decl.hpp>
namespace boost { namespace process { namespace detail {
#include <string>
#include <vector>
#include <type_traits>
#include <initializer_list>
#include <boost/filesystem/path.hpp>
#include <boost/process/detail/traits/decl.hpp>
namespace boost { namespace process { namespace detail {
template<typename Char>
struct cmd_or_exe_tag {};
template<typename Char>
struct cmd_or_exe_tag {};
struct shell_;
struct shell_;
template<> struct initializer_tag<const char* > { typedef cmd_or_exe_tag<char> type;};
template<> struct initializer_tag<const wchar_t* > { typedef cmd_or_exe_tag<wchar_t> type;};
template<> struct initializer_tag<const char* > { typedef cmd_or_exe_tag<char> type;};
template<> struct initializer_tag<const wchar_t* > { typedef cmd_or_exe_tag<wchar_t> type;};
template<> struct initializer_tag<char* > { typedef cmd_or_exe_tag<char> type;};
template<> struct initializer_tag<wchar_t* > { typedef cmd_or_exe_tag<wchar_t> type;};
template<> struct initializer_tag<char* > { typedef cmd_or_exe_tag<char> type;};
template<> struct initializer_tag<wchar_t* > { typedef cmd_or_exe_tag<wchar_t> type;};
template<std::size_t Size> struct initializer_tag<const char [Size]> { typedef cmd_or_exe_tag<char> type;};
template<std::size_t Size> struct initializer_tag<const wchar_t [Size]> { typedef cmd_or_exe_tag<wchar_t> type;};
template<std::size_t Size> struct initializer_tag<const char [Size]> { typedef cmd_or_exe_tag<char> type;};
template<std::size_t Size> struct initializer_tag<const wchar_t [Size]> { typedef cmd_or_exe_tag<wchar_t> type;};
template<std::size_t Size> struct initializer_tag<const char (&)[Size]> { typedef cmd_or_exe_tag<char> type;};
template<std::size_t Size> struct initializer_tag<const wchar_t (&)[Size]> { typedef cmd_or_exe_tag<wchar_t> type;};
template<std::size_t Size> struct initializer_tag<const char (&)[Size]> { typedef cmd_or_exe_tag<char> type;};
template<std::size_t Size> struct initializer_tag<const wchar_t (&)[Size]> { typedef cmd_or_exe_tag<wchar_t> type;};
template<> struct initializer_tag<std::basic_string<char >> { typedef cmd_or_exe_tag<char> type;};
template<> struct initializer_tag<std::basic_string<wchar_t >> { typedef cmd_or_exe_tag<wchar_t> type;};
template<> struct initializer_tag<std::basic_string<char >> { typedef cmd_or_exe_tag<char> type;};
template<> struct initializer_tag<std::basic_string<wchar_t >> { typedef cmd_or_exe_tag<wchar_t> type;};
template<> struct initializer_tag<std::vector<std::basic_string<char >>> { typedef cmd_or_exe_tag<char> type;};
template<> struct initializer_tag<std::vector<std::basic_string<wchar_t >>> { typedef cmd_or_exe_tag<wchar_t> type;};
template<> struct initializer_tag<std::vector<std::basic_string<char >>> { typedef cmd_or_exe_tag<char> type;};
template<> struct initializer_tag<std::vector<std::basic_string<wchar_t >>> { typedef cmd_or_exe_tag<wchar_t> type;};
template<> struct initializer_tag<std::initializer_list<std::basic_string<char >>> { typedef cmd_or_exe_tag<char> type;};
template<> struct initializer_tag<std::initializer_list<std::basic_string<wchar_t >>> { typedef cmd_or_exe_tag<wchar_t> type;};
template<> struct initializer_tag<std::initializer_list<std::basic_string<char >>> { typedef cmd_or_exe_tag<char> type;};
template<> struct initializer_tag<std::initializer_list<std::basic_string<wchar_t >>> { typedef cmd_or_exe_tag<wchar_t> type;};
template<> struct initializer_tag<std::vector<char *>> { typedef cmd_or_exe_tag<char> type;};
template<> struct initializer_tag<std::vector<wchar_t *>> { typedef cmd_or_exe_tag<wchar_t> type;};
template<> struct initializer_tag<std::vector<char *>> { typedef cmd_or_exe_tag<char> type;};
template<> struct initializer_tag<std::vector<wchar_t *>> { typedef cmd_or_exe_tag<wchar_t> type;};
template<> struct initializer_tag<std::initializer_list<char *>> { typedef cmd_or_exe_tag<char> type;};
template<> struct initializer_tag<std::initializer_list<wchar_t *>> { typedef cmd_or_exe_tag<wchar_t> type;};
template<> struct initializer_tag<std::initializer_list<char *>> { typedef cmd_or_exe_tag<char> type;};
template<> struct initializer_tag<std::initializer_list<wchar_t *>> { typedef cmd_or_exe_tag<wchar_t> type;};
template<> struct initializer_tag<std::initializer_list<const char *>> { typedef cmd_or_exe_tag<char> type;};
template<> struct initializer_tag<std::initializer_list<const wchar_t *>> { typedef cmd_or_exe_tag<wchar_t> type;};
template<> struct initializer_tag<std::initializer_list<const char *>> { typedef cmd_or_exe_tag<char> type;};
template<> struct initializer_tag<std::initializer_list<const wchar_t *>> { typedef cmd_or_exe_tag<wchar_t> type;};
template<> struct initializer_tag<shell_>
{
typedef cmd_or_exe_tag<typename boost::filesystem::path::value_type> type;
};
template<> struct initializer_tag<shell_>
{
typedef cmd_or_exe_tag<typename boost::filesystem::path::value_type> type;
};
template<> struct initializer_tag<boost::filesystem::path>
{
typedef cmd_or_exe_tag<typename boost::filesystem::path::value_type> type;
};
template<> struct initializer_tag<boost::filesystem::path>
{
typedef cmd_or_exe_tag<typename boost::filesystem::path::value_type> type;
};
template <typename Char>
struct exe_setter_;
template <typename Char, bool Append = false>
struct arg_setter_;
template <typename Char>
struct exe_setter_;
template <typename Char, bool Append = false>
struct arg_setter_;
template <typename Char, bool Append>
struct initializer_tag<arg_setter_<Char, Append>> { typedef cmd_or_exe_tag<Char> type;};
template <typename Char, bool Append>
struct initializer_tag<arg_setter_<Char, Append>> { typedef cmd_or_exe_tag<Char> type;};
template<typename Char> struct initializer_tag<exe_setter_<Char>> { typedef cmd_or_exe_tag<Char> type;};
template<typename Char> struct initializer_tag<exe_setter_<Char>> { typedef cmd_or_exe_tag<Char> type;};
template<>
struct initializer_builder<cmd_or_exe_tag<char>>;
template<>
struct initializer_builder<cmd_or_exe_tag<char>>;
template<>
struct initializer_builder<cmd_or_exe_tag<wchar_t>>;
template<>
struct initializer_builder<cmd_or_exe_tag<wchar_t>>;
}}}
}}}
#endif /* BOOST_PROCESS_DETAIL_STRING_TRAITS_HPP_ */
#endif /* BOOST_PROCESS_DETAIL_STRING_TRAITS_HPP_ */

View File

@@ -1,76 +1,76 @@
// Copyright (c) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Copyright (c) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PROCESS_DETAIL_TRAITS_DECL_HPP_
#define BOOST_PROCESS_DETAIL_TRAITS_DECL_HPP_
#ifndef BOOST_PROCESS_DETAIL_TRAITS_DECL_HPP_
#define BOOST_PROCESS_DETAIL_TRAITS_DECL_HPP_
#include <boost/process/detail/config.hpp>
#include <boost/none.hpp>
#include <type_traits>
#include <boost/process/detail/config.hpp>
#include <boost/none.hpp>
#include <type_traits>
#if defined(BOOST_POSIX_API)
#include <boost/process/detail/posix/handler.hpp>
#elif defined(BOOST_WINDOWS_API)
#include <boost/process/detail/windows/handler.hpp>
#endif
#if defined(BOOST_POSIX_API)
#include <boost/process/detail/posix/handler.hpp>
#elif defined(BOOST_WINDOWS_API)
#include <boost/process/detail/windows/handler.hpp>
#endif
namespace boost { namespace process { namespace detail {
namespace boost { namespace process { namespace detail {
template<typename T>
struct is_initializer : std::is_base_of<handler_base, T> {};
template<typename T>
struct is_initializer : std::is_base_of<handler_base, T> {};
template<typename T>
struct is_initializer<T&> : std::is_base_of<handler_base, T> {};
template<typename T>
struct is_initializer<T&> : std::is_base_of<handler_base, T> {};
template<typename T>
struct initializer_tag;// { typedef void type; };
template<typename T>
struct initializer_tag;// { typedef void type; };
//remove const
template<typename T>
struct initializer_tag<const T> { typedef typename initializer_tag<T>::type type; };
//remove const
template<typename T>
struct initializer_tag<const T> { typedef typename initializer_tag<T>::type type; };
//remove &
template<typename T>
struct initializer_tag<T&> { typedef typename initializer_tag<T>::type type; };
//remove &
template<typename T>
struct initializer_tag<T&> { typedef typename initializer_tag<T>::type type; };
//remove const &
template<typename T>
struct initializer_tag<const T&> { typedef typename initializer_tag<T>::type type; };
//remove const &
template<typename T>
struct initializer_tag<const T&> { typedef typename initializer_tag<T>::type type; };
template<typename T>
struct initializer_builder;
template<typename T>
struct initializer_builder;
template<typename First, typename ...Args>
struct valid_argument_list;
template<typename First, typename ...Args>
struct valid_argument_list;
template<typename First>
struct valid_argument_list<First>
{
constexpr static bool value = is_initializer<First>::value || !std::is_void<typename initializer_tag<First>::type>::value;
typedef std::integral_constant<bool, value> type;
};
template<typename First>
struct valid_argument_list<First>
{
constexpr static bool value = is_initializer<First>::value || !std::is_void<typename initializer_tag<First>::type>::value;
typedef std::integral_constant<bool, value> type;
};
template<typename First, typename ...Args>
struct valid_argument_list
{
constexpr static bool my_value = is_initializer<First>::value || !std::is_void<typename initializer_tag<First>::type>::value;
constexpr static bool value = valid_argument_list<Args...>::value && my_value;
typedef std::integral_constant<bool, value> type;
};
template<typename First, typename ...Args>
struct valid_argument_list
{
constexpr static bool my_value = is_initializer<First>::value || !std::is_void<typename initializer_tag<First>::type>::value;
constexpr static bool value = valid_argument_list<Args...>::value && my_value;
typedef std::integral_constant<bool, value> type;
};
}}}
}}}
#endif /* BOOST_PROCESS_DETAIL_HANDLER_HPP_ */
#endif /* BOOST_PROCESS_DETAIL_HANDLER_HPP_ */

View File

@@ -1,53 +1,53 @@
// Copyright (c) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Copyright (c) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PROCESS_DETAIL_TRAITS_ENV_HPP_
#define BOOST_PROCESS_DETAIL_TRAITS_ENV_HPP_
#ifndef BOOST_PROCESS_DETAIL_TRAITS_ENV_HPP_
#define BOOST_PROCESS_DETAIL_TRAITS_ENV_HPP_
#include <boost/process/detail/traits/decl.hpp>
#include <boost/process/detail/traits/decl.hpp>
namespace boost { namespace process {
namespace boost { namespace process {
template<typename Char>
class basic_environment;
template<typename Char>
class basic_environment;
template<typename Char>
class basic_native_environment;
template<typename Char>
class basic_native_environment;
namespace detail {
namespace detail {
template<typename Char>
struct env_tag {};
template<typename Char>
struct env_tag {};
template<typename Char> struct env_set;
template<typename Char> struct env_append;
template<typename Char> struct env_set;
template<typename Char> struct env_append;
template<typename Char> struct env_reset;
template<typename Char> struct env_init;
template<typename Char> struct env_reset;
template<typename Char> struct env_init;
template<typename Char> struct initializer_tag<env_set<Char>> { typedef env_tag<Char> type; };
template<typename Char> struct initializer_tag<env_append<Char>> { typedef env_tag<Char> type; };
template<typename Char> struct initializer_tag<env_set<Char>> { typedef env_tag<Char> type; };
template<typename Char> struct initializer_tag<env_append<Char>> { typedef env_tag<Char> type; };
template<typename Char> struct initializer_tag<env_reset<Char>> { typedef env_tag<Char> type;};
template<typename Char> struct initializer_tag<env_init <Char>> { typedef env_tag<Char> type;};
template<typename Char> struct initializer_tag<env_reset<Char>> { typedef env_tag<Char> type;};
template<typename Char> struct initializer_tag<env_init <Char>> { typedef env_tag<Char> type;};
template<typename Char> struct initializer_tag<::boost::process::basic_environment<Char>> { typedef env_tag<Char> type; };
template<typename Char> struct initializer_tag<::boost::process::basic_native_environment<Char>> { typedef env_tag<Char> type; };
template<typename Char> struct initializer_tag<::boost::process::basic_environment<Char>> { typedef env_tag<Char> type; };
template<typename Char> struct initializer_tag<::boost::process::basic_native_environment<Char>> { typedef env_tag<Char> type; };
template<> struct initializer_builder<env_tag<char>>;
template<> struct initializer_builder<env_tag<wchar_t>>;
template<> struct initializer_builder<env_tag<char>>;
template<> struct initializer_builder<env_tag<wchar_t>>;
}
}
}}
}}
#endif /* INCLUDE_BOOST_PROCESS_DETAIL_ENV_HPP_ */
#endif /* INCLUDE_BOOST_PROCESS_DETAIL_ENV_HPP_ */

View File

@@ -1,27 +1,27 @@
// Copyright (c) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Copyright (c) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PROCESS_DETAIL_TRAITS_ERROR_HPP_
#define BOOST_PROCESS_DETAIL_TRAITS_ERROR_HPP_
#ifndef BOOST_PROCESS_DETAIL_TRAITS_ERROR_HPP_
#define BOOST_PROCESS_DETAIL_TRAITS_ERROR_HPP_
#include <boost/process/detail/config.hpp>
#include <system_error>
#include <boost/process/detail/traits/decl.hpp>
#include <boost/process/detail/config.hpp>
#include <system_error>
#include <boost/process/detail/traits/decl.hpp>
namespace boost { namespace process { namespace detail {
namespace boost { namespace process { namespace detail {
struct error_tag;
struct error_tag;
template<>
struct initializer_tag<std::error_code>;
template<>
struct initializer_tag<std::error_code>;
}}}
}}}
#endif /* BOOST_PROCESS_DETAIL_HANDLER_HPP_ */
#endif /* BOOST_PROCESS_DETAIL_HANDLER_HPP_ */

View File

@@ -19,27 +19,35 @@ template<typename Allocator>
class basic_streambuf;
typedef basic_streambuf<std::allocator<char>> streambuf;
class io_service;
class io_context;
template <typename Handler>
class basic_yield_context;
namespace windows {
#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
class stream_handle_service;
template <typename StreamHandleService>
class basic_stream_handle;
typedef basic_stream_handle<stream_handle_service> stream_handle;
#else /* defined(BOOST_ASIO_ENABLE_OLD_SERVICES) */
class stream_handle;
#endif /* defined(BOOST_ASIO_ENABLE_OLD_SERVICES) */
#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
class object_handle_service;
template <typename ObjectHandleService>
class basic_object_handle;
typedef basic_object_handle<object_handle_service> object_handle;
#else /* defined(BOOST_ASIO_ENABLE_OLD_SERVICES) */
class object_handle;
#endif /* defined(BOOST_ASIO_ENABLE_OLD_SERVICES) */
} //windows
} //asio

View File

@@ -1,40 +1,40 @@
// Copyright (c) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Copyright (c) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PROCESS_WINDOWS_ASYNC_HANDLER_HPP_
#define BOOST_PROCESS_WINDOWS_ASYNC_HANDLER_HPP_
#ifndef BOOST_PROCESS_WINDOWS_ASYNC_HANDLER_HPP_
#define BOOST_PROCESS_WINDOWS_ASYNC_HANDLER_HPP_
#include <boost/process/detail/windows/handler.hpp>
#include <type_traits>
#include <boost/process/detail/windows/handler.hpp>
#include <type_traits>
namespace boost { namespace process { namespace detail { namespace windows {
namespace boost { namespace process { namespace detail { namespace windows {
struct require_io_service {};
struct require_io_context {};
struct async_handler : handler_base_ext, require_io_service
{
};
struct async_handler : handler_base_ext, require_io_context
{
};
template<typename T>
struct is_async_handler : std::is_base_of<async_handler, T> {};
template<typename T>
struct is_async_handler<T&> : std::is_base_of<async_handler, T> {};
template<typename T>
struct is_async_handler<const T&> : std::is_base_of<async_handler, T> {};
template<typename T>
struct is_async_handler : std::is_base_of<async_handler, T> {};
template<typename T>
struct is_async_handler<T&> : std::is_base_of<async_handler, T> {};
template<typename T>
struct is_async_handler<const T&> : std::is_base_of<async_handler, T> {};
template<typename T>
struct does_require_io_service : std::is_base_of<require_io_service, T> {};
template<typename T>
struct does_require_io_context : std::is_base_of<require_io_context, T> {};
template<typename T>
struct does_require_io_service<T&> : std::is_base_of<require_io_service, T> {};
template<typename T>
struct does_require_io_context<T&> : std::is_base_of<require_io_context, T> {};
template<typename T>
struct does_require_io_service<const T&> : std::is_base_of<require_io_service, T> {};
template<typename T>
struct does_require_io_context<const T&> : std::is_base_of<require_io_context, T> {};
}}}}
}}}}
#endif /* BOOST_PROCESS_WINDOWS_ASYNC_HANDLER_HPP_ */
#endif /* BOOST_PROCESS_WINDOWS_ASYNC_HANDLER_HPP_ */

View File

@@ -1,105 +1,105 @@
// 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)
// 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)
#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_ASYNC_IN_HPP
#define BOOST_PROCESS_WINDOWS_INITIALIZERS_ASYNC_IN_HPP
#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_ASYNC_IN_HPP
#define BOOST_PROCESS_WINDOWS_INITIALIZERS_ASYNC_IN_HPP
#include <boost/detail/winapi/process.hpp>
#include <boost/detail/winapi/handles.hpp>
#include <boost/detail/winapi/handle_info.hpp>
#include <boost/detail/winapi/error_codes.hpp>
#include <boost/winapi/process.hpp>
#include <boost/winapi/handles.hpp>
#include <boost/winapi/handle_info.hpp>
#include <boost/winapi/error_codes.hpp>
#include <boost/asio/write.hpp>
#include <boost/process/detail/handler_base.hpp>
#include <boost/process/detail/windows/async_handler.hpp>
#include <boost/process/detail/windows/asio_fwd.hpp>
#include <boost/process/async_pipe.hpp>
#include <memory>
#include <future>
#include <boost/asio/write.hpp>
#include <boost/process/detail/handler_base.hpp>
#include <boost/process/detail/windows/async_handler.hpp>
#include <boost/process/detail/windows/asio_fwd.hpp>
#include <boost/process/async_pipe.hpp>
#include <memory>
#include <future>
namespace boost { namespace process { namespace detail { namespace windows {
namespace boost { namespace process { namespace detail { namespace windows {
template<typename Buffer>
struct async_in_buffer : ::boost::process::detail::windows::handler_base_ext,
::boost::process::detail::windows::require_io_service
{
Buffer & buf;
template<typename Buffer>
struct async_in_buffer : ::boost::process::detail::windows::handler_base_ext,
::boost::process::detail::windows::require_io_context
{
Buffer & buf;
std::shared_ptr<std::promise<void>> promise;
async_in_buffer operator>(std::future<void> & fut)
{
promise = std::make_shared<std::promise<void>>();
fut = promise->get_future(); return std::move(*this);
}
std::shared_ptr<std::promise<void>> promise;
async_in_buffer operator>(std::future<void> & fut)
{
promise = std::make_shared<std::promise<void>>();
fut = promise->get_future(); return std::move(*this);
}
std::shared_ptr<boost::process::async_pipe> pipe;
std::shared_ptr<boost::process::async_pipe> pipe;
async_in_buffer(Buffer & buf) : buf(buf)
{
}
template <typename Executor>
inline void on_success(Executor&)
{
auto pipe = this->pipe;
async_in_buffer(Buffer & buf) : buf(buf)
{
}
template <typename Executor>
inline void on_success(Executor&)
{
auto pipe = this->pipe;
if (this->promise)
{
auto promise = this->promise;
if (this->promise)
{
auto promise = this->promise;
boost::asio::async_write(*pipe, buf,
[promise](const boost::system::error_code & ec, std::size_t)
{
if (ec && (ec.value() != ::boost::detail::winapi::ERROR_BROKEN_PIPE_))
{
std::error_code e(ec.value(), std::system_category());
promise->set_exception(std::make_exception_ptr(process_error(e)));
}
promise->set_value();
});
}
else
boost::asio::async_write(*pipe, buf,
[pipe](const boost::system::error_code&, std::size_t){});
boost::asio::async_write(*pipe, buf,
[promise](const boost::system::error_code & ec, std::size_t)
{
if (ec && (ec.value() != ::boost::winapi::ERROR_BROKEN_PIPE_))
{
std::error_code e(ec.value(), std::system_category());
promise->set_exception(std::make_exception_ptr(process_error(e)));
}
promise->set_value();
});
}
else
boost::asio::async_write(*pipe, buf,
[pipe](const boost::system::error_code&, std::size_t){});
std::move(*pipe).source().close();
std::move(*pipe).source().close();
this->pipe = nullptr;
}
this->pipe = nullptr;
}
template<typename Executor>
void on_error(Executor &, const std::error_code &) const
{
::boost::detail::winapi::CloseHandle(pipe->native_source());
}
template<typename Executor>
void on_error(Executor &, const std::error_code &) const
{
::boost::winapi::CloseHandle(pipe->native_source());
}
template <typename WindowsExecutor>
void on_setup(WindowsExecutor &exec)
{
if (!pipe)
pipe = std::make_shared<boost::process::async_pipe>(get_io_service(exec.seq));
template <typename WindowsExecutor>
void on_setup(WindowsExecutor &exec)
{
if (!pipe)
pipe = std::make_shared<boost::process::async_pipe>(get_io_context(exec.seq));
::boost::detail::winapi::HANDLE_ source_handle = std::move(*pipe).source().native_handle();
::boost::winapi::HANDLE_ source_handle = std::move(*pipe).source().native_handle();
boost::detail::winapi::SetHandleInformation(source_handle,
boost::detail::winapi::HANDLE_FLAG_INHERIT_,
boost::detail::winapi::HANDLE_FLAG_INHERIT_);
boost::winapi::SetHandleInformation(source_handle,
boost::winapi::HANDLE_FLAG_INHERIT_,
boost::winapi::HANDLE_FLAG_INHERIT_);
exec.startup_info.hStdInput = source_handle;
exec.startup_info.dwFlags |= boost::detail::winapi::STARTF_USESTDHANDLES_;
exec.inherit_handles = true;
}
};
exec.startup_info.hStdInput = source_handle;
exec.startup_info.dwFlags |= boost::winapi::STARTF_USESTDHANDLES_;
exec.inherit_handles = true;
}
};
}}}}
}}}}
#endif
#endif

View File

@@ -1,176 +1,179 @@
// 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)
// 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)
#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_ASYNC_OUT_HPP
#define BOOST_PROCESS_WINDOWS_INITIALIZERS_ASYNC_OUT_HPP
#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_ASYNC_OUT_HPP
#define BOOST_PROCESS_WINDOWS_INITIALIZERS_ASYNC_OUT_HPP
#include <boost/detail/winapi/process.hpp>
#include <boost/detail/winapi/handles.hpp>
#include <boost/detail/winapi/handle_info.hpp>
#include <boost/asio/read.hpp>
#include <boost/process/detail/handler_base.hpp>
#include <boost/process/detail/windows/asio_fwd.hpp>
#include <boost/detail/winapi/error_codes.hpp>
#include <boost/winapi/process.hpp>
#include <boost/winapi/handles.hpp>
#include <boost/winapi/handle_info.hpp>
#include <boost/winapi/error_codes.hpp>
#include <boost/asio/read.hpp>
#include <boost/process/detail/handler_base.hpp>
#include <boost/process/detail/windows/asio_fwd.hpp>
#include <istream>
#include <memory>
#include <exception>
#include <future>
#include <istream>
#include <memory>
#include <exception>
#include <future>
namespace boost { namespace process { namespace detail { namespace windows {
namespace boost { namespace process { namespace detail { namespace windows {
template <typename Executor>
inline void apply_out_handles(Executor &e, void* handle, std::integral_constant<int, 1>, std::integral_constant<int, -1>)
{
boost::detail::winapi::SetHandleInformation(handle,
boost::detail::winapi::HANDLE_FLAG_INHERIT_,
boost::detail::winapi::HANDLE_FLAG_INHERIT_);
template <typename Executor>
inline void apply_out_handles(Executor &e, void* handle, std::integral_constant<int, 1>, std::integral_constant<int, -1>)
{
boost::winapi::SetHandleInformation(handle,
boost::winapi::HANDLE_FLAG_INHERIT_,
boost::winapi::HANDLE_FLAG_INHERIT_);
e.startup_info.hStdOutput = handle;
e.startup_info.dwFlags |= ::boost::detail::winapi::STARTF_USESTDHANDLES_;
e.inherit_handles = true;
}
e.startup_info.hStdOutput = handle;
e.startup_info.dwFlags |= ::boost::winapi::STARTF_USESTDHANDLES_;
e.inherit_handles = true;
}
template <typename Executor>
inline void apply_out_handles(Executor &e, void* handle, std::integral_constant<int, 2>, std::integral_constant<int, -1>)
{
boost::detail::winapi::SetHandleInformation(handle,
boost::detail::winapi::HANDLE_FLAG_INHERIT_,
boost::detail::winapi::HANDLE_FLAG_INHERIT_);
template <typename Executor>
inline void apply_out_handles(Executor &e, void* handle, std::integral_constant<int, 2>, std::integral_constant<int, -1>)
{
boost::winapi::SetHandleInformation(handle,
boost::winapi::HANDLE_FLAG_INHERIT_,
boost::winapi::HANDLE_FLAG_INHERIT_);
e.startup_info.hStdError = handle;
e.startup_info.dwFlags |= ::boost::detail::winapi::STARTF_USESTDHANDLES_;
e.inherit_handles = true;
}
e.startup_info.hStdError = handle;
e.startup_info.dwFlags |= ::boost::winapi::STARTF_USESTDHANDLES_;
e.inherit_handles = true;
}
template <typename Executor>
inline void apply_out_handles(Executor &e, void* handle, std::integral_constant<int, 1>, std::integral_constant<int, 2>)
{
boost::detail::winapi::SetHandleInformation(handle,
boost::detail::winapi::HANDLE_FLAG_INHERIT_,
boost::detail::winapi::HANDLE_FLAG_INHERIT_);
template <typename Executor>
inline void apply_out_handles(Executor &e, void* handle, std::integral_constant<int, 1>, std::integral_constant<int, 2>)
{
boost::winapi::SetHandleInformation(handle,
boost::winapi::HANDLE_FLAG_INHERIT_,
boost::winapi::HANDLE_FLAG_INHERIT_);
e.startup_info.hStdOutput = handle;
e.startup_info.hStdError = handle;
e.startup_info.dwFlags |= ::boost::detail::winapi::STARTF_USESTDHANDLES_;
e.inherit_handles = true;
}
e.startup_info.hStdOutput = handle;
e.startup_info.hStdError = handle;
e.startup_info.dwFlags |= ::boost::winapi::STARTF_USESTDHANDLES_;
e.inherit_handles = true;
}
template<int p1, int p2, typename Buffer>
struct async_out_buffer : ::boost::process::detail::windows::handler_base_ext,
::boost::process::detail::windows::require_io_service
{
Buffer & buf;
template<int p1, int p2, typename Buffer>
struct async_out_buffer : ::boost::process::detail::windows::handler_base_ext,
::boost::process::detail::windows::require_io_context
{
Buffer & buf;
std::shared_ptr<boost::process::async_pipe> pipe;
std::shared_ptr<boost::process::async_pipe> pipe;
async_out_buffer(Buffer & buf) : buf(buf)
{
}
template <typename Executor>
inline void on_success(Executor&)
{
auto pipe = this->pipe;
boost::asio::async_read(*pipe, buf,
[pipe](const boost::system::error_code&, std::size_t){});
std::move(*pipe).sink().close();
this->pipe = nullptr;
async_out_buffer(Buffer & buf) : buf(buf)
{
}
template <typename Executor>
inline void on_success(Executor&)
{
auto pipe = this->pipe;
boost::asio::async_read(*pipe, buf,
[pipe](const boost::system::error_code&, std::size_t){});
std::move(*pipe).sink().close();
this->pipe = nullptr;
}
}
template<typename Executor>
void on_error(Executor &, const std::error_code &) const
{
std::move(*pipe).sink().close();
}
template<typename Executor>
void on_error(Executor &, const std::error_code &) const
{
std::move(*pipe).sink().close();
}
template <typename WindowsExecutor>
void on_setup(WindowsExecutor &exec)
{
if (!pipe)
pipe = std::make_shared<boost::process::async_pipe>(get_io_service(exec.seq));
apply_out_handles(exec, std::move(*pipe).sink().native_handle(),
std::integral_constant<int, p1>(), std::integral_constant<int, p2>());
}
};
template <typename WindowsExecutor>
void on_setup(WindowsExecutor &exec)
{
if (!pipe)
pipe = std::make_shared<boost::process::async_pipe>(get_io_context(exec.seq));
apply_out_handles(exec, std::move(*pipe).sink().native_handle(),
std::integral_constant<int, p1>(), std::integral_constant<int, p2>());
}
};
template<int p1, int p2, typename Type>
struct async_out_future : ::boost::process::detail::windows::handler_base_ext,
::boost::process::detail::windows::require_io_service
{
std::shared_ptr<boost::process::async_pipe> pipe;
std::shared_ptr<std::promise<Type>> promise = std::make_shared<std::promise<Type>>();
std::shared_ptr<boost::asio::streambuf> buffer = std::make_shared<boost::asio::streambuf>();
template<int p1, int p2, typename Type>
struct async_out_future : ::boost::process::detail::windows::handler_base_ext,
::boost::process::detail::windows::require_io_context
{
std::shared_ptr<boost::process::async_pipe> pipe;
std::shared_ptr<std::promise<Type>> promise = std::make_shared<std::promise<Type>>();
std::shared_ptr<boost::asio::streambuf> buffer = std::make_shared<boost::asio::streambuf>();
async_out_future(std::future<Type> & fut)
{
fut = promise->get_future();
}
template <typename Executor>
inline void on_success(Executor&)
{
auto pipe = this->pipe;
auto buffer = this->buffer;
auto promise = this->promise;
std::move(*pipe).sink().close();
boost::asio::async_read(*pipe, *buffer,
[pipe, buffer, promise](const boost::system::error_code& ec, std::size_t)
{
if (ec && (ec.value() != ::boost::detail::winapi::ERROR_BROKEN_PIPE_))
{
std::error_code e(ec.value(), std::system_category());
promise->set_exception(std::make_exception_ptr(process_error(e)));
}
else
{
std::istream is (buffer.get());
Type arg;
arg.resize(buffer->size());
is.read(&*arg.begin(), buffer->size());
async_out_future(std::future<Type> & fut)
{
fut = promise->get_future();
}
template <typename Executor>
inline void on_success(Executor&)
{
auto pipe = this->pipe;
auto buffer = this->buffer;
auto promise = this->promise;
std::move(*pipe).sink().close();
boost::asio::async_read(*pipe, *buffer,
[pipe, buffer, promise](const boost::system::error_code& ec, std::size_t)
{
if (ec && (ec.value() != ::boost::winapi::ERROR_BROKEN_PIPE_))
{
std::error_code e(ec.value(), std::system_category());
promise->set_exception(std::make_exception_ptr(process_error(e)));
}
else
{
std::istream is (buffer.get());
Type arg;
if (buffer->size() > 0)
{
arg.resize(buffer->size());
is.read(&*arg.begin(), buffer->size());
}
promise->set_value(std::move(arg));
promise->set_value(std::move(arg));
}
});
this->pipe = nullptr;
this->buffer = nullptr;
this->promise = nullptr;
}
});
this->pipe = nullptr;
this->buffer = nullptr;
this->promise = nullptr;
}
}
template<typename Executor>
void on_error(Executor &, const std::error_code &) const
{
std::move(*pipe).sink().close();
}
template<typename Executor>
void on_error(Executor &, const std::error_code &) const
{
std::move(*pipe).sink().close();
}
template <typename WindowsExecutor>
void on_setup(WindowsExecutor &exec)
{
if (!pipe)
pipe = std::make_shared<boost::process::async_pipe>(get_io_service(exec.seq));
template <typename WindowsExecutor>
void on_setup(WindowsExecutor &exec)
{
if (!pipe)
pipe = std::make_shared<boost::process::async_pipe>(get_io_context(exec.seq));
apply_out_handles(exec, std::move(*pipe).sink().native_handle(),
std::integral_constant<int, p1>(), std::integral_constant<int, p2>());
}
};
apply_out_handles(exec, std::move(*pipe).sink().native_handle(),
std::integral_constant<int, p1>(), std::integral_constant<int, p2>());
}
};
}}}}
}}}}
#endif
#endif

View File

@@ -6,15 +6,16 @@
#ifndef BOOST_PROCESS_DETAIL_WINDOWS_ASYNC_PIPE_HPP_
#define BOOST_PROCESS_DETAIL_WINDOWS_ASYNC_PIPE_HPP_
#include <boost/detail/winapi/basic_types.hpp>
#include <boost/detail/winapi/pipes.hpp>
#include <boost/detail/winapi/handles.hpp>
#include <boost/detail/winapi/file_management.hpp>
#include <boost/detail/winapi/get_last_error.hpp>
#include <boost/detail/winapi/access_rights.hpp>
#include <boost/detail/winapi/process.hpp>
#include <boost/winapi/basic_types.hpp>
#include <boost/winapi/pipes.hpp>
#include <boost/winapi/handles.hpp>
#include <boost/winapi/file_management.hpp>
#include <boost/winapi/get_last_error.hpp>
#include <boost/winapi/access_rights.hpp>
#include <boost/winapi/process.hpp>
#include <boost/process/detail/windows/basic_pipe.hpp>
#include <boost/asio/windows/stream_handle.hpp>
#include <atomic>
#include <system_error>
#include <string>
@@ -24,9 +25,9 @@ inline std::string make_pipe_name()
{
std::string name = "\\\\.\\pipe\\boost_process_auto_pipe_";
auto pid = ::boost::detail::winapi::GetCurrentProcessId();
auto pid = ::boost::winapi::GetCurrentProcessId();
static unsigned long long cnt = 0;
static std::atomic_size_t cnt{0};
name += std::to_string(pid);
name += "_";
name += std::to_string(cnt++);
@@ -39,33 +40,33 @@ class async_pipe
::boost::asio::windows::stream_handle _source;
::boost::asio::windows::stream_handle _sink ;
public:
typedef ::boost::detail::winapi::HANDLE_ native_handle_type;
typedef ::boost::winapi::HANDLE_ native_handle_type;
typedef ::boost::asio::windows::stream_handle handle_type;
inline async_pipe(boost::asio::io_service & ios,
inline async_pipe(boost::asio::io_context & ios,
const std::string & name = make_pipe_name())
: async_pipe(ios, ios, name) {}
inline async_pipe(boost::asio::io_service & ios_source,
boost::asio::io_service & ios_sink,
inline async_pipe(boost::asio::io_context & ios_source,
boost::asio::io_context & ios_sink,
const std::string & name = make_pipe_name());
inline async_pipe(const async_pipe& rhs);
async_pipe(async_pipe&& rhs) : _source(std::move(rhs._source)), _sink(std::move(rhs._sink))
{
rhs._source.assign (::boost::detail::winapi::INVALID_HANDLE_VALUE_);
rhs._sink .assign (::boost::detail::winapi::INVALID_HANDLE_VALUE_);
rhs._source.assign (::boost::winapi::INVALID_HANDLE_VALUE_);
rhs._sink .assign (::boost::winapi::INVALID_HANDLE_VALUE_);
}
template<class CharT, class Traits = std::char_traits<CharT>>
explicit async_pipe(::boost::asio::io_service & ios_source,
::boost::asio::io_service & ios_sink,
explicit async_pipe(::boost::asio::io_context & ios_source,
::boost::asio::io_context & ios_sink,
const basic_pipe<CharT, Traits> & p)
: _source(ios_source, p.native_source()), _sink(ios_sink, p.native_sink())
{
}
template<class CharT, class Traits = std::char_traits<CharT>>
explicit async_pipe(boost::asio::io_service & ios, const basic_pipe<CharT, Traits> & p)
explicit async_pipe(boost::asio::io_context & ios, const basic_pipe<CharT, Traits> & p)
: async_pipe(ios, ios, p)
{
}
@@ -78,10 +79,8 @@ public:
~async_pipe()
{
if (_sink .native() != ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
::boost::detail::winapi::CloseHandle(_sink.native());
if (_source.native() != ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
::boost::detail::winapi::CloseHandle(_source.native());
boost::system::error_code ec;
close(ec);
}
template<class CharT, class Traits = std::char_traits<CharT>>
@@ -100,12 +99,12 @@ public:
if (_sink.is_open())
{
_sink.close();
_sink = handle_type(_sink.get_io_service());
_sink = handle_type(_sink.get_io_context());
}
if (_source.is_open())
{
_source.close();
_source = handle_type(_source.get_io_service());
_source = handle_type(_source.get_io_context());
}
}
void close(boost::system::error_code & ec)
@@ -113,12 +112,12 @@ public:
if (_sink.is_open())
{
_sink.close(ec);
_sink = handle_type(_sink.get_io_service());
_sink = handle_type(_sink.get_io_context());
}
if (_source.is_open())
{
_source.close(ec);
_source = handle_type(_source.get_io_service());
_source = handle_type(_source.get_io_context());
}
}
@@ -129,9 +128,9 @@ public:
void async_close()
{
if (_sink.is_open())
_sink.get_io_service(). post([this]{_sink.close();});
_sink.get_io_context(). post([this]{_sink.close();});
if (_source.is_open())
_source.get_io_service().post([this]{_source.close();});
_source.get_io_context().post([this]{_source.close();});
}
template<typename MutableBufferSequence>
@@ -145,8 +144,8 @@ public:
return _sink.write_some(buffers);
}
native_handle_type native_source() const {return const_cast<boost::asio::windows::stream_handle&>(_source).native();}
native_handle_type native_sink () const {return const_cast<boost::asio::windows::stream_handle&>(_sink ).native();}
native_handle_type native_source() const {return const_cast<boost::asio::windows::stream_handle&>(_source).native_handle();}
native_handle_type native_sink () const {return const_cast<boost::asio::windows::stream_handle&>(_sink ).native_handle();}
template<typename MutableBufferSequence,
typename ReadHandler>
@@ -176,47 +175,47 @@ public:
handle_type && source() && { return std::move(_source); }
handle_type && sink() && { return std::move(_sink); }
handle_type source(::boost::asio::io_service& ios) &&
handle_type source(::boost::asio::io_context& ios) &&
{
::boost::asio::windows::stream_handle stolen(ios, _source.native_handle());
_source.assign(::boost::detail::winapi::INVALID_HANDLE_VALUE_);
_source.assign(::boost::winapi::INVALID_HANDLE_VALUE_);
return stolen;
}
handle_type sink (::boost::asio::io_service& ios) &&
handle_type sink (::boost::asio::io_context& ios) &&
{
::boost::asio::windows::stream_handle stolen(ios, _sink.native_handle());
_sink.assign(::boost::detail::winapi::INVALID_HANDLE_VALUE_);
_sink.assign(::boost::winapi::INVALID_HANDLE_VALUE_);
return stolen;
}
handle_type source(::boost::asio::io_service& ios) const &
handle_type source(::boost::asio::io_context& ios) const &
{
auto proc = ::boost::detail::winapi::GetCurrentProcess();
auto proc = ::boost::winapi::GetCurrentProcess();
::boost::detail::winapi::HANDLE_ source;
auto source_in = const_cast<handle_type&>(_source).native();
if (source_in == ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
source = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
else if (!::boost::detail::winapi::DuplicateHandle(
::boost::winapi::HANDLE_ source;
auto source_in = const_cast<handle_type&>(_source).native_handle();
if (source_in == ::boost::winapi::INVALID_HANDLE_VALUE_)
source = ::boost::winapi::INVALID_HANDLE_VALUE_;
else if (!::boost::winapi::DuplicateHandle(
proc, source_in, proc, &source, 0,
static_cast<::boost::detail::winapi::BOOL_>(true),
::boost::detail::winapi::DUPLICATE_SAME_ACCESS_))
static_cast<::boost::winapi::BOOL_>(true),
::boost::winapi::DUPLICATE_SAME_ACCESS_))
throw_last_error("Duplicate Pipe Failed");
return ::boost::asio::windows::stream_handle(ios, source);
}
handle_type sink (::boost::asio::io_service& ios) const &
handle_type sink (::boost::asio::io_context& ios) const &
{
auto proc = ::boost::detail::winapi::GetCurrentProcess();
auto proc = ::boost::winapi::GetCurrentProcess();
::boost::detail::winapi::HANDLE_ sink;
auto sink_in = const_cast<handle_type&>(_sink).native();
if (sink_in == ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
sink = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
else if (!::boost::detail::winapi::DuplicateHandle(
::boost::winapi::HANDLE_ sink;
auto sink_in = const_cast<handle_type&>(_sink).native_handle();
if (sink_in == ::boost::winapi::INVALID_HANDLE_VALUE_)
sink = ::boost::winapi::INVALID_HANDLE_VALUE_;
else if (!::boost::winapi::DuplicateHandle(
proc, sink_in, proc, &sink, 0,
static_cast<::boost::detail::winapi::BOOL_>(true),
::boost::detail::winapi::DUPLICATE_SAME_ACCESS_))
static_cast<::boost::winapi::BOOL_>(true),
::boost::winapi::DUPLICATE_SAME_ACCESS_))
throw_last_error("Duplicate Pipe Failed");
return ::boost::asio::windows::stream_handle(ios, sink);
@@ -226,32 +225,32 @@ public:
async_pipe::async_pipe(const async_pipe& p) :
_source(const_cast<handle_type&>(p._source).get_io_service()),
_sink (const_cast<handle_type&>(p._sink).get_io_service())
_source(const_cast<handle_type&>(p._source).get_io_context()),
_sink (const_cast<handle_type&>(p._sink).get_io_context())
{
auto proc = ::boost::detail::winapi::GetCurrentProcess();
auto proc = ::boost::winapi::GetCurrentProcess();
::boost::detail::winapi::HANDLE_ source;
::boost::detail::winapi::HANDLE_ sink;
::boost::winapi::HANDLE_ source;
::boost::winapi::HANDLE_ sink;
//cannot get the handle from a const object.
auto source_in = const_cast<handle_type&>(p._source).native();
auto sink_in = const_cast<handle_type&>(p._sink).native();
auto source_in = const_cast<handle_type&>(p._source).native_handle();
auto sink_in = const_cast<handle_type&>(p._sink).native_handle();
if (source_in == ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
source = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
else if (!::boost::detail::winapi::DuplicateHandle(
if (source_in == ::boost::winapi::INVALID_HANDLE_VALUE_)
source = ::boost::winapi::INVALID_HANDLE_VALUE_;
else if (!::boost::winapi::DuplicateHandle(
proc, source_in, proc, &source, 0,
static_cast<::boost::detail::winapi::BOOL_>(true),
::boost::detail::winapi::DUPLICATE_SAME_ACCESS_))
static_cast<::boost::winapi::BOOL_>(true),
::boost::winapi::DUPLICATE_SAME_ACCESS_))
throw_last_error("Duplicate Pipe Failed");
if (sink_in == ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
sink = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
else if (!::boost::detail::winapi::DuplicateHandle(
if (sink_in == ::boost::winapi::INVALID_HANDLE_VALUE_)
sink = ::boost::winapi::INVALID_HANDLE_VALUE_;
else if (!::boost::winapi::DuplicateHandle(
proc, sink_in, proc, &sink, 0,
static_cast<::boost::detail::winapi::BOOL_>(true),
::boost::detail::winapi::DUPLICATE_SAME_ACCESS_))
static_cast<::boost::winapi::BOOL_>(true),
::boost::winapi::DUPLICATE_SAME_ACCESS_))
throw_last_error("Duplicate Pipe Failed");
_source.assign(source);
@@ -259,32 +258,40 @@ async_pipe::async_pipe(const async_pipe& p) :
}
async_pipe::async_pipe(boost::asio::io_service & ios_source,
boost::asio::io_service & ios_sink,
async_pipe::async_pipe(boost::asio::io_context & ios_source,
boost::asio::io_context & ios_sink,
const std::string & name) : _source(ios_source), _sink(ios_sink)
{
static constexpr int FILE_FLAG_OVERLAPPED_ = 0x40000000; //temporary
::boost::detail::winapi::HANDLE_ source = ::boost::detail::winapi::create_named_pipe(
::boost::winapi::HANDLE_ source = ::boost::winapi::create_named_pipe(
#if defined(BOOST_NO_ANSI_APIS)
::boost::process::detail::convert(name).c_str(),
#else
name.c_str(),
::boost::detail::winapi::PIPE_ACCESS_INBOUND_
#endif
::boost::winapi::PIPE_ACCESS_INBOUND_
| FILE_FLAG_OVERLAPPED_, //write flag
0, 1, 8192, 8192, 0, nullptr);
if (source == boost::detail::winapi::INVALID_HANDLE_VALUE_)
if (source == boost::winapi::INVALID_HANDLE_VALUE_)
::boost::process::detail::throw_last_error("create_named_pipe(" + name + ") failed");
_source.assign(source);
::boost::detail::winapi::HANDLE_ sink = boost::detail::winapi::create_file(
::boost::winapi::HANDLE_ sink = boost::winapi::create_file(
#if defined(BOOST_NO_ANSI_APIS)
::boost::process::detail::convert(name).c_str(),
#else
name.c_str(),
::boost::detail::winapi::GENERIC_WRITE_, 0, nullptr,
::boost::detail::winapi::OPEN_EXISTING_,
#endif
::boost::winapi::GENERIC_WRITE_, 0, nullptr,
::boost::winapi::OPEN_EXISTING_,
FILE_FLAG_OVERLAPPED_, //to allow read
nullptr);
if (sink == ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
if (sink == ::boost::winapi::INVALID_HANDLE_VALUE_)
::boost::process::detail::throw_last_error("create_file() failed");
_sink.assign(sink);
@@ -292,79 +299,79 @@ async_pipe::async_pipe(boost::asio::io_service & ios_source,
async_pipe& async_pipe::operator=(const async_pipe & p)
{
auto proc = ::boost::detail::winapi::GetCurrentProcess();
auto proc = ::boost::winapi::GetCurrentProcess();
::boost::detail::winapi::HANDLE_ source;
::boost::detail::winapi::HANDLE_ sink;
::boost::winapi::HANDLE_ source;
::boost::winapi::HANDLE_ sink;
//cannot get the handle from a const object.
auto &source_in = const_cast<::boost::asio::windows::stream_handle &>(p._source);
auto &sink_in = const_cast<::boost::asio::windows::stream_handle &>(p._sink);
if (source_in.native() == ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
source = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
else if (!::boost::detail::winapi::DuplicateHandle(
proc, source_in.native(), proc, &source, 0,
static_cast<::boost::detail::winapi::BOOL_>(true),
::boost::detail::winapi::DUPLICATE_SAME_ACCESS_))
if (source_in.native_handle() == ::boost::winapi::INVALID_HANDLE_VALUE_)
source = ::boost::winapi::INVALID_HANDLE_VALUE_;
else if (!::boost::winapi::DuplicateHandle(
proc, source_in.native_handle(), proc, &source, 0,
static_cast<::boost::winapi::BOOL_>(true),
::boost::winapi::DUPLICATE_SAME_ACCESS_))
throw_last_error("Duplicate Pipe Failed");
if (sink_in.native() == ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
sink = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
else if (!::boost::detail::winapi::DuplicateHandle(
proc, sink_in.native(), proc, &sink, 0,
static_cast<::boost::detail::winapi::BOOL_>(true),
::boost::detail::winapi::DUPLICATE_SAME_ACCESS_))
if (sink_in.native_handle() == ::boost::winapi::INVALID_HANDLE_VALUE_)
sink = ::boost::winapi::INVALID_HANDLE_VALUE_;
else if (!::boost::winapi::DuplicateHandle(
proc, sink_in.native_handle(), proc, &sink, 0,
static_cast<::boost::winapi::BOOL_>(true),
::boost::winapi::DUPLICATE_SAME_ACCESS_))
throw_last_error("Duplicate Pipe Failed");
//so we also assign the io_service
_source = ::boost::asio::windows::stream_handle(source_in.get_io_service(), source);
_sink = ::boost::asio::windows::stream_handle(source_in.get_io_service(), sink);
//so we also assign the io_context
_source = ::boost::asio::windows::stream_handle(source_in.get_io_context(), source);
_sink = ::boost::asio::windows::stream_handle(source_in.get_io_context(), sink);
return *this;
}
async_pipe& async_pipe::operator=(async_pipe && rhs)
{
if (_source.native_handle() != ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
::boost::detail::winapi::CloseHandle(_source.native());
if (_source.native_handle() != ::boost::winapi::INVALID_HANDLE_VALUE_)
::boost::winapi::CloseHandle(_source.native_handle());
if (_sink.native_handle() != ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
::boost::detail::winapi::CloseHandle(_sink.native());
if (_sink.native_handle() != ::boost::winapi::INVALID_HANDLE_VALUE_)
::boost::winapi::CloseHandle(_sink.native_handle());
_source.assign(rhs._source.native_handle());
_sink .assign(rhs._sink .native_handle());
rhs._source.assign(::boost::detail::winapi::INVALID_HANDLE_VALUE_);
rhs._sink .assign(::boost::detail::winapi::INVALID_HANDLE_VALUE_);
rhs._source.assign(::boost::winapi::INVALID_HANDLE_VALUE_);
rhs._sink .assign(::boost::winapi::INVALID_HANDLE_VALUE_);
return *this;
}
template<class CharT, class Traits>
async_pipe::operator basic_pipe<CharT, Traits>() const
{
auto proc = ::boost::detail::winapi::GetCurrentProcess();
auto proc = ::boost::winapi::GetCurrentProcess();
::boost::detail::winapi::HANDLE_ source;
::boost::detail::winapi::HANDLE_ sink;
::boost::winapi::HANDLE_ source;
::boost::winapi::HANDLE_ sink;
//cannot get the handle from a const object.
auto source_in = const_cast<::boost::asio::windows::stream_handle &>(_source).native();
auto sink_in = const_cast<::boost::asio::windows::stream_handle &>(_sink).native();
auto source_in = const_cast<::boost::asio::windows::stream_handle &>(_source).native_handle();
auto sink_in = const_cast<::boost::asio::windows::stream_handle &>(_sink).native_handle();
if (source_in == ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
source = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
else if (!::boost::detail::winapi::DuplicateHandle(
if (source_in == ::boost::winapi::INVALID_HANDLE_VALUE_)
source = ::boost::winapi::INVALID_HANDLE_VALUE_;
else if (!::boost::winapi::DuplicateHandle(
proc, source_in, proc, &source, 0,
static_cast<::boost::detail::winapi::BOOL_>(true),
::boost::detail::winapi::DUPLICATE_SAME_ACCESS_))
static_cast<::boost::winapi::BOOL_>(true),
::boost::winapi::DUPLICATE_SAME_ACCESS_))
throw_last_error("Duplicate Pipe Failed");
if (sink_in == ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
sink = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
else if (!::boost::detail::winapi::DuplicateHandle(
if (sink_in == ::boost::winapi::INVALID_HANDLE_VALUE_)
sink = ::boost::winapi::INVALID_HANDLE_VALUE_;
else if (!::boost::winapi::DuplicateHandle(
proc, sink_in, proc, &sink, 0,
static_cast<::boost::detail::winapi::BOOL_>(true),
::boost::detail::winapi::DUPLICATE_SAME_ACCESS_))
static_cast<::boost::winapi::BOOL_>(true),
::boost::winapi::DUPLICATE_SAME_ACCESS_))
throw_last_error("Duplicate Pipe Failed");
return basic_pipe<CharT, Traits>{source, sink};

View File

@@ -1,164 +1,178 @@
// Copyright (c) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Copyright (c) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PROCESS_DETAIL_WINDOWS_BASIC_CMD_HPP_
#define BOOST_PROCESS_DETAIL_WINDOWS_BASIC_CMD_HPP_
#ifndef BOOST_PROCESS_DETAIL_WINDOWS_BASIC_CMD_HPP_
#define BOOST_PROCESS_DETAIL_WINDOWS_BASIC_CMD_HPP_
#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <boost/process/shell.hpp>
#include <boost/process/detail/windows/handler.hpp>
#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <boost/process/shell.hpp>
#include <boost/process/detail/windows/handler.hpp>
#include <vector>
#include <string>
#include <iterator>
#include <vector>
#include <string>
#include <iterator>
namespace boost
{
namespace process
{
namespace detail
{
namespace windows
{
namespace boost
{
namespace process
{
namespace detail
{
namespace windows
{
inline std::string build_args(const std::string & exe, std::vector<std::string> && data)
{
std::string st = exe;
inline std::string build_args(const std::string & exe, std::vector<std::string> && data)
{
std::string st = exe;
//put in quotes if it has spaces
{
boost::replace_all(st, "\"", "\\\"");
//put in quotes if it has spaces
{
boost::replace_all(st, "\"", "\\\"");
auto it = std::find(st.begin(), st.end(), ' ');
auto it = std::find(st.begin(), st.end(), ' ');
if (it != st.end())//contains spaces.
{
st.insert(st.begin(), '"');
st += '"';
}
}
if (it != st.end())//contains spaces.
{
st.insert(st.begin(), '"');
st += '"';
}
}
for (auto & arg : data)
{
boost::replace_all(arg, "\"", "\\\"");
for (auto & arg : data)
{
boost::replace_all(arg, "\"", "\\\"");
auto it = std::find(arg.begin(), arg.end(), ' ');//contains space?
if (it != arg.end())//ok, contains spaces.
{
//the first one is put directly onto the output,
//because then I don't have to copy the whole string
arg.insert(arg.begin(), '"');
arg += '"'; //thats the post one.
}
auto it = std::find(arg.begin(), arg.end(), ' ');//contains space?
if (it != arg.end())//ok, contains spaces.
{
//the first one is put directly onto the output,
//because then I don't have to copy the whole string
arg.insert(arg.begin(), '"');
arg += '"'; //thats the post one.
}
if (!st.empty())//first one does not need a preceeding space
st += ' ';
if (!st.empty())//first one does not need a preceeding space
st += ' ';
st += arg;
}
return st;
}
st += arg;
}
return st;
}
inline std::wstring build_args(const std::wstring & exe, std::vector<std::wstring> && data)
{
std::wstring st = exe;
for (auto & arg : data)
{
boost::replace_all(arg, L"\"", L"\\\"");
inline std::wstring build_args(const std::wstring & exe, std::vector<std::wstring> && data)
{
std::wstring st = exe;
auto it = std::find(arg.begin(), arg.end(), ' ');//contains space?
if (it != arg.end())//ok, contains spaces.
{
//the first one is put directly onto the output,
//because then I don't have to copy the whole string
arg.insert(arg.begin(), L'"');
arg += L'"'; //thats the post one.
}
//put in quotes if it has spaces
{
boost::replace_all(st, L"\"", L"\\\"");
if (!st.empty())//first one does not need a preceeding space
st += L' ';
auto it = std::find(st.begin(), st.end(), L' ');
st += arg;
}
return st;
}
if (it != st.end())//contains spaces.
{
st.insert(st.begin(), L'"');
st += L'"';
}
}
template<typename Char>
struct exe_cmd_init : handler_base_ext
{
using value_type = Char;
using string_type = std::basic_string<value_type>;
for (auto & arg : data)
{
boost::replace_all(arg, L"\"", L"\\\"");
static const char* c_arg(char) { return "/c";}
static const wchar_t* c_arg(wchar_t) { return L"/c";}
auto it = std::find(arg.begin(), arg.end(), L' ');//contains space?
if (it != arg.end())//ok, contains spaces.
{
//the first one is put directly onto the output,
//because then I don't have to copy the whole string
arg.insert(arg.begin(), L'"');
arg += L'"'; //thats the post one.
}
exe_cmd_init(const string_type & exe, bool cmd_only = false)
: exe(exe), args({}), cmd_only(cmd_only) {};
exe_cmd_init(string_type && exe, bool cmd_only = false)
: exe(std::move(exe)), args({}), cmd_only(cmd_only) {};
if (!st.empty())//first one does not need a preceeding space
st += L' ';
exe_cmd_init(string_type && exe, std::vector<string_type> && args)
: exe(std::move(exe)), args(build_args(this->exe, std::move(args))), cmd_only(false) {};
template <class Executor>
void on_setup(Executor& exec) const
{
st += arg;
}
return st;
}
if (cmd_only && args.empty())
exec.cmd_line = exe.c_str();
else
{
exec.exe = exe.c_str();
exec.cmd_line = args.c_str();
}
}
static exe_cmd_init<Char> exe_args(string_type && exe, std::vector<string_type> && args)
{
return exe_cmd_init<Char>(std::move(exe), std::move(args));
}
static exe_cmd_init<Char> cmd(string_type&& cmd)
{
return exe_cmd_init<Char>(std::move(cmd), true);
}
static exe_cmd_init<Char> exe_args_shell(string_type && exe, std::vector<string_type> && args)
{
std::vector<string_type> args_ = {c_arg(Char()), std::move(exe)};
args_.insert(args_.end(), std::make_move_iterator(args.begin()), std::make_move_iterator(args.end()));
string_type sh = get_shell(Char());
template<typename Char>
struct exe_cmd_init : handler_base_ext
{
using value_type = Char;
using string_type = std::basic_string<value_type>;
return exe_cmd_init<Char>(std::move(sh), std::move(args_));
}
static const char* c_arg(char) { return "/c";}
static const wchar_t* c_arg(wchar_t) { return L"/c";}
static std:: string get_shell(char) {return shell(). string(codecvt()); }
static std::wstring get_shell(wchar_t) {return shell().wstring(codecvt());}
exe_cmd_init(const string_type & exe, bool cmd_only = false)
: exe(exe), args({}), cmd_only(cmd_only) {};
exe_cmd_init(string_type && exe, bool cmd_only = false)
: exe(std::move(exe)), args({}), cmd_only(cmd_only) {};
static exe_cmd_init<Char> cmd_shell(string_type&& cmd)
{
std::vector<string_type> args = {c_arg(Char()), std::move(cmd)};
string_type sh = get_shell(Char());
exe_cmd_init(string_type && exe, std::vector<string_type> && args)
: exe(std::move(exe)), args(build_args(this->exe, std::move(args))), cmd_only(false) {};
template <class Executor>
void on_setup(Executor& exec) const
{
return exe_cmd_init<Char>(
std::move(sh),
std::move(args));
}
private:
string_type exe;
string_type args;
bool cmd_only;
};
if (cmd_only && args.empty())
exec.cmd_line = exe.c_str();
else
{
exec.exe = exe.c_str();
exec.cmd_line = args.c_str();
}
}
static exe_cmd_init<Char> exe_args(string_type && exe, std::vector<string_type> && args)
{
return exe_cmd_init<Char>(std::move(exe), std::move(args));
}
static exe_cmd_init<Char> cmd(string_type&& cmd)
{
return exe_cmd_init<Char>(std::move(cmd), true);
}
static exe_cmd_init<Char> exe_args_shell(string_type && exe, std::vector<string_type> && args)
{
std::vector<string_type> args_ = {c_arg(Char()), std::move(exe)};
args_.insert(args_.end(), std::make_move_iterator(args.begin()), std::make_move_iterator(args.end()));
string_type sh = get_shell(Char());
}
return exe_cmd_init<Char>(std::move(sh), std::move(args_));
}
static std:: string get_shell(char) {return shell(). string(codecvt()); }
static std::wstring get_shell(wchar_t) {return shell().wstring(codecvt());}
static exe_cmd_init<Char> cmd_shell(string_type&& cmd)
{
std::vector<string_type> args = {c_arg(Char()), std::move(cmd)};
string_type sh = get_shell(Char());
return exe_cmd_init<Char>(
std::move(sh),
std::move(args));
}
private:
string_type exe;
string_type args;
bool cmd_only;
};
}
}
}
}
}
}
}
#endif /* INCLUDE_BOOST_PROCESS_WINDOWS_ARGS_HPP_ */
#endif /* INCLUDE_BOOST_PROCESS_WINDOWS_ARGS_HPP_ */

View File

@@ -6,14 +6,14 @@
#ifndef BOOST_PROCESS_DETAIL_WINDOWS_PIPE_HPP
#define BOOST_PROCESS_DETAIL_WINDOWS_PIPE_HPP
#include <boost/detail/winapi/basic_types.hpp>
#include <boost/detail/winapi/error_codes.hpp>
#include <boost/detail/winapi/pipes.hpp>
#include <boost/detail/winapi/handles.hpp>
#include <boost/detail/winapi/file_management.hpp>
#include <boost/detail/winapi/get_last_error.hpp>
#include <boost/detail/winapi/access_rights.hpp>
#include <boost/detail/winapi/process.hpp>
#include <boost/winapi/basic_types.hpp>
#include <boost/winapi/error_codes.hpp>
#include <boost/winapi/pipes.hpp>
#include <boost/winapi/handles.hpp>
#include <boost/winapi/file_management.hpp>
#include <boost/winapi/get_last_error.hpp>
#include <boost/winapi/access_rights.hpp>
#include <boost/winapi/process.hpp>
#include <boost/process/detail/windows/compare_handles.hpp>
#include <system_error>
#include <string>
@@ -24,33 +24,33 @@ namespace boost { namespace process { namespace detail { namespace windows {
template<class CharT, class Traits = std::char_traits<CharT>>
class basic_pipe
{
::boost::detail::winapi::HANDLE_ _source = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
::boost::detail::winapi::HANDLE_ _sink = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
::boost::winapi::HANDLE_ _source = ::boost::winapi::INVALID_HANDLE_VALUE_;
::boost::winapi::HANDLE_ _sink = ::boost::winapi::INVALID_HANDLE_VALUE_;
public:
typedef CharT char_type ;
typedef Traits traits_type;
typedef typename Traits::int_type int_type ;
typedef typename Traits::pos_type pos_type ;
typedef typename Traits::off_type off_type ;
typedef ::boost::detail::winapi::HANDLE_ native_handle_type;
typedef ::boost::winapi::HANDLE_ native_handle_type;
explicit basic_pipe(::boost::detail::winapi::HANDLE_ source, ::boost::detail::winapi::HANDLE_ sink)
explicit basic_pipe(::boost::winapi::HANDLE_ source, ::boost::winapi::HANDLE_ sink)
: _source(source), _sink(sink) {}
inline explicit basic_pipe(const std::string & name);
inline basic_pipe(const basic_pipe& p);
basic_pipe(basic_pipe&& lhs) : _source(lhs._source), _sink(lhs._sink)
{
lhs._source = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
lhs._sink = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
lhs._source = ::boost::winapi::INVALID_HANDLE_VALUE_;
lhs._sink = ::boost::winapi::INVALID_HANDLE_VALUE_;
}
inline basic_pipe& operator=(const basic_pipe& p);
inline basic_pipe& operator=(basic_pipe&& lhs);
~basic_pipe()
{
if (_sink != ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
::boost::detail::winapi::CloseHandle(_sink);
if (_source != ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
::boost::detail::winapi::CloseHandle(_source);
if (_sink != ::boost::winapi::INVALID_HANDLE_VALUE_)
::boost::winapi::CloseHandle(_sink);
if (_source != ::boost::winapi::INVALID_HANDLE_VALUE_)
::boost::winapi::CloseHandle(_source);
}
native_handle_type native_source() const {return _source;}
native_handle_type native_sink () const {return _sink;}
@@ -60,21 +60,21 @@ public:
basic_pipe()
{
if (!::boost::detail::winapi::CreatePipe(&_source, &_sink, nullptr, 0))
if (!::boost::winapi::CreatePipe(&_source, &_sink, nullptr, 0))
throw_last_error("CreatePipe() failed");
}
int_type write(const char_type * data, int_type count)
{
::boost::detail::winapi::DWORD_ write_len;
if (!::boost::detail::winapi::WriteFile(
::boost::winapi::DWORD_ write_len;
if (!::boost::winapi::WriteFile(
_sink, data, count * sizeof(char_type), &write_len, nullptr
))
{
auto ec = ::boost::process::detail::get_last_error();
if ((ec.value() == ::boost::detail::winapi::ERROR_BROKEN_PIPE_) ||
(ec.value() == ::boost::detail::winapi::ERROR_NO_DATA_))
if ((ec.value() == ::boost::winapi::ERROR_BROKEN_PIPE_) ||
(ec.value() == ::boost::winapi::ERROR_NO_DATA_))
return 0;
else
throw process_error(ec, "WriteFile failed");
@@ -83,14 +83,14 @@ public:
}
int_type read(char_type * data, int_type count)
{
::boost::detail::winapi::DWORD_ read_len;
if (!::boost::detail::winapi::ReadFile(
::boost::winapi::DWORD_ read_len;
if (!::boost::winapi::ReadFile(
_source, data, count * sizeof(char_type), &read_len, nullptr
))
{
auto ec = ::boost::process::detail::get_last_error();
if ((ec.value() == ::boost::detail::winapi::ERROR_BROKEN_PIPE_) ||
(ec.value() == ::boost::detail::winapi::ERROR_NO_DATA_))
if ((ec.value() == ::boost::winapi::ERROR_BROKEN_PIPE_) ||
(ec.value() == ::boost::winapi::ERROR_NO_DATA_))
return 0;
else
throw process_error(ec, "ReadFile failed");
@@ -100,38 +100,38 @@ public:
bool is_open()
{
return (_source != ::boost::detail::winapi::INVALID_HANDLE_VALUE_) ||
(_sink != ::boost::detail::winapi::INVALID_HANDLE_VALUE_);
return (_source != ::boost::winapi::INVALID_HANDLE_VALUE_) ||
(_sink != ::boost::winapi::INVALID_HANDLE_VALUE_);
}
void close()
{
::boost::detail::winapi::CloseHandle(_source);
::boost::detail::winapi::CloseHandle(_sink);
_source = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
_sink = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
::boost::winapi::CloseHandle(_source);
::boost::winapi::CloseHandle(_sink);
_source = ::boost::winapi::INVALID_HANDLE_VALUE_;
_sink = ::boost::winapi::INVALID_HANDLE_VALUE_;
}
};
template<class Char, class Traits>
basic_pipe<Char, Traits>::basic_pipe(const basic_pipe & p)
{
auto proc = ::boost::detail::winapi::GetCurrentProcess();
auto proc = ::boost::winapi::GetCurrentProcess();
if (p._source == ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
_source = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
else if (!::boost::detail::winapi::DuplicateHandle(
if (p._source == ::boost::winapi::INVALID_HANDLE_VALUE_)
_source = ::boost::winapi::INVALID_HANDLE_VALUE_;
else if (!::boost::winapi::DuplicateHandle(
proc, p._source, proc, &_source, 0,
static_cast<::boost::detail::winapi::BOOL_>(true),
::boost::detail::winapi::DUPLICATE_SAME_ACCESS_))
static_cast<::boost::winapi::BOOL_>(true),
::boost::winapi::DUPLICATE_SAME_ACCESS_))
throw_last_error("Duplicate Pipe Failed");
if (p._sink == ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
_sink = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
else if (!::boost::detail::winapi::DuplicateHandle(
if (p._sink == ::boost::winapi::INVALID_HANDLE_VALUE_)
_sink = ::boost::winapi::INVALID_HANDLE_VALUE_;
else if (!::boost::winapi::DuplicateHandle(
proc, p._sink, proc, &_sink, 0,
static_cast<::boost::detail::winapi::BOOL_>(true),
::boost::detail::winapi::DUPLICATE_SAME_ACCESS_))
static_cast<::boost::winapi::BOOL_>(true),
::boost::winapi::DUPLICATE_SAME_ACCESS_))
throw_last_error("Duplicate Pipe Failed");
}
@@ -143,23 +143,23 @@ basic_pipe<Char, Traits>::basic_pipe(const std::string & name)
static constexpr int FILE_FLAG_OVERLAPPED_ = 0x40000000; //temporary
//static constexpr int FILE_ATTRIBUTE_NORMAL_ = 0x00000080; //temporary
::boost::detail::winapi::HANDLE_ source = ::boost::detail::winapi::create_named_pipe(
::boost::winapi::HANDLE_ source = ::boost::winapi::create_named_pipe(
name.c_str(),
::boost::detail::winapi::PIPE_ACCESS_INBOUND_
::boost::winapi::PIPE_ACCESS_INBOUND_
| FILE_FLAG_OVERLAPPED_, //write flag
0, 1, 8192, 8192, 0, nullptr);
if (source == boost::detail::winapi::INVALID_HANDLE_VALUE_)
if (source == boost::winapi::INVALID_HANDLE_VALUE_)
::boost::process::detail::throw_last_error("create_named_pipe() failed");
::boost::detail::winapi::HANDLE_ sink = boost::detail::winapi::create_file(
::boost::winapi::HANDLE_ sink = boost::winapi::create_file(
name.c_str(),
::boost::detail::winapi::GENERIC_WRITE_, 0, nullptr,
::boost::winapi::GENERIC_WRITE_, 0, nullptr,
OPEN_EXISTING_,
FILE_FLAG_OVERLAPPED_, //to allow read
nullptr);
if (sink == ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
if (sink == ::boost::winapi::INVALID_HANDLE_VALUE_)
::boost::process::detail::throw_last_error("create_file() failed");
_source = source;
@@ -169,22 +169,22 @@ basic_pipe<Char, Traits>::basic_pipe(const std::string & name)
template<class Char, class Traits>
basic_pipe<Char, Traits>& basic_pipe<Char, Traits>::operator=(const basic_pipe & p)
{
auto proc = ::boost::detail::winapi::GetCurrentProcess();
auto proc = ::boost::winapi::GetCurrentProcess();
if (p._source == ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
_source = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
else if (!::boost::detail::winapi::DuplicateHandle(
if (p._source == ::boost::winapi::INVALID_HANDLE_VALUE_)
_source = ::boost::winapi::INVALID_HANDLE_VALUE_;
else if (!::boost::winapi::DuplicateHandle(
proc, p._source, proc, &_source, 0,
static_cast<::boost::detail::winapi::BOOL_>(true),
::boost::detail::winapi::DUPLICATE_SAME_ACCESS_))
static_cast<::boost::winapi::BOOL_>(true),
::boost::winapi::DUPLICATE_SAME_ACCESS_))
throw_last_error("Duplicate Pipe Failed");
if (p._sink == ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
_sink = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
else if (!::boost::detail::winapi::DuplicateHandle(
if (p._sink == ::boost::winapi::INVALID_HANDLE_VALUE_)
_sink = ::boost::winapi::INVALID_HANDLE_VALUE_;
else if (!::boost::winapi::DuplicateHandle(
proc, p._sink, proc, &_sink, 0,
static_cast<::boost::detail::winapi::BOOL_>(true),
::boost::detail::winapi::DUPLICATE_SAME_ACCESS_))
static_cast<::boost::winapi::BOOL_>(true),
::boost::winapi::DUPLICATE_SAME_ACCESS_))
throw_last_error("Duplicate Pipe Failed");
return *this;
@@ -193,16 +193,16 @@ basic_pipe<Char, Traits>& basic_pipe<Char, Traits>::operator=(const basic_pipe &
template<class Char, class Traits>
basic_pipe<Char, Traits>& basic_pipe<Char, Traits>::operator=(basic_pipe && lhs)
{
if (_source != ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
::boost::detail::winapi::CloseHandle(_source);
if (_source != ::boost::winapi::INVALID_HANDLE_VALUE_)
::boost::winapi::CloseHandle(_source);
if (_sink != ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
::boost::detail::winapi::CloseHandle(_sink);
if (_sink != ::boost::winapi::INVALID_HANDLE_VALUE_)
::boost::winapi::CloseHandle(_sink);
_source = lhs._source;
_sink = lhs._sink;
lhs._source = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
lhs._sink = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
lhs._source = ::boost::winapi::INVALID_HANDLE_VALUE_;
lhs._sink = ::boost::winapi::INVALID_HANDLE_VALUE_;
return *this;
}

View File

@@ -11,9 +11,9 @@
#define BOOST_PROCESS_WINDOWS_CHILD_HPP
#include <boost/move/move.hpp>
#include <boost/detail/winapi/handles.hpp>
#include <boost/detail/winapi/process.hpp>
#include <boost/detail/winapi/jobs.hpp>
#include <boost/winapi/handles.hpp>
#include <boost/winapi/process.hpp>
#include <boost/winapi/jobs.hpp>
namespace boost { namespace process { namespace detail { namespace windows {
@@ -21,18 +21,18 @@ typedef int pid_t;
struct child_handle
{
::boost::detail::winapi::PROCESS_INFORMATION_ proc_info{nullptr, nullptr, 0,0};
::boost::winapi::PROCESS_INFORMATION_ proc_info{nullptr, nullptr, 0,0};
explicit child_handle(const ::boost::detail::winapi::PROCESS_INFORMATION_ &pi) :
explicit child_handle(const ::boost::winapi::PROCESS_INFORMATION_ &pi) :
proc_info(pi)
{}
explicit child_handle(pid_t pid) :
proc_info{nullptr, nullptr, 0,0}
{
auto h = ::boost::detail::winapi::OpenProcess(
::boost::detail::winapi::PROCESS_ALL_ACCESS_,
static_cast<::boost::detail::winapi::BOOL_>(0),
auto h = ::boost::winapi::OpenProcess(
::boost::winapi::PROCESS_ALL_ACCESS_,
static_cast<::boost::winapi::BOOL_>(0),
pid);
if (h == nullptr)
@@ -44,23 +44,23 @@ struct child_handle
child_handle() = default;
~child_handle()
{
::boost::detail::winapi::CloseHandle(proc_info.hProcess);
::boost::detail::winapi::CloseHandle(proc_info.hThread);
::boost::winapi::CloseHandle(proc_info.hProcess);
::boost::winapi::CloseHandle(proc_info.hThread);
}
child_handle(const child_handle & c) = delete;
child_handle(child_handle && c) : proc_info(c.proc_info)
{
c.proc_info.hProcess = ::boost::detail::winapi::invalid_handle_value;
c.proc_info.hThread = ::boost::detail::winapi::invalid_handle_value;
c.proc_info.hProcess = ::boost::winapi::invalid_handle_value;
c.proc_info.hThread = ::boost::winapi::invalid_handle_value;
}
child_handle &operator=(const child_handle & c) = delete;
child_handle &operator=(child_handle && c)
{
::boost::detail::winapi::CloseHandle(proc_info.hProcess);
::boost::detail::winapi::CloseHandle(proc_info.hThread);
::boost::winapi::CloseHandle(proc_info.hProcess);
::boost::winapi::CloseHandle(proc_info.hThread);
proc_info = c.proc_info;
c.proc_info.hProcess = ::boost::detail::winapi::invalid_handle_value;
c.proc_info.hThread = ::boost::detail::winapi::invalid_handle_value;
c.proc_info.hProcess = ::boost::winapi::invalid_handle_value;
c.proc_info.hThread = ::boost::winapi::invalid_handle_value;
return *this;
}
@@ -69,25 +69,25 @@ struct child_handle
return static_cast<int>(proc_info.dwProcessId);
}
typedef ::boost::detail::winapi::HANDLE_ process_handle_t;
typedef ::boost::winapi::HANDLE_ process_handle_t;
process_handle_t process_handle() const { return proc_info.hProcess; }
bool valid() const
{
return (proc_info.hProcess != nullptr) &&
(proc_info.hProcess != ::boost::detail::winapi::INVALID_HANDLE_VALUE_);
(proc_info.hProcess != ::boost::winapi::INVALID_HANDLE_VALUE_);
}
bool in_group() const
{
::boost::detail::winapi::BOOL_ value;
if (!::boost::detail::winapi::IsProcessInJob(proc_info.hProcess, nullptr, &value))
::boost::winapi::BOOL_ value;
if (!::boost::winapi::IsProcessInJob(proc_info.hProcess, nullptr, &value))
throw_last_error("IsProcessinJob Failed");
return value!=0;
}
bool in_group(std::error_code &ec) const noexcept
{
::boost::detail::winapi::BOOL_ value;
if (!::boost::detail::winapi::IsProcessInJob(proc_info.hProcess, nullptr, &value))
::boost::winapi::BOOL_ value;
if (!::boost::winapi::IsProcessInJob(proc_info.hProcess, nullptr, &value))
ec = get_last_error();
return value!=0;
}

View File

@@ -10,8 +10,8 @@
#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_CLOSE_IN_HPP
#define BOOST_PROCESS_WINDOWS_INITIALIZERS_CLOSE_IN_HPP
#include <boost/detail/winapi/process.hpp>
#include <boost/detail/winapi/handles.hpp>
#include <boost/winapi/process.hpp>
#include <boost/winapi/handles.hpp>
#include <boost/process/detail/handler_base.hpp>
namespace boost { namespace process { namespace detail { namespace windows {
@@ -21,8 +21,8 @@ struct close_in : public ::boost::process::detail::handler_base
template <class WindowsExecutor>
void on_setup(WindowsExecutor &e) const
{
e.startup_info.hStdInput = boost::detail::winapi::INVALID_HANDLE_VALUE_;
e.startup_info.dwFlags |= boost::detail::winapi::STARTF_USESTDHANDLES_;
e.startup_info.hStdInput = boost::winapi::INVALID_HANDLE_VALUE_;
e.startup_info.dwFlags |= boost::winapi::STARTF_USESTDHANDLES_;
}
};

View File

@@ -10,8 +10,8 @@
#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_CLOSE_OUT_HPP
#define BOOST_PROCESS_WINDOWS_INITIALIZERS_CLOSE_OUT_HPP
#include <boost/detail/winapi/process.hpp>
#include <boost/detail/winapi/handles.hpp>
#include <boost/winapi/process.hpp>
#include <boost/winapi/handles.hpp>
#include <boost/process/detail/handler_base.hpp>
namespace boost { namespace process { namespace detail { namespace windows {
@@ -27,25 +27,25 @@ template<>
template<typename WindowsExecutor>
void close_out<1,-1>::on_setup(WindowsExecutor &e) const
{
e.startup_info.hStdOutput = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
e.startup_info.dwFlags |= ::boost::detail::winapi::STARTF_USESTDHANDLES_;
e.startup_info.hStdOutput = ::boost::winapi::INVALID_HANDLE_VALUE_;
e.startup_info.dwFlags |= ::boost::winapi::STARTF_USESTDHANDLES_;
}
template<>
template<typename WindowsExecutor>
void close_out<2,-1>::on_setup(WindowsExecutor &e) const
{
e.startup_info.hStdError = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
e.startup_info.dwFlags |= ::boost::detail::winapi::STARTF_USESTDHANDLES_;
e.startup_info.hStdError = ::boost::winapi::INVALID_HANDLE_VALUE_;
e.startup_info.dwFlags |= ::boost::winapi::STARTF_USESTDHANDLES_;
}
template<>
template<typename WindowsExecutor>
void close_out<1,2>::on_setup(WindowsExecutor &e) const
{
e.startup_info.hStdOutput = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
e.startup_info.hStdError = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
e.startup_info.dwFlags |= ::boost::detail::winapi::STARTF_USESTDHANDLES_;
e.startup_info.hStdOutput = ::boost::winapi::INVALID_HANDLE_VALUE_;
e.startup_info.hStdError = ::boost::winapi::INVALID_HANDLE_VALUE_;
e.startup_info.dwFlags |= ::boost::winapi::STARTF_USESTDHANDLES_;
}
}}}}

View File

@@ -1,49 +1,49 @@
// Copyright (c) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Copyright (c) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PROCESS_WINDOWS_CMD_HPP_
#define BOOST_PROCESS_WINDOWS_CMD_HPP_
#ifndef BOOST_PROCESS_WINDOWS_CMD_HPP_
#define BOOST_PROCESS_WINDOWS_CMD_HPP_
#include <string>
#include <string>
namespace boost
{
namespace process
{
namespace detail
{
namespace windows
{
namespace boost
{
namespace process
{
namespace detail
{
namespace windows
{
template<typename CharType>
struct cmd_setter_ : ::boost::process::detail::handler_base
{
typedef CharType value_type;
typedef std::basic_string<value_type> string_type;
template<typename CharType>
struct cmd_setter_ : ::boost::process::detail::handler_base
{
typedef CharType value_type;
typedef std::basic_string<value_type> string_type;
cmd_setter_(string_type && cmd_line) : _cmd_line(std::move(cmd_line)) {}
cmd_setter_(const string_type & cmd_line) : _cmd_line(cmd_line) {}
template <class Executor>
void on_setup(Executor& exec)
{
exec.cmd_line = _cmd_line.c_str();
}
const string_type & str() const {return _cmd_line;}
cmd_setter_(string_type && cmd_line) : _cmd_line(std::move(cmd_line)) {}
cmd_setter_(const string_type & cmd_line) : _cmd_line(cmd_line) {}
template <class Executor>
void on_setup(Executor& exec)
{
exec.cmd_line = _cmd_line.c_str();
}
const string_type & str() const {return _cmd_line;}
private:
string_type _cmd_line;
};
private:
string_type _cmd_line;
};
}
}
}
}
}
}
}
}
#endif /* INCLUDE_BOOST_PROCESS_WINDOWS_ARGS_HPP_ */
#endif /* INCLUDE_BOOST_PROCESS_WINDOWS_ARGS_HPP_ */

View File

@@ -6,28 +6,28 @@
#ifndef BOOST_PROCESS_DETAIL_WINDOWS_COMPARE_HANDLES_HPP_
#define BOOST_PROCESS_DETAIL_WINDOWS_COMPARE_HANDLES_HPP_
#include <boost/detail/winapi/handles.hpp>
#include <boost/detail/winapi/file_management.hpp>
#include <boost/winapi/handles.hpp>
#include <boost/winapi/file_management.hpp>
#include <boost/process/detail/config.hpp>
namespace boost { namespace process { namespace detail { namespace windows {
inline bool compare_handles(boost::detail::winapi::HANDLE_ lhs, boost::detail::winapi::HANDLE_ rhs)
inline bool compare_handles(boost::winapi::HANDLE_ lhs, boost::winapi::HANDLE_ rhs)
{
if ( (lhs == ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
|| (rhs == ::boost::detail::winapi::INVALID_HANDLE_VALUE_))
if ( (lhs == ::boost::winapi::INVALID_HANDLE_VALUE_)
|| (rhs == ::boost::winapi::INVALID_HANDLE_VALUE_))
return false;
if (lhs == rhs)
return true;
::boost::detail::winapi::BY_HANDLE_FILE_INFORMATION_ lhs_info{0,{0,0},{0,0},{0,0},0,0,0,0,0,0};
::boost::detail::winapi::BY_HANDLE_FILE_INFORMATION_ rhs_info{0,{0,0},{0,0},{0,0},0,0,0,0,0,0};
::boost::winapi::BY_HANDLE_FILE_INFORMATION_ lhs_info{0,{0,0},{0,0},{0,0},0,0,0,0,0,0};
::boost::winapi::BY_HANDLE_FILE_INFORMATION_ rhs_info{0,{0,0},{0,0},{0,0},0,0,0,0,0,0};
if (!::boost::detail::winapi::GetFileInformationByHandle(lhs, &lhs_info))
if (!::boost::winapi::GetFileInformationByHandle(lhs, &lhs_info))
::boost::process::detail::throw_last_error("GetFileInformationByHandle");
if (!::boost::detail::winapi::GetFileInformationByHandle(rhs, &rhs_info))
if (!::boost::winapi::GetFileInformationByHandle(rhs, &rhs_info))
::boost::process::detail::throw_last_error("GetFileInformationByHandle");
return (lhs_info.nFileIndexHigh == rhs_info.nFileIndexHigh)

View File

@@ -7,8 +7,8 @@
#ifndef BOOST_PROCESS_DETAIL_WINDOWS_ENV_INIT_HPP_
#define BOOST_PROCESS_DETAIL_WINDOWS_ENV_INIT_HPP_
#include <boost/detail/winapi/error_codes.hpp>
#include <boost/detail/winapi/process.hpp>
#include <boost/winapi/error_codes.hpp>
#include <boost/winapi/process.hpp>
#include <boost/process/detail/config.hpp>
@@ -25,10 +25,10 @@ struct env_init : public ::boost::process::detail::handler_base
env_init(boost::process::basic_environment<Char> && env) : env(std::move(env)) {};
env_init(const boost::process::basic_environment<Char> & env) : env(env) {};
constexpr static ::boost::detail::winapi::DWORD_ creation_flag(char) {return 0u;}
constexpr static ::boost::detail::winapi::DWORD_ creation_flag(wchar_t)
constexpr static ::boost::winapi::DWORD_ creation_flag(char) {return 0u;}
constexpr static ::boost::winapi::DWORD_ creation_flag(wchar_t)
{
return ::boost::detail::winapi::CREATE_UNICODE_ENVIRONMENT_;
return ::boost::winapi::CREATE_UNICODE_ENVIRONMENT_;
}
template <class WindowsExecutor>
@@ -37,7 +37,7 @@ struct env_init : public ::boost::process::detail::handler_base
auto e = env.native_handle();
if (*e == null_char<char>())
{
exec.set_error(std::error_code(::boost::detail::winapi::ERROR_BAD_ENVIRONMENT_, std::system_category()),
exec.set_error(std::error_code(::boost::winapi::ERROR_BAD_ENVIRONMENT_, std::system_category()),
"Empty Environment");
}

View File

@@ -1,356 +1,354 @@
// Copyright (c) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PROCESS_DETAIL_WINDOWS_ENV_STORAGE_HPP_
#define BOOST_PROCESS_DETAIL_WINDOWS_ENV_STORAGE_HPP_
#include <string>
#include <vector>
#include <unordered_map>
#include <boost/detail/winapi/error_codes.hpp>
#include <boost/detail/winapi/environment.hpp>
#include <boost/process/detail/config.hpp>
#include <boost/detail/winapi/get_current_process.hpp>
#include <boost/detail/winapi/get_current_process_id.hpp>
#include <algorithm>
#include <boost/process/locale.hpp>
namespace boost { namespace process { namespace detail { namespace windows {
template<typename Char>
class native_environment_impl
{
static void _deleter(Char* p) {boost::detail::winapi::free_environment_strings(p);};
std::unique_ptr<Char[], void(*)(Char*)> _buf{boost::detail::winapi::get_environment_strings<Char>(), &native_environment_impl::_deleter};
static inline std::vector<Char*> _load_var(Char* p);
std::vector<Char*> _env_arr{_load_var(_buf.get())};
public:
using char_type = Char;
using pointer_type = const char_type*;
using string_type = std::basic_string<char_type>;
using native_handle_type = pointer_type;
void reload()
{
_buf.reset(boost::detail::winapi::get_environment_strings<Char>());
_env_arr = _load_var(_buf.get());
_env_impl = &*_env_arr.begin();
}
string_type get(const pointer_type id);
void set(const pointer_type id, const pointer_type value);
void reset(const pointer_type id);
string_type get(const string_type & id) {return get(id.c_str());}
void set(const string_type & id, const string_type & value) {set(id.c_str(), value.c_str()); }
void reset(const string_type & id) {reset(id.c_str());}
native_environment_impl() = default;
native_environment_impl(const native_environment_impl& ) = delete;
native_environment_impl(native_environment_impl && ) = default;
native_environment_impl & operator=(const native_environment_impl& ) = delete;
native_environment_impl & operator=(native_environment_impl && ) = default;
Char ** _env_impl = &*_env_arr.begin();
native_handle_type native_handle() const {return _buf.get();}
};
template<typename Char>
inline auto native_environment_impl<Char>::get(const pointer_type id) -> string_type
{
Char buf[4096];
auto size = boost::detail::winapi::get_environment_variable(id, buf, sizeof(buf));
if (size == 0) //failed
{
auto err = ::boost::detail::winapi::GetLastError();
if (err == ::boost::detail::winapi::ERROR_ENVVAR_NOT_FOUND_)//well, then we consider that an empty value
return "";
else
throw process_error(std::error_code(err, std::system_category()),
"GetEnvironmentVariable() failed");
}
if (size == sizeof(buf)) //the return size gives the size without the null, so I know this went wrong
{
/*limit defined here https://msdn.microsoft.com/en-us/library/windows/desktop/ms683188(v=vs.85).aspx
* but I used 32768 so it is a multiple of 4096.
*/
constexpr static std::size_t max_size = 32768;
//Handle variables longer then buf.
std::size_t buf_size = sizeof(buf);
while (buf_size <= max_size)
{
std::vector<Char> buf(buf_size);
auto size = boost::detail::winapi::get_environment_variable(id, buf.data(), buf.size());
if (size == buf_size) //buffer to small
buf_size *= 2;
else if (size == 0)
::boost::process::detail::throw_last_error("GetEnvironmentVariable() failed");
else
return std::basic_string<Char>(
buf.data(), buf.data()+ size + 1);
}
}
return std::basic_string<Char>(buf, buf+size+1);
}
template<typename Char>
inline void native_environment_impl<Char>::set(const pointer_type id, const pointer_type value)
{
boost::detail::winapi::set_environment_variable(id, value);
}
template<typename Char>
inline void native_environment_impl<Char>::reset(const pointer_type id)
{
boost::detail::winapi::set_environment_variable(id, nullptr);
}
template<typename Char>
std::vector<Char*> native_environment_impl<Char>::_load_var(Char* p)
{
std::vector<Char*> ret;
if (*p != null_char<Char>())
{
ret.push_back(p);
while ((*p != null_char<Char>()) || (*(p+1) != null_char<Char>()))
{
if (*p==null_char<Char>())
{
p++;
ret.push_back(p);
}
else
p++;
}
}
p++;
ret.push_back(nullptr);
return ret;
}
template<typename Char>
struct basic_environment_impl
{
std::vector<Char> _data = {null_char<Char>()};
static std::vector<Char*> _load_var(Char* p);
std::vector<Char*> _env_arr{_load_var(_data.data())};
public:
using char_type = Char;
using pointer_type = const char_type*;
using string_type = std::basic_string<char_type>;
using native_handle_type = pointer_type;
std::size_t size() const { return _data.size();}
void reload()
{
_env_arr = _load_var(_data.data());
_env_impl = _env_arr.data();
}
string_type get(const pointer_type id) {return get(string_type(id));}
void set(const pointer_type id, const pointer_type value) {set(string_type(id), value);}
void reset(const pointer_type id) {reset(string_type(id));}
string_type get(const string_type & id);
void set(const string_type & id, const string_type & value);
void reset(const string_type & id);
inline basic_environment_impl(const native_environment_impl<Char> & nei);
basic_environment_impl() = default;
basic_environment_impl(const basic_environment_impl& rhs)
: _data(rhs._data)
{
}
basic_environment_impl(basic_environment_impl && rhs)
: _data(std::move(rhs._data)),
_env_arr(std::move(rhs._env_arr)),
_env_impl(_env_arr.data())
{
}
basic_environment_impl &operator=(basic_environment_impl && rhs)
{
_data = std::move(rhs._data);
//reload();
_env_arr = std::move(rhs._env_arr);
_env_impl = _env_arr.data();
return *this;
}
basic_environment_impl & operator=(const basic_environment_impl& rhs)
{
_data = rhs._data;
reload();
return *this;
}
template<typename CharR>
explicit inline basic_environment_impl(
const basic_environment_impl<CharR>& rhs,
const ::boost::process::codecvt_type & cv = ::boost::process::codecvt())
: _data(::boost::process::detail::convert(rhs._data, cv))
{
}
template<typename CharR>
basic_environment_impl & operator=(const basic_environment_impl<CharR>& rhs)
{
_data = ::boost::process::detail::convert(rhs._data);
_env_arr = _load_var(&*_data.begin());
_env_impl = &*_env_arr.begin();
return *this;
}
Char ** _env_impl = &*_env_arr.begin();
native_handle_type native_handle() const {return &*_data.begin();}
};
template<typename Char>
basic_environment_impl<Char>::basic_environment_impl(const native_environment_impl<Char> & nei)
{
auto beg = nei.native_handle();
auto p = beg;
while ((*p != null_char<Char>()) || (*(p+1) != null_char<Char>()))
p++;
p++; //pointing to the second nullchar
p++; //to get the pointer behing the second nullchar, so it's end.
this->_data.assign(beg, p);
this->reload();
}
template<typename Char>
inline auto basic_environment_impl<Char>::get(const string_type &id) -> string_type
{
if (std::equal(id.begin(), id.end(), _data.begin()) && (_data[id.size()] == equal_sign<Char>()))
return string_type(_data.data()); //null-char is handled by the string.
std::vector<Char> seq = {'\0'}; //using a vector, because strings might cause problems with nullchars
seq.insert(seq.end(), id.begin(), id.end());
seq.push_back('=');
auto itr = std::search(_data.begin(), _data.end(), seq.begin(), seq.end());
if (itr == _data.end()) //not found
return "";
itr += seq.size(); //advance to the value behind the '='; the std::string will take care of finding the null-char.
return string_type(&*itr);
}
template<typename Char>
inline void basic_environment_impl<Char>::set(const string_type &id, const string_type &value)
{
reset(id);
// Copyright (c) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PROCESS_DETAIL_WINDOWS_ENV_STORAGE_HPP_
#define BOOST_PROCESS_DETAIL_WINDOWS_ENV_STORAGE_HPP_
#include <string>
#include <vector>
#include <unordered_map>
#include <boost/winapi/error_codes.hpp>
#include <boost/winapi/environment.hpp>
#include <boost/winapi/get_current_process.hpp>
#include <boost/winapi/get_current_process_id.hpp>
#include <boost/process/detail/config.hpp>
#include <algorithm>
#include <boost/process/locale.hpp>
namespace boost { namespace process { namespace detail { namespace windows {
template<typename Char>
class native_environment_impl
{
static void _deleter(Char* p) {boost::winapi::free_environment_strings(p);};
std::unique_ptr<Char[], void(*)(Char*)> _buf{boost::winapi::get_environment_strings<Char>(), &native_environment_impl::_deleter};
static inline std::vector<Char*> _load_var(Char* p);
std::vector<Char*> _env_arr{_load_var(_buf.get())};
public:
using char_type = Char;
using pointer_type = const char_type*;
using string_type = std::basic_string<char_type>;
using native_handle_type = pointer_type;
void reload()
{
_buf.reset(boost::winapi::get_environment_strings<Char>());
_env_arr = _load_var(_buf.get());
_env_impl = &*_env_arr.begin();
}
string_type get(const pointer_type id);
void set(const pointer_type id, const pointer_type value);
void reset(const pointer_type id);
string_type get(const string_type & id) {return get(id.c_str());}
void set(const string_type & id, const string_type & value) {set(id.c_str(), value.c_str()); }
void reset(const string_type & id) {reset(id.c_str());}
native_environment_impl() = default;
native_environment_impl(const native_environment_impl& ) = delete;
native_environment_impl(native_environment_impl && ) = default;
native_environment_impl & operator=(const native_environment_impl& ) = delete;
native_environment_impl & operator=(native_environment_impl && ) = default;
Char ** _env_impl = &*_env_arr.begin();
native_handle_type native_handle() const {return _buf.get();}
};
template<typename Char>
inline auto native_environment_impl<Char>::get(const pointer_type id) -> string_type
{
Char buf[4096];
auto size = boost::winapi::get_environment_variable(id, buf, sizeof(buf));
if (size == 0) //failed
{
auto err = ::boost::winapi::GetLastError();
if (err == ::boost::winapi::ERROR_ENVVAR_NOT_FOUND_)//well, then we consider that an empty value
return "";
else
throw process_error(std::error_code(err, std::system_category()),
"GetEnvironmentVariable() failed");
}
if (size == sizeof(buf)) //the return size gives the size without the null, so I know this went wrong
{
/*limit defined here https://msdn.microsoft.com/en-us/library/windows/desktop/ms683188(v=vs.85).aspx
* but I used 32768 so it is a multiple of 4096.
*/
constexpr static std::size_t max_size = 32768;
//Handle variables longer then buf.
std::size_t buf_size = sizeof(buf);
while (buf_size <= max_size)
{
std::vector<Char> buf(buf_size);
auto size = boost::winapi::get_environment_variable(id, buf.data(), buf.size());
if (size == buf_size) //buffer to small
buf_size *= 2;
else if (size == 0)
::boost::process::detail::throw_last_error("GetEnvironmentVariable() failed");
else
return std::basic_string<Char>(
buf.data(), buf.data()+ size + 1);
}
}
return std::basic_string<Char>(buf, buf+size+1);
}
template<typename Char>
inline void native_environment_impl<Char>::set(const pointer_type id, const pointer_type value)
{
boost::winapi::set_environment_variable(id, value);
}
template<typename Char>
inline void native_environment_impl<Char>::reset(const pointer_type id)
{
boost::winapi::set_environment_variable(id, nullptr);
}
template<typename Char>
std::vector<Char*> native_environment_impl<Char>::_load_var(Char* p)
{
std::vector<Char*> ret;
if (*p != null_char<Char>())
{
ret.push_back(p);
while ((*p != null_char<Char>()) || (*(p+1) != null_char<Char>()))
{
if (*p==null_char<Char>())
{
p++;
ret.push_back(p);
}
else
p++;
}
}
p++;
ret.push_back(nullptr);
return ret;
}
template<typename Char>
struct basic_environment_impl
{
std::vector<Char> _data = {null_char<Char>()};
static std::vector<Char*> _load_var(Char* p);
std::vector<Char*> _env_arr{_load_var(_data.data())};
public:
using char_type = Char;
using pointer_type = const char_type*;
using string_type = std::basic_string<char_type>;
using native_handle_type = pointer_type;
std::size_t size() const { return _data.size();}
void reload()
{
_env_arr = _load_var(_data.data());
_env_impl = _env_arr.data();
}
string_type get(const pointer_type id) {return get(string_type(id));}
void set(const pointer_type id, const pointer_type value) {set(string_type(id), value);}
void reset(const pointer_type id) {reset(string_type(id));}
string_type get(const string_type & id);
void set(const string_type & id, const string_type & value);
void reset(const string_type & id);
inline basic_environment_impl(const native_environment_impl<Char> & nei);
basic_environment_impl() = default;
basic_environment_impl(const basic_environment_impl& rhs)
: _data(rhs._data)
{
}
basic_environment_impl(basic_environment_impl && rhs)
: _data(std::move(rhs._data)),
_env_arr(std::move(rhs._env_arr)),
_env_impl(_env_arr.data())
{
}
basic_environment_impl &operator=(basic_environment_impl && rhs)
{
_data = std::move(rhs._data);
//reload();
_env_arr = std::move(rhs._env_arr);
_env_impl = _env_arr.data();
return *this;
}
basic_environment_impl & operator=(const basic_environment_impl& rhs)
{
_data = rhs._data;
reload();
return *this;
}
template<typename CharR>
explicit inline basic_environment_impl(
const basic_environment_impl<CharR>& rhs,
const ::boost::process::codecvt_type & cv = ::boost::process::codecvt())
: _data(::boost::process::detail::convert(rhs._data, cv))
{
}
template<typename CharR>
basic_environment_impl & operator=(const basic_environment_impl<CharR>& rhs)
{
_data = ::boost::process::detail::convert(rhs._data);
_env_arr = _load_var(&*_data.begin());
_env_impl = &*_env_arr.begin();
return *this;
}
Char ** _env_impl = &*_env_arr.begin();
native_handle_type native_handle() const {return &*_data.begin();}
};
template<typename Char>
basic_environment_impl<Char>::basic_environment_impl(const native_environment_impl<Char> & nei)
{
auto beg = nei.native_handle();
auto p = beg;
while ((*p != null_char<Char>()) || (*(p+1) != null_char<Char>()))
p++;
p++; //pointing to the second nullchar
p++; //to get the pointer behing the second nullchar, so it's end.
this->_data.assign(beg, p);
this->reload();
}
template<typename Char>
inline auto basic_environment_impl<Char>::get(const string_type &id) -> string_type
{
if (std::equal(id.begin(), id.end(), _data.begin()) && (_data[id.size()] == equal_sign<Char>()))
return string_type(_data.data()); //null-char is handled by the string.
std::vector<Char> seq = {'\0'}; //using a vector, because strings might cause problems with nullchars
seq.insert(seq.end(), id.begin(), id.end());
seq.push_back('=');
auto itr = std::search(_data.begin(), _data.end(), seq.begin(), seq.end());
if (itr == _data.end()) //not found
return "";
itr += seq.size(); //advance to the value behind the '='; the std::string will take care of finding the null-char.
return string_type(&*itr);
}
template<typename Char>
inline void basic_environment_impl<Char>::set(const string_type &id, const string_type &value)
{
reset(id);
std::vector<Char> insertion;
std::vector<Char> insertion;
insertion.insert(insertion.end(), id.begin(), id.end());
insertion.push_back('=');
insertion.insert(insertion.end(), value.begin(), value.end());
insertion.push_back('\0');
insertion.insert(insertion.end(), id.begin(), id.end());
insertion.push_back('=');
insertion.insert(insertion.end(), value.begin(), value.end());
insertion.push_back('\0');
_data.insert(_data.end() -1, insertion.begin(), insertion.end());
_data.insert(_data.end() -1, insertion.begin(), insertion.end());
reload();
}
reload();
}
template<typename Char>
inline void basic_environment_impl<Char>::reset(const string_type &id)
{
//ok, we need to check the size of data first
if (id.size() >= _data.size()) //ok, so it's impossible id is in there.
return;
template<typename Char>
inline void basic_environment_impl<Char>::reset(const string_type &id)
{
//ok, we need to check the size of data first
if (id.size() >= _data.size()) //ok, so it's impossible id is in there.
return;
//check if it's the first one, spares us the search.
if (std::equal(id.begin(), id.end(), _data.begin()) && (_data[id.size()] == equal_sign<Char>()))
{
auto beg = _data.begin();
auto end = beg;
//check if it's the first one, spares us the search.
if (std::equal(id.begin(), id.end(), _data.begin()) && (_data[id.size()] == equal_sign<Char>()))
{
auto beg = _data.begin();
auto end = beg;
while (*end != '\0')
end++;
while (*end != '\0')
end++;
end++; //to point behind the last null-char
end++; //to point behind the last null-char
_data.erase(beg, end); //and remove the thingy
_data.erase(beg, end); //and remove the thingy
}
}
std::vector<Char> seq = {'\0'}; //using a vector, because strings might cause problems with nullchars
seq.insert(seq.end(), id.begin(), id.end());
seq.push_back('=');
std::vector<Char> seq = {'\0'}; //using a vector, because strings might cause problems with nullchars
seq.insert(seq.end(), id.begin(), id.end());
seq.push_back('=');
auto itr = std::search(_data.begin(), _data.end(), seq.begin(), seq.end());
auto itr = std::search(_data.begin(), _data.end(), seq.begin(), seq.end());
if (itr == _data.end())
return;//nothing to return if it's empty anyway...
if (itr == _data.end())
return;//nothing to return if it's empty anyway...
auto end = itr;
auto end = itr;
while (*end != '\0')
end++;
while (*++end != '\0');
end ++; //to point behind the last null-char
_data.erase(itr, end);//and remove it
reload();
_data.erase(itr, end);//and remove it
reload();
}
}
template<typename Char>
std::vector<Char*> basic_environment_impl<Char>::_load_var(Char* p)
{
std::vector<Char*> ret;
if (*p != null_char<Char>())
{
ret.push_back(p);
while ((*p != null_char<Char>()) || (*(p+1) != null_char<Char>()))
{
if (*p==null_char<Char>())
{
p++;
ret.push_back(p);
}
else
p++;
}
}
p++;
ret.push_back(nullptr);
return ret;
}
template<typename Char>
std::vector<Char*> basic_environment_impl<Char>::_load_var(Char* p)
{
std::vector<Char*> ret;
if (*p != null_char<Char>())
{
ret.push_back(p);
while ((*p != null_char<Char>()) || (*(p+1) != null_char<Char>()))
{
if (*p==null_char<Char>())
{
p++;
ret.push_back(p);
}
else
p++;
}
}
p++;
ret.push_back(nullptr);
return ret;
}
template<typename T> constexpr T env_seperator();
template<> constexpr char env_seperator() {return ';'; }
template<> constexpr wchar_t env_seperator() {return L';'; }
template<typename T> constexpr T env_seperator();
template<> constexpr char env_seperator() {return ';'; }
template<> constexpr wchar_t env_seperator() {return L';'; }
inline int get_id() {return boost::detail::winapi::GetCurrentProcessId();}
inline void* native_handle() {return boost::detail::winapi::GetCurrentProcess(); }
inline int get_id() {return boost::winapi::GetCurrentProcessId();}
inline void* native_handle() {return boost::winapi::GetCurrentProcess(); }
typedef void* native_handle_t;
typedef void* native_handle_t;
}
}
}
}
}
}
}
}
#endif /* BOOST_PROCESS_DETAIL_WINDOWS_ENV_STORAGE_HPP_ */
#endif /* BOOST_PROCESS_DETAIL_WINDOWS_ENV_STORAGE_HPP_ */

View File

@@ -16,8 +16,8 @@
#include <boost/process/detail/traits.hpp>
#include <boost/process/error.hpp>
#include <boost/fusion/algorithm/iteration/for_each.hpp>
#include <boost/detail/winapi/handles.hpp>
#include <boost/detail/winapi/process.hpp>
#include <boost/winapi/handles.hpp>
#include <boost/winapi/process.hpp>
#include <boost/none.hpp>
#include <system_error>
#include <memory>
@@ -33,13 +33,13 @@ template<typename CharType> struct startup_info;
template<> struct startup_info<char>
{
typedef ::boost::detail::winapi::STARTUPINFOA_ type;
typedef ::boost::winapi::STARTUPINFOA_ type;
};
#endif
template<> struct startup_info<wchar_t>
{
typedef ::boost::detail::winapi::STARTUPINFOW_ type;
typedef ::boost::winapi::STARTUPINFOW_ type;
};
#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6
@@ -49,13 +49,13 @@ template<typename CharType> struct startup_info_ex;
#if !defined( BOOST_NO_ANSI_APIS )
template<> struct startup_info_ex<char>
{
typedef ::boost::detail::winapi::STARTUPINFOEXA_ type;
typedef ::boost::winapi::STARTUPINFOEXA_ type;
};
#endif
template<> struct startup_info_ex<wchar_t>
{
typedef ::boost::detail::winapi::STARTUPINFOEXW_ type;
typedef ::boost::winapi::STARTUPINFOEXW_ type;
};
@@ -66,7 +66,7 @@ template<> struct startup_info_ex<wchar_t>
template<typename CharT>
struct startup_info_impl
{
::boost::detail::winapi::DWORD_ creation_flags = 0;
::boost::winapi::DWORD_ creation_flags = 0;
typedef typename startup_info_ex<CharT>::type startup_info_ex_t;
typedef typename startup_info<CharT>::type startup_info_t;
@@ -74,9 +74,9 @@ struct startup_info_impl
startup_info_ex_t startup_info_ex
{startup_info_t {sizeof(startup_info_t), nullptr, nullptr, nullptr,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, nullptr,
::boost::detail::winapi::invalid_handle_value,
::boost::detail::winapi::invalid_handle_value,
::boost::detail::winapi::invalid_handle_value},
::boost::winapi::invalid_handle_value,
::boost::winapi::invalid_handle_value,
::boost::winapi::invalid_handle_value},
nullptr
};
startup_info_t & startup_info = startup_info_ex.StartupInfo;
@@ -84,7 +84,7 @@ struct startup_info_impl
void set_startup_info_ex()
{
startup_info.cb = sizeof(startup_info_ex_t);
creation_flags = ::boost::detail::winapi::EXTENDED_STARTUPINFO_PRESENT_;
creation_flags = ::boost::winapi::EXTENDED_STARTUPINFO_PRESENT_;
}
};
@@ -96,13 +96,13 @@ struct startup_info_impl
{
typedef typename startup_info<CharT>::type startup_info_t;
::boost::detail::winapi::DWORD_ creation_flags = 0;
::boost::winapi::DWORD_ creation_flags = 0;
startup_info_t startup_info
{sizeof(startup_info_t), nullptr, nullptr, nullptr,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, nullptr,
::boost::detail::winapi::invalid_handle_value,
::boost::detail::winapi::invalid_handle_value,
::boost::detail::winapi::invalid_handle_value};
::boost::winapi::invalid_handle_value,
::boost::winapi::invalid_handle_value,
::boost::winapi::invalid_handle_value};
};
#endif
@@ -186,7 +186,7 @@ public:
}
//NOTE: The non-cast cmd-line string can only be modified by the wchar_t variant which is currently disabled.
int err_code = ::boost::detail::winapi::create_process(
int err_code = ::boost::winapi::create_process(
exe, // LPCSTR_ lpApplicationName,
const_cast<Char*>(cmd_line), // LPSTR_ lpCommandLine,
proc_attrs, // LPSECURITY_ATTRIBUTES_ lpProcessAttributes,
@@ -232,9 +232,9 @@ public:
const std::error_code& error() const {return _ec;}
::boost::detail::winapi::LPSECURITY_ATTRIBUTES_ proc_attrs = nullptr;
::boost::detail::winapi::LPSECURITY_ATTRIBUTES_ thread_attrs = nullptr;
::boost::detail::winapi::BOOL_ inherit_handles = false;
::boost::winapi::LPSECURITY_ATTRIBUTES_ proc_attrs = nullptr;
::boost::winapi::LPSECURITY_ATTRIBUTES_ thread_attrs = nullptr;
::boost::winapi::BOOL_ inherit_handles = false;
const Char * work_dir = nullptr;
const Char * cmd_line = nullptr;
const Char * exe = nullptr;
@@ -242,7 +242,7 @@ public:
Sequence & seq;
::boost::detail::winapi::PROCESS_INFORMATION_ proc_info{nullptr, nullptr, 0,0};
::boost::winapi::PROCESS_INFORMATION_ proc_info{nullptr, nullptr, 0,0};
};

View File

@@ -1,104 +1,112 @@
// Copyright (c) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Copyright (c) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PROCESS_DETAIL_WINDOWS_FILE_DESCRIPTOR_HPP_
#define BOOST_PROCESS_DETAIL_WINDOWS_FILE_DESCRIPTOR_HPP_
#ifndef BOOST_PROCESS_DETAIL_WINDOWS_FILE_DESCRIPTOR_HPP_
#define BOOST_PROCESS_DETAIL_WINDOWS_FILE_DESCRIPTOR_HPP_
#include <boost/detail/winapi/basic_types.hpp>
#include <boost/detail/winapi/handles.hpp>
#include <boost/detail/winapi/file_management.hpp>
#include <string>
#include <boost/filesystem/path.hpp>
#include <boost/winapi/basic_types.hpp>
#include <boost/winapi/handles.hpp>
#include <boost/winapi/file_management.hpp>
#include <string>
#include <boost/filesystem/path.hpp>
namespace boost { namespace process { namespace detail { namespace windows {
namespace boost { namespace process { namespace detail { namespace windows {
struct file_descriptor
{
enum mode_t
{
read = 1,
write = 2,
read_write = 3
};
static ::boost::detail::winapi::DWORD_ desired_access(mode_t mode)
{
switch(mode)
{
case read:
return ::boost::detail::winapi::GENERIC_READ_;
case write:
return ::boost::detail::winapi::GENERIC_WRITE_;
case read_write:
return ::boost::detail::winapi::GENERIC_READ_
| ::boost::detail::winapi::GENERIC_WRITE_;
default:
return 0u;
}
}
struct file_descriptor
{
enum mode_t
{
read = 1,
write = 2,
read_write = 3
};
static ::boost::winapi::DWORD_ desired_access(mode_t mode)
{
switch(mode)
{
case read:
return ::boost::winapi::GENERIC_READ_;
case write:
return ::boost::winapi::GENERIC_WRITE_;
case read_write:
return ::boost::winapi::GENERIC_READ_
| ::boost::winapi::GENERIC_WRITE_;
default:
return 0u;
}
}
file_descriptor() = default;
file_descriptor(const boost::filesystem::path& p, mode_t mode = read_write)
: file_descriptor(p.native(), mode)
{
}
file_descriptor() = default;
file_descriptor(const boost::filesystem::path& p, mode_t mode = read_write)
: file_descriptor(p.native(), mode)
{
}
file_descriptor(const std::string & path , mode_t mode = read_write)
: file_descriptor(path.c_str(), mode) {}
file_descriptor(const std::wstring & path, mode_t mode = read_write)
: file_descriptor(path.c_str(), mode) {}
file_descriptor(const std::string & path , mode_t mode = read_write)
#if defined(BOOST_NO_ANSI_APIS)
: file_descriptor(::boost::process::detail::convert(path), mode)
#else
: file_descriptor(path.c_str(), mode)
#endif
{}
file_descriptor(const std::wstring & path, mode_t mode = read_write)
: file_descriptor(path.c_str(), mode) {}
file_descriptor(const char* path, mode_t mode = read_write)
: _handle(
::boost::detail::winapi::create_file(
path,
desired_access(mode),
::boost::detail::winapi::FILE_SHARE_READ_ |
::boost::detail::winapi::FILE_SHARE_WRITE_,
nullptr,
::boost::detail::winapi::OPEN_ALWAYS_,
file_descriptor(const char* path, mode_t mode = read_write)
#if defined(BOOST_NO_ANSI_APIS)
: file_descriptor(std::string(path), mode)
#else
: _handle(
::boost::winapi::create_file(
path,
desired_access(mode),
::boost::winapi::FILE_SHARE_READ_ |
::boost::winapi::FILE_SHARE_WRITE_,
nullptr,
::boost::winapi::OPEN_ALWAYS_,
::boost::detail::winapi::FILE_ATTRIBUTE_NORMAL_,
nullptr
))
{
::boost::winapi::FILE_ATTRIBUTE_NORMAL_,
nullptr
))
#endif
{
}
file_descriptor(const wchar_t * path, mode_t mode = read_write)
: _handle(
::boost::winapi::create_file(
path,
desired_access(mode),
::boost::winapi::FILE_SHARE_READ_ |
::boost::winapi::FILE_SHARE_WRITE_,
nullptr,
::boost::winapi::OPEN_ALWAYS_,
}
file_descriptor(const wchar_t * path, mode_t mode = read_write)
: _handle(
::boost::detail::winapi::create_file(
path,
desired_access(mode),
::boost::detail::winapi::FILE_SHARE_READ_ |
::boost::detail::winapi::FILE_SHARE_WRITE_,
nullptr,
::boost::detail::winapi::OPEN_ALWAYS_,
::boost::winapi::FILE_ATTRIBUTE_NORMAL_,
nullptr
))
{
::boost::detail::winapi::FILE_ATTRIBUTE_NORMAL_,
nullptr
))
{
}
file_descriptor(const file_descriptor & ) = delete;
file_descriptor(file_descriptor && ) = default;
}
file_descriptor(const file_descriptor & ) = delete;
file_descriptor(file_descriptor && ) = default;
file_descriptor& operator=(const file_descriptor & ) = delete;
file_descriptor& operator=(file_descriptor && ) = default;
file_descriptor& operator=(const file_descriptor & ) = delete;
file_descriptor& operator=(file_descriptor && ) = default;
~file_descriptor()
{
if (_handle != ::boost::winapi::INVALID_HANDLE_VALUE_)
::boost::winapi::CloseHandle(_handle);
}
~file_descriptor()
{
if (_handle != ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
::boost::detail::winapi::CloseHandle(_handle);
}
::boost::winapi::HANDLE_ handle() const { return _handle;}
::boost::detail::winapi::HANDLE_ handle() const { return _handle;}
private:
::boost::winapi::HANDLE_ _handle = ::boost::winapi::INVALID_HANDLE_VALUE_;
};
private:
::boost::detail::winapi::HANDLE_ _handle = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
};
}}}}
}}}}
#endif /* BOOST_PROCESS_DETAIL_WINDOWS_FILE_DESCRIPTOR_HPP_ */
#endif /* BOOST_PROCESS_DETAIL_WINDOWS_FILE_DESCRIPTOR_HPP_ */

View File

@@ -1,44 +1,44 @@
// 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)
// 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)
#ifndef BOOST_PROCESS_DETAIL_WINDOWS_FILE_IN_HPP
#define BOOST_PROCESS_DETAIL_WINDOWS_FILE_IN_HPP
#ifndef BOOST_PROCESS_DETAIL_WINDOWS_FILE_IN_HPP
#define BOOST_PROCESS_DETAIL_WINDOWS_FILE_IN_HPP
#include <boost/detail/winapi/process.hpp>
#include <boost/detail/winapi/handles.hpp>
#include <boost/process/detail/handler_base.hpp>
#include <boost/process/detail/windows/file_descriptor.hpp>
#include <io.h>
#include <boost/winapi/process.hpp>
#include <boost/winapi/handles.hpp>
#include <boost/process/detail/handler_base.hpp>
#include <boost/process/detail/windows/file_descriptor.hpp>
#include <io.h>
namespace boost { namespace process { namespace detail { namespace windows {
namespace boost { namespace process { namespace detail { namespace windows {
struct file_in : public ::boost::process::detail::handler_base
{
file_descriptor file;
::boost::detail::winapi::HANDLE_ handle = file.handle();
struct file_in : public ::boost::process::detail::handler_base
{
file_descriptor file;
::boost::winapi::HANDLE_ handle = file.handle();
template<typename T>
file_in(T&& t) : file(std::forward<T>(t), file_descriptor::read) {}
file_in(FILE * f) : handle(reinterpret_cast<::boost::detail::winapi::HANDLE_>(_get_osfhandle(_fileno(f)))) {}
template<typename T>
file_in(T&& t) : file(std::forward<T>(t), file_descriptor::read) {}
file_in(FILE * f) : handle(reinterpret_cast<::boost::winapi::HANDLE_>(_get_osfhandle(_fileno(f)))) {}
template <class WindowsExecutor>
void on_setup(WindowsExecutor &e) const
{
boost::detail::winapi::SetHandleInformation(handle,
boost::detail::winapi::HANDLE_FLAG_INHERIT_,
boost::detail::winapi::HANDLE_FLAG_INHERIT_);
e.startup_info.hStdInput = handle;
e.startup_info.dwFlags |= boost::detail::winapi::STARTF_USESTDHANDLES_;
e.inherit_handles = true;
}
};
template <class WindowsExecutor>
void on_setup(WindowsExecutor &e) const
{
boost::winapi::SetHandleInformation(handle,
boost::winapi::HANDLE_FLAG_INHERIT_,
boost::winapi::HANDLE_FLAG_INHERIT_);
e.startup_info.hStdInput = handle;
e.startup_info.dwFlags |= boost::winapi::STARTF_USESTDHANDLES_;
e.inherit_handles = true;
}
};
}}}}
}}}}
#endif
#endif

View File

@@ -1,77 +1,77 @@
// 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)
// 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)
#ifndef BOOST_PROCESS_DETAIL_WINDOWS_FILE_OUT_HPP
#define BOOST_PROCESS_DETAIL_WINDOWS_FILE_OUT_HPP
#ifndef BOOST_PROCESS_DETAIL_WINDOWS_FILE_OUT_HPP
#define BOOST_PROCESS_DETAIL_WINDOWS_FILE_OUT_HPP
#include <boost/detail/winapi/process.hpp>
#include <boost/detail/winapi/handles.hpp>
#include <boost/detail/winapi/handle_info.hpp>
#include <boost/process/detail/handler_base.hpp>
#include <boost/process/detail/windows/file_descriptor.hpp>
#include <boost/winapi/process.hpp>
#include <boost/winapi/handles.hpp>
#include <boost/winapi/handle_info.hpp>
#include <boost/process/detail/handler_base.hpp>
#include <boost/process/detail/windows/file_descriptor.hpp>
namespace boost { namespace process { namespace detail { namespace windows {
namespace boost { namespace process { namespace detail { namespace windows {
template<int p1, int p2>
struct file_out : public ::boost::process::detail::handler_base
{
file_descriptor file;
::boost::detail::winapi::HANDLE_ handle = file.handle();
template<int p1, int p2>
struct file_out : public ::boost::process::detail::handler_base
{
file_descriptor file;
::boost::winapi::HANDLE_ handle = file.handle();
template<typename T>
file_out(T&& t) : file(std::forward<T>(t), file_descriptor::write) {}
file_out(FILE * f) : handle(reinterpret_cast<void*>(_get_osfhandle(_fileno(f)))) {}
template<typename T>
file_out(T&& t) : file(std::forward<T>(t), file_descriptor::write) {}
file_out(FILE * f) : handle(reinterpret_cast<void*>(_get_osfhandle(_fileno(f)))) {}
template <typename WindowsExecutor>
inline void on_setup(WindowsExecutor &e) const;
};
template <typename WindowsExecutor>
inline void on_setup(WindowsExecutor &e) const;
};
template<>
template<typename WindowsExecutor>
void file_out<1,-1>::on_setup(WindowsExecutor &e) const
{
boost::detail::winapi::SetHandleInformation(handle,
boost::detail::winapi::HANDLE_FLAG_INHERIT_,
boost::detail::winapi::HANDLE_FLAG_INHERIT_);
template<>
template<typename WindowsExecutor>
void file_out<1,-1>::on_setup(WindowsExecutor &e) const
{
boost::winapi::SetHandleInformation(handle,
boost::winapi::HANDLE_FLAG_INHERIT_,
boost::winapi::HANDLE_FLAG_INHERIT_);
e.startup_info.hStdOutput = handle;
e.startup_info.dwFlags |= ::boost::detail::winapi::STARTF_USESTDHANDLES_;
e.inherit_handles = true;
}
e.startup_info.hStdOutput = handle;
e.startup_info.dwFlags |= ::boost::winapi::STARTF_USESTDHANDLES_;
e.inherit_handles = true;
}
template<>
template<typename WindowsExecutor>
void file_out<2,-1>::on_setup(WindowsExecutor &e) const
{
boost::detail::winapi::SetHandleInformation(handle,
boost::detail::winapi::HANDLE_FLAG_INHERIT_,
boost::detail::winapi::HANDLE_FLAG_INHERIT_);
template<>
template<typename WindowsExecutor>
void file_out<2,-1>::on_setup(WindowsExecutor &e) const
{
boost::winapi::SetHandleInformation(handle,
boost::winapi::HANDLE_FLAG_INHERIT_,
boost::winapi::HANDLE_FLAG_INHERIT_);
e.startup_info.hStdError = handle;
e.startup_info.dwFlags |= ::boost::detail::winapi::STARTF_USESTDHANDLES_;
e.inherit_handles = true;
}
e.startup_info.hStdError = handle;
e.startup_info.dwFlags |= ::boost::winapi::STARTF_USESTDHANDLES_;
e.inherit_handles = true;
}
template<>
template<typename WindowsExecutor>
void file_out<1,2>::on_setup(WindowsExecutor &e) const
{
boost::detail::winapi::SetHandleInformation(handle,
boost::detail::winapi::HANDLE_FLAG_INHERIT_,
boost::detail::winapi::HANDLE_FLAG_INHERIT_);
template<>
template<typename WindowsExecutor>
void file_out<1,2>::on_setup(WindowsExecutor &e) const
{
boost::winapi::SetHandleInformation(handle,
boost::winapi::HANDLE_FLAG_INHERIT_,
boost::winapi::HANDLE_FLAG_INHERIT_);
e.startup_info.hStdOutput = handle;
e.startup_info.hStdError = handle;
e.startup_info.dwFlags |= ::boost::detail::winapi::STARTF_USESTDHANDLES_;
e.inherit_handles = true;
}
e.startup_info.hStdOutput = handle;
e.startup_info.hStdError = handle;
e.startup_info.dwFlags |= ::boost::winapi::STARTF_USESTDHANDLES_;
e.inherit_handles = true;
}
}}}}
}}}}
#endif
#endif

View File

@@ -7,14 +7,14 @@
#define BOOST_PROCESS_DETAIL_WINDOWS_GROUP_HPP_
#include <boost/process/detail/windows/handler.hpp>
#include <boost/detail/winapi/jobs.hpp>
#include <boost/winapi/jobs.hpp>
#include <boost/process/detail/windows/child_handle.hpp>
#include <boost/process/detail/windows/job_workaround.hpp>
#include <system_error>
namespace boost { namespace process { namespace detail { namespace windows {
inline bool break_away_enabled(::boost::detail::winapi::HANDLE_ h)
inline bool break_away_enabled(::boost::winapi::HANDLE_ h)
{
workaround::JOBOBJECT_EXTENDED_LIMIT_INFORMATION_ info;
@@ -29,7 +29,7 @@ inline bool break_away_enabled(::boost::detail::winapi::HANDLE_ h)
return (info.BasicLimitInformation.LimitFlags & workaround::JOB_OBJECT_LIMIT_BREAKAWAY_OK_) != 0;
}
inline void enable_break_away(::boost::detail::winapi::HANDLE_ h)
inline void enable_break_away(::boost::winapi::HANDLE_ h)
{
workaround::JOBOBJECT_EXTENDED_LIMIT_INFORMATION_ info;
@@ -54,7 +54,7 @@ inline void enable_break_away(::boost::detail::winapi::HANDLE_ h)
throw_last_error("SetInformationJobObject() failed");
}
inline void enable_break_away(::boost::detail::winapi::HANDLE_ h, std::error_code & ec)
inline void enable_break_away(::boost::winapi::HANDLE_ h, std::error_code & ec)
{
workaround::JOBOBJECT_EXTENDED_LIMIT_INFORMATION_ info;
@@ -91,9 +91,9 @@ inline void enable_break_away(::boost::detail::winapi::HANDLE_ h, std::error_cod
struct group_handle
{
::boost::detail::winapi::HANDLE_ _job_object;
::boost::winapi::HANDLE_ _job_object;
typedef ::boost::detail::winapi::HANDLE_ handle_t;
typedef ::boost::winapi::HANDLE_ handle_t;
handle_t handle() const { return _job_object; }
explicit group_handle(handle_t h) :
@@ -103,52 +103,52 @@ struct group_handle
}
group_handle() : group_handle(::boost::detail::winapi::CreateJobObjectA(nullptr, nullptr))
group_handle() : group_handle(::boost::winapi::CreateJobObjectW(nullptr, nullptr))
{
}
~group_handle()
{
::boost::detail::winapi::CloseHandle(_job_object);
::boost::winapi::CloseHandle(_job_object);
}
group_handle(const group_handle & c) = delete;
group_handle(group_handle && c) : _job_object(c._job_object)
{
c._job_object = ::boost::detail::winapi::invalid_handle_value;
c._job_object = ::boost::winapi::invalid_handle_value;
}
group_handle &operator=(const group_handle & c) = delete;
group_handle &operator=(group_handle && c)
{
::boost::detail::winapi::CloseHandle(_job_object);
::boost::winapi::CloseHandle(_job_object);
_job_object = c._job_object;
c._job_object = ::boost::detail::winapi::invalid_handle_value;
c._job_object = ::boost::winapi::invalid_handle_value;
return *this;
}
void add(handle_t proc)
{
if (!::boost::detail::winapi::AssignProcessToJobObject(_job_object, proc))
if (!::boost::winapi::AssignProcessToJobObject(_job_object, proc))
throw_last_error();
}
void add(handle_t proc, std::error_code & ec) noexcept
{
if (!::boost::detail::winapi::AssignProcessToJobObject(_job_object, proc))
if (!::boost::winapi::AssignProcessToJobObject(_job_object, proc))
ec = get_last_error();
}
bool has(handle_t proc)
{
::boost::detail::winapi::BOOL_ is;
if (!::boost::detail::winapi::IsProcessInJob(proc, _job_object, &is))
::boost::winapi::BOOL_ is;
if (!::boost::winapi::IsProcessInJob(proc, _job_object, &is))
throw_last_error();
return is!=0;
}
bool has(handle_t proc, std::error_code & ec) noexcept
{
::boost::detail::winapi::BOOL_ is;
if (!::boost::detail::winapi::IsProcessInJob(proc, _job_object, &is))
::boost::winapi::BOOL_ is;
if (!::boost::winapi::IsProcessInJob(proc, _job_object, &is))
ec = get_last_error();
return is!=0;
}
@@ -162,13 +162,13 @@ struct group_handle
inline void terminate(const group_handle &p)
{
if (!::boost::detail::winapi::TerminateJobObject(p.handle(), EXIT_FAILURE))
if (!::boost::winapi::TerminateJobObject(p.handle(), EXIT_FAILURE))
boost::process::detail::throw_last_error("TerminateJobObject() failed");
}
inline void terminate(const group_handle &p, std::error_code &ec) noexcept
{
if (!::boost::detail::winapi::TerminateJobObject(p.handle(), EXIT_FAILURE))
if (!::boost::winapi::TerminateJobObject(p.handle(), EXIT_FAILURE))
ec = boost::process::detail::get_last_error();
else
ec.clear();
@@ -176,8 +176,8 @@ inline void terminate(const group_handle &p, std::error_code &ec) noexcept
inline bool in_group()
{
::boost::detail::winapi::BOOL_ res;
if (!::boost::detail::winapi::IsProcessInJob(boost::detail::winapi::GetCurrentProcess(), nullptr, &res))
::boost::winapi::BOOL_ res;
if (!::boost::winapi::IsProcessInJob(boost::winapi::GetCurrentProcess(), nullptr, &res))
throw_last_error("IsProcessInJob failed");
return res!=0;

View File

@@ -8,7 +8,7 @@
#include <boost/process/detail/config.hpp>
#include <boost/process/detail/windows/group_handle.hpp>
#include <boost/detail/winapi/process.hpp>
#include <boost/winapi/process.hpp>
#include <boost/process/detail/windows/handler.hpp>
namespace boost { namespace process {
@@ -19,7 +19,7 @@ namespace detail { namespace windows {
struct group_ref : handler_base_ext
{
::boost::detail::winapi::HANDLE_ handle;
::boost::winapi::HANDLE_ handle;
explicit group_ref(group_handle &g) :
handle(g.handle())
@@ -30,14 +30,14 @@ struct group_ref : handler_base_ext
{
//I can only enable this if the current process supports breakaways.
if (in_group() && break_away_enabled(nullptr))
exec.creation_flags |= boost::detail::winapi::CREATE_BREAKAWAY_FROM_JOB_;
exec.creation_flags |= boost::winapi::CREATE_BREAKAWAY_FROM_JOB_;
}
template <class Executor>
void on_success(Executor& exec) const
{
if (!::boost::detail::winapi::AssignProcessToJobObject(handle, exec.proc_info.hProcess))
if (!::boost::winapi::AssignProcessToJobObject(handle, exec.proc_info.hProcess))
exec.set_error(::boost::process::detail::get_last_error(),
"AssignProcessToJobObject() failed.");

View File

@@ -1,20 +1,20 @@
// Copyright (c) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Copyright (c) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PROCESS_DETAIL_WINDOWS_HANDLER_HPP_
#define BOOST_PROCESS_DETAIL_WINDOWS_HANDLER_HPP_
#ifndef BOOST_PROCESS_DETAIL_WINDOWS_HANDLER_HPP_
#define BOOST_PROCESS_DETAIL_WINDOWS_HANDLER_HPP_
#include <boost/process/detail/handler_base.hpp>
#include <boost/process/detail/handler_base.hpp>
namespace boost { namespace process { namespace detail { namespace windows {
namespace boost { namespace process { namespace detail { namespace windows {
//does not extend anything.
struct handler_base_ext : handler_base {};
//does not extend anything.
struct handler_base_ext : handler_base {};
}}}}
}}}}
#endif /* BOOST_PROCESS_DETAIL_WINDOWS_HANDLER_HPP_ */
#endif /* BOOST_PROCESS_DETAIL_WINDOWS_HANDLER_HPP_ */

View File

@@ -1,160 +1,160 @@
// Copyright (c) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Copyright (c) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PROCESS_WINDOWS_IO_SERVICE_REF_HPP_
#define BOOST_PROCESS_WINDOWS_IO_SERVICE_REF_HPP_
#ifndef BOOST_PROCESS_WINDOWS_IO_SERVICE_REF_HPP_
#define BOOST_PROCESS_WINDOWS_IO_SERVICE_REF_HPP_
#include <boost/process/detail/handler_base.hpp>
#include <boost/process/detail/windows/async_handler.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/asio/windows/object_handle.hpp>
#include <boost/detail/winapi/process.hpp>
#include <boost/detail/winapi/handles.hpp>
#include <boost/process/detail/handler_base.hpp>
#include <boost/process/detail/windows/async_handler.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/windows/object_handle.hpp>
#include <boost/winapi/process.hpp>
#include <boost/winapi/handles.hpp>
#include <boost/fusion/algorithm/iteration/for_each.hpp>
#include <boost/fusion/algorithm/transformation/filter_if.hpp>
#include <boost/fusion/algorithm/transformation/transform.hpp>
#include <boost/fusion/view/transform_view.hpp>
#include <boost/fusion/container/vector/convert.hpp>
#include <boost/fusion/algorithm/iteration/for_each.hpp>
#include <boost/fusion/algorithm/transformation/filter_if.hpp>
#include <boost/fusion/algorithm/transformation/transform.hpp>
#include <boost/fusion/view/transform_view.hpp>
#include <boost/fusion/container/vector/convert.hpp>
#include <functional>
#include <type_traits>
#include <memory>
#include <atomic>
#include <vector>
#include <functional>
#include <type_traits>
#include <memory>
#include <atomic>
#include <vector>
#include <boost/type_index.hpp>
#include <boost/type_index.hpp>
namespace boost { namespace process { namespace detail { namespace windows {
namespace boost { namespace process { namespace detail { namespace windows {
template<typename Executor>
struct on_exit_handler_transformer
{
Executor & exec;
on_exit_handler_transformer(Executor & exec) : exec(exec) {}
template<typename Sig>
struct result;
template<typename Executor>
struct on_exit_handler_transformer
{
Executor & exec;
on_exit_handler_transformer(Executor & exec) : exec(exec) {}
template<typename Sig>
struct result;
template<typename T>
struct result<on_exit_handler_transformer<Executor>(T&)>
{
typedef typename T::on_exit_handler_t type;
};
template<typename T>
struct result<on_exit_handler_transformer<Executor>(T&)>
{
typedef typename T::on_exit_handler_t type;
};
template<typename T>
auto operator()(T& t) const -> typename T::on_exit_handler_t
{
return t.on_exit_handler(exec);
}
};
template<typename T>
auto operator()(T& t) const -> typename T::on_exit_handler_t
{
return t.on_exit_handler(exec);
}
};
template<typename Executor>
struct async_handler_collector
{
Executor & exec;
std::vector<std::function<void(int, const std::error_code & ec)>> &handlers;
template<typename Executor>
struct async_handler_collector
{
Executor & exec;
std::vector<std::function<void(int, const std::error_code & ec)>> &handlers;
async_handler_collector(Executor & exec,
std::vector<std::function<void(int, const std::error_code & ec)>> &handlers)
: exec(exec), handlers(handlers) {}
async_handler_collector(Executor & exec,
std::vector<std::function<void(int, const std::error_code & ec)>> &handlers)
: exec(exec), handlers(handlers) {}
template<typename T>
void operator()(T & t) const
{
handlers.push_back(t.on_exit_handler(exec));
}
};
template<typename T>
void operator()(T & t) const
{
handlers.push_back(t.on_exit_handler(exec));
}
};
//Also set's up waiting for the exit, so it can close async stuff.
struct io_service_ref : boost::process::detail::handler_base
{
//Also set's up waiting for the exit, so it can close async stuff.
struct io_context_ref : boost::process::detail::handler_base
{
io_service_ref(boost::asio::io_service & ios)
: ios(ios)
{
}
boost::asio::io_service &get() {return ios;};
io_context_ref(boost::asio::io_context & ios)
: ios(ios)
{
}
boost::asio::io_context &get() {return ios;};
template <class Executor>
void on_success(Executor& exec) const
{
auto asyncs = boost::fusion::filter_if<
is_async_handler<
typename std::remove_reference< boost::mpl::_ > ::type
>>(exec.seq);
template <class Executor>
void on_success(Executor& exec) const
{
auto asyncs = boost::fusion::filter_if<
is_async_handler<
typename std::remove_reference< boost::mpl::_ > ::type
>>(exec.seq);
//ok, check if there are actually any.
if (boost::fusion::empty(asyncs))
{
return;
}
//ok, check if there are actually any.
if (boost::fusion::empty(asyncs))
{
return;
}
::boost::detail::winapi::PROCESS_INFORMATION_ & proc = exec.proc_info;
auto this_proc = ::boost::detail::winapi::GetCurrentProcess();
::boost::winapi::PROCESS_INFORMATION_ & proc = exec.proc_info;
auto this_proc = ::boost::winapi::GetCurrentProcess();
auto proc_in = proc.hProcess;;
::boost::detail::winapi::HANDLE_ process_handle;
auto proc_in = proc.hProcess;;
::boost::winapi::HANDLE_ process_handle;
if (!::boost::detail::winapi::DuplicateHandle(
this_proc, proc_in, this_proc, &process_handle, 0,
static_cast<::boost::detail::winapi::BOOL_>(true),
::boost::detail::winapi::DUPLICATE_SAME_ACCESS_))
if (!::boost::winapi::DuplicateHandle(
this_proc, proc_in, this_proc, &process_handle, 0,
static_cast<::boost::winapi::BOOL_>(true),
::boost::winapi::DUPLICATE_SAME_ACCESS_))
exec.set_error(::boost::process::detail::get_last_error(),
"Duplicate Pipe Failed");
exec.set_error(::boost::process::detail::get_last_error(),
"Duplicate Pipe Failed");
std::vector<std::function<void(int, const std::error_code & ec)>> funcs;
funcs.reserve(boost::fusion::size(asyncs));
boost::fusion::for_each(asyncs, async_handler_collector<Executor>(exec, funcs));
std::vector<std::function<void(int, const std::error_code & ec)>> funcs;
funcs.reserve(boost::fusion::size(asyncs));
boost::fusion::for_each(asyncs, async_handler_collector<Executor>(exec, funcs));
wait_handler wh(std::move(funcs), ios, process_handle, exec.exit_status);
wait_handler wh(std::move(funcs), ios, process_handle, exec.exit_status);
auto handle_p = wh.handle.get();
handle_p->async_wait(std::move(wh));
}
auto handle_p = wh.handle.get();
handle_p->async_wait(std::move(wh));
}
struct wait_handler
{
std::vector<std::function<void(int, const std::error_code & ec)>> funcs;
std::unique_ptr<boost::asio::windows::object_handle> handle;
std::shared_ptr<std::atomic<int>> exit_status;
wait_handler(const wait_handler & ) = delete;
wait_handler(wait_handler && ) = default;
wait_handler(std::vector<std::function<void(int, const std::error_code & ec)>> && funcs,
boost::asio::io_service & ios, void * handle,
const std::shared_ptr<std::atomic<int>> &exit_status)
: funcs(std::move(funcs)),
handle(new boost::asio::windows::object_handle(ios, handle)),
exit_status(exit_status)
{
struct wait_handler
{
std::vector<std::function<void(int, const std::error_code & ec)>> funcs;
std::unique_ptr<boost::asio::windows::object_handle> handle;
std::shared_ptr<std::atomic<int>> exit_status;
wait_handler(const wait_handler & ) = delete;
wait_handler(wait_handler && ) = default;
wait_handler(std::vector<std::function<void(int, const std::error_code & ec)>> && funcs,
boost::asio::io_context & ios, void * handle,
const std::shared_ptr<std::atomic<int>> &exit_status)
: funcs(std::move(funcs)),
handle(new boost::asio::windows::object_handle(ios, handle)),
exit_status(exit_status)
{
}
void operator()(const boost::system::error_code & ec_in)
{
std::error_code ec;
if (ec_in)
ec = std::error_code(ec_in.value(), std::system_category());
}
void operator()(const boost::system::error_code & ec_in)
{
std::error_code ec;
if (ec_in)
ec = std::error_code(ec_in.value(), std::system_category());
::boost::detail::winapi::DWORD_ code;
::boost::detail::winapi::GetExitCodeProcess(handle->native(), &code);
exit_status->store(code);
::boost::winapi::DWORD_ code;
::boost::winapi::GetExitCodeProcess(handle->native_handle(), &code);
exit_status->store(code);
for (auto & func : funcs)
func(code, ec);
}
for (auto & func : funcs)
func(code, ec);
}
};
};
private:
boost::asio::io_service &ios;
};
private:
boost::asio::io_context &ios;
};
}}}}
}}}}
#endif /* BOOST_PROCESS_WINDOWS_IO_SERVICE_REF_HPP_ */
#endif /* BOOST_PROCESS_WINDOWS_IO_SERVICE_REF_HPP_ */

View File

@@ -9,36 +9,20 @@
#include <boost/process/detail/config.hpp>
#include <system_error>
#include <cstdlib>
#include <boost/detail/winapi/process.hpp>
#include <boost/winapi/process.hpp>
namespace boost { namespace process { namespace detail { namespace windows {
constexpr static ::boost::detail::winapi::DWORD_ still_active = 259;
constexpr static ::boost::winapi::DWORD_ still_active = 259;
struct child_handle;
inline bool is_running(const child_handle &p, int & exit_code)
{
::boost::detail::winapi::DWORD_ code;
//single value, not needed in the winapi.
if (!::boost::detail::winapi::GetExitCodeProcess(p.process_handle(), &code))
::boost::process::detail::throw_last_error("GetExitCodeProcess() failed");
if (code == still_active)
return true;
else
{
exit_code = code;
return false;
}
}
inline bool is_running(const child_handle &p, int & exit_code, std::error_code &ec) noexcept
{
::boost::detail::winapi::DWORD_ code;
::boost::winapi::DWORD_ code;
//single value, not needed in the winapi.
if (!::boost::detail::winapi::GetExitCodeProcess(p.process_handle(), &code))
if (!::boost::winapi::GetExitCodeProcess(p.process_handle(), &code))
ec = ::boost::process::detail::get_last_error();
else
ec.clear();
@@ -49,7 +33,15 @@ inline bool is_running(const child_handle &p, int & exit_code, std::error_code &
{
exit_code = code;
return false;
}
}
}
inline bool is_running(const child_handle &p, int & exit_code)
{
std::error_code ec;
bool b = is_running(p, exit_code, ec);
boost::process::detail::throw_error(ec, "GetExitCodeProcess() failed in is_running");
return b;
}
inline bool is_running(int code)

View File

@@ -6,9 +6,9 @@
#ifndef BOOST_PROCESS_DETAIL_WINDOWS_JOB_WORKAROUND_HPP_
#define BOOST_PROCESS_DETAIL_WINDOWS_JOB_WORKAROUND_HPP_
#include <boost/detail/winapi/config.hpp>
#include <boost/detail/winapi/basic_types.hpp>
#include <boost/detail/winapi/dll.hpp>
#include <boost/winapi/config.hpp>
#include <boost/winapi/basic_types.hpp>
#include <boost/winapi/dll.hpp>
namespace boost { namespace process { namespace detail { namespace windows { namespace workaround {
@@ -42,35 +42,35 @@ typedef enum _JOBOBJECTINFOCLASS_ {
} JOBOBJECTINFOCLASS_;
typedef struct _JOBOBJECT_BASIC_LIMIT_INFORMATION_ {
::boost::detail::winapi::LARGE_INTEGER_ PerProcessUserTimeLimit;
::boost::detail::winapi::LARGE_INTEGER_ PerJobUserTimeLimit;
::boost::detail::winapi::DWORD_ LimitFlags;
::boost::detail::winapi::SIZE_T_ MinimumWorkingSetSize;
::boost::detail::winapi::SIZE_T_ MaximumWorkingSetSize;
::boost::detail::winapi::DWORD_ ActiveProcessLimit;
::boost::detail::winapi::ULONG_PTR_ Affinity;
::boost::detail::winapi::DWORD_ PriorityClass;
::boost::detail::winapi::DWORD_ SchedulingClass;
::boost::winapi::LARGE_INTEGER_ PerProcessUserTimeLimit;
::boost::winapi::LARGE_INTEGER_ PerJobUserTimeLimit;
::boost::winapi::DWORD_ LimitFlags;
::boost::winapi::SIZE_T_ MinimumWorkingSetSize;
::boost::winapi::SIZE_T_ MaximumWorkingSetSize;
::boost::winapi::DWORD_ ActiveProcessLimit;
::boost::winapi::ULONG_PTR_ Affinity;
::boost::winapi::DWORD_ PriorityClass;
::boost::winapi::DWORD_ SchedulingClass;
} JOBOBJECT_BASIC_LIMIT_INFORMATION_;
typedef struct _IO_COUNTERS_ {
::boost::detail::winapi::ULONGLONG_ ReadOperationCount;
::boost::detail::winapi::ULONGLONG_ WriteOperationCount;
::boost::detail::winapi::ULONGLONG_ OtherOperationCount;
::boost::detail::winapi::ULONGLONG_ ReadTransferCount;
::boost::detail::winapi::ULONGLONG_ WriteTransferCount;
::boost::detail::winapi::ULONGLONG_ OtherTransferCount;
::boost::winapi::ULONGLONG_ ReadOperationCount;
::boost::winapi::ULONGLONG_ WriteOperationCount;
::boost::winapi::ULONGLONG_ OtherOperationCount;
::boost::winapi::ULONGLONG_ ReadTransferCount;
::boost::winapi::ULONGLONG_ WriteTransferCount;
::boost::winapi::ULONGLONG_ OtherTransferCount;
} IO_COUNTERS_;
typedef struct _JOBOBJECT_EXTENDED_LIMIT_INFORMATION_ {
JOBOBJECT_BASIC_LIMIT_INFORMATION_ BasicLimitInformation;
IO_COUNTERS_ IoInfo;
::boost::detail::winapi::SIZE_T_ ProcessMemoryLimit;
::boost::detail::winapi::SIZE_T_ JobMemoryLimit;
::boost::detail::winapi::SIZE_T_ PeakProcessMemoryUsed;
::boost::detail::winapi::SIZE_T_ PeakJobMemoryUsed;
::boost::winapi::SIZE_T_ ProcessMemoryLimit;
::boost::winapi::SIZE_T_ JobMemoryLimit;
::boost::winapi::SIZE_T_ PeakProcessMemoryUsed;
::boost::winapi::SIZE_T_ PeakJobMemoryUsed;
} JOBOBJECT_EXTENDED_LIMIT_INFORMATION_;
@@ -82,23 +82,23 @@ typedef struct _JOBOBJECT_EXTENDED_LIMIT_INFORMATION_ {
_Out_opt_ LPDWORD lpReturnLength
);
*/
typedef ::boost::detail::winapi::BOOL_ ( WINAPI *query_information_job_object_p)(
::boost::detail::winapi::HANDLE_,
typedef ::boost::winapi::BOOL_ ( WINAPI *query_information_job_object_p)(
::boost::winapi::HANDLE_,
JOBOBJECTINFOCLASS_,
void *,
::boost::detail::winapi::DWORD_,
::boost::detail::winapi::DWORD_ *);
::boost::winapi::DWORD_,
::boost::winapi::DWORD_ *);
inline ::boost::detail::winapi::BOOL_ WINAPI query_information_job_object(
::boost::detail::winapi::HANDLE_ hJob,
inline ::boost::winapi::BOOL_ WINAPI query_information_job_object(
::boost::winapi::HANDLE_ hJob,
JOBOBJECTINFOCLASS_ JobObjectInfoClass,
void * lpJobObjectInfo,
::boost::detail::winapi::DWORD_ cbJobObjectInfoLength,
::boost::detail::winapi::DWORD_ *lpReturnLength)
::boost::winapi::DWORD_ cbJobObjectInfoLength,
::boost::winapi::DWORD_ *lpReturnLength)
{
static ::boost::detail::winapi::HMODULE_ h = ::boost::detail::winapi::get_module_handle("Kernel32.dll");
static query_information_job_object_p f = reinterpret_cast<query_information_job_object_p>(::boost::detail::winapi::get_proc_address(h, "QueryInformationJobObject"));
static ::boost::winapi::HMODULE_ h = ::boost::winapi::get_module_handle(L"Kernel32.dll");
static query_information_job_object_p f = reinterpret_cast<query_information_job_object_p>(::boost::winapi::get_proc_address(h, "QueryInformationJobObject"));
return (*f)(hJob, JobObjectInfoClass, lpJobObjectInfo, cbJobObjectInfoLength, lpReturnLength);
}
@@ -110,27 +110,27 @@ inline ::boost::detail::winapi::BOOL_ WINAPI query_information_job_object(
_In_ DWORD cbJobObjectInfoLength
);*/
typedef ::boost::detail::winapi::BOOL_ ( WINAPI *set_information_job_object_p)(
::boost::detail::winapi::HANDLE_,
typedef ::boost::winapi::BOOL_ ( WINAPI *set_information_job_object_p)(
::boost::winapi::HANDLE_,
JOBOBJECTINFOCLASS_,
void *,
::boost::detail::winapi::DWORD_);
::boost::winapi::DWORD_);
}
inline ::boost::detail::winapi::BOOL_ WINAPI set_information_job_object(
::boost::detail::winapi::HANDLE_ hJob,
inline ::boost::winapi::BOOL_ WINAPI set_information_job_object(
::boost::winapi::HANDLE_ hJob,
JOBOBJECTINFOCLASS_ JobObjectInfoClass,
void * lpJobObjectInfo,
::boost::detail::winapi::DWORD_ cbJobObjectInfoLength)
::boost::winapi::DWORD_ cbJobObjectInfoLength)
{
static ::boost::detail::winapi::HMODULE_ h = ::boost::detail::winapi::get_module_handle("Kernel32.dll");
static set_information_job_object_p f = reinterpret_cast<set_information_job_object_p>(::boost::detail::winapi::get_proc_address(h, "SetInformationJobObject"));
static ::boost::winapi::HMODULE_ h = ::boost::winapi::get_module_handle(L"Kernel32.dll");
static set_information_job_object_p f = reinterpret_cast<set_information_job_object_p>(::boost::winapi::get_proc_address(h, "SetInformationJobObject"));
return (*f)(hJob, JobObjectInfoClass, lpJobObjectInfo, cbJobObjectInfoLength);
}
constexpr static ::boost::detail::winapi::DWORD_ JOB_OBJECT_LIMIT_BREAKAWAY_OK_ = 0x00000800;
constexpr static ::boost::winapi::DWORD_ JOB_OBJECT_LIMIT_BREAKAWAY_OK_ = 0x00000800;
}}}}}

View File

@@ -1,103 +1,111 @@
// Copyright (c) 2016 Klemens D. Morgenstern
// Copyright (c) 2008 Beman Dawes
//
// 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)
// Copyright (c) 2016 Klemens D. Morgenstern
// Copyright (c) 2008 Beman Dawes
//
// 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_DETAIL_WINDOWS_LOCALE_HPP_
#define BOOST_PROCESS_DETAIL_WINDOWS_LOCALE_HPP_
#ifndef BOOST_PROCESS_DETAIL_WINDOWS_LOCALE_HPP_
#define BOOST_PROCESS_DETAIL_WINDOWS_LOCALE_HPP_
#include <locale>
#include <boost/core/ignore_unused.hpp>
#include <boost/detail/winapi/file_management.hpp>
#include <boost/detail/winapi/character_code_conversion.hpp>
#include <locale>
#include <boost/core/ignore_unused.hpp>
#include <boost/winapi/file_management.hpp>
#include <boost/winapi/character_code_conversion.hpp>
namespace boost
{
namespace process
{
namespace detail
{
namespace windows
{
namespace boost
{
namespace process
{
namespace detail
{
namespace windows
{
//copied from boost.filesystem
class windows_file_codecvt
: public std::codecvt< wchar_t, char, std::mbstate_t >
{
public:
explicit windows_file_codecvt(std::size_t refs = 0)
: std::codecvt<wchar_t, char, std::mbstate_t>(refs) {}
protected:
//copied from boost.filesystem
class windows_file_codecvt
: public std::codecvt< wchar_t, char, std::mbstate_t >
{
public:
explicit windows_file_codecvt(std::size_t refs = 0)
: std::codecvt<wchar_t, char, std::mbstate_t>(refs) {}
protected:
bool do_always_noconv() const noexcept override { return false; }
bool do_always_noconv() const noexcept override { return false; }
// seems safest to assume variable number of characters since we don't
// actually know what codepage is active
int do_encoding() const noexcept override { return 0; }
// seems safest to assume variable number of characters since we don't
// actually know what codepage is active
int do_encoding() const noexcept override { return 0; }
std::codecvt_base::result do_in(std::mbstate_t& state,
const char* from, const char* from_end, const char*& from_next,
wchar_t* to, wchar_t* to_end, wchar_t*& to_next) const override
{
boost::ignore_unused(state);
::boost::detail::winapi::UINT_ codepage = AreFileApisANSI() ?
::boost::detail::winapi::CP_ACP_ :
::boost::detail::winapi::CP_OEMCP_;
std::codecvt_base::result do_in(std::mbstate_t& state,
const char* from, const char* from_end, const char*& from_next,
wchar_t* to, wchar_t* to_end, wchar_t*& to_next) const override
{
boost::ignore_unused(state);
int count;
if ((count = ::boost::detail::winapi::MultiByteToWideChar(codepage,
::boost::detail::winapi::MB_PRECOMPOSED_, from,
static_cast<int>(from_end - from), to, static_cast<int>(to_end - to))) == 0)
{
return error; // conversion failed
}
auto codepage =
#if !defined(BOOST_NO_ANSI_APIS)
::boost::winapi::AreFileApisANSI() ?
::boost::winapi::CP_ACP_ :
#endif
::boost::winapi::CP_OEMCP_;
from_next = from_end;
to_next = to + count;
*to_next = L'\0';
return ok;
}
int count = 0;
if ((count = ::boost::winapi::MultiByteToWideChar(codepage,
::boost::winapi::MB_PRECOMPOSED_, from,
static_cast<int>(from_end - from), to, static_cast<int>(to_end - to))) == 0)
{
return error; // conversion failed
}
std::codecvt_base::result do_out(std::mbstate_t & state,
const wchar_t* from, const wchar_t* from_end, const wchar_t*& from_next,
char* to, char* to_end, char*& to_next) const override
{
boost::ignore_unused(state);
auto codepage = ::boost::detail::winapi::AreFileApisANSI() ?
::boost::detail::winapi::CP_ACP_ :
::boost::detail::winapi::CP_OEMCP_;
from_next = from_end;
to_next = to + count;
*to_next = L'\0';
return ok;
}
int count;
if ((count = ::boost::detail::winapi::WideCharToMultiByte(codepage,
::boost::detail::winapi::WC_NO_BEST_FIT_CHARS_, from,
static_cast<int>(from_end - from), to, static_cast<int>(to_end - to), 0, 0)) == 0)
{
return error; // conversion failed
}
std::codecvt_base::result do_out(std::mbstate_t & state,
const wchar_t* from, const wchar_t* from_end, const wchar_t*& from_next,
char* to, char* to_end, char*& to_next) const override
{
boost::ignore_unused(state);
auto codepage =
#if !defined(BOOST_NO_ANSI_APIS)
::boost::winapi::AreFileApisANSI() ?
::boost::winapi::CP_ACP_ :
#endif
::boost::winapi::CP_OEMCP_;
int count = 0;
from_next = from_end;
to_next = to + count;
*to_next = '\0';
return ok;
}
std::codecvt_base::result do_unshift(std::mbstate_t&,
char* /*from*/, char* /*to*/, char* & /*next*/) const override { return ok; }
if ((count = ::boost::winapi::WideCharToMultiByte(codepage,
::boost::winapi::WC_NO_BEST_FIT_CHARS_, from,
static_cast<int>(from_end - from), to, static_cast<int>(to_end - to), 0, 0)) == 0)
{
return error; // conversion failed
}
int do_length(std::mbstate_t&,
const char* /*from*/, const char* /*from_end*/, std::size_t /*max*/) const override { return 0; }
from_next = from_end;
to_next = to + count;
*to_next = '\0';
return ok;
}
int do_max_length() const noexcept override { return 0; }
};
std::codecvt_base::result do_unshift(std::mbstate_t&,
char* /*from*/, char* /*to*/, char* & /*next*/) const override { return ok; }
int do_length(std::mbstate_t&,
const char* /*from*/, const char* /*from_end*/, std::size_t /*max*/) const override { return 0; }
int do_max_length() const noexcept override { return 0; }
};
}
}
}
}
}
}
}
}
#endif /* BOOST_PROCESS_LOCALE_HPP_ */
#endif /* BOOST_PROCESS_LOCALE_HPP_ */

View File

@@ -1,41 +1,41 @@
// 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)
// 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)
#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_NULL_IN_HPP
#define BOOST_PROCESS_WINDOWS_INITIALIZERS_NULL_IN_HPP
#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_NULL_IN_HPP
#define BOOST_PROCESS_WINDOWS_INITIALIZERS_NULL_IN_HPP
#include <boost/detail/winapi/process.hpp>
#include <boost/detail/winapi/handles.hpp>
#include <boost/detail/winapi/handle_info.hpp>
#include <boost/process/detail/handler_base.hpp>
#include <boost/process/detail/windows/file_descriptor.hpp>
#include <boost/winapi/process.hpp>
#include <boost/winapi/handles.hpp>
#include <boost/winapi/handle_info.hpp>
#include <boost/process/detail/handler_base.hpp>
#include <boost/process/detail/windows/file_descriptor.hpp>
namespace boost { namespace process { namespace detail { namespace windows {
namespace boost { namespace process { namespace detail { namespace windows {
struct null_in : public ::boost::process::detail::handler_base
{
file_descriptor source{"NUL", file_descriptor::read};
struct null_in : public ::boost::process::detail::handler_base
{
file_descriptor source{"NUL", file_descriptor::read};
public:
template <class WindowsExecutor>
void on_setup(WindowsExecutor &e) const
{
boost::detail::winapi::SetHandleInformation(source.handle(),
boost::detail::winapi::HANDLE_FLAG_INHERIT_,
boost::detail::winapi::HANDLE_FLAG_INHERIT_);
public:
template <class WindowsExecutor>
void on_setup(WindowsExecutor &e) const
{
boost::winapi::SetHandleInformation(source.handle(),
boost::winapi::HANDLE_FLAG_INHERIT_,
boost::winapi::HANDLE_FLAG_INHERIT_);
e.startup_info.hStdInput = source.handle();
e.startup_info.dwFlags |= boost::detail::winapi::STARTF_USESTDHANDLES_;
e.inherit_handles = true;
}
};
e.startup_info.hStdInput = source.handle();
e.startup_info.dwFlags |= boost::winapi::STARTF_USESTDHANDLES_;
e.inherit_handles = true;
}
};
}}}}
}}}}
#endif
#endif

View File

@@ -1,75 +1,75 @@
// 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)
// 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)
#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_NULL_OUT_HPP
#define BOOST_PROCESS_WINDOWS_INITIALIZERS_NULL_OUT_HPP
#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_NULL_OUT_HPP
#define BOOST_PROCESS_WINDOWS_INITIALIZERS_NULL_OUT_HPP
#include <boost/detail/winapi/process.hpp>
#include <boost/detail/winapi/handles.hpp>
#include <boost/detail/winapi/handle_info.hpp>
#include <boost/process/detail/handler_base.hpp>
#include <boost/process/detail/windows/file_descriptor.hpp>
#include <boost/winapi/process.hpp>
#include <boost/winapi/handles.hpp>
#include <boost/winapi/handle_info.hpp>
#include <boost/process/detail/handler_base.hpp>
#include <boost/process/detail/windows/file_descriptor.hpp>
namespace boost { namespace process { namespace detail { namespace windows {
namespace boost { namespace process { namespace detail { namespace windows {
template<int p1, int p2>
struct null_out : public ::boost::process::detail::handler_base
{
file_descriptor sink {"NUL", file_descriptor::write}; //works because it gets destroyed AFTER launch.
template<int p1, int p2>
struct null_out : public ::boost::process::detail::handler_base
{
file_descriptor sink {"NUL", file_descriptor::write}; //works because it gets destroyed AFTER launch.
template <typename WindowsExecutor>
void on_setup(WindowsExecutor &e) const;
};
template <typename WindowsExecutor>
void on_setup(WindowsExecutor &e) const;
};
template<>
template<typename WindowsExecutor>
void null_out<1,-1>::on_setup(WindowsExecutor &e) const
{
boost::detail::winapi::SetHandleInformation(sink.handle(),
boost::detail::winapi::HANDLE_FLAG_INHERIT_,
boost::detail::winapi::HANDLE_FLAG_INHERIT_);
template<>
template<typename WindowsExecutor>
void null_out<1,-1>::on_setup(WindowsExecutor &e) const
{
boost::winapi::SetHandleInformation(sink.handle(),
boost::winapi::HANDLE_FLAG_INHERIT_,
boost::winapi::HANDLE_FLAG_INHERIT_);
e.startup_info.hStdOutput = sink.handle();
e.startup_info.dwFlags |= ::boost::detail::winapi::STARTF_USESTDHANDLES_;
e.inherit_handles = true;
e.startup_info.hStdOutput = sink.handle();
e.startup_info.dwFlags |= ::boost::winapi::STARTF_USESTDHANDLES_;
e.inherit_handles = true;
}
}
template<>
template<typename WindowsExecutor>
void null_out<2,-1>::on_setup(WindowsExecutor &e) const
{
boost::detail::winapi::SetHandleInformation(sink.handle(),
boost::detail::winapi::HANDLE_FLAG_INHERIT_,
boost::detail::winapi::HANDLE_FLAG_INHERIT_);
template<>
template<typename WindowsExecutor>
void null_out<2,-1>::on_setup(WindowsExecutor &e) const
{
boost::winapi::SetHandleInformation(sink.handle(),
boost::winapi::HANDLE_FLAG_INHERIT_,
boost::winapi::HANDLE_FLAG_INHERIT_);
e.startup_info.hStdError = sink.handle();
e.startup_info.dwFlags |= ::boost::detail::winapi::STARTF_USESTDHANDLES_;
e.inherit_handles = true;
e.startup_info.hStdError = sink.handle();
e.startup_info.dwFlags |= ::boost::winapi::STARTF_USESTDHANDLES_;
e.inherit_handles = true;
}
}
template<>
template<typename WindowsExecutor>
void null_out<1,2>::on_setup(WindowsExecutor &e) const
{
boost::detail::winapi::SetHandleInformation(sink.handle(),
boost::detail::winapi::HANDLE_FLAG_INHERIT_,
boost::detail::winapi::HANDLE_FLAG_INHERIT_);
template<>
template<typename WindowsExecutor>
void null_out<1,2>::on_setup(WindowsExecutor &e) const
{
boost::winapi::SetHandleInformation(sink.handle(),
boost::winapi::HANDLE_FLAG_INHERIT_,
boost::winapi::HANDLE_FLAG_INHERIT_);
e.startup_info.hStdOutput = sink.handle();
e.startup_info.hStdError = sink.handle();
e.startup_info.dwFlags |= ::boost::detail::winapi::STARTF_USESTDHANDLES_;
e.inherit_handles = true;
e.startup_info.hStdOutput = sink.handle();
e.startup_info.hStdError = sink.handle();
e.startup_info.dwFlags |= ::boost::winapi::STARTF_USESTDHANDLES_;
e.inherit_handles = true;
}
}
}}}}
}}}}
#endif
#endif

View File

@@ -1,40 +1,39 @@
// Copyright (c) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Copyright (c) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PROCESS_WINDOWS_ON_EXIT_HPP_
#define BOOST_PROCESS_WINDOWS_ON_EXIT_HPP_
#ifndef BOOST_PROCESS_WINDOWS_ON_EXIT_HPP_
#define BOOST_PROCESS_WINDOWS_ON_EXIT_HPP_
#include <boost/process/detail/config.hpp>
#include <boost/process/detail/handler_base.hpp>
#include <boost/process/detail/windows/async_handler.hpp>
#include <boost/detail/winapi/process.hpp>
#include <system_error>
#include <functional>
#include <boost/process/detail/config.hpp>
#include <boost/process/detail/handler_base.hpp>
#include <boost/process/detail/windows/async_handler.hpp>
#include <system_error>
#include <functional>
namespace boost { namespace process { namespace detail { namespace windows {
namespace boost { namespace process { namespace detail { namespace windows {
struct on_exit_ : boost::process::detail::windows::async_handler
{
std::function<void(int, const std::error_code&)> handler;
on_exit_(const std::function<void(int, const std::error_code&)> & handler) : handler(handler)
{
struct on_exit_ : boost::process::detail::windows::async_handler
{
std::function<void(int, const std::error_code&)> handler;
on_exit_(const std::function<void(int, const std::error_code&)> & handler) : handler(handler)
{
}
}
template<typename Executor>
std::function<void(int, const std::error_code&)> on_exit_handler(Executor&)
{
auto handler = this->handler;
return [handler](int exit_code, const std::error_code & ec)
{
handler(static_cast<int>(exit_code), ec);
};
template<typename Executor>
std::function<void(int, const std::error_code&)> on_exit_handler(Executor&)
{
auto handler = this->handler;
return [handler](int exit_code, const std::error_code & ec)
{
handler(static_cast<int>(exit_code), ec);
};
}
};
}
};
}}}}
#endif /* INCLUDE_BOOST_PROCESS_WINDOWS_ON_EXIT_HPP_ */
}}}}
#endif /* INCLUDE_BOOST_PROCESS_WINDOWS_ON_EXIT_HPP_ */

View File

@@ -1,89 +1,89 @@
// 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)
// 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)
#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_PIPE_IN_HPP
#define BOOST_PROCESS_WINDOWS_INITIALIZERS_PIPE_IN_HPP
#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_PIPE_IN_HPP
#define BOOST_PROCESS_WINDOWS_INITIALIZERS_PIPE_IN_HPP
#include <boost/detail/winapi/process.hpp>
#include <boost/detail/winapi/handles.hpp>
#include <boost/process/detail/handler_base.hpp>
#include <boost/winapi/process.hpp>
#include <boost/winapi/handles.hpp>
#include <boost/process/detail/handler_base.hpp>
namespace boost { namespace process { namespace detail { namespace windows {
namespace boost { namespace process { namespace detail { namespace windows {
struct pipe_in : public ::boost::process::detail::handler_base
{
::boost::detail::winapi::HANDLE_ handle;
struct pipe_in : public ::boost::process::detail::handler_base
{
::boost::winapi::HANDLE_ handle;
pipe_in(::boost::detail::winapi::HANDLE_ handle) : handle(handle) {}
pipe_in(::boost::winapi::HANDLE_ handle) : handle(handle) {}
template<typename T> //async_pipe
pipe_in(T & p) : handle(p.native_source())
{
p.assign_source(::boost::detail::winapi::INVALID_HANDLE_VALUE_);
}
template<typename T> //async_pipe
pipe_in(T & p) : handle(p.native_source())
{
p.assign_source(::boost::winapi::INVALID_HANDLE_VALUE_);
}
template <class WindowsExecutor>
void on_setup(WindowsExecutor &e) const
{
boost::detail::winapi::SetHandleInformation(handle,
boost::detail::winapi::HANDLE_FLAG_INHERIT_,
boost::detail::winapi::HANDLE_FLAG_INHERIT_);
template <class WindowsExecutor>
void on_setup(WindowsExecutor &e) const
{
boost::winapi::SetHandleInformation(handle,
boost::winapi::HANDLE_FLAG_INHERIT_,
boost::winapi::HANDLE_FLAG_INHERIT_);
e.startup_info.hStdInput = handle;
e.startup_info.dwFlags |= boost::detail::winapi::STARTF_USESTDHANDLES_;
e.inherit_handles = true;
}
template<typename WindowsExecutor>
void on_error(WindowsExecutor &, const std::error_code &) const
{
::boost::detail::winapi::CloseHandle(handle);
}
e.startup_info.hStdInput = handle;
e.startup_info.dwFlags |= boost::winapi::STARTF_USESTDHANDLES_;
e.inherit_handles = true;
}
template<typename WindowsExecutor>
void on_error(WindowsExecutor &, const std::error_code &) const
{
::boost::winapi::CloseHandle(handle);
}
template<typename WindowsExecutor>
void on_success(WindowsExecutor &) const
{
::boost::detail::winapi::CloseHandle(handle);
}
};
template<typename WindowsExecutor>
void on_success(WindowsExecutor &) const
{
::boost::winapi::CloseHandle(handle);
}
};
class async_pipe;
class async_pipe;
struct async_pipe_in : public pipe_in
{
async_pipe &pipe;
struct async_pipe_in : public pipe_in
{
async_pipe &pipe;
template<typename AsyncPipe>
async_pipe_in(AsyncPipe & p) : pipe_in(p.native_source()), pipe(p)
{
}
template<typename AsyncPipe>
async_pipe_in(AsyncPipe & p) : pipe_in(p.native_source()), pipe(p)
{
}
template<typename Pipe, typename Executor>
static void close(Pipe & pipe, Executor &)
{
boost::system::error_code ec;
std::move(pipe).source().close(ec);
}
template<typename Pipe, typename Executor>
static void close(Pipe & pipe, Executor &)
{
boost::system::error_code ec;
std::move(pipe).source().close(ec);
}
template<typename Executor>
void on_error(Executor & exec, const std::error_code &)
{
close(pipe, exec);
}
template<typename Executor>
void on_error(Executor & exec, const std::error_code &)
{
close(pipe, exec);
}
template<typename Executor>
void on_success(Executor &exec)
{
close(pipe, exec);
}
};
template<typename Executor>
void on_success(Executor &exec)
{
close(pipe, exec);
}
};
}}}}
}}}}
#endif
#endif

View File

@@ -1,122 +1,122 @@
// 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) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// 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) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PROCESS_WINDOWS_PIPE_OUT_HPP
#define BOOST_PROCESS_WINDOWS_PIPE_OUT_HPP
#ifndef BOOST_PROCESS_WINDOWS_PIPE_OUT_HPP
#define BOOST_PROCESS_WINDOWS_PIPE_OUT_HPP
#include <boost/detail/winapi/process.hpp>
#include <boost/detail/winapi/handles.hpp>
#include <boost/process/detail/handler_base.hpp>
#include <boost/winapi/process.hpp>
#include <boost/winapi/handles.hpp>
#include <boost/process/detail/handler_base.hpp>
namespace boost { namespace process { namespace detail { namespace windows {
namespace boost { namespace process { namespace detail { namespace windows {
template<int p1, int p2>
struct pipe_out : public ::boost::process::detail::handler_base
{
::boost::detail::winapi::HANDLE_ handle;
template<int p1, int p2>
struct pipe_out : public ::boost::process::detail::handler_base
{
::boost::winapi::HANDLE_ handle;
pipe_out(::boost::detail::winapi::HANDLE_ handle) : handle(handle) {}
template<typename T>
pipe_out(T & p) : handle(p.native_sink())
{
p.assign_sink(::boost::detail::winapi::INVALID_HANDLE_VALUE_);
}
pipe_out(::boost::winapi::HANDLE_ handle) : handle(handle) {}
template<typename T>
pipe_out(T & p) : handle(p.native_sink())
{
p.assign_sink(::boost::winapi::INVALID_HANDLE_VALUE_);
}
template<typename WindowsExecutor>
void on_setup(WindowsExecutor &e) const;
template<typename WindowsExecutor>
void on_setup(WindowsExecutor &e) const;
template<typename WindowsExecutor>
void on_error(WindowsExecutor &, const std::error_code &) const
{
::boost::detail::winapi::CloseHandle(handle);
}
template<typename WindowsExecutor>
void on_error(WindowsExecutor &, const std::error_code &) const
{
::boost::winapi::CloseHandle(handle);
}
template<typename WindowsExecutor>
void on_success(WindowsExecutor &) const
{
::boost::detail::winapi::CloseHandle(handle);
}
};
template<typename WindowsExecutor>
void on_success(WindowsExecutor &) const
{
::boost::winapi::CloseHandle(handle);
}
};
template<>
template<typename WindowsExecutor>
void pipe_out<1,-1>::on_setup(WindowsExecutor &e) const
{
boost::detail::winapi::SetHandleInformation(handle,
boost::detail::winapi::HANDLE_FLAG_INHERIT_,
boost::detail::winapi::HANDLE_FLAG_INHERIT_);
template<>
template<typename WindowsExecutor>
void pipe_out<1,-1>::on_setup(WindowsExecutor &e) const
{
boost::winapi::SetHandleInformation(handle,
boost::winapi::HANDLE_FLAG_INHERIT_,
boost::winapi::HANDLE_FLAG_INHERIT_);
e.startup_info.hStdOutput = handle;
e.startup_info.dwFlags |= ::boost::detail::winapi::STARTF_USESTDHANDLES_;
e.inherit_handles = true;
}
e.startup_info.hStdOutput = handle;
e.startup_info.dwFlags |= ::boost::winapi::STARTF_USESTDHANDLES_;
e.inherit_handles = true;
}
template<>
template<typename WindowsExecutor>
void pipe_out<2,-1>::on_setup(WindowsExecutor &e) const
{
boost::detail::winapi::SetHandleInformation(handle,
boost::detail::winapi::HANDLE_FLAG_INHERIT_,
boost::detail::winapi::HANDLE_FLAG_INHERIT_);
template<>
template<typename WindowsExecutor>
void pipe_out<2,-1>::on_setup(WindowsExecutor &e) const
{
boost::winapi::SetHandleInformation(handle,
boost::winapi::HANDLE_FLAG_INHERIT_,
boost::winapi::HANDLE_FLAG_INHERIT_);
e.startup_info.hStdError = handle;
e.startup_info.dwFlags |= ::boost::detail::winapi::STARTF_USESTDHANDLES_;
e.inherit_handles = true;
}
e.startup_info.hStdError = handle;
e.startup_info.dwFlags |= ::boost::winapi::STARTF_USESTDHANDLES_;
e.inherit_handles = true;
}
template<>
template<typename WindowsExecutor>
void pipe_out<1,2>::on_setup(WindowsExecutor &e) const
{
boost::detail::winapi::SetHandleInformation(handle,
boost::detail::winapi::HANDLE_FLAG_INHERIT_,
boost::detail::winapi::HANDLE_FLAG_INHERIT_);
template<>
template<typename WindowsExecutor>
void pipe_out<1,2>::on_setup(WindowsExecutor &e) const
{
boost::winapi::SetHandleInformation(handle,
boost::winapi::HANDLE_FLAG_INHERIT_,
boost::winapi::HANDLE_FLAG_INHERIT_);
e.startup_info.hStdOutput = handle;
e.startup_info.hStdError = handle;
e.startup_info.dwFlags |= ::boost::detail::winapi::STARTF_USESTDHANDLES_;
e.inherit_handles = true;
}
e.startup_info.hStdOutput = handle;
e.startup_info.hStdError = handle;
e.startup_info.dwFlags |= ::boost::winapi::STARTF_USESTDHANDLES_;
e.inherit_handles = true;
}
template<int p1, int p2>
struct async_pipe_out : public pipe_out<p1, p2>
{
async_pipe &pipe;
template<typename AsyncPipe>
async_pipe_out(AsyncPipe & p) : pipe_out<p1, p2>(p.native_sink()), pipe(p)
{
}
template<int p1, int p2>
struct async_pipe_out : public pipe_out<p1, p2>
{
async_pipe &pipe;
template<typename AsyncPipe>
async_pipe_out(AsyncPipe & p) : pipe_out<p1, p2>(p.native_sink()), pipe(p)
{
}
template<typename Pipe, typename Executor>
static void close(Pipe & pipe, Executor &)
{
boost::system::error_code ec;
std::move(pipe).sink().close(ec);
}
template<typename Pipe, typename Executor>
static void close(Pipe & pipe, Executor &)
{
boost::system::error_code ec;
std::move(pipe).sink().close(ec);
}
template<typename Executor>
void on_error(Executor & exec, const std::error_code &)
{
close(pipe, exec);
}
template<typename Executor>
void on_error(Executor & exec, const std::error_code &)
{
close(pipe, exec);
}
template<typename Executor>
void on_success(Executor &exec)
{
close(pipe, exec);
}
};
template<typename Executor>
void on_success(Executor &exec)
{
close(pipe, exec);
}
};
}}}}
}}}}
#endif
#endif

View File

@@ -19,9 +19,8 @@
#include <array>
#include <atomic>
#include <cstdlib>
#include <boost/detail/winapi/shell.hpp>
#include <boost/winapi/shell.hpp>
#include <boost/process/environment.hpp>
namespace boost { namespace process { namespace detail { namespace windows {
@@ -29,20 +28,46 @@ inline boost::filesystem::path search_path(
const boost::filesystem::path &filename,
const std::vector<boost::filesystem::path> &path)
{
const ::boost::process::wnative_environment ne{};
typedef typename ::boost::process::wnative_environment::const_entry_type value_type;
const auto id = L"PATHEXT";
auto itr = std::find_if(ne.cbegin(), ne.cend(),
[&](const value_type & e)
{return id == ::boost::to_upper_copy(e.get_name(), ::boost::process::detail::process_locale());});
auto extensions_in = itr->to_vector();
std::vector<std::wstring> extensions((extensions_in.size() * 2) + 1);
auto it_ex = extensions.begin();
it_ex++;
it_ex = std::transform(extensions_in.begin(), extensions_in.end(), it_ex,
[](const std::wstring & ws){return boost::to_lower_copy(ws, ::boost::process::detail::process_locale());});
std::transform(extensions_in.begin(), extensions_in.end(), it_ex,
[](const std::wstring & ws){return boost::to_upper_copy(ws, ::boost::process::detail::process_locale());});
std::copy(std::make_move_iterator(extensions_in.begin()), std::make_move_iterator(extensions_in.end()), extensions.begin() + 1);
for (auto & ext : extensions)
boost::to_lower(ext);
for (const boost::filesystem::path & pp : path)
{
auto full = pp / filename;
std::array<std::string, 4> extensions {{ "", ".exe", ".com", ".bat" }};
auto p = pp / filename;
for (boost::filesystem::path ext : extensions)
{
auto p = full;
p += ext;
boost::filesystem::path pp = p;
pp += ext;
boost::system::error_code ec;
bool file = boost::filesystem::is_regular_file(p, ec);
bool file = boost::filesystem::is_regular_file(pp, ec);
if (!ec && file &&
::boost::detail::winapi::sh_get_file_info(p.string().c_str(), 0, 0, 0, ::boost::detail::winapi::SHGFI_EXETYPE_))
::boost::winapi::sh_get_file_info(pp.native().c_str(), 0, 0, 0, ::boost::winapi::SHGFI_EXETYPE_))
{
return p;
return pp;
}
}
}

View File

@@ -13,15 +13,15 @@
#include <boost/process/detail/config.hpp>
#include <system_error>
#include <boost/filesystem/path.hpp>
#include <boost/detail/winapi/basic_types.hpp>
#include <boost/detail/winapi/get_system_directory.hpp>
#include <boost/winapi/basic_types.hpp>
#include <boost/winapi/get_system_directory.hpp>
namespace boost { namespace process { namespace detail { namespace windows {
inline boost::filesystem::path shell_path()
{
::boost::detail::winapi::WCHAR_ sysdir[260];
unsigned int size = ::boost::detail::winapi::get_system_directory(sysdir, sizeof(sysdir));
::boost::winapi::WCHAR_ sysdir[260];
unsigned int size = ::boost::winapi::get_system_directory(sysdir, sizeof(sysdir));
if (!size)
throw_last_error("GetSystemDirectory() failed");
@@ -32,12 +32,12 @@ inline boost::filesystem::path shell_path()
inline boost::filesystem::path shell_path(std::error_code &ec) noexcept
{
::boost::detail::winapi::WCHAR_ sysdir[260];
unsigned int size = ::boost::detail::winapi::get_system_directory(sysdir, sizeof(sysdir));
::boost::winapi::WCHAR_ sysdir[260];
unsigned int size = ::boost::winapi::get_system_directory(sysdir, sizeof(sysdir));
boost::filesystem::path p;
if (!size)
ec = std::error_code(
::boost::detail::winapi::GetLastError(),
::boost::winapi::GetLastError(),
std::system_category());
else
{

View File

@@ -1,39 +1,45 @@
// 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) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// 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) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PROCESS_WINDOWS_SHOW_WINDOW_HPP
#define BOOST_PROCESS_WINDOWS_SHOW_WINDOW_HPP
#ifndef BOOST_PROCESS_WINDOWS_SHOW_WINDOW_HPP
#define BOOST_PROCESS_WINDOWS_SHOW_WINDOW_HPP
#include <boost/detail/winapi/process.hpp>
#include <boost/detail/winapi/show_window.hpp>
#include <boost/process/detail/handler_base.hpp>
#include <boost/winapi/process.hpp>
#include <boost/winapi/show_window.hpp>
#include <boost/process/detail/handler_base.hpp>
namespace boost { namespace process { namespace detail { namespace windows {
namespace boost { namespace process { namespace detail { namespace windows {
template<::boost::detail::winapi::WORD_ Flags>
struct show_window : ::boost::process::detail::handler_base
{
template <class WindowsExecutor>
void on_setup(WindowsExecutor &e) const
{
e.startup_info.dwFlags |= ::boost::detail::winapi::STARTF_USESHOWWINDOW_;
e.startup_info.wShowWindow |= Flags;
}
};
template<::boost::winapi::WORD_ Flags>
struct show_window : ::boost::process::detail::handler_base
{
template <class WindowsExecutor>
void on_setup(WindowsExecutor &e) const
{
e.startup_info.dwFlags |= ::boost::winapi::STARTF_USESHOWWINDOW_;
e.startup_info.wShowWindow |= Flags;
}
};
struct create_no_window_ : public ::boost::process::detail::handler_base
{
template <class Executor>
void on_setup(Executor &exec) const
{
exec.creation_flags |= ::boost::detail::winapi::CREATE_NO_WINDOW_;
}
};
}}}}
}}}}
#endif
#endif

View File

@@ -1,36 +1,36 @@
// 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)
// 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)
#ifndef BOOST_PROCESS_DETAIL_WINDOWS_START_DIR_HPP
#define BOOST_PROCESS_DETAIL_WINDOWS_START_DIR_HPP
#ifndef BOOST_PROCESS_DETAIL_WINDOWS_START_DIR_HPP
#define BOOST_PROCESS_DETAIL_WINDOWS_START_DIR_HPP
#include <string>
#include <boost/process/detail/windows/handler.hpp>
#include <string>
#include <boost/process/detail/windows/handler.hpp>
namespace boost { namespace process { namespace detail { namespace windows {
namespace boost { namespace process { namespace detail { namespace windows {
template<typename Char>
struct start_dir_init : handler_base_ext
{
start_dir_init(const std::basic_string<Char> &s) : s_(s) {}
template<typename Char>
struct start_dir_init : handler_base_ext
{
start_dir_init(const std::basic_string<Char> &s) : s_(s) {}
template <class Executor>
void on_setup(Executor& exec) const
{
exec.work_dir = s_.c_str();
}
template <class Executor>
void on_setup(Executor& exec) const
{
exec.work_dir = s_.c_str();
}
const std::basic_string<Char> &str() const {return s_;}
private:
std::basic_string<Char> s_;
};
const std::basic_string<Char> &str() const {return s_;}
private:
std::basic_string<Char> s_;
};
}}}}
}}}}
#endif
#endif

View File

@@ -13,36 +13,31 @@
#include <boost/process/detail/config.hpp>
#include <system_error>
#include <cstdlib>
#include <boost/detail/winapi/process.hpp>
#include <boost/detail/winapi/get_last_error.hpp>
#include <boost/winapi/process.hpp>
#include <boost/winapi/get_last_error.hpp>
namespace boost { namespace process { namespace detail { namespace windows {
struct child_handle;
inline void terminate(child_handle &p)
{
if (!::boost::detail::winapi::TerminateProcess(p.process_handle(), EXIT_FAILURE))
boost::process::detail::throw_last_error("TerminateProcess() failed");
::boost::detail::winapi::CloseHandle(p.proc_info.hProcess);
p.proc_info.hProcess = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
}
inline void terminate(child_handle &p, std::error_code &ec) noexcept
{
if (!::boost::detail::winapi::TerminateProcess(p.process_handle(), EXIT_FAILURE))
if (!::boost::winapi::TerminateProcess(p.process_handle(), EXIT_FAILURE))
ec = boost::process::detail::get_last_error();
else
{
ec.clear();
::boost::detail::winapi::CloseHandle(p.proc_info.hProcess);
p.proc_info.hProcess = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
::boost::winapi::CloseHandle(p.proc_info.hProcess);
p.proc_info.hProcess = ::boost::winapi::INVALID_HANDLE_VALUE_;
}
}
inline void terminate(child_handle &p)
{
std::error_code ec;
terminate(p, ec);
boost::process::detail::throw_error(ec, "TerminateProcess() failed in terminate");
}
}}}}

View File

@@ -13,147 +13,41 @@
#include <boost/process/detail/config.hpp>
#include <system_error>
#include <boost/detail/winapi/synchronization.hpp>
#include <boost/detail/winapi/process.hpp>
#include <boost/winapi/synchronization.hpp>
#include <boost/winapi/process.hpp>
#include <boost/process/detail/windows/child_handle.hpp>
#include <chrono>
namespace boost { namespace process { namespace detail { namespace windows {
inline void wait(child_handle &p, int & exit_code)
{
if (::boost::detail::winapi::WaitForSingleObject(p.process_handle(),
::boost::detail::winapi::infinite) == ::boost::detail::winapi::wait_failed)
throw_last_error("WaitForSingleObject() failed");
::boost::detail::winapi::DWORD_ _exit_code;
if (!::boost::detail::winapi::GetExitCodeProcess(p.process_handle(), &_exit_code))
throw_last_error("GetExitCodeProcess() failed");
::boost::detail::winapi::CloseHandle(p.proc_info.hProcess);
p.proc_info.hProcess = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
exit_code = static_cast<int>(_exit_code);
}
inline void wait(child_handle &p, int & exit_code, std::error_code &ec) noexcept
{
::boost::detail::winapi::DWORD_ _exit_code = 1;
::boost::winapi::DWORD_ _exit_code = 1;
if (::boost::detail::winapi::WaitForSingleObject(p.process_handle(),
::boost::detail::winapi::infinite) == ::boost::detail::winapi::wait_failed)
if (::boost::winapi::WaitForSingleObject(p.process_handle(),
::boost::winapi::infinite) == ::boost::winapi::wait_failed)
ec = std::error_code(
::boost::detail::winapi::GetLastError(),
::boost::winapi::GetLastError(),
std::system_category());
else if (!::boost::detail::winapi::GetExitCodeProcess(p.process_handle(), &_exit_code))
else if (!::boost::winapi::GetExitCodeProcess(p.process_handle(), &_exit_code))
ec = std::error_code(
::boost::detail::winapi::GetLastError(),
::boost::winapi::GetLastError(),
std::system_category());
else
ec.clear();
::boost::detail::winapi::CloseHandle(p.proc_info.hProcess);
p.proc_info.hProcess = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
::boost::winapi::CloseHandle(p.proc_info.hProcess);
p.proc_info.hProcess = ::boost::winapi::INVALID_HANDLE_VALUE_;
exit_code = static_cast<int>(_exit_code);
}
template< class Rep, class Period >
inline bool wait_for(
child_handle &p,
int & exit_code,
const std::chrono::duration<Rep, Period>& rel_time)
inline void wait(child_handle &p, int & exit_code)
{
std::chrono::milliseconds ms = std::chrono::duration_cast<std::chrono::milliseconds>(rel_time);
::boost::detail::winapi::DWORD_ wait_code;
wait_code = ::boost::detail::winapi::WaitForSingleObject(p.process_handle(),
static_cast<::boost::detail::winapi::DWORD_>(ms.count()));
if (wait_code == ::boost::detail::winapi::wait_failed)
throw_last_error("WaitForSingleObject() failed");
else if (wait_code == ::boost::detail::winapi::wait_timeout)
return false; //
::boost::detail::winapi::DWORD_ _exit_code;
if (!::boost::detail::winapi::GetExitCodeProcess(p.process_handle(), &_exit_code))
throw_last_error("GetExitCodeProcess() failed");
exit_code = static_cast<int>(_exit_code);
::boost::detail::winapi::CloseHandle(p.proc_info.hProcess);
p.proc_info.hProcess = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
return true;
std::error_code ec;
wait(p, exit_code, ec);
boost::process::detail::throw_error(ec, "wait error");
}
template< class Rep, class Period >
inline bool wait_for(
child_handle &p,
int & exit_code,
const std::chrono::duration<Rep, Period>& rel_time,
std::error_code &ec) noexcept
{
std::chrono::milliseconds ms = std::chrono::duration_cast<std::chrono::milliseconds>(rel_time);
::boost::detail::winapi::DWORD_ wait_code;
wait_code = ::boost::detail::winapi::WaitForSingleObject(p.process_handle(),
static_cast<::boost::detail::winapi::DWORD_>(ms.count()));
if (wait_code == ::boost::detail::winapi::wait_failed)
ec = std::error_code(
::boost::detail::winapi::GetLastError(),
std::system_category());
else if (wait_code == ::boost::detail::winapi::wait_timeout)
return false; //
::boost::detail::winapi::DWORD_ _exit_code = 1;
if (!::boost::detail::winapi::GetExitCodeProcess(p.process_handle(), &_exit_code))
{
ec = std::error_code(
::boost::detail::winapi::GetLastError(),
std::system_category());
return false;
}
else
ec.clear();
exit_code = static_cast<int>(_exit_code);
::boost::detail::winapi::CloseHandle(p.proc_info.hProcess);
p.proc_info.hProcess = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
return true;
;
}
template< class Clock, class Duration >
inline bool wait_until(
child_handle &p,
int & exit_code,
const std::chrono::time_point<Clock, Duration>& timeout_time)
{
std::chrono::milliseconds ms =
std::chrono::duration_cast<std::chrono::milliseconds>(
timeout_time - std::chrono::system_clock::now());
::boost::detail::winapi::DWORD_ wait_code;
wait_code = ::boost::detail::winapi::WaitForSingleObject(p.process_handle(),
static_cast<::boost::detail::winapi::DWORD_>(ms.count()));
if (wait_code == ::boost::detail::winapi::wait_failed)
throw_last_error("WaitForSingleObject() failed");
else if (wait_code == ::boost::detail::winapi::wait_timeout)
return false;
::boost::detail::winapi::DWORD_ _exit_code;
if (!::boost::detail::winapi::GetExitCodeProcess(p.process_handle(), &_exit_code))
throw_last_error("GetExitCodeProcess() failed");
exit_code = static_cast<int>(_exit_code);
::boost::detail::winapi::CloseHandle(p.proc_info.hProcess);
p.proc_info.hProcess = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
return true;
}
template< class Clock, class Duration >
inline bool wait_until(
child_handle &p,
@@ -163,30 +57,66 @@ inline bool wait_until(
{
std::chrono::milliseconds ms =
std::chrono::duration_cast<std::chrono::milliseconds>(
timeout_time - std::chrono::system_clock::now());
timeout_time - Clock::now());
::boost::detail::winapi::DWORD_ _exit_code = 1;
::boost::winapi::DWORD_ wait_code;
wait_code = ::boost::winapi::WaitForSingleObject(p.process_handle(),
static_cast<::boost::winapi::DWORD_>(ms.count()));
if (::boost::detail::winapi::WaitForSingleObject(p.process_handle(),
static_cast<::boost::detail::winapi::DWORD_>(ms.count()))
== ::boost::detail::winapi::wait_failed)
if (wait_code == ::boost::winapi::wait_failed)
ec = std::error_code(
::boost::detail::winapi::GetLastError(),
::boost::winapi::GetLastError(),
std::system_category());
else if (!::boost::detail::winapi::GetExitCodeProcess(p.process_handle(), &_exit_code))
else if (wait_code == ::boost::winapi::wait_timeout)
return false;
::boost::winapi::DWORD_ _exit_code;
if (!::boost::winapi::GetExitCodeProcess(p.process_handle(), &_exit_code))
ec = std::error_code(
::boost::detail::winapi::GetLastError(),
::boost::winapi::GetLastError(),
std::system_category());
else
ec.clear();
exit_code = static_cast<int>(exit_code);
::boost::detail::winapi::CloseHandle(p.proc_info.hProcess);
p.proc_info.hProcess = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
exit_code = static_cast<int>(_exit_code);
::boost::winapi::CloseHandle(p.proc_info.hProcess);
p.proc_info.hProcess = ::boost::winapi::INVALID_HANDLE_VALUE_;
return true;
;
}
template< class Clock, class Duration >
inline bool wait_until(
child_handle &p,
int & exit_code,
const std::chrono::time_point<Clock, Duration>& timeout_time)
{
std::error_code ec;
bool b = wait_until(p, exit_code, timeout_time, ec);
boost::process::detail::throw_error(ec, "wait_until error");
return b;
}
template< class Rep, class Period >
inline bool wait_for(
child_handle &p,
int & exit_code,
const std::chrono::duration<Rep, Period>& rel_time,
std::error_code &ec) noexcept
{
return wait_until(p, exit_code, std::chrono::steady_clock::now() + rel_time, ec);
}
template< class Rep, class Period >
inline bool wait_for(
child_handle &p,
int & exit_code,
const std::chrono::duration<Rep, Period>& rel_time)
{
std::error_code ec;
bool b = wait_for(p, exit_code, rel_time, ec);
boost::process::detail::throw_error(ec, "wait_for error");
return b;
}
}}}}

View File

@@ -7,65 +7,45 @@
#define BOOST_PROCESS_DETAIL_WINDOWS_WAIT_GROUP_HPP_
#include <boost/process/detail/config.hpp>
#include <boost/detail/winapi/jobs.hpp>
#include <boost/detail/winapi/wait.hpp>
#include <boost/winapi/jobs.hpp>
#include <boost/winapi/wait.hpp>
#include <chrono>
namespace boost { namespace process { namespace detail { namespace windows {
struct group_handle;
inline void wait(const group_handle &p)
{
if (::boost::detail::winapi::WaitForSingleObject(p.handle(),
::boost::detail::winapi::infinite) == ::boost::detail::winapi::wait_failed)
throw_last_error("WaitForSingleObject() failed");
}
inline void wait(const group_handle &p, std::error_code &ec)
{
if (::boost::detail::winapi::WaitForSingleObject(p.handle(),
::boost::detail::winapi::infinite) == ::boost::detail::winapi::wait_failed)
if (::boost::winapi::WaitForSingleObject(p.handle(),
::boost::winapi::infinite) == ::boost::winapi::wait_failed)
ec = get_last_error();
}
template< class Rep, class Period >
inline bool wait_for(
const group_handle &p,
const std::chrono::duration<Rep, Period>& rel_time)
inline void wait(const group_handle &p)
{
std::chrono::milliseconds ms = std::chrono::duration_cast<std::chrono::milliseconds>(rel_time);
::boost::detail::winapi::DWORD_ wait_code;
wait_code = ::boost::detail::winapi::WaitForSingleObject(p.handle(), ms.count());
if (wait_code == ::boost::detail::winapi::wait_failed)
throw_last_error("WaitForSingleObject() failed");
else if (wait_code == ::boost::detail::winapi::wait_timeout)
return false; //
return true;
std::error_code ec;
wait(p, ec);
boost::process::detail::throw_error(ec, "wait error");
}
template< class Rep, class Period >
inline bool wait_for(
template< class Clock, class Duration >
inline bool wait_until(
const group_handle &p,
const std::chrono::duration<Rep, Period>& rel_time,
const std::chrono::time_point<Clock, Duration>& timeout_time,
std::error_code &ec)
{
std::chrono::milliseconds ms =
std::chrono::duration_cast<std::chrono::milliseconds>(
timeout_time - Clock::now());
std::chrono::milliseconds ms = std::chrono::duration_cast<std::chrono::milliseconds>(rel_time);
::boost::winapi::DWORD_ wait_code;
wait_code = ::boost::winapi::WaitForSingleObject(p.handle(), ms.count());
::boost::detail::winapi::DWORD_ wait_code;
wait_code = ::boost::detail::winapi::WaitForSingleObject(p.handle(), ms.count());
if (wait_code == ::boost::detail::winapi::wait_failed)
if (wait_code == ::boost::winapi::wait_failed)
ec = get_last_error();
else if (wait_code == ::boost::detail::winapi::wait_timeout)
else if (wait_code == ::boost::winapi::wait_timeout)
return false; //
return true;
@@ -76,44 +56,30 @@ inline bool wait_until(
const group_handle &p,
const std::chrono::time_point<Clock, Duration>& timeout_time)
{
std::chrono::milliseconds ms =
std::chrono::duration_cast<std::chrono::milliseconds>(
timeout_time - std::chrono::system_clock::now());
::boost::detail::winapi::DWORD_ wait_code;
wait_code = ::boost::detail::winapi::WaitForSingleObject(p.handle(), ms.count());
if (wait_code == ::boost::detail::winapi::wait_failed)
throw_last_error("WaitForSingleObject() failed");
else if (wait_code == ::boost::detail::winapi::wait_timeout)
return false; //
return true;
std::error_code ec;
bool b = wait_until(p, timeout_time, ec);
boost::process::detail::throw_error(ec, "wait_until error");
return b;
}
template< class Clock, class Duration >
inline bool wait_until(
template< class Rep, class Period >
inline bool wait_for(
const group_handle &p,
const std::chrono::time_point<Clock, Duration>& timeout_time,
const std::chrono::duration<Rep, Period>& rel_time,
std::error_code &ec)
{
std::chrono::milliseconds ms =
std::chrono::duration_cast<std::chrono::milliseconds>(
timeout_time - std::chrono::system_clock::now());
return wait_until(p, std::chrono::steady_clock::now() + rel_time, ec);
}
::boost::detail::winapi::DWORD_ wait_code;
wait_code = ::boost::detail::winapi::WaitForSingleObject(p.handle(), ms.count());
if (wait_code == ::boost::detail::winapi::wait_failed)
ec = get_last_error();
else if (wait_code == ::boost::detail::winapi::wait_timeout)
return false; //
return true;
;
template< class Rep, class Period >
inline bool wait_for(
const group_handle &p,
const std::chrono::duration<Rep, Period>& rel_time)
{
std::error_code ec;
bool b = wait_for(p, rel_time, ec);
boost::process::detail::throw_error(ec, "wait_for error");
return b;
}
}}}}

View File

@@ -1,502 +1,502 @@
// Copyright (c) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PROCESS_DETAIL_ENV_HPP_
#define BOOST_PROCESS_DETAIL_ENV_HPP_
#include <boost/process/environment.hpp>
#include <boost/none.hpp>
#if defined(BOOST_POSIX_API)
#include <boost/process/detail/posix/env_init.hpp>
#elif defined(BOOST_WINDOWS_API)
#include <boost/process/detail/windows/env_init.hpp>
#endif
/** \file boost/process/env.hpp
*
* This header which provides the `env` property. It allows the modification of the
* environment the child process will run in, in a functional style.
*
* \xmlonly
<programlisting>
namespace boost {
namespace process {
<emphasis>unspecified</emphasis> <globalname alt="boost::process::env">env</globalname>;
}
}
</programlisting>
* \endxmlonly
*
* For additional information see the platform documentations:
*
* - [windows](https://msdn.microsoft.com/en-US/library/windows/desktop/ms682653.aspx)
* - [posix](http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html)
*
*/
namespace boost {
namespace process { namespace detail {
template<typename Char>
std::size_t make_env_string_size(const std::basic_string<Char> & ch)
{
return ch.size() + 1;
}
template<typename Char>
std::size_t make_env_string_size(const Char * ch)
{
std::size_t sz = 0;
while (ch[sz] != null_char<Char>())
sz++;
sz++;
return sz;
}
template<typename Char, typename Container>
inline std::basic_string<Char> make_env_string(const Container & value)
{
std::size_t sz = 0;
for (auto & v : value)
sz += make_env_string_size(v);
std::basic_string<Char> s;
s.reserve(sz); //+1 for ;, end doesn't have one.
for (auto & val : value)
(s += val) += api::env_seperator<Char>();
s.resize(s.size() -1); //remove last ';'
return s;
}
template<typename Char>
struct env_set
{
using string_type = std::basic_string<Char>;
string_type key;
string_type value;
};
template<typename Char>
struct env_append
{
using string_type = std::basic_string<Char>;
string_type key;
string_type value;
};
template<typename Char>
struct env_reset
{
using string_type = std::basic_string<Char>;
string_type key;
};
template<> struct is_wchar_t<env_set<wchar_t>> : std::true_type {};
template<> struct is_wchar_t<env_append<wchar_t>> : std::true_type {};
template<> struct is_wchar_t<env_reset<wchar_t>> : std::true_type {};
template<> struct is_wchar_t<basic_environment<wchar_t>> : std::true_type {};
template<>
struct char_converter<char, env_set<wchar_t>>
{
static env_set<char> conv(const env_set<wchar_t> & in)
{
return {::boost::process::detail::convert(in.key),
::boost::process::detail::convert(in.value)};
}
};
template<>
struct char_converter<wchar_t, env_set<char>>
{
static env_set<wchar_t> conv(const env_set<char> & in)
{
return {::boost::process::detail::convert(in.key),
::boost::process::detail::convert(in.value)};
}
};
template<>
struct char_converter<char, env_append<wchar_t>>
{
static env_append<char> conv(const env_append<wchar_t> & in)
{
return {::boost::process::detail::convert(in.key),
::boost::process::detail::convert(in.value)};
}
};
template<>
struct char_converter<wchar_t, env_append<char>>
{
static env_append<wchar_t> conv(const env_append<char> & in)
{
return {::boost::process::detail::convert(in.key),
::boost::process::detail::convert(in.value)};
}
};
template<>
struct char_converter<char, env_reset<wchar_t>>
{
static env_reset<char> conv(const env_reset<wchar_t> & in)
{
return {::boost::process::detail::convert(in.key)};
}
};
template<>
struct char_converter<wchar_t, env_reset<char>>
{
static env_reset<wchar_t> conv(const env_reset<char> & in)
{
return {::boost::process::detail::convert(in.key)};
}
};
template<typename Char>
struct env_init
{
basic_environment<Char> env;
};
template<>
struct char_converter<char, env_init<wchar_t>>
{
static env_init<char> conv(const env_init<wchar_t> & in)
{
return {basic_environment<char>(in.env)};
}
};
template<>
struct char_converter<wchar_t, env_init<char>>
{
static env_init<wchar_t> conv(const env_init<char> & in)
{
return {basic_environment<wchar_t>(in.env)};
}
};
template<>
struct char_converter<char, basic_environment<wchar_t>>
{
static basic_environment<char> conv(const basic_environment<wchar_t> & in)
{
return { basic_environment<char>(in) };
}
};
template<>
struct char_converter<wchar_t, basic_environment<char>>
{
static basic_environment<wchar_t> conv(const basic_environment<char> & in)
{
return { basic_environment<wchar_t>(in) };
}
};
template<typename Char>
struct env_proxy
{
using string_type = std::basic_string<Char>;
string_type key;
env_set<Char> operator=(const string_type & value)
{
return {std::move(key), value};
}
env_set<Char> operator=(const std::vector<string_type> & value)
{
return {std::move(key), make_env_string<Char>(value)};
}
env_set<Char> operator=(const std::initializer_list<const Char*> & value)
{
return {std::move(key), make_env_string<Char>(value)};
}
env_append<Char> operator+=(const string_type & value)
{
return {std::move(key), value};
}
env_append<Char> operator+=(const std::vector<string_type> & value)
{
return {std::move(key), make_env_string<Char>(value)};
}
env_append<Char> operator+=(const std::initializer_list<const Char*> & value)
{
return {std::move(key), make_env_string<Char>(value)};
}
env_reset<Char> operator=(boost::none_t)
{
return {std::move(key)};
}
};
struct env_
{
constexpr env_() {};
template<typename Char>
env_set<Char> operator()(const std::basic_string<Char> & key,
const std::basic_string<Char> & value) const
{
return {key, value};
}
template<typename Char>
env_set<Char> operator()(const std::basic_string<Char> & key,
const std::vector<std::basic_string<Char>> & value) const
{
return {key, make_env_string<Char>(value)};
}
template<typename Char>
env_set<Char> operator()(const std::basic_string<Char> & key,
const std::initializer_list<Char*> & value) const
{
return {key, make_env_string<Char>(value)};
}
template<typename Char>
env_reset<Char> operator()(const std::basic_string<Char> & key, boost::none_t)
{
return {key};
}
template<typename Char>
env_proxy<Char> operator[](const std::basic_string<Char> & key) const
{
return {key};
}
template<typename Char>
env_proxy<Char> operator[](const Char* key) const
{
return {key};
}
template<typename Char>
env_init<Char> operator()(const basic_environment<Char> & env) const
{
return {env};
}
template<typename Char>
env_init<Char> operator= (const basic_environment<Char> & env) const
{
return {env};
}
};
template<typename Char>
struct env_builder
{
basic_environment<Char> env;
env_builder() : env{basic_native_environment<Char>()} {}
void operator()(const basic_environment<Char> & e)
{
env = e;
}
void operator()(env_init<Char> & ei)
{
env = std::move(ei.env);
}
void operator()(env_set<Char> & es)
{
env[es.key] = es.value;
}
void operator()(env_reset<Char> & es)
{
env.erase(es.key);
}
template<typename T>
void operator()(env_append<T> & es)
{
env[es.key] += es.value;
}
typedef api::env_init<Char> result_type;
api::env_init<Char> get_initializer()
{
return api::env_init<Char>(std::move(env));
}
};
template<>
struct initializer_builder<env_tag<char>>
{
typedef env_builder<char> type;
};
template<>
struct initializer_builder<env_tag<wchar_t>>
{
typedef env_builder<wchar_t> type;
};
}
/**
The `env` property provides a functional way to modify the environment used by
the child process. If none is passed the environment is inherited from the father
process. Appending means that the environment will be interpreted as a ';' or ':'
seperated list as used in `PATH`.
On both `posix` and `windows` the environment variables can be lists of strings,
seperated by ';'. This is typically used for the `PATH` variable.
By default the environment will be inherited from the launching process,
which is also true if environment are modified with this initializer.
\section env_details Details
\subsection env_operations Operations
\subsubsection env_set_var Setting variables
// Copyright (c) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PROCESS_DETAIL_ENV_HPP_
#define BOOST_PROCESS_DETAIL_ENV_HPP_
#include <boost/process/environment.hpp>
#include <boost/none.hpp>
#if defined(BOOST_POSIX_API)
#include <boost/process/detail/posix/env_init.hpp>
#elif defined(BOOST_WINDOWS_API)
#include <boost/process/detail/windows/env_init.hpp>
#endif
/** \file boost/process/env.hpp
*
* This header which provides the `env` property. It allows the modification of the
* environment the child process will run in, in a functional style.
*
* \xmlonly
<programlisting>
namespace boost {
namespace process {
<emphasis>unspecified</emphasis> <globalname alt="boost::process::env">env</globalname>;
}
}
</programlisting>
* \endxmlonly
*
* For additional information see the platform documentations:
*
* - [windows](https://msdn.microsoft.com/en-US/library/windows/desktop/ms682653.aspx)
* - [posix](http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html)
*
*/
namespace boost {
namespace process { namespace detail {
template<typename Char>
std::size_t make_env_string_size(const std::basic_string<Char> & ch)
{
return ch.size() + 1;
}
template<typename Char>
std::size_t make_env_string_size(const Char * ch)
{
std::size_t sz = 0;
while (ch[sz] != null_char<Char>())
sz++;
sz++;
return sz;
}
template<typename Char, typename Container>
inline std::basic_string<Char> make_env_string(const Container & value)
{
std::size_t sz = 0;
for (auto & v : value)
sz += make_env_string_size(v);
std::basic_string<Char> s;
s.reserve(sz); //+1 for ;, end doesn't have one.
for (auto & val : value)
(s += val) += api::env_seperator<Char>();
s.resize(s.size() -1); //remove last ';'
return s;
}
template<typename Char>
struct env_set
{
using string_type = std::basic_string<Char>;
string_type key;
string_type value;
};
template<typename Char>
struct env_append
{
using string_type = std::basic_string<Char>;
string_type key;
string_type value;
};
template<typename Char>
struct env_reset
{
using string_type = std::basic_string<Char>;
string_type key;
};
template<> struct is_wchar_t<env_set<wchar_t>> : std::true_type {};
template<> struct is_wchar_t<env_append<wchar_t>> : std::true_type {};
template<> struct is_wchar_t<env_reset<wchar_t>> : std::true_type {};
template<> struct is_wchar_t<basic_environment<wchar_t>> : std::true_type {};
template<>
struct char_converter<char, env_set<wchar_t>>
{
static env_set<char> conv(const env_set<wchar_t> & in)
{
return {::boost::process::detail::convert(in.key),
::boost::process::detail::convert(in.value)};
}
};
template<>
struct char_converter<wchar_t, env_set<char>>
{
static env_set<wchar_t> conv(const env_set<char> & in)
{
return {::boost::process::detail::convert(in.key),
::boost::process::detail::convert(in.value)};
}
};
template<>
struct char_converter<char, env_append<wchar_t>>
{
static env_append<char> conv(const env_append<wchar_t> & in)
{
return {::boost::process::detail::convert(in.key),
::boost::process::detail::convert(in.value)};
}
};
template<>
struct char_converter<wchar_t, env_append<char>>
{
static env_append<wchar_t> conv(const env_append<char> & in)
{
return {::boost::process::detail::convert(in.key),
::boost::process::detail::convert(in.value)};
}
};
template<>
struct char_converter<char, env_reset<wchar_t>>
{
static env_reset<char> conv(const env_reset<wchar_t> & in)
{
return {::boost::process::detail::convert(in.key)};
}
};
template<>
struct char_converter<wchar_t, env_reset<char>>
{
static env_reset<wchar_t> conv(const env_reset<char> & in)
{
return {::boost::process::detail::convert(in.key)};
}
};
template<typename Char>
struct env_init
{
basic_environment<Char> env;
};
template<>
struct char_converter<char, env_init<wchar_t>>
{
static env_init<char> conv(const env_init<wchar_t> & in)
{
return {basic_environment<char>(in.env)};
}
};
template<>
struct char_converter<wchar_t, env_init<char>>
{
static env_init<wchar_t> conv(const env_init<char> & in)
{
return {basic_environment<wchar_t>(in.env)};
}
};
template<>
struct char_converter<char, basic_environment<wchar_t>>
{
static basic_environment<char> conv(const basic_environment<wchar_t> & in)
{
return { basic_environment<char>(in) };
}
};
template<>
struct char_converter<wchar_t, basic_environment<char>>
{
static basic_environment<wchar_t> conv(const basic_environment<char> & in)
{
return { basic_environment<wchar_t>(in) };
}
};
template<typename Char>
struct env_proxy
{
using string_type = std::basic_string<Char>;
string_type key;
env_set<Char> operator=(const string_type & value)
{
return {std::move(key), value};
}
env_set<Char> operator=(const std::vector<string_type> & value)
{
return {std::move(key), make_env_string<Char>(value)};
}
env_set<Char> operator=(const std::initializer_list<const Char*> & value)
{
return {std::move(key), make_env_string<Char>(value)};
}
env_append<Char> operator+=(const string_type & value)
{
return {std::move(key), value};
}
env_append<Char> operator+=(const std::vector<string_type> & value)
{
return {std::move(key), make_env_string<Char>(value)};
}
env_append<Char> operator+=(const std::initializer_list<const Char*> & value)
{
return {std::move(key), make_env_string<Char>(value)};
}
env_reset<Char> operator=(boost::none_t)
{
return {std::move(key)};
}
};
struct env_
{
constexpr env_() {};
template<typename Char>
env_set<Char> operator()(const std::basic_string<Char> & key,
const std::basic_string<Char> & value) const
{
return {key, value};
}
template<typename Char>
env_set<Char> operator()(const std::basic_string<Char> & key,
const std::vector<std::basic_string<Char>> & value) const
{
return {key, make_env_string<Char>(value)};
}
template<typename Char>
env_set<Char> operator()(const std::basic_string<Char> & key,
const std::initializer_list<Char*> & value) const
{
return {key, make_env_string<Char>(value)};
}
template<typename Char>
env_reset<Char> operator()(const std::basic_string<Char> & key, boost::none_t)
{
return {key};
}
template<typename Char>
env_proxy<Char> operator[](const std::basic_string<Char> & key) const
{
return {key};
}
template<typename Char>
env_proxy<Char> operator[](const Char* key) const
{
return {key};
}
template<typename Char>
env_init<Char> operator()(const basic_environment<Char> & env) const
{
return {env};
}
template<typename Char>
env_init<Char> operator= (const basic_environment<Char> & env) const
{
return {env};
}
};
template<typename Char>
struct env_builder
{
basic_environment<Char> env;
env_builder() : env{basic_native_environment<Char>()} {}
void operator()(const basic_environment<Char> & e)
{
env = e;
}
void operator()(env_init<Char> & ei)
{
env = std::move(ei.env);
}
void operator()(env_set<Char> & es)
{
env[es.key] = es.value;
}
void operator()(env_reset<Char> & es)
{
env.erase(es.key);
}
template<typename T>
void operator()(env_append<T> & es)
{
env[es.key] += es.value;
}
typedef api::env_init<Char> result_type;
api::env_init<Char> get_initializer()
{
return api::env_init<Char>(std::move(env));
}
};
template<>
struct initializer_builder<env_tag<char>>
{
typedef env_builder<char> type;
};
template<>
struct initializer_builder<env_tag<wchar_t>>
{
typedef env_builder<wchar_t> type;
};
}
/**
The `env` property provides a functional way to modify the environment used by
the child process. If none is passed the environment is inherited from the father
process. Appending means that the environment will be interpreted as a ';' or ':'
separated list as used in `PATH`.
On both `posix` and `windows` the environment variables can be lists of strings,
separated by ';'. This is typically used for the `PATH` variable.
By default the environment will be inherited from the launching process,
which is also true if environment are modified with this initializer.
\section env_details Details
\subsection env_operations Operations
To set a variable `id` the value `value` the following syntax can be used.
\subsubsection env_set_var Setting variables
\code{.cpp}
env[id] = value;
env(id, value);
\endcode
To set a variable `id` the value `value` the following syntax can be used.
`std::initializer_list` is among the allowed types, so the following syntax is also possible.
\code{.cpp}
env[id] = value;
env(id, value);
\endcode
\code{.cpp}
env[id] = {value1, value2};
env(id, {value1, value2});
\endcode
`std::initializer_list` is among the allowed types, so the following syntax is also possible.
\note Creates the variable if it does not exist.
\code{.cpp}
env[id] = {value1, value2};
env(id, {value1, value2});
\endcode
The following lists contain possible value types, with `char_type` being either `char` or `wchar_t`
for both `id` and `value`.
\note Creates the variable if it does not exist.
\paragraph id id
The following lists contain possible value types, with `char_type` being either `char` or `wchar_t`
for both `id` and `value`.
- `std::basic_string<char_type>`
- `const char_type *`
\paragraph id id
\paragraph env_set_var_value value
- `std::basic_string<char_type>`
- `const char_type *`
- `std::basic_string<char_type>`
- `const char_type * `
- `std::initializer_list<const char_type *>`
- `std::vector<std::basic_string<char_type>>`
\paragraph env_set_var_value value
- `std::basic_string<char_type>`
- `const char_type * `
- `std::initializer_list<const char_type *>`
- `std::vector<std::basic_string<char_type>>`
\note Using `std::vector` or `std::initializer_list`
\subsubsection env_append_var Append variables
\note Using `std::vector` or `std::initializer_list`
Appending means, that a variable will be interpreted as a
To append a variable `id` the value `value` the following syntax can be used:
\subsubsection env_append_var Append variables
\code{.cpp}
env[id] += value;
\endcode
Appending means, that a variable will be interpreted as a
To append a variable `id` the value `value` the following syntax can be used:
`std::initializer_list` is among the allowed types, so the following syntax is also possible.
\code{.cpp}
env[id] += value;
\endcode
\code{.cpp}
env[id] += {value1, value2};
\endcode
`std::initializer_list` is among the allowed types, so the following syntax is also possible.
\note Creates the variable if it does not exist.
\code{.cpp}
env[id] += {value1, value2};
\endcode
The following lists contain possible value types, with `char_type` being either `char` or `wchar_t`
for both `id` and `value`.
\note Creates the variable if it does not exist.
\paragraph env_append_var_id id
The following lists contain possible value types, with `char_type` being either `char` or `wchar_t`
for both `id` and `value`.
- `std::basic_string<char_type>`
- `const char_type *`
\paragraph env_append_var_id id
\paragraph env_append_var_value value
- `std::basic_string<char_type>`
- `const char_type *`
- `std::basic_string<char_type>`
- `const char_type *`
- `std::initializer_list<const char_type *>`
- `std::vector<std::basic_string<char_type>>`
\paragraph env_append_var_value value
- `std::basic_string<char_type>`
- `const char_type *`
- `std::initializer_list<const char_type *>`
- `std::vector<std::basic_string<char_type>>`
\subsubsection env_reset Reset variables
Reseting signle variables can be done in the following way:
\subsubsection env_reset Reset variables
\code{.cpp}
env[id] = boost::none;
env(id, boost::none);
\endcode
Reseting signle variables can be done in the following way:
\note This does not set the value empty, but removes it from the list.
\code{.cpp}
env[id] = boost::none;
env(id, boost::none);
\endcode
The following lists contain possible value types, with `char_type` being either `char` or `wchar_t`:
\note This does not set the value empty, but removes it from the list.
\paragraph env_reset_var_id id
The following lists contain possible value types, with `char_type` being either `char` or `wchar_t`:
- `std::basic_string<char_type>`
- `const char_type *`
\paragraph env_reset_var_id id
\subsubsection env_init Initialize the environment
- `std::basic_string<char_type>`
- `const char_type *`
The whole environment can be initialized from an object of type
\xmlonly <classname>boost::process::environment</classname> \endxmlonly
\subsubsection env_init Initialize the environment
\code{.cpp}
env=env;
env(env);
\endcode
The whole environment can be initialized from an object of type
\xmlonly <classname>boost::process::environment</classname> \endxmlonly
\note The passed `environment` can also be default-constructed to get an empty environment.
\code{.cpp}
env=env;
env(env);
\endcode
\paragraph env_init_var_id id
\note The passed `environment` can also be default-constructed to get an empty environment.
- `std::basic_string<char_type>`
- `const char_type *`
\paragraph env_init_var_id id
\paragraph env_init_var_value value
- `std::basic_string<char_type>`
- `const char_type *`
- `boost::process::basic_environment<char_type>`
\paragraph env_init_var_value value
\subsection env_example Example
- `boost::process::basic_environment<char_type>`
\code{.cpp}
spawn("b2", env["PATH"]+="F:/boost", env["SOME_VAR"]=boost::none, env["NEW_VAR"]="VALUE");
\endcode
\subsection env_example Example
If the overload style should be done by passing an instance of
\xmlonly <classname>boost::process::environment</classname> \endxmlonly
the above example would look like this.
\code{.cpp}
spawn("b2", env["PATH"]+="F:/boost", env["SOME_VAR"]=boost::none, env["NEW_VAR"]="VALUE");
\endcode
\code{.cpp}
environment e = this_process::environment();
e["PATH"] += "F:/boost";
e.erase("SOME_VAR");
e["NEW_VAR"] = "VALUE";
spawn("b2", e);
\endcode
If the overload style should be done by passing an instance of
\xmlonly <classname>boost::process::environment</classname> \endxmlonly
the above example would look like this.
\warning Passing an empty environment will cause undefined behaviour.
\code{.cpp}
environment e = this_process::environment();
e["PATH"] += "F:/boost";
e.erase("SOME_VAR");
e["NEW_VAR"] = "VALUE";
spawn("b2", e);
\endcode
*/
constexpr boost::process::detail::env_ env{};
\warning Passing an empty environment will cause undefined behaviour.
*/
constexpr boost::process::detail::env_ env{};
}}
#endif /* INCLUDE_BOOST_PROCESS_DETAIL_ENV_HPP_ */
}}
#endif /* INCLUDE_BOOST_PROCESS_DETAIL_ENV_HPP_ */

View File

@@ -472,17 +472,17 @@ public:
///Assign a string to the value
void assign(const string_type &value);
///Assign a set of strings to the entry; they will be seperated by ';' or ':'.
///Assign a set of strings to the entry; they will be separated by ';' or ':'.
void assign(const std::vector<string_type> &value);
///Append a string to the end of the entry, it will seperated by ';' or ':'.
///Append a string to the end of the entry, it will separated by ';' or ':'.
void append(const string_type &value);
///Reset the value
void clear();
///Assign a string to the entry.
entry &operator=(const string_type & value);
///Assign a set of strings to the entry; they will be seperated by ';' or ':'.
///Assign a set of strings to the entry; they will be separated by ';' or ':'.
entry &operator=(const std::vector<string_type> & value);
///Append a string to the end of the entry, it will seperated by ';' or ':'.
///Append a string to the end of the entry, it will separated by ';' or ':'.
entry &operator+=(const string_type & value);
};
@@ -592,17 +592,17 @@ public:
///Assign a string to the value
void assign(const string_type &value);
///Assign a set of strings to the entry; they will be seperated by ';' or ':'.
///Assign a set of strings to the entry; they will be separated by ';' or ':'.
void assign(const std::vector<string_type> &value);
///Append a string to the end of the entry, it will seperated by ';' or ':'.
///Append a string to the end of the entry, it will separated by ';' or ':'.
void append(const string_type &value);
///Reset the value
void clear();
///Assign a string to the entry.
entry &operator=(const string_type & value);
///Assign a set of strings to the entry; they will be seperated by ';' or ':'.
///Assign a set of strings to the entry; they will be separated by ';' or ':'.
entry &operator=(const std::vector<string_type> & value);
///Append a string to the end of the entry, it will seperated by ';' or ':'.
///Append a string to the end of the entry, it will separated by ';' or ':'.
entry &operator+=(const string_type & value);
};
@@ -631,14 +631,17 @@ public:
};
#if !defined(BOOST_NO_ANSI_APIS)
///Definition of the environment for the current process.
typedef basic_native_environment<char> native_environment;
#endif
///Definition of the environment for the current process.
typedef basic_native_environment<wchar_t> wnative_environment;
#if !defined(BOOST_NO_ANSI_APIS)
///Type definition to hold a seperate environment.
typedef basic_environment<char> environment;
#endif
///Type definition to hold a seperate environment.
typedef basic_environment<wchar_t> wenvironment;
@@ -651,8 +654,10 @@ namespace this_process
///Definition of the native handle type.
typedef ::boost::process::detail::api::native_handle_t native_handle_type;
#if !defined(BOOST_NO_ANSI_APIS)
///Definition of the environment for this process.
using ::boost::process::native_environment;
#endif
///Definition of the environment for this process.
using ::boost::process::wnative_environment;
@@ -660,8 +665,10 @@ using ::boost::process::wnative_environment;
inline int get_id() { return ::boost::process::detail::api::get_id();}
///Get the native handle of the current process.
inline native_handle_type native_handle() { return ::boost::process::detail::api::native_handle();}
#if !defined(BOOST_NO_ANSI_APIS)
///Get the enviroment of the current process.
inline native_environment environment() { return ::boost::process:: native_environment(); }
#endif
///Get the enviroment of the current process.
inline wnative_environment wenvironment() { return ::boost::process::wnative_environment(); }
///Get the path environment variable of the current process runs.

View File

@@ -1,79 +1,79 @@
// 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) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// 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) 2016 Klemens D. Morgenstern
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PROCESS_EXE_HPP
#define BOOST_PROCESS_EXE_HPP
#ifndef BOOST_PROCESS_EXE_HPP
#define BOOST_PROCESS_EXE_HPP
#include <boost/process/detail/basic_cmd.hpp>
#include <boost/process/detail/basic_cmd.hpp>
/** \file boost/process/exe.hpp
*
* Header which provides the exe property.
\xmlonly
<programlisting>
namespace boost {
namespace process {
<emphasis>unspecified</emphasis> <globalname alt="boost::process::exe">exe</globalname>;
}
}
</programlisting>
\endxmlonly
*/
namespace boost { namespace process { namespace detail {
/** \file boost/process/exe.hpp
*
* Header which provides the exe property.
\xmlonly
<programlisting>
namespace boost {
namespace process {
<emphasis>unspecified</emphasis> <globalname alt="boost::process::exe">exe</globalname>;
}
}
</programlisting>
\endxmlonly
*/
namespace boost { namespace process { namespace detail {
struct exe_
{
template<typename Char>
inline exe_setter_<Char> operator()(const Char *s) const
{
return exe_setter_<Char>(s);
}
template<typename Char>
inline exe_setter_<Char> operator= (const Char *s) const
{
return exe_setter_<Char>(s);
}
struct exe_
{
template<typename Char>
inline exe_setter_<Char> operator()(const Char *s) const
{
return exe_setter_<Char>(s);
}
template<typename Char>
inline exe_setter_<Char> operator= (const Char *s) const
{
return exe_setter_<Char>(s);
}
template<typename Char>
inline exe_setter_<Char> operator()(const std::basic_string<Char> &s) const
{
return exe_setter_<Char>(s);
}
template<typename Char>
inline exe_setter_<Char> operator= (const std::basic_string<Char> &s) const
{
return exe_setter_<Char>(s);
}
};
template<typename Char>
inline exe_setter_<Char> operator()(const std::basic_string<Char> &s) const
{
return exe_setter_<Char>(s);
}
template<typename Char>
inline exe_setter_<Char> operator= (const std::basic_string<Char> &s) const
{
return exe_setter_<Char>(s);
}
};
}
}
/** The exe property allows to explicitly set the executable.
/** The exe property allows to explicitly set the executable.
The overload form applies when to the first, when several strings are passed to a launching
function.
The overload form applies when to the first, when several strings are passed to a launching
function.
The following expressions are valid, with `value` being either a C-String or
a `std::basic_string` with `char` or `wchar_t` or a `boost::filesystem::path`.
The following expressions are valid, with `value` being either a C-String or
a `std::basic_string` with `char` or `wchar_t` or a `boost::filesystem::path`.
\code{.cpp}
exe="value";
exe(value);
\endcode
\code{.cpp}
exe="value";
exe(value);
\endcode
The property can only be used for assignments.
The property can only be used for assignments.
*/
constexpr boost::process::detail::exe_ exe{};
*/
constexpr boost::process::detail::exe_ exe{};
}}
}}
#endif
#endif

View File

@@ -33,7 +33,7 @@ namespace boost {
namespace process {
namespace detail {
template<typename Tuple>
inline asio::io_service& get_io_service(const Tuple & tup);
inline asio::io_context& get_io_context(const Tuple & tup);
}
@@ -57,9 +57,9 @@ struct windows_executor;
#endif
using ::boost::process::detail::handler;
using ::boost::process::detail::api::require_io_service;
using ::boost::process::detail::api::require_io_context;
using ::boost::process::detail::api::async_handler;
using ::boost::process::detail::get_io_service;
using ::boost::process::detail::get_io_context;
using ::boost::process::detail::get_last_error;
using ::boost::process::detail::throw_last_error;
@@ -91,13 +91,13 @@ inline void throw_last_error(const std::string & msg);
inline void throw_last_error();
/** This function gets the io_service from the initializer sequence.
/** This function gets the io_context from the initializer sequence.
*
* \attention Yields a compile-time error if no `io_service` is provided.
* \attention Yields a compile-time error if no `io_context` is provided.
* \param seq The Sequence of the initializer.
*/
template<typename Sequence>
inline asio::io_service& get_io_service(const Sequence & seq);
inline asio::io_context& get_io_context(const Sequence & seq);
/** This class is the base for every initializer, to be used for extensions.
*
@@ -149,14 +149,14 @@ struct handler
};
/** Inheriting the class will tell the launching process that an `io_service` is
* needed. This should always be used when \ref get_io_service is used.
/** Inheriting the class will tell the launching process that an `io_context` is
* needed. This should always be used when \ref get_io_context is used.
*
*/
struct require_io_service {};
struct require_io_context {};
/** Inheriting this class will tell the launching function, that an event handler
* shall be invoked when the process exits. This automatically does also inherit
* \ref require_io_service.
* \ref require_io_context.
*
* You must add the following function to your implementation:
*
@@ -179,7 +179,7 @@ std::function<void(int, const std::error_code&)> on_exit_handler(Executor & exec
*
* \warning Cannot be used with \ref boost::process::spawn
*/
struct async_handler : handler, require_io_service
struct async_handler : handler, require_io_context
{
};
@@ -241,7 +241,7 @@ struct posix_executor
char **env = ::environ;
///The pid of the process - it will be -1 before invoking [fork](http://pubs.opengroup.org/onlinepubs/009695399/functions/fork.html), and after forking either 0 for the new process or a positive value if in the current process. */
pid_t pid = -1;
///This shared-pointer holds the exit code. It's done this way, so it can be shared between an `asio::io_service` and \ref child.
///This shared-pointer holds the exit code. It's done this way, so it can be shared between an `asio::io_context` and \ref child.
std::shared_ptr<std::atomic<int>> exit_status = std::make_shared<std::atomic<int>>(still_active);
///This function returns a const reference to the error state of the executor.
@@ -302,7 +302,7 @@ struct windows_executor
::boost::detail::winapi::PROCESS_INFORMATION_ proc_info{nullptr, nullptr, 0,0};
///This shared-pointer holds the exit code. It's done this way, so it can be shared between an `asio::io_service` and \ref child.
///This shared-pointer holds the exit code. It's done this way, so it can be shared between an `asio::io_context` and \ref child.
std::shared_ptr<std::atomic<int>> exit_status = std::make_shared<std::atomic<int>>(still_active);
///This function returns a const reference to the error state of the executor.

File diff suppressed because it is too large Load Diff

View File

@@ -1,246 +1,246 @@
// Copyright (c) 2016 Klemens D. Morgenstern
// Copyright (c) 2008 Beman Dawes
// 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)
// Copyright (c) 2016 Klemens D. Morgenstern
// Copyright (c) 2008 Beman Dawes
// 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_LOCALE_HPP_
#define BOOST_PROCESS_LOCALE_HPP_
#ifndef BOOST_PROCESS_LOCALE_HPP_
#define BOOST_PROCESS_LOCALE_HPP_
#include <system_error>
#include <boost/process/detail/config.hpp>
#include <system_error>
#include <boost/process/detail/config.hpp>
#if defined(BOOST_WINDOWS_API)
#include <boost/process/detail/windows/locale.hpp>
# elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) \
|| defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__HAIKU__)
#include <codecvt>
#endif
#if defined(BOOST_WINDOWS_API)
#include <boost/process/detail/windows/locale.hpp>
# elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) \
|| defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__HAIKU__)
#include <codecvt>
#endif
#include <locale>
#include <locale>
namespace boost
{
namespace process
{
namespace detail
{
namespace boost
{
namespace process
{
namespace detail
{
class codecvt_category_t : public std::error_category
{
public:
codecvt_category_t(){}
const char* name() const noexcept override {return "codecvt";}
std::string message(int ev) const override
{
std::string str;
switch (ev)
{
case std::codecvt_base::ok:
str = "ok";
break;
case std::codecvt_base::partial:
str = "partial";
break;
case std::codecvt_base::error:
str = "error";
break;
case std::codecvt_base::noconv:
str = "noconv";
break;
default:
str = "unknown error";
}
return str;
}
};
class codecvt_category_t : public std::error_category
{
public:
codecvt_category_t(){}
const char* name() const noexcept override {return "codecvt";}
std::string message(int ev) const override
{
std::string str;
switch (ev)
{
case std::codecvt_base::ok:
str = "ok";
break;
case std::codecvt_base::partial:
str = "partial";
break;
case std::codecvt_base::error:
str = "error";
break;
case std::codecvt_base::noconv:
str = "noconv";
break;
default:
str = "unknown error";
}
return str;
}
};
}
}
///Internally used error cateory for code conversion.
inline const std::error_category& codecvt_category()
{
static const ::boost::process::detail::codecvt_category_t cat;
return cat;
}
///Internally used error cateory for code conversion.
inline const std::error_category& codecvt_category()
{
static const ::boost::process::detail::codecvt_category_t cat;
return cat;
}
namespace detail
{
//copied from boost.filesystem
inline std::locale default_locale()
{
# if defined(BOOST_WINDOWS_API)
std::locale global_loc = std::locale();
return std::locale(global_loc, new boost::process::detail::windows::windows_file_codecvt);
# elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) \
|| defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__HAIKU__)
std::locale global_loc = std::locale();
return std::locale(global_loc, new std::codecvt_utf8<wchar_t>);
# else // Other POSIX
// ISO C calls std::locale("") "the locale-specific native environment", and this
// locale is the default for many POSIX-based operating systems such as Linux.
return std::locale("");
# endif
}
namespace detail
{
//copied from boost.filesystem
inline std::locale default_locale()
{
# if defined(BOOST_WINDOWS_API)
std::locale global_loc = std::locale();
return std::locale(global_loc, new boost::process::detail::windows::windows_file_codecvt);
# elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) \
|| defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__HAIKU__)
std::locale global_loc = std::locale();
return std::locale(global_loc, new std::codecvt_utf8<wchar_t>);
# else // Other POSIX
// ISO C calls std::locale("") "the locale-specific native environment", and this
// locale is the default for many POSIX-based operating systems such as Linux.
return std::locale("");
# endif
}
inline std::locale& process_locale()
{
static std::locale loc(default_locale());
return loc;
}
inline std::locale& process_locale()
{
static std::locale loc(default_locale());
return loc;
}
}
}
///The internally used type for code conversion.
typedef std::codecvt<wchar_t, char, std::mbstate_t> codecvt_type;
///The internally used type for code conversion.
typedef std::codecvt<wchar_t, char, std::mbstate_t> codecvt_type;
///Get a reference to the currently used code converter.
inline const codecvt_type& codecvt()
{
return std::use_facet<std::codecvt<wchar_t, char, std::mbstate_t>>(
detail::process_locale());
}
///Get a reference to the currently used code converter.
inline const codecvt_type& codecvt()
{
return std::use_facet<std::codecvt<wchar_t, char, std::mbstate_t>>(
detail::process_locale());
}
///Set the locale of the library.
inline std::locale imbue(const std::locale& loc)
{
std::locale temp(detail::process_locale());
detail::process_locale() = loc;
return temp;
}
///Set the locale of the library.
inline std::locale imbue(const std::locale& loc)
{
std::locale temp(detail::process_locale());
detail::process_locale() = loc;
return temp;
}
namespace detail
{
namespace detail
{
inline std::size_t convert(const char* from,
const char* from_end,
wchar_t* to, wchar_t* to_end,
const ::boost::process::codecvt_type & cvt =
::boost::process::codecvt())
{
std::mbstate_t state = std::mbstate_t(); // perhaps unneeded, but cuts bug reports
const char* from_next;
wchar_t* to_next;
inline std::size_t convert(const char* from,
const char* from_end,
wchar_t* to, wchar_t* to_end,
const ::boost::process::codecvt_type & cvt =
::boost::process::codecvt())
{
std::mbstate_t state = std::mbstate_t(); // perhaps unneeded, but cuts bug reports
const char* from_next;
wchar_t* to_next;
auto res = cvt.in(state, from, from_end, from_next,
to, to_end, to_next);
auto res = cvt.in(state, from, from_end, from_next,
to, to_end, to_next);
if (res != std::codecvt_base::ok)
throw process_error(res, ::boost::process::codecvt_category(),
"boost::process codecvt to wchar_t");
if (res != std::codecvt_base::ok)
throw process_error(res, ::boost::process::codecvt_category(),
"boost::process codecvt to wchar_t");
return to_next - to;
return to_next - to;
}
}
inline std::size_t convert(const wchar_t* from,
const wchar_t* from_end,
char* to, char* to_end,
const ::boost::process::codecvt_type & cvt =
::boost::process::codecvt())
{
std::mbstate_t state = std::mbstate_t(); // perhaps unneeded, but cuts bug reports
const wchar_t* from_next;
char* to_next;
inline std::size_t convert(const wchar_t* from,
const wchar_t* from_end,
char* to, char* to_end,
const ::boost::process::codecvt_type & cvt =
::boost::process::codecvt())
{
std::mbstate_t state = std::mbstate_t(); // perhaps unneeded, but cuts bug reports
const wchar_t* from_next;
char* to_next;
std::codecvt_base::result res;
std::codecvt_base::result res;
if ((res=cvt.out(state, from, from_end, from_next,
to, to_end, to_next)) != std::codecvt_base::ok)
throw process_error(res, ::boost::process::codecvt_category(),
"boost::process codecvt to char");
if ((res=cvt.out(state, from, from_end, from_next,
to, to_end, to_next)) != std::codecvt_base::ok)
throw process_error(res, ::boost::process::codecvt_category(),
"boost::process codecvt to char");
return to_next - to;
}
return to_next - to;
}
inline std::wstring convert(const std::string & st,
const ::boost::process::codecvt_type & cvt =
::boost::process::codecvt())
{
std::wstring out(st.size() + 10, ' '); //just to be sure
auto sz = convert(st.c_str(), st.c_str() + st.size(),
&out.front(), &out.back(), cvt);
inline std::wstring convert(const std::string & st,
const ::boost::process::codecvt_type & cvt =
::boost::process::codecvt())
{
std::wstring out(st.size() + 10, ' '); //just to be sure
auto sz = convert(st.c_str(), st.c_str() + st.size(),
&out.front(), &out.back(), cvt);
out.resize(sz);
return out;
}
out.resize(sz);
return out;
}
inline std::string convert(const std::wstring & st,
const ::boost::process::codecvt_type & cvt =
::boost::process::codecvt())
{
std::string out(st.size() * 2, ' '); //just to be sure
auto sz = convert(st.c_str(), st.c_str() + st.size(),
&out.front(), &out.back(), cvt);
inline std::string convert(const std::wstring & st,
const ::boost::process::codecvt_type & cvt =
::boost::process::codecvt())
{
std::string out(st.size() * 2, ' '); //just to be sure
auto sz = convert(st.c_str(), st.c_str() + st.size(),
&out.front(), &out.back(), cvt);
out.resize(sz);
return out;
}
out.resize(sz);
return out;
}
inline std::vector<wchar_t> convert(const std::vector<char> & st,
const ::boost::process::codecvt_type & cvt =
::boost::process::codecvt())
{
std::vector<wchar_t> out(st.size() + 10); //just to be sure
auto sz = convert(st.data(), st.data() + st.size(),
&out.front(), &out.back(), cvt);
inline std::vector<wchar_t> convert(const std::vector<char> & st,
const ::boost::process::codecvt_type & cvt =
::boost::process::codecvt())
{
std::vector<wchar_t> out(st.size() + 10); //just to be sure
auto sz = convert(st.data(), st.data() + st.size(),
&out.front(), &out.back(), cvt);
out.resize(sz);
return out;
}
out.resize(sz);
return out;
}
inline std::vector<char> convert(const std::vector<wchar_t> & st,
const ::boost::process::codecvt_type & cvt =
::boost::process::codecvt())
{
std::vector<char> out(st.size() * 2); //just to be sure
auto sz = convert(st.data(), st.data() + st.size(),
&out.front(), &out.back(), cvt);
inline std::vector<char> convert(const std::vector<wchar_t> & st,
const ::boost::process::codecvt_type & cvt =
::boost::process::codecvt())
{
std::vector<char> out(st.size() * 2); //just to be sure
auto sz = convert(st.data(), st.data() + st.size(),
&out.front(), &out.back(), cvt);
out.resize(sz);
return out;
}
out.resize(sz);
return out;
}
inline std::wstring convert(const char *begin, const char* end,
const ::boost::process::codecvt_type & cvt =
::boost::process::codecvt())
{
auto size = end-begin;
std::wstring out(size + 10, ' '); //just to be sure
using namespace std;
auto sz = convert(begin, end,
&out.front(), &out.back(), cvt);
out.resize(sz);
return out;
}
inline std::wstring convert(const char *begin, const char* end,
const ::boost::process::codecvt_type & cvt =
::boost::process::codecvt())
{
auto size = end-begin;
std::wstring out(size + 10, ' '); //just to be sure
using namespace std;
auto sz = convert(begin, end,
&out.front(), &out.back(), cvt);
out.resize(sz);
return out;
}
inline std::string convert(const wchar_t * begin, const wchar_t *end,
const ::boost::process::codecvt_type & cvt =
::boost::process::codecvt())
{
auto size = end-begin;
inline std::string convert(const wchar_t * begin, const wchar_t *end,
const ::boost::process::codecvt_type & cvt =
::boost::process::codecvt())
{
auto size = end-begin;
std::string out(size * 2, ' '); //just to be sure
auto sz = convert(begin, end ,
&out.front(), &out.back(), cvt);
std::string out(size * 2, ' '); //just to be sure
auto sz = convert(begin, end ,
&out.front(), &out.back(), cvt);
out.resize(sz);
return out;
}
out.resize(sz);
return out;
}
}
}
}
}
}
}
#endif /* BOOST_PROCESS_LOCALE_HPP_ */
#endif /* BOOST_PROCESS_LOCALE_HPP_ */

View File

@@ -262,7 +262,7 @@ public:
typedef typename Traits::off_type off_type ;
///Get access to the underlying stream_buf
basic_pipebuf<CharT, Traits>* rdbuf() const {return _buf;};
basic_pipebuf<CharT, Traits>* rdbuf() {return &_buf;};
///Default constructor.
basic_ipstream() : std::basic_istream<CharT, Traits>(nullptr)

View File

@@ -39,7 +39,7 @@ namespace boost { namespace process {
*
* \param filename The base of the filename to find
*
* \param path the set of paths so search, defaults to "PATH" environment variable.
* \param path the set of paths to search, defaults to the "PATH" environment variable.
*
* \returns the absolute path to the executable filename or an
* empty string if filename isn't found

View File

@@ -42,7 +42,7 @@ but will also cause the system to be unable to wait for the child to exit.
\note This will set `SIGCHLD` to `SIGIGN` on posix.
\warning This function does not allow asynchronous operations, since it cannot wait for the end of the process.
It will fail to compile if a reference to `boost::asio::io_service` is passed.
It will fail to compile if a reference to `boost::asio::io_context` is passed.
*/
template<typename ...Args>

Some files were not shown because too many files have changed in this diff Show More