整理
This commit is contained in:
143
include/boost/process/v2/shell.hpp
Normal file
143
include/boost/process/v2/shell.hpp
Normal file
@@ -0,0 +1,143 @@
|
||||
// Copyright (c) 2022 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_V2_SHELL_HPP
|
||||
#define BOOST_PROCESS_V2_SHELL_HPP
|
||||
|
||||
#include <boost/core/exchange.hpp>
|
||||
#include <boost/process/v2/cstring_ref.hpp>
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
#include <boost/process/v2/detail/utf8.hpp>
|
||||
#include <boost/process/v2/detail/throw_error.hpp>
|
||||
#include <boost/process/v2/environment.hpp>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
|
||||
/// Error category used by the shell parser.
|
||||
extern BOOST_PROCESS_V2_DECL const error_category& get_shell_category();
|
||||
static const error_category& shell_category = get_shell_category();
|
||||
|
||||
/// Utility to parse commands
|
||||
/** This utility class parses command lines into tokens
|
||||
* and allows users to executed based on textual inputs.
|
||||
*
|
||||
* In v1, this was possible directly when starting a process,
|
||||
* but has been removed based on the security risks associated with this.
|
||||
*
|
||||
* By making the shell parsing explicitly, it encourages
|
||||
* a user to run a sanity check on the executable before launching it.
|
||||
*
|
||||
* @par Example
|
||||
* @code {.cpp}
|
||||
* asio::io_context ctx;
|
||||
*
|
||||
* auto cmd = shell("my-app --help");
|
||||
* auto exe = cmd.exe();
|
||||
* check_if_malicious(exe);
|
||||
*
|
||||
* process proc{ctx, exe, cmd.args()};
|
||||
*
|
||||
* @endcode
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct shell
|
||||
{
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
using char_type = wchar_t;
|
||||
using args_type = const wchar_t *;
|
||||
#else
|
||||
using char_type = char;
|
||||
using args_type = const char **;
|
||||
#endif
|
||||
|
||||
shell() = default;
|
||||
|
||||
template<typename Char, typename Traits>
|
||||
shell(basic_string_view<Char, Traits> input)
|
||||
: buffer_(detail::conv_string<char_type>(input.data(), input.size()))
|
||||
{
|
||||
parse_();
|
||||
}
|
||||
|
||||
shell(basic_cstring_ref<char_type> input) : input_(input) {parse_();}
|
||||
shell(basic_string_view<
|
||||
typename std::conditional<
|
||||
std::is_same<char_type, char>::value,
|
||||
wchar_t, char>::type> input) : buffer_(detail::conv_string<char_type>(input.data(), input.size()))
|
||||
{
|
||||
parse_();
|
||||
}
|
||||
|
||||
shell(const shell &) = delete;
|
||||
shell& operator=(const shell &) = delete;
|
||||
|
||||
shell(shell && lhs) noexcept
|
||||
: buffer_(std::move(lhs.buffer_)),
|
||||
input_(std::move(lhs.input_)),
|
||||
argc_(boost::exchange(lhs.argc_, 0)),
|
||||
argv_(boost::exchange(lhs.argv_, nullptr))
|
||||
#if defined(BOOST_PROCESS_V2_POSIX)
|
||||
, free_argv_(boost::exchange(lhs.free_argv_, nullptr))
|
||||
#endif
|
||||
{
|
||||
}
|
||||
shell& operator=(shell && lhs) noexcept
|
||||
{
|
||||
shell tmp(std::move(*this));
|
||||
buffer_ = std::move(lhs.buffer_);
|
||||
input_ = std::move(lhs.input_);
|
||||
argc_ = boost::exchange(lhs.argc_, 0);
|
||||
argv_ = boost::exchange(lhs.argv_, nullptr);
|
||||
#if defined(BOOST_PROCESS_V2_POSIX)
|
||||
free_argv_ = boost::exchange(lhs.free_argv_, nullptr);
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
// the length of the parsed shell, including the executable
|
||||
int argc() const { return argc_; }
|
||||
char_type** argv() const { return argv_; }
|
||||
|
||||
char_type** begin() const {return argv();}
|
||||
char_type** end() const {return argv() + argc();}
|
||||
|
||||
bool empty() const {return argc() == 0;}
|
||||
std::size_t size() const {return static_cast<std::size_t>(argc()); }
|
||||
/// Native representation of the arguments to be used - excluding the executable
|
||||
BOOST_PROCESS_V2_DECL args_type args() const;
|
||||
template<typename Environment = environment::current_view>
|
||||
filesystem::path exe(Environment && env = environment::current()) const
|
||||
{
|
||||
if (argc() == 0)
|
||||
return "";
|
||||
else
|
||||
return environment::find_executable(0[argv()], std::forward<Environment>(env));
|
||||
}
|
||||
BOOST_PROCESS_V2_DECL ~shell();
|
||||
|
||||
private:
|
||||
|
||||
friend struct make_cmd_shell_;
|
||||
|
||||
BOOST_PROCESS_V2_DECL void parse_();
|
||||
|
||||
// storage in case we need a conversion
|
||||
std::basic_string<char_type> buffer_;
|
||||
basic_cstring_ref<char_type> input_{buffer_};
|
||||
// impl details
|
||||
int argc_ = 0;
|
||||
char_type ** argv_ = nullptr;
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_POSIX)
|
||||
void(*free_argv_)(int, char **);
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
#endif //BOOST_PROCESS_V2_ERROR_HPP
|
||||
Reference in New Issue
Block a user