Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:50:13

0001 // Copyright (c) 2022 Klemens D. Morgenstern
0002 //
0003 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0004 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0005 #ifndef BOOST_PROCESS_V2_SHELL_HPP
0006 #define BOOST_PROCESS_V2_SHELL_HPP
0007 
0008 #include <boost/core/exchange.hpp>
0009 #include <boost/process/v2/cstring_ref.hpp>
0010 #include <boost/process/v2/detail/config.hpp>
0011 #include <boost/process/v2/detail/utf8.hpp>
0012 #include <boost/process/v2/detail/throw_error.hpp>
0013 #include <boost/process/v2/environment.hpp>
0014 #include <memory>
0015 #include <string>
0016 
0017 BOOST_PROCESS_V2_BEGIN_NAMESPACE
0018 
0019 /// Error category used by the shell parser.
0020 extern BOOST_PROCESS_V2_DECL const error_category& get_shell_category();
0021 static const error_category& shell_category = get_shell_category();
0022 
0023 /// Utility to parse commands 
0024 /** This utility class parses command lines into tokens
0025  * and allows users to executed based on textual inputs.
0026  * 
0027  * In v1, this was possible directly when starting a process,
0028  * but has been removed based on the security risks associated with this.
0029  * 
0030  * By making the shell parsing explicitly, it encourages
0031  * a user to run a sanity check on the executable before launching it.
0032  * 
0033  * @par Example
0034  * @code {.cpp}
0035  * asio::io_context ctx;
0036  * 
0037  * auto cmd = shell("my-app --help");
0038  * auto exe = cmd.exe();
0039  * check_if_malicious(exe);
0040  * 
0041  * process proc{ctx, exe, cmd.args()};
0042  * 
0043  * @endcode
0044  * 
0045  * 
0046  */
0047 struct shell
0048 {    
0049 #if defined(BOOST_PROCESS_V2_WINDOWS)
0050     using char_type = wchar_t; 
0051     using args_type = const wchar_t *;
0052 #else
0053     using char_type = char;
0054     using args_type = const char **;
0055 #endif
0056 
0057     shell() = default;
0058 
0059     template<typename Char, typename Traits>
0060     shell(basic_string_view<Char, Traits> input) 
0061         : buffer_(detail::conv_string<char_type>(input.data(), input.size())) 
0062     {
0063         parse_();
0064     }
0065 
0066     shell(basic_cstring_ref<char_type> input) : input_(input) {parse_();}
0067     shell(basic_string_view<
0068                     typename std::conditional<
0069                         std::is_same<char_type, char>::value,
0070                         wchar_t, char>::type> input) : buffer_(detail::conv_string<char_type>(input.data(), input.size())) 
0071     {
0072         parse_();
0073     }
0074 
0075     shell(const shell &) = delete;
0076     shell& operator=(const shell &) = delete;
0077 
0078     shell(shell && lhs) noexcept 
0079         : buffer_(std::move(lhs.buffer_)),
0080           input_(std::move(lhs.input_)),
0081           argc_(boost::exchange(lhs.argc_, 0)),
0082           argv_(boost::exchange(lhs.argv_, nullptr))
0083 #if defined(BOOST_PROCESS_V2_POSIX)
0084         , free_argv_(boost::exchange(lhs.free_argv_, nullptr))
0085 #endif
0086     {
0087     }
0088     shell& operator=(shell && lhs) noexcept
0089     {
0090         shell tmp(std::move(*this));
0091         buffer_ = std::move(lhs.buffer_);
0092         input_ = std::move(lhs.input_);
0093         argc_  = boost::exchange(lhs.argc_, 0);
0094         argv_ = boost::exchange(lhs.argv_, nullptr);
0095 #if defined(BOOST_PROCESS_V2_POSIX)
0096         free_argv_ = boost::exchange(lhs.free_argv_, nullptr);
0097 #endif
0098         return *this;
0099     }
0100 
0101     // the length of the parsed shell, including the executable
0102     int argc() const { return argc_; }
0103     char_type** argv() const { return argv_; }
0104         
0105     char_type** begin() const {return argv();}
0106     char_type** end()   const {return argv() + argc();}
0107 
0108     bool empty() const {return argc() == 0;}
0109     std::size_t size() const {return static_cast<std::size_t>(argc()); }
0110     /// Native representation of the arguments to be used - excluding the executable
0111     BOOST_PROCESS_V2_DECL args_type args() const;
0112     template<typename Environment = environment::current_view>
0113     filesystem::path exe(Environment && env = environment::current()) const
0114     {
0115         if (argc() == 0)
0116             return "";
0117         else
0118             return environment::find_executable(0[argv()], std::forward<Environment>(env)); 
0119     }
0120     BOOST_PROCESS_V2_DECL ~shell();
0121 
0122   private:
0123 
0124     friend struct make_cmd_shell_;
0125 
0126     BOOST_PROCESS_V2_DECL void parse_();
0127     
0128     // storage in case we need a conversion
0129     std::basic_string<char_type> buffer_;
0130     basic_cstring_ref<char_type> input_{buffer_}; 
0131     // impl details
0132     int argc_ = 0;
0133     char_type  ** argv_ = nullptr;
0134 
0135 #if defined(BOOST_PROCESS_V2_POSIX)
0136     void(*free_argv_)(int, char **);
0137 #endif
0138     
0139 };
0140 
0141 BOOST_PROCESS_V2_END_NAMESPACE
0142 
0143 #if defined(BOOST_PROCESS_V2_HEADER_ONLY)
0144 
0145 #include <boost/process/v2/impl/shell.ipp>
0146 
0147 #endif
0148 
0149 #endif //BOOST_PROCESS_V2_ERROR_HPP