mirror of
https://github.com/boostorg/process.git
synced 2026-01-20 16:52:14 +00:00
Compare commits
170 Commits
boost-1.64
...
boost-1.67
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f1c6909eb0 | ||
|
|
35fda5aa6a | ||
|
|
1f7f805858 | ||
|
|
d47b7f7ac4 | ||
|
|
2bc2531d2a | ||
|
|
c5798fdf7f | ||
|
|
5e43e7c07c | ||
|
|
4fc4784506 | ||
|
|
900aab5d6d | ||
|
|
f61a61cf59 | ||
|
|
8e8d36772e | ||
|
|
ec04919825 | ||
|
|
6625999765 | ||
|
|
0d3688aca5 | ||
|
|
40be786c43 | ||
|
|
d4a0444223 | ||
|
|
f99cfe77f4 | ||
|
|
ed32531369 | ||
|
|
751af041cd | ||
|
|
a0ceebd59f | ||
|
|
b0b37f2ce6 | ||
|
|
cf1f904ae2 | ||
|
|
8aaf53d76d | ||
|
|
76c03ded89 | ||
|
|
e6fa19b4c5 | ||
|
|
92ee239891 | ||
|
|
c37e2a7524 | ||
|
|
a610fe74ff | ||
|
|
ea49952da2 | ||
|
|
a55946eb5d | ||
|
|
9f6c338631 | ||
|
|
60302c0017 | ||
|
|
08eaf8b7a1 | ||
|
|
cc70ec9362 | ||
|
|
b58ecc7c9d | ||
|
|
668cbcdaf4 | ||
|
|
6d7cbd0989 | ||
|
|
0764f788a6 | ||
|
|
2b95dd7011 | ||
|
|
ae380c30ad | ||
|
|
d2265890bd | ||
|
|
831d49c1b3 | ||
|
|
6935c53510 | ||
|
|
f30d90a179 | ||
|
|
55cfcecfb8 | ||
|
|
233f46a2cb | ||
|
|
342554b3d8 | ||
|
|
7aa812a0e1 | ||
|
|
c4ffd0c18d | ||
|
|
a411f06dc4 | ||
|
|
d085262076 | ||
|
|
0396740467 | ||
|
|
0fd7de9481 | ||
|
|
ba790dad0a | ||
|
|
f2e8776965 | ||
|
|
444d5eb702 | ||
|
|
3e12e989ab | ||
|
|
917030c3cd | ||
|
|
faf848bd8b | ||
|
|
d78c7901b3 | ||
|
|
09e98d8746 | ||
|
|
ab6e5b54ec | ||
|
|
b268e0e1fb | ||
|
|
996f4b357c | ||
|
|
8ce3e760dc | ||
|
|
6e60928b1f | ||
|
|
e27baa7628 | ||
|
|
337a6e3e83 | ||
|
|
bbfc334c93 | ||
|
|
1a9fa2cc2c | ||
|
|
1296e02372 | ||
|
|
585104605e | ||
|
|
d0c07b7c63 | ||
|
|
7c9ce7f8b9 | ||
|
|
c388f24d6e | ||
|
|
b1f50e953b | ||
|
|
852d8f3d9d | ||
|
|
2c026e43a8 | ||
|
|
51396227a0 | ||
|
|
75d3049199 | ||
|
|
3d9a8b2353 | ||
|
|
8097c2e07a | ||
|
|
d9231d466c | ||
|
|
153e05eac0 | ||
|
|
883b6ac937 | ||
|
|
764fff1f65 | ||
|
|
16ff42290a | ||
|
|
6adf1bf545 | ||
|
|
126659f2f9 | ||
|
|
90adf118ac | ||
|
|
63952fa2a6 | ||
|
|
2f00162817 | ||
|
|
28b402eed1 | ||
|
|
3f12d82e00 | ||
|
|
e01c1e0d37 | ||
|
|
c2602e86e9 | ||
|
|
e2a2a57820 | ||
|
|
547c04fc1f | ||
|
|
6ab2ed1723 | ||
|
|
79e26878b1 | ||
|
|
d15e7be16a | ||
|
|
3ab038fc0f | ||
|
|
66989a25f2 | ||
|
|
c748fff766 | ||
|
|
4772a08f89 | ||
|
|
054d7980ab | ||
|
|
4c6b0fff2a | ||
|
|
449eef0b98 | ||
|
|
3992965359 | ||
|
|
264b517b38 | ||
|
|
71c2fad8ce | ||
|
|
5b45fad163 | ||
|
|
e899189bf4 | ||
|
|
241883c9e4 | ||
|
|
aeee4e5dbb | ||
|
|
e08e095fd1 | ||
|
|
da34b4020d | ||
|
|
99001ccb50 | ||
|
|
f402f48138 | ||
|
|
1960360099 | ||
|
|
83019b5f70 | ||
|
|
76418ca191 | ||
|
|
f02e72304f | ||
|
|
4850ae493f | ||
|
|
77aecb43b8 | ||
|
|
66e576806f | ||
|
|
15445fd2bf | ||
|
|
6f49261c6e | ||
|
|
062b26e046 | ||
|
|
bb0fe86292 | ||
|
|
a3d3a98d5b | ||
|
|
950f16fe42 | ||
|
|
225b322e56 | ||
|
|
3e31d43d61 | ||
|
|
085adc07ec | ||
|
|
6aaefedf25 | ||
|
|
8df9c467e5 | ||
|
|
529d09f43b | ||
|
|
ce2a06f3a6 | ||
|
|
93a077e911 | ||
|
|
9ed2ebef27 | ||
|
|
7882bad799 | ||
|
|
92e1e04ae4 | ||
|
|
cf19c451fa | ||
|
|
74dd6570e3 | ||
|
|
826177a12e | ||
|
|
6712c54827 | ||
|
|
6a64b9e0bd | ||
|
|
34377ecad0 | ||
|
|
ae2b0a9024 | ||
|
|
712ebf772b | ||
|
|
7a99be71d3 | ||
|
|
210efd8dc5 | ||
|
|
ed15395f6d | ||
|
|
05443af621 | ||
|
|
a25665aeff | ||
|
|
ee4428c226 | ||
|
|
74814e46c1 | ||
|
|
f27898cdcd | ||
|
|
007dd97486 | ||
|
|
f0082aa797 | ||
|
|
ba14d9f870 | ||
|
|
684f9bcf11 | ||
|
|
51735a5640 | ||
|
|
d6b242c54a | ||
|
|
9daf3b4717 | ||
|
|
9cab8d455a | ||
|
|
f1bd81d56e | ||
|
|
28dc0c8830 | ||
|
|
7e217fe012 |
96
.gitattributes
vendored
Normal file
96
.gitattributes
vendored
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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: | [](https://travis-ci.org/klemens-morgenstern/boost-process) [](https://ci.appveyor.com/project/klemens-morgenstern/boost-process) | [](https://coveralls.io/github/klemens-morgenstern/boost-process?branch=develop) |
|
||||
Master: | [] (https://travis-ci.org/klemens-morgenstern/boost-process) [](https://ci.appveyor.com/project/klemens-morgenstern/boost-process/branch/master) | [](https://coveralls.io/github/klemens-morgenstern/boost-process?branch=master) |
|
||||
Master: | [](https://travis-ci.org/klemens-morgenstern/boost-process) [](https://ci.appveyor.com/project/klemens-morgenstern/boost-process/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.
|
||||
|
||||
@@ -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`.
|
||||
|
||||
@@ -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]
|
||||
|
||||
128
doc/faq.qbk
128
doc/faq.qbk
@@ -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]
|
||||
@@ -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"};
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace bp = boost::process;
|
||||
|
||||
int main()
|
||||
{
|
||||
boost::asio::io_service ios;
|
||||
boost::asio::io_context ios;
|
||||
boost::asio::streambuf buffer;
|
||||
|
||||
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 &;
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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)};
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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...);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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 >
|
||||
|
||||
@@ -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';}
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,20 @@ 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();}
|
||||
template<typename MutableBufferSequence>
|
||||
std::size_t read_some(const MutableBufferSequence & buffers, boost::system::error_code & ec) noexcept
|
||||
{
|
||||
return _source.read_some(buffers, ec);
|
||||
}
|
||||
template<typename MutableBufferSequence>
|
||||
std::size_t write_some(const MutableBufferSequence & buffers, boost::system::error_code & ec) noexcept
|
||||
{
|
||||
return _sink.write_some(buffers, ec);
|
||||
}
|
||||
|
||||
|
||||
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 +169,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 +218,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 +239,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 +250,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 +277,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 +289,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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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_ */
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}}}}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 "";
|
||||
|
||||
122
include/boost/process/detail/posix/sigchld_service.hpp
Normal file
122
include/boost/process/detail/posix/sigchld_service.hpp
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}}}}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}}}}
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,20 @@ 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();}
|
||||
|
||||
template<typename MutableBufferSequence>
|
||||
std::size_t read_some(const MutableBufferSequence & buffers, boost::system::error_code & ec) noexcept
|
||||
{
|
||||
return _source.read_some(buffers, ec);
|
||||
}
|
||||
template<typename MutableBufferSequence>
|
||||
std::size_t write_some(const MutableBufferSequence & buffers, boost::system::error_code & ec) noexcept
|
||||
{
|
||||
return _sink.write_some(buffers, ec);
|
||||
}
|
||||
|
||||
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 +187,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 +237,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 +270,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 +311,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};
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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_;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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_;
|
||||
}
|
||||
|
||||
}}}}
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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};
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.");
|
||||
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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_ */
|
||||
@@ -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)
|
||||
|
||||
@@ -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_ (*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_ 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_ (*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_ 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;
|
||||
|
||||
}}}}}
|
||||
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
}}}}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}}}}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}}}}
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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_ */
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user