Back to home page

EIC code displayed by LXR

 
 

    


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

0001 // Copyright (c) 2016 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 
0006 
0007 #ifndef BOOST_PROCESS_DETAIL_POSIX_BASIC_CMD_HPP_
0008 #define BOOST_PROCESS_DETAIL_POSIX_BASIC_CMD_HPP_
0009 
0010 #include <boost/process/detail/posix/handler.hpp>
0011 #include <boost/process/detail/posix/cmd.hpp>
0012 #include <boost/algorithm/string/replace.hpp>
0013 #include <boost/process/shell.hpp>
0014 #include <boost/algorithm/string/trim.hpp>
0015 #include <boost/algorithm/string/join.hpp>
0016 #include <string>
0017 #include <vector>
0018 
0019 namespace boost
0020 {
0021 namespace process
0022 {
0023 namespace detail
0024 {
0025 namespace posix
0026 {
0027 
0028 
0029 inline std::string build_cmd_shell(const std::string & exe, std::vector<std::string> && data)
0030 {
0031     std::string st = exe;
0032     for (auto & arg : data)
0033     {
0034         boost::replace_all(arg, "\"", "\\\"");
0035 
0036         auto it = std::find(arg.begin(), arg.end(), ' ');//contains space?
0037         if (it != arg.end())//ok, contains spaces.
0038         {
0039             //the first one is put directly onto the output,
0040             //because then I don't have to copy the whole string
0041             arg.insert(arg.begin(), '"' );
0042             arg += '"'; //that is the post one.
0043         }
0044 
0045         if (!st.empty())//first one does not need a preceding space
0046             st += ' ';
0047 
0048         st += arg;
0049     }
0050     return  st ;
0051 }
0052 
0053 inline std::vector<std::string>  build_args(const std::string & data)
0054 {
0055     std::vector<std::string>  st;
0056     
0057     typedef std::string::const_iterator itr_t;
0058 
0059     //normal quotes outside can be stripped, inside ones marked as \" will be replaced.
0060     auto make_entry = [](const itr_t & begin, const itr_t & end)
0061     {
0062         std::string data;
0063         if ((*begin == '"') && (*(end-1) == '"'))
0064             data.assign(begin+1, end-1);
0065         else
0066             data.assign(begin, end);
0067 
0068         boost::replace_all(data, "\\\"", "\"");
0069         return data;
0070 
0071     };
0072 
0073     bool in_quote = false;
0074 
0075     auto part_beg = data.cbegin();
0076     auto itr = data.cbegin();
0077 
0078     for (; itr != data.cend(); itr++)
0079     {
0080         if (*itr == '"')
0081             in_quote ^= true;
0082 
0083         if (!in_quote && (*itr == ' '))
0084         {
0085             //alright, got a space
0086 
0087             if ((itr != data.cbegin()) && (*(itr -1) != ' ' ))
0088                 st.push_back(make_entry(part_beg, itr));
0089 
0090             part_beg = itr+1;
0091         }
0092     }
0093     if (part_beg != itr)
0094         st.emplace_back(make_entry(part_beg, itr));
0095 
0096 
0097     return st;
0098 }
0099 
0100 template<typename Char>
0101 struct exe_cmd_init;
0102 
0103 template<>
0104 struct exe_cmd_init<char> : boost::process::detail::api::handler_base_ext
0105 {
0106     exe_cmd_init(const exe_cmd_init & ) = delete;
0107     exe_cmd_init(exe_cmd_init && ) = default;
0108     exe_cmd_init(std::string && exe, std::vector<std::string> && args)
0109             : exe(std::move(exe)), args(std::move(args)) {};
0110     template <class Executor>
0111     void on_setup(Executor& exec) 
0112     {
0113         if (exe.empty()) //cmd style
0114         {
0115             if (args.empty())
0116                 exec.exe = "";
0117             else
0118                 exec.exe = args.front().c_str();    
0119             exec.cmd_style = true;
0120         }
0121         else
0122             exec.exe = &exe.front();
0123 
0124         cmd_impl = make_cmd();
0125         exec.cmd_line = cmd_impl.data();
0126     }
0127     static exe_cmd_init exe_args(std::string && exe, std::vector<std::string> && args) {return exe_cmd_init(std::move(exe), std::move(args));}
0128     static exe_cmd_init cmd     (std::string && cmd)
0129     {
0130         auto args = build_args(cmd);
0131         return exe_cmd_init({}, std::move(args));
0132     }
0133 
0134     static exe_cmd_init exe_args_shell(std::string&& exe, std::vector<std::string> && args)
0135     {
0136         auto cmd = build_cmd_shell(std::move(exe), std::move(args));
0137 
0138         std::vector<std::string> args_ = {"-c", std::move(cmd)};
0139         std::string sh = shell().string();
0140 
0141         return exe_cmd_init(std::move(sh), std::move(args_));
0142     }
0143     static exe_cmd_init cmd_shell(std::string&& cmd)
0144     {
0145         std::vector<std::string> args = {"-c", cmd};
0146         std::string sh = shell().string();
0147 
0148         return exe_cmd_init(
0149                 std::move(sh),
0150                 {std::move(args)});
0151     }
0152 private:
0153     inline std::vector<char*> make_cmd();
0154     std::string exe;
0155     std::vector<std::string> args;
0156     std::vector<char*> cmd_impl;
0157 };
0158 
0159 std::vector<char*> exe_cmd_init<char>::make_cmd()
0160 {
0161     // any string must be writable.
0162     static char empty_string[1] = "";
0163     std::vector<char*> vec;
0164     if (!exe.empty())
0165         vec.push_back(exe.empty() ? empty_string : &exe.front());
0166 
0167     if (!args.empty()) {
0168         for (auto & v : args)
0169             vec.push_back(v.empty() ? empty_string : &v.front());
0170     }
0171 
0172     vec.push_back(nullptr);
0173 
0174     return vec;
0175 }
0176 
0177 
0178 }}}}
0179 
0180 #endif