初始化内容

This commit is contained in:
2026-09-16 14:07:40 +08:00
parent 6934b390bf
commit 4f643c1e7c
18350 changed files with 6088489 additions and 305 deletions
+20
View File
@@ -0,0 +1,20 @@
# EditorConfig is awesome: http://EditorConfig.org
# top-most EditorConfig file
root = true
# Unix-style newlines with a newline ending every file
[*]
charset = utf-8
indent_style = space
indent_size = 4
end_of_line = lf
[*.{c,cppi,cc,h,hpp}]
indent_size = 2
# Tab indentation (no size specified)
[Makefile,makefile,GNUmakefile]
indent_style = tab
#[*.{js,py}]
@@ -0,0 +1,76 @@
# This starter workflow is for a CMake project running on multiple platforms. There is a different starter workflow if you just want a single platform.
# See: https://github.com/actions/starter-workflows/blob/main/ci/cmake-single-platform.yml
name: CMake on multiple platforms
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
# Set fail-fast to false to ensure that feedback is delivered for all matrix combinations. Consider changing this to true when your workflow is stable.
fail-fast: false
# Set up a matrix to run the following 3 configurations:
# 1. <Windows, Debug, latest MSVC compiler toolchain on the default runner image, default generator>
# 2. <Linux, Debug, latest GCC compiler toolchain on the default runner image, default generator>
# 3. <Linux, Debug, latest Clang compiler toolchain on the default runner image, default generator>
#
# To add more build types (Release, Debug, RelWithDebInfo, etc.) customize the build_type list.
matrix:
os: [ubuntu-latest, windows-latest]
build_type: [Debug]
c_compiler: [gcc, clang, cl]
include:
- os: windows-latest
c_compiler: cl
cpp_compiler: cl
- os: ubuntu-latest
c_compiler: gcc
cpp_compiler: g++
- os: ubuntu-latest
c_compiler: clang
cpp_compiler: clang++
exclude:
- os: windows-latest
c_compiler: gcc
- os: windows-latest
c_compiler: clang
- os: ubuntu-latest
c_compiler: cl
steps:
- uses: actions/checkout@v3
- name: Set reusable strings
# Turn repeated input strings (such as the build output directory) into step outputs. These step outputs can be used throughout the workflow file.
id: strings
shell: bash
run: |
echo "build-output-dir=${{ github.workspace }}/build" >> "$GITHUB_OUTPUT"
- name: Configure CMake
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
# See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
run: >
cmake -B ${{ steps.strings.outputs.build-output-dir }}
-DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }}
-DCMAKE_C_COMPILER=${{ matrix.c_compiler }}
-DCMAKE_BUILD_TYPE=${{ matrix.build_type }}
-DSUBPROCESS_TESTS=ON
-S ${{ github.workspace }}
- name: Build
# Build your program with the given configuration. Note that --config is needed because the default Windows generator is a multi-config generator (Visual Studio generator).
run: cmake --build ${{ steps.strings.outputs.build-output-dir }} --config ${{ matrix.build_type }}
- name: Test
working-directory: ${{ steps.strings.outputs.build-output-dir }}
# Execute tests defined by the CMake configuration. Note that --build-config is needed because the default Windows generator is a multi-config generator (Visual Studio generator).
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
run: ctest --build-config ${{ matrix.build_type }} --timeout 10 -j4
+2
View File
@@ -0,0 +1,2 @@
build
.vscode
+63
View File
@@ -0,0 +1,63 @@
cmake_minimum_required(VERSION 3.5)
project(subprocess VERSION 2.2 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 11 CACHE STRING "C++ standard to use")
option(EXPORT_COMPILE_COMMANDS "create clang compile database" ON)
option(SUBPROCESS_TESTS "enable subprocess tests" OFF)
option(SUBPROCESS_INSTALL "enable subprocess install" OFF)
find_package(Threads REQUIRED)
add_library(subprocess INTERFACE)
target_link_libraries(subprocess INTERFACE Threads::Threads)
target_sources(subprocess PUBLIC
FILE_SET HEADERS
FILES
cpp-subprocess/subprocess.hpp
BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/
)
add_library(cpp-subprocess::subprocess ALIAS subprocess)
if(SUBPROCESS_INSTALL)
install(
TARGETS subprocess COMPONENT subprocess
EXPORT subprocess
FILE_SET HEADERS DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)
include(CMakePackageConfigHelpers)
configure_package_config_file(
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/subprocess-config.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/subprocess-config.cmake"
INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/subprocess"
PATH_VARS PROJECT_NAME PROJECT_VERSION
)
write_basic_package_version_file(
"${CMAKE_CURRENT_BINARY_DIR}/beman.exemplar-version.cmake"
VERSION ${PROJECT_VERSION}
COMPATIBILITY ExactVersion
)
install(
FILES
"${CMAKE_CURRENT_BINARY_DIR}/subprocess-config.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/subprocess-version.cmake"
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/subprocess"
COMPONENT subprocess
)
install(
EXPORT subprocess
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/beman.exemplar"
NAMESPACE cpp-subprocess::
FILE subprocess-targets.cmake
COMPONENT subprocess
)
endif()
if(SUBPROCESS_TESTS)
include(CTest)
add_subdirectory(test)
endif()
+22
View File
@@ -0,0 +1,22 @@
The library is licensed under the MIT License
<http://opensource.org/licenses/MIT>:
Copyright (c) 2016-2018 Arun Muralidharan
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+152
View File
@@ -0,0 +1,152 @@
## [Subprocessing in C++]
## Design Goals
The only goal was to develop something that is as close as python2.7 subprocess module in dealing with processes.
Could not find anything similar done for C++ and here we are.
This library had these design goals:
- **Intuitive Interface**. Using modern C++ features, made the API usage as simple as that in python in most cases and even better in some (See pipiing example).
- **Correctness**. Dealing with processes is not a simple job. It has many low level details that needs to be taken care of. This library takes care of dealing with those low level details making it easier to launch processes.
- **Error Handling**. Currently the error handling is achieved via the use of exceptions. It is important that no errors are ignored silently. I am working towards achieving this goal, but most of the error conditions have been taken care of.
## Supported Platforms
This library supports MAC OS and Linux.
Support for Windows is limited at this time. Please report any specific use-cases that fail,
and they will be fixed as they are reported.
## Integration
Subprocess library has just a single source `subprocess.hpp` present at the top directory of this repository. All you need to do is add
```cpp
#include "cpp-subprocess/subprocess.hpp"
using namespace subprocess;
// OR
// namespace sp = subprocess;
// Or give any other alias you like.
```
to the files where you want to make use of subprocessing. Make sure to add necessary switches to add C++11 support (-std=c++11 in g++ and clang).
Checkout http://templated-thoughts.blogspot.in/2016/03/sub-processing-with-modern-c.html as well.
## CMake Projects
```cmake
include(FetchContent)
FetchContent_Declare(
cpp-subprocess
GIT_REPOSITORY https://github.com/arun11299/cpp-subprocess.git
GIT_TAG v2.2
)
FetchContent_MakeAvailable(cpp-subprocess)
target_link_libraries(<your_target> PRIVATE cpp-subprocess::subprocess)
```
## Compiler Support
Linux - g++ 4.8 and above
Mac OS - Clang 3.4 and later
Windows - MSVC 2015 and above
## Examples
Here are few examples to show how to get started:
1) Executing simple unix commands
The easy way:
```cpp
auto obuf = check_output({"ls", "-l"});
std::cout << "Data : " << obuf.buf.data() << std::endl;
std::cout << "Data len: " << obuf.length << std::endl;
```
More detailed way:
```cpp
auto p = Popen({"ls", "-l"}, output{PIPE});
auto obuf = p.communicate().first;
std::cout << "Data : " << obuf.buf.data() << std::endl;
std::cout << "Data len: " << obuf.length << std::endl;
```
2) Output redirection
Redirecting a message input to `cat` command to a file.
```cpp
auto p = Popen({"cat", "-"}, input{PIPE}, output{"cat_fredirect.txt"});
auto msg = "through stdin to stdout";
p.send(msg, strlen(msg));
p.wait();
```
OR
```cpp
auto p = Popen({"cat", "-"}, input{PIPE}, output{"cat_fredirect.txt"});
auto msg = "through stdin to stdout";
p.communicate(msg, strlen(msg))
```
OR Reading redirected output from stdout
```cpp
auto p = Popen({"grep", "f"}, output{PIPE}, input{PIPE});
auto msg = "one\ntwo\nthree\nfour\nfive\n";
p.send(msg, strlen(msg));
auto res = p.communicate();
std::cout << res.first.buf.data() << std::endl;
```
3) Piping Support
Your regular unix command piping
Ex: cat subprocess.hpp | grep template | cut -d, -f 1
```cpp
auto cat = Popen({"cat", "../subprocess.hpp"}, output{PIPE});
auto grep = Popen({"grep", "template"}, input{cat.output()}, output{PIPE});
auto cut = Popen({"cut", "-d,", "-f", "1"}, input{grep.output()}, output{PIPE});
auto res = cut.communicate().first;
std::cout << res.buf.data() << std::endl;
```
4) Easy Piping
There is another way to do piping for simple commands like above:
```cpp
auto res = pipeline("cat ../subprocess.hpp", "grep Args", "grep template");
std::cout << res.buf.data() << std::endl;
```
The commands provided to the `pipeline` function is in the order that would have appeared in your regular unix command.
5) Environment variables
For example, if a shell script requires some new environment variables to be defined, you can provide it with the below easy to use syntax.
```cpp
int st= Popen("./env_script.sh", environment{{
{"NEW_ENV1", "VALUE-1"},
{"NEW_ENV2", "VALUE-2"},
{"NEW_ENV3", "VALUE-3"}
}}).wait();
assert (st == 0);
```
5) Other examples
There are lots of other examples in the tests with lot more overloaded API's to support most of the functionalities supported by python2.7.
## License
<img align="right" src="http://opensource.org/trademarks/opensource/OSI-Approved-License-100x137.png">
The class is licensed under the [MIT License](http://opensource.org/licenses/MIT):
Copyright &copy; 2016-2018 [Arun Muralidharan]
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+7
View File
@@ -0,0 +1,7 @@
set(SUBPROCESS_VERSION @PROJECT_VERSION@)
@PACKAGE_INIT@
include(${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@-targets.cmake)
check_required_components(@PROJECT_NAME@)
File diff suppressed because it is too large Load Diff
+35
View File
@@ -0,0 +1,35 @@
set(test_names test_subprocess test_cat test_double_quotes test_env test_err_redirection test_exception test_split test_main test_ret_code)
set(test_files env_script.sh write_err.sh write_err.txt)
foreach(test_name IN LISTS test_names)
add_executable(${test_name} ${test_name}.cc)
target_link_libraries(${test_name} PRIVATE subprocess)
add_test(
NAME ${test_name}
COMMAND $<TARGET_FILE:${test_name}>
)
endforeach()
foreach(test_file IN LISTS test_files)
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/${test_file}
${CMAKE_CURRENT_BINARY_DIR}/${test_file}
COPYONLY
)
endforeach()
set(TEST_REDIRECTION_PYTHON_SCRIPT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/test_redirection.py)
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/test_redirection.cc.in
${CMAKE_CURRENT_BINARY_DIR}/test_redirection.cc
@ONLY
)
add_executable(test_redirection ${CMAKE_CURRENT_BINARY_DIR}/test_redirection.cc)
target_link_libraries(test_redirection PRIVATE subprocess)
add_test(
NAME test_redirection
COMMAND $<TARGET_FILE:test_redirection>
)
+1
View File
@@ -0,0 +1 @@
through stdin to stdout
+5
View File
@@ -0,0 +1,5 @@
#!/bin/bash
echo "ENV1 = ${NEW_ENV1}"
echo "ENV2 = ${NEW_ENV2}"
echo "ENV3 = ${NEW_ENV3}"
BIN
View File
Binary file not shown.
+74
View File
@@ -0,0 +1,74 @@
#include <iostream>
#include <cpp-subprocess/subprocess.hpp>
namespace sp = subprocess;
void test_cat_pipe_redirection()
{
std::cout << "Test::test_cat_pipe_redirection" << std::endl;
auto p = sp::Popen({"cat", "-"}, sp::input{sp::PIPE}, sp::output{sp::PIPE});
auto msg = "through stdin to stdout";
auto res_buf = p.communicate(msg, strlen(msg)).first;
assert(res_buf.length == strlen(msg));
std::cout << "END_TEST" << std::endl;
}
void test_cat_file_redirection()
{
std::cout << "Test::test_cat_file_redirection" << std::endl;
auto p = sp::Popen({"cat", "-"}, sp::input{sp::PIPE}, sp::output{"cat_fredirect.txt"});
auto msg = "through stdin to stdout";
int wr_bytes = p.send(msg, strlen(msg));
assert (wr_bytes == (int)strlen(msg));
std::cout << "END_TEST" << std::endl;
}
void test_cat_send_terminate()
{
std::cout << "Test::test_cat_send_terminate" << std::endl;
std::vector<sp::Popen> pops;
for (int i=0; i < 5; i++) {
pops.emplace_back(sp::Popen({"cat", "-"}, sp::input{sp::PIPE}));
pops[i].send("3 5\n", 5);
pops[i].close_input();
}
for (int i=0; i < 5; i++) {
pops[i].wait();
}
std::cout << "END_TEST" << std::endl;
}
void test_buffer_growth()
{
auto obuf = sp::check_output({"cat", "../subprocess.hpp"});
std::cout << obuf.length << std::endl;
assert (obuf.length > sp::DEFAULT_BUF_CAP_BYTES);
}
void test_buffer_growth_threaded_comm()
{
std::cout << "Test::test_buffer_growth_threaded_comm" << std::endl;
auto buf = sp::check_output("cat ../subprocess.hpp", sp::error{sp::PIPE});
std::cout << buf.length << std::endl;
assert (buf.length > sp::DEFAULT_BUF_CAP_BYTES);
std::cout << "END_TEST" << std::endl;
}
int main() {
#ifndef __USING_WINDOWS__
// test_cat_pipe_redirection();
test_cat_send_terminate();
/*
test_cat_file_redirection();
test_buffer_growth();
test_buffer_growth_threaded_comm();
*/
#endif
return 0;
}
+30
View File
@@ -0,0 +1,30 @@
#include <cpp-subprocess/subprocess.hpp>
#include <cassert>
#include <string>
namespace sp = subprocess;
// JSON requires the use of double quotes (see: https://json.org/).
// This test verifies proper handling of them.
void test_double_quotes()
{
// A simple JSON object.
const std::string expected{"{\"name\": \"value\"}"};
#ifdef __USING_WINDOWS__
const std::string command{"cmd.exe /c echo "};
#else
const std::string command{"echo "};
#endif
auto p = sp::Popen(command + expected, sp::output{sp::PIPE});
const auto out = p.communicate().first;
std::string result{out.buf.begin(), out.buf.end()};
// The `echo` command appends a newline.
result.erase(result.find_last_not_of(" \n\r\t") + 1);
assert(result == expected);
}
int main() {
test_double_quotes();
return 0;
}
+25
View File
@@ -0,0 +1,25 @@
#include <iostream>
#include <cpp-subprocess/subprocess.hpp>
using namespace subprocess;
#ifndef __USING_WINDOWS__
void test_env()
{
int st= Popen("./env_script.sh", environment{{
{"NEW_ENV1", "VALUE-1"},
{"NEW_ENV2", "VALUE-2"},
{"NEW_ENV3", "VALUE-3"}
}}).wait();
assert (st == 0);
}
#endif
int main() {
#ifndef __USING_WINDOWS__
test_env();
#endif
return 0;
}
+18
View File
@@ -0,0 +1,18 @@
#include <iostream>
#include <cpp-subprocess/subprocess.hpp>
using namespace subprocess;
void test_redirect()
{
auto p = Popen("./write_err.sh", output{"write_err.txt"}, error{STDOUT});
std::cout << p.poll() << std::endl;
}
int main() {
#ifndef __USING_WINDOWS__
test_redirect();
#endif
return 0;
}
+27
View File
@@ -0,0 +1,27 @@
#include <cassert>
#include <cstring>
#include <cpp-subprocess/subprocess.hpp>
namespace sp = subprocess;
void test_exception()
{
bool caught = false;
try {
auto p = sp::Popen("invalid_command");
assert(false); // Expected to throw
} catch (sp::CalledProcessError& e) {
#ifdef __USING_WINDOWS__
assert(std::strstr(e.what(), "CreateProcess failed: The system cannot find the file specified."));
#else
assert(std::strstr(e.what(), "execve failed: No such file or directory"));
#endif
caught = true;
}
assert(caught);
}
int main() {
test_exception();
return 0;
}
+42
View File
@@ -0,0 +1,42 @@
#include <iostream>
#include <utility>
struct bufsize { int siz_; };
struct executable { std::string exe_; };
class Ex {
public:
template <typename... Args>
Ex(Args&&... args) {
set_options(std::forward<Args>(args)...);
}
template <typename T>
void set_options(T&& arg) {
set_option(std::forward<T>(arg));
}
template <typename T, typename... Args>
void set_options(T&& first, Args&&... rem_args) {
set_option(std::forward<T>(first));
set_options(std::forward<Args>(rem_args)...);
}
void set_option(bufsize&& bufs) {
std::cout << "bufsize opt" << std::endl;
bufsiz_ = bufs.siz_;
}
void set_option(executable&& exe) {
std::cout << "exe opt" << std::endl;
exe_name_ = std::move(exe.exe_);
}
private:
int bufsiz_ = 0;
std::string exe_name_;
};
int main() {
Ex e(bufsize{1}, executable{"finger"});
return 0;
}
+23
View File
@@ -0,0 +1,23 @@
#include <cpp-subprocess/subprocess.hpp>
#include <cstdlib>
#include <string>
#include <tuple>
using namespace subprocess;
int main() {
auto p = Popen("python3 @TEST_REDIRECTION_PYTHON_SCRIPT_PATH@", output{PIPE}, error{PIPE});
OutBuffer out_buf;
ErrBuffer err_buf;
std::tie(out_buf, err_buf) = p.communicate();
std::string out{out_buf.buf.data()};
std::string err{err_buf.buf.data()};
if (out.find("Hello message.") == std::string::npos) return EXIT_FAILURE;
if (err.find("Hello message.") != std::string::npos) return EXIT_FAILURE;
if (out.find("Error report.") != std::string::npos) return EXIT_FAILURE;
if (err.find("Error report.") == std::string::npos) return EXIT_FAILURE;
return EXIT_SUCCESS;
}
+7
View File
@@ -0,0 +1,7 @@
#!/usr/bin/env python3
import sys
if __name__ == "__main__":
print("Hello message.")
print("Error report.", file=sys.stderr)
+59
View File
@@ -0,0 +1,59 @@
#include <iostream>
#include <cpp-subprocess/subprocess.hpp>
namespace sp = subprocess;
void test_ret_code()
{
std::cout << "Test::test_poll_ret_code" << std::endl;
#ifdef __USING_WINDOWS__
auto p = sp::Popen({"cmd.exe", "/c", "exit", "1"});
#else
auto p = sp::Popen({"/usr/bin/false"});
#endif
while (p.poll() == -1) {
#ifdef __USING_WINDOWS__
Sleep(100);
#else
usleep(1000 * 100);
#endif
}
assert (p.retcode() == 1);
}
void test_ret_code_comm()
{
using namespace sp;
auto cat = Popen({"cat", "../subprocess.hpp"}, output{PIPE});
auto grep = Popen({"grep", "template"}, input{cat.output()}, output{PIPE});
auto cut = Popen({"cut", "-d,", "-f", "1"}, input{grep.output()}, output{PIPE});
auto res = cut.communicate().first;
std::cout << res.buf.data() << std::endl;
std::cout << "retcode: " << cut.retcode() << std::endl;
}
void test_ret_code_check_output()
{
using namespace sp;
bool caught = false;
try {
auto obuf = check_output({"/bin/false"}, shell{false});
assert(false); // Expected to throw
} catch (CalledProcessError &e) {
std::cout << "retcode: " << e.retcode << std::endl;
assert (e.retcode == 1);
caught = true;
}
assert(caught);
}
int main() {
test_ret_code();
#ifndef __USING_WINDOWS__
test_ret_code_comm();
test_ret_code_check_output();
#endif
return 0;
}
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleIdentifier</key>
<string>com.apple.xcode.dsym.test_ret_code</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>dSYM</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>
+42
View File
@@ -0,0 +1,42 @@
#include <iostream>
#include <string>
#include <vector>
std::vector<std::string>
split(const std::string& str, const std::string& delims=" \t")
{
std::vector<std::string> res;
size_t init = 0;
while (true) {
auto pos = str.find_first_of(delims, init);
if (pos == std::string::npos) {
res.emplace_back(str.substr(init, str.length()));
break;
}
res.emplace_back(str.substr(init, pos - init));
pos++;
init = pos;
}
return res;
}
std::string join(const std::vector<std::string>& vec)
{
std::string res;
for (auto& elem : vec) {
res.append(elem + " ");
}
res.erase(--res.end());
return res;
}
int main() {
auto vec = split ("a b c");
for (auto elem : vec) { std::cout << elem << std::endl; }
std::cout << join(vec).length() << std::endl;
return 0;
}
+99
View File
@@ -0,0 +1,99 @@
#include <iostream>
#include <cpp-subprocess/subprocess.hpp>
using namespace subprocess;
void test_exename()
{
#ifdef __USING_WINDOWS__
auto ret = call({"--version"}, executable{"cmake"}, shell{false});
#else
auto ret = call({"-l"}, executable{"ls"}, shell{false});
#endif
std::cout << ret << std::endl;
}
void test_input()
{
auto p = Popen({"grep", "f"}, output{PIPE}, input{PIPE});
const char* msg = "one\ntwo\nthree\nfour\nfive\n";
p.send(msg, strlen(msg));
auto res = p.communicate(nullptr, 0);
std::cout << res.first.buf.data() << std::endl;
}
void test_piping()
{
auto cat = Popen({"cat", "../subprocess.hpp"}, output{PIPE});
auto grep = Popen({"grep", "template"}, input{cat.output()}, output{PIPE});
auto cut = Popen({"cut", "-d,", "-f", "1"}, input{grep.output()}, output{PIPE});
auto res = cut.communicate().first;
std::cout << res.buf.data() << std::endl;
}
void test_easy_piping()
{
auto res = pipeline("cat ../subprocess.hpp", "grep Args", "grep template");
std::cout << res.buf.data() << std::endl;
}
void test_shell()
{
#ifdef __USING_WINDOWS__
auto obuf = check_output({"cmake", "--version"}, shell{false});
#else
auto obuf = check_output({"ls", "-l"}, shell{false});
#endif
std::cout << obuf.buf.data() << std::endl;
}
void test_sleep()
{
auto p = Popen({"sleep", "30"}, shell{true});
while (p.poll() == -1)
{
std::cout << "Waiting..." << std::endl;
#ifdef __USING_WINDOWS__
#else
sleep(1);
#endif
}
std::cout << "Sleep ended: ret code = " << p.retcode() << std::endl;
}
void test_read_all()
{
Popen p = Popen({"echo", "12345678"}, output{PIPE});
std::vector<char> buf(6);
int rbytes = util::read_all(p.output(), buf);
std::string out(buf.begin(), buf.end());
assert(out == "12345678\n" && rbytes == 9); // echo puts a new line at the end of output
std::cout << "read_all() succeeded" << std::endl;
}
void test_simple_cmd()
{
auto p = Popen({"ls", "-l"}, output{PIPE});
auto obuf = p.communicate().first;
std::cout << "Data : " << obuf.buf.data() << std::endl;
std::cout << "Data len: " << obuf.length << std::endl;
}
int main() {
/*
test_exename();
test_input();
test_piping();
test_easy_piping();
test_shell();
test_sleep();
test_read_all();
*/
test_simple_cmd();
return 0;
}
+2
View File
@@ -0,0 +1,2 @@
#!/bin/bash
>&2 echo "This is going to be a big chunk of error text consisting of garbage words that would never make sense....so here it goes....shouldnt I be doing my work instead ???? ...anyways....lets get to it......dsmvnskmnv;lsdnv;la,mdfv;, lasdnvs, dv;lknvlka;dv laldmflasmdlgvma lm glfdmg lasfgl;mflgms,vdmlmsdfl'bmsldfkmblsdfm blksdfmblk fsdl,b sdlfnbksan kjskanfkjbhv snf p'owMF;OANDOPGIHWEPO;JFOIEHGUYHT JNTG JWEBGIJN FV SDKMNV KJNKJ nokfnrgok weoirgoinfs ijbzx,mv;lksdcnvpisfuhgu wnergorgok nvglk;bn;mkf bkngfkbm fdlb;gfnb ;kdfgn b,mfdl's,g'l;am nsgaosnblm;adrg;lnklf nglkfmnvklb njfknblsmdnkfngsjdfbgsjdbghjb iblnrfgiof n gjsndv vewflkjvekrjgnlkmv mjbeijdfnwek vkijnnfg'koqrnbon nq'eopkfm[qef[lfkdnb ;smknv jk fnkmv ntipjvn kbvn iprtu ghj9p84w5toihnvlkmnlmk nvoijh90rjqo3mrok34 nfkm nnkof nerokmnrgo[j0igjwlkngvmfgnvml oirejgoiewjrfgoiwejrgko[ mwbkm grioejqg[ktrwngk;wnmb;mn;wfkb oirjgiontrgmnwe;fklvnfiobjneiorgn;mbn ijorgenowg;lwbenkownfboiwnrtgiovwnrtblntbontriobnwkrn; onboirw noignjwmKFCV;MKNSDVIUNRIPTN5I KNVK;JN ION EOQWNQ;LDKN V;FMNVKFN[B WPORJGOP[ WLERGNA;SLDKNV;MF NPOINRG;JWN;KNRPEFGI9485JBEKMSD NK;NKL; NFOSAJFKOSNKMN;CV, KAD;FKM;SOGMVLKSMD;,R F;OKA;FL APSLFM ADL;SKOK OKNEW KDJFOKSDJ Alpwpowejgoplwefkmglk p[reg porej gokwem vkl wmo ao[jk [klqmpkoem gpofem lksjn zflkvbn;kf hgioniog krngkmadnv;mfsdn bkleqrjl;wgnpoekw jqbfk mv;lm,redop[ jor[f klqr3ko[j vioadm ;lksdcmn ovj['or'aewnjkopj 'wk;w;k fwrite_err.sh sadkjlbnlfkblfkn blndsf kjwern gfpjknerkgn fknv k;qkgn kfv mscvlkmsn ldkfv nkamdkmv efkgv n;kemf mvwfbkm nfgkmbk bklwnmgklwmtrklgnfkl;b nwkjn glkwmfn lkmnrknwrkpg nkf nlmk nwljkengjklnwflgbnflkjbngkljwfgbn jnk wngpkwrtgnpo n"
+5
View File
@@ -0,0 +1,5 @@
writing error to stderr
This is going to be a big chunk of error text consisting of garbage words that would never make sense....so here it goes....shouldnt I be doing my work instead ???? ...anyways....lets get to it......dsmvnskmnv;lsdnv;la,mdfv;, lasdnvs, dv;lknvlka;dv laldmflasmdlgvma lm glfdmg lasfgl;mflgms,vdmlmsdfl'bmsldfkmblsdfm blksdfmblk fsdl,b sdlfnbksan kjskanfkjbhv snf p'owMF;OANDOPGIHWEPO;JFOIEHGUYHT JNTG JWEBGIJN FV SDKMNV KJNKJ nokfnrgok weoirgoinfs ijbzx,mv;lksdcnvpisfuhgu wnergorgok nvglk;bn;mkf bkngfkbm fdlb;gfnb ;kdfgn b,mfdl's,g'l;am nsgaosnblm;adrg;lnklf nglkfmnvklb njfknblsmdnkfngsjdfbgsjdbghjb iblnrfgiof n gjsndv vewflkjvekrjgnlkmv mjbeijdfnwek vkijnnfg'koqrnbon nq'eopkfm[qef[lfkdnb ;smknv jk fnkmv ntipjvn kbvn iprtu ghj9p84w5toihnvlkmnlmk nvoijh90rjqo3mrok34 nfkm nnkof nerokmnrgo[j0igjwlkngvmfgnvml oirejgoiewjrfgoiwejrgko[ mwbkm grioejqg[ktrwngk;wnmb;mn;wfkb oirjgiontrgmnwe;fklvnfiobjneiorgn;mbn ijorgenowg;lwbenkownfboiwnrtgiovwnrtblntbontriobnwkrn; onboirw noignjwmKFCV;MKNSDVIUNRIPTN5I KNVK;JN ION EOQWNQ;LDKN V;FMNVKFN[B WPORJGOP[ WLERGNA;SLDKNV;MF NPOINRG;JWN;KNRPEFGI9485JBEKMSD NK;NKL; NFOSAJFKOSNKMN;CV, KAD;FKM;SOGMVLKSMD;,R F;OKA;FL APSLFM ADL;SKOK OKNEW KDJFOKSDJ Alpwpowejgoplwefkmglk p[reg porej gokwem vkl wmo ao[jk [klqmpkoem gpofem lksjn zflkvbn;kf hgioniog krngkmadnv;mfsdn bkleqrjl;wgnpoekw jqbfk mv;lm,redop[ jor[f klqr3ko[j vioadm ;lksdcmn ovj['or'aewnjkopj 'wk;w;k fwrite_err.sh sadkjlbnlfkblfkn blndsf kjwern gfpjknerkgn fknv k;qkgn kfv mscvlkmsn ldkfv nkamdkmv efkgv n;kemf mvwfbkm nfgkmbk bklwnmgklwmtrklgnfkl;b nwkjn glkwmfn lkmnrknwrkpg nkf nlmk nwljkengjklnwflgbnflkjbngkljwfgbn jnk wngpkwrtgnpo n
This is going to be a big chunk of error text consisting of garbage words that would never make sense....so here it goes....shouldnt I be doing my work instead ???? ...anyways....lets get to it......dsmvnskmnv;lsdnv;la,mdfv;, lasdnvs, dv;lknvlka;dv laldmflasmdlgvma lm glfdmg lasfgl;mflgms,vdmlmsdfl'bmsldfkmblsdfm blksdfmblk fsdl,b sdlfnbksan kjskanfkjbhv snf p'owMF;OANDOPGIHWEPO;JFOIEHGUYHT JNTG JWEBGIJN FV SDKMNV KJNKJ nokfnrgok weoirgoinfs ijbzx,mv;lksdcnvpisfuhgu wnergorgok nvglk;bn;mkf bkngfkbm fdlb;gfnb ;kdfgn b,mfdl's,g'l;am nsgaosnblm;adrg;lnklf nglkfmnvklb njfknblsmdnkfngsjdfbgsjdbghjb iblnrfgiof n gjsndv vewflkjvekrjgnlkmv mjbeijdfnwek vkijnnfg'koqrnbon nq'eopkfm[qef[lfkdnb ;smknv jk fnkmv ntipjvn kbvn iprtu ghj9p84w5toihnvlkmnlmk nvoijh90rjqo3mrok34 nfkm nnkof nerokmnrgo[j0igjwlkngvmfgnvml oirejgoiewjrfgoiwejrgko[ mwbkm grioejqg[ktrwngk;wnmb;mn;wfkb oirjgiontrgmnwe;fklvnfiobjneiorgn;mbn ijorgenowg;lwbenkownfboiwnrtgiovwnrtblntbontriobnwkrn; onboirw noignjwmKFCV;MKNSDVIUNRIPTN5I KNVK;JN ION EOQWNQ;LDKN V;FMNVKFN[B WPORJGOP[ WLERGNA;SLDKNV;MF NPOINRG;JWN;KNRPEFGI9485JBEKMSD NK;NKL; NFOSAJFKOSNKMN;CV, KAD;FKM;SOGMVLKSMD;,R F;OKA;FL APSLFM ADL;SKOK OKNEW KDJFOKSDJ Alpwpowejgoplwefkmglk p[reg porej gokwem vkl wmo ao[jk [klqmpkoem gpofem lksjn zflkvbn;kf hgioniog krngkmadnv;mfsdn bkleqrjl;wgnpoekw jqbfk mv;lm,redop[ jor[f klqr3ko[j vioadm ;lksdcmn ovj['or'aewnjkopj 'wk;w;k fwrite_err.sh sadkjlbnlfkblfkn blndsf kjwern gfpjknerkgn fknv k;qkgn kfv mscvlkmsn ldkfv nkamdkmv efkgv n;kemf mvwfbkm nfgkmbk bklwnmgklwmtrklgnfkl;b nwkjn glkwmfn lkmnrknwrkpg nkf nlmk nwljkengjklnwflgbnflkjbngkljwfgbn jnk wngpkwrtgnpo n
This is going to be a big chunk of error text consisting of garbage words that would never make sense....so here it goes....shouldnt I be doing my work instead ???? ...anyways....lets get to it......dsmvnskmnv;lsdnv;la,mdfv;, lasdnvs, dv;lknvlka;dv laldmflasmdlgvma lm glfdmg lasfgl;mflgms,vdmlmsdfl'bmsldfkmblsdfm blksdfmblk fsdl,b sdlfnbksan kjskanfkjbhv snf p'owMF;OANDOPGIHWEPO;JFOIEHGUYHT JNTG JWEBGIJN FV SDKMNV KJNKJ nokfnrgok weoirgoinfs ijbzx,mv;lksdcnvpisfuhgu wnergorgok nvglk;bn;mkf bkngfkbm fdlb;gfnb ;kdfgn b,mfdl's,g'l;am nsgaosnblm;adrg;lnklf nglkfmnvklb njfknblsmdnkfngsjdfbgsjdbghjb iblnrfgiof n gjsndv vewflkjvekrjgnlkmv mjbeijdfnwek vkijnnfg'koqrnbon nq'eopkfm[qef[lfkdnb ;smknv jk fnkmv ntipjvn kbvn iprtu ghj9p84w5toihnvlkmnlmk nvoijh90rjqo3mrok34 nfkm nnkof nerokmnrgo[j0igjwlkngvmfgnvml oirejgoiewjrfgoiwejrgko[ mwbkm grioejqg[ktrwngk;wnmb;mn;wfkb oirjgiontrgmnwe;fklvnfiobjneiorgn;mbn ijorgenowg;lwbenkownfboiwnrtgiovwnrtblntbontriobnwkrn; onboirw noignjwmKFCV;MKNSDVIUNRIPTN5I KNVK;JN ION EOQWNQ;LDKN V;FMNVKFN[B WPORJGOP[ WLERGNA;SLDKNV;MF NPOINRG;JWN;KNRPEFGI9485JBEKMSD NK;NKL; NFOSAJFKOSNKMN;CV, KAD;FKM;SOGMVLKSMD;,R F;OKA;FL APSLFM ADL;SKOK OKNEW KDJFOKSDJ Alpwpowejgoplwefkmglk p[reg porej gokwem vkl wmo ao[jk [klqmpkoem gpofem lksjn zflkvbn;kf hgioniog krngkmadnv;mfsdn bkleqrjl;wgnpoekw jqbfk mv;lm,redop[ jor[f klqr3ko[j vioadm ;lksdcmn ovj['or'aewnjkopj 'wk;w;k fwrite_err.sh sadkjlbnlfkblfkn blndsf kjwern gfpjknerkgn fknv k;qkgn kfv mscvlkmsn ldkfv nkamdkmv efkgv n;kemf mvwfbkm nfgkmbk bklwnmgklwmtrklgnfkl;b nwkjn glkwmfn lkmnrknwrkpg nkf nlmk nwljkengjklnwflgbnflkjbngkljwfgbn jnk wngpkwrtgnpo n
This is going to be a big chunk of error text consisting of garbage words that would never make sense....so here it goes....shouldnt I be doing my work instead ???? ...anyways....lets get to it......dsmvnskmnv;lsdnv;la,mdfv;, lasdnvs, dv;lknvlka;dv laldmflasmdlgvma lm glfdmg lasfgl;mflgms,vdmlmsdfl'bmsldfkmblsdfm blksdfmblk fsdl,b sdlfnbksan kjskanfkjbhv snf p'owMF;OANDOPGIHWEPO;JFOIEHGUYHT JNTG JWEBGIJN FV SDKMNV KJNKJ nokfnrgok weoirgoinfs ijbzx,mv;lksdcnvpisfuhgu wnergorgok nvglk;bn;mkf bkngfkbm fdlb;gfnb ;kdfgn b,mfdl's,g'l;am nsgaosnblm;adrg;lnklf nglkfmnvklb njfknblsmdnkfngsjdfbgsjdbghjb iblnrfgiof n gjsndv vewflkjvekrjgnlkmv mjbeijdfnwek vkijnnfg'koqrnbon nq'eopkfm[qef[lfkdnb ;smknv jk fnkmv ntipjvn kbvn iprtu ghj9p84w5toihnvlkmnlmk nvoijh90rjqo3mrok34 nfkm nnkof nerokmnrgo[j0igjwlkngvmfgnvml oirejgoiewjrfgoiwejrgko[ mwbkm grioejqg[ktrwngk;wnmb;mn;wfkb oirjgiontrgmnwe;fklvnfiobjneiorgn;mbn ijorgenowg;lwbenkownfboiwnrtgiovwnrtblntbontriobnwkrn; onboirw noignjwmKFCV;MKNSDVIUNRIPTN5I KNVK;JN ION EOQWNQ;LDKN V;FMNVKFN[B WPORJGOP[ WLERGNA;SLDKNV;MF NPOINRG;JWN;KNRPEFGI9485JBEKMSD NK;NKL; NFOSAJFKOSNKMN;CV, KAD;FKM;SOGMVLKSMD;,R F;OKA;FL APSLFM ADL;SKOK OKNEW KDJFOKSDJ Alpwpowejgoplwefkmglk p[reg porej gokwem vkl wmo ao[jk [klqmpkoem gpofem lksjn zflkvbn;kf hgioniog krngkmadnv;mfsdn bkleqrjl;wgnpoekw jqbfk mv;lm,redop[ jor[f klqr3ko[j vioadm ;lksdcmn ovj['or'aewnjkopj 'wk;w;k fwrite_err.sh sadkjlbnlfkblfkn blndsf kjwern gfpjknerkgn fknv k;qkgn kfv mscvlkmsn ldkfv nkamdkmv efkgv n;kemf mvwfbkm nfgkmbk bklwnmgklwmtrklgnfkl;b nwkjn glkwmfn lkmnrknwrkpg nkf nlmk nwljkengjklnwflgbnflkjbngkljwfgbn jnk wngpkwrtgnpo n