1 /** 2 * Copyright (c) 2015, Timothy Stack 3 * 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * * Redistributions of source code must retain the above copyright notice, this 10 * list of conditions and the following disclaimer. 11 * * Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * * Neither the name of Timothy Stack nor the names of its contributors 15 * may be used to endorse or promote products derived from this software 16 * without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY 19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 25 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #ifndef LNAV_COMMAND_EXECUTOR_H 31 #define LNAV_COMMAND_EXECUTOR_H 32 33 #include <sqlite3.h> 34 35 #include <future> 36 #include <string> 37 38 #include "fmt/format.h" 39 #include "optional.hpp" 40 #include "auto_fd.hh" 41 #include "attr_line.hh" 42 #include "shlex.hh" 43 #include "log_format.hh" 44 #include "bookmarks.hh" 45 46 struct exec_context; 47 48 typedef int (*sql_callback_t)(exec_context &ec, sqlite3_stmt *stmt); 49 int sql_callback(exec_context &ec, sqlite3_stmt *stmt); 50 51 typedef std::future<std::string> (*pipe_callback_t)( 52 exec_context &ec, const std::string &cmdline, auto_fd &fd); 53 54 struct exec_context { 55 enum class perm_t { 56 READ_WRITE, 57 READ_ONLY, 58 }; 59 60 using output_t = std::pair<FILE *, int(*)(FILE *)>; 61 exec_contextexec_context62 exec_context(std::vector<logline_value> *line_values = nullptr, 63 sql_callback_t sql_callback = ::sql_callback, 64 pipe_callback_t pipe_callback = nullptr) 65 : ec_line_values(line_values), 66 ec_sql_callback(sql_callback), 67 ec_pipe_callback(pipe_callback) { 68 this->ec_local_vars.push(std::map<std::string, std::string>()); 69 this->ec_path_stack.emplace_back("."); 70 this->ec_source.emplace("command", 1); 71 this->ec_output_stack.emplace_back("screen", nonstd::nullopt); 72 } 73 is_read_writeexec_context74 bool is_read_write() const { 75 return this->ec_perms == perm_t::READ_WRITE; 76 } 77 is_read_onlyexec_context78 bool is_read_only() const { 79 return this->ec_perms == perm_t::READ_ONLY; 80 } 81 with_permsexec_context82 exec_context& with_perms(perm_t perms) { 83 this->ec_perms = perms; 84 return *this; 85 } 86 87 std::string get_error_prefix(); 88 89 template<typename ...Args> make_errorexec_context90 Result<std::string, std::string> make_error( 91 fmt::string_view format_str, const Args& ...args) { 92 return Err(this->get_error_prefix() + 93 fmt::vformat(format_str, fmt::make_format_args(args...))); 94 } 95 get_outputexec_context96 nonstd::optional<FILE *> get_output() { 97 for (auto iter = this->ec_output_stack.rbegin(); 98 iter != this->ec_output_stack.rend(); 99 ++iter) { 100 if (iter->second && (*iter->second).first) { 101 return (*iter->second).first; 102 } 103 } 104 105 return nonstd::nullopt; 106 } 107 108 void set_output(const std::string& name, FILE *file, int (*closer)(FILE *)); 109 110 void clear_output(); 111 112 struct source_guard { source_guardexec_context::source_guard113 source_guard(exec_context &context) : sg_context(context) { 114 115 } 116 ~source_guardexec_context::source_guard117 ~source_guard() { 118 this->sg_context.ec_source.pop(); 119 } 120 121 exec_context &sg_context; 122 }; 123 124 struct output_guard { 125 explicit output_guard(exec_context &context, 126 std::string name = "default", 127 const nonstd::optional<output_t>& file = nonstd::nullopt); 128 129 ~output_guard(); 130 131 exec_context &sg_context; 132 }; 133 enter_sourceexec_context134 source_guard enter_source(const std::string& path, int line_number) { 135 this->ec_source.emplace(path, line_number); 136 return source_guard(*this); 137 } 138 create_resolverexec_context139 scoped_resolver create_resolver() { 140 return { 141 &this->ec_local_vars.top(), 142 &this->ec_global_vars, 143 }; 144 } 145 146 vis_line_t ec_top_line{0_vl}; 147 bool ec_dry_run{false}; 148 perm_t ec_perms{perm_t::READ_WRITE}; 149 150 std::map<std::string, std::string> ec_override; 151 std::vector<logline_value> *ec_line_values; 152 std::stack<std::map<std::string, std::string> > ec_local_vars; 153 std::map<std::string, std::string> ec_global_vars; 154 std::vector<ghc::filesystem::path> ec_path_stack; 155 std::stack<std::pair<std::string, int>> ec_source; 156 157 std::vector<std::pair<std::string, nonstd::optional<output_t>>> ec_output_stack; 158 159 attr_line_t ec_accumulator; 160 161 sql_callback_t ec_sql_callback; 162 pipe_callback_t ec_pipe_callback; 163 }; 164 165 Result<std::string, std::string> execute_command(exec_context &ec, const std::string &cmdline); 166 167 Result<std::string, std::string> execute_sql(exec_context &ec, const std::string &sql, std::string &alt_msg); 168 Result<std::string, std::string> execute_file(exec_context &ec, const std::string &path_and_args, bool multiline = true); 169 Result<std::string, std::string> execute_any(exec_context &ec, const std::string &cmdline); 170 void execute_init_commands(exec_context &ec, std::vector<std::pair<Result<std::string, std::string>, std::string> > &msgs); 171 172 std::future<std::string> pipe_callback( 173 exec_context &ec, const std::string &cmdline, auto_fd &fd); 174 175 int sql_progress(const struct log_cursor &lc); 176 void sql_progress_finished(); 177 178 void add_global_vars(exec_context &ec); 179 180 #endif //LNAV_COMMAND_EXECUTOR_H 181