2018-11-09 17:45:19 +00:00
|
|
|
/**
|
|
|
|
* Copyright (c) 2018, Timothy Stack
|
|
|
|
*
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions are met:
|
|
|
|
*
|
|
|
|
* * Redistributions of source code must retain the above copyright notice, this
|
|
|
|
* list of conditions and the following disclaimer.
|
|
|
|
* * Redistributions in binary form must reproduce the above copyright notice,
|
|
|
|
* this list of conditions and the following disclaimer in the documentation
|
|
|
|
* and/or other materials provided with the distribution.
|
|
|
|
* * Neither the name of Timothy Stack nor the names of its contributors
|
|
|
|
* may be used to endorse or promote products derived from this software
|
|
|
|
* without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
|
|
|
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
|
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
|
|
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
|
|
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
|
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
2022-03-16 22:38:08 +00:00
|
|
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
|
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
2018-11-09 17:45:19 +00:00
|
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
|
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
2022-03-16 22:38:08 +00:00
|
|
|
#include "log_actions.hh"
|
2018-11-09 17:45:19 +00:00
|
|
|
|
2022-03-13 22:49:41 +00:00
|
|
|
#include "base/fs_util.hh"
|
2022-07-20 06:48:25 +00:00
|
|
|
#include "base/injector.hh"
|
|
|
|
#include "bound_tags.hh"
|
2022-03-16 22:38:08 +00:00
|
|
|
#include "config.h"
|
2022-03-13 22:49:41 +00:00
|
|
|
#include "piper_proc.hh"
|
2018-11-09 17:45:19 +00:00
|
|
|
|
2022-03-31 15:59:19 +00:00
|
|
|
std::string
|
|
|
|
action_delegate::execute_action(const std::string& action_name)
|
2018-11-09 17:45:19 +00:00
|
|
|
{
|
2022-07-20 06:48:25 +00:00
|
|
|
static auto& lnav_flags = injector::get<unsigned long&, lnav_flags_tag>();
|
|
|
|
|
|
|
|
if (lnav_flags & LNF_SECURE_MODE) {
|
|
|
|
return "unavailable in secure mode";
|
|
|
|
}
|
|
|
|
|
2022-03-13 22:49:41 +00:00
|
|
|
auto& ldh = this->ad_log_helper;
|
|
|
|
auto value_index = this->ad_press_value;
|
2022-07-25 06:29:46 +00:00
|
|
|
logline_value& lv = ldh.ldh_line_values.lvv_values[value_index];
|
2022-03-31 15:59:19 +00:00
|
|
|
auto lf = ldh.ldh_file;
|
2020-12-01 19:27:03 +00:00
|
|
|
const auto format = lf->get_format();
|
2018-11-09 17:45:19 +00:00
|
|
|
pid_t child_pid;
|
2022-03-31 15:59:19 +00:00
|
|
|
std::string retval;
|
2018-11-09 17:45:19 +00:00
|
|
|
|
2022-03-13 22:49:41 +00:00
|
|
|
auto iter = format->lf_action_defs.find(action_name);
|
2018-11-09 17:45:19 +00:00
|
|
|
|
2022-03-16 22:38:08 +00:00
|
|
|
const log_format::action_def& action = iter->second;
|
2018-11-09 17:45:19 +00:00
|
|
|
|
|
|
|
auto_pipe in_pipe(STDIN_FILENO);
|
|
|
|
auto_pipe out_pipe(STDOUT_FILENO);
|
|
|
|
|
|
|
|
in_pipe.open();
|
2019-06-15 13:32:02 +00:00
|
|
|
if (action.ad_capture_output) {
|
2018-11-09 17:45:19 +00:00
|
|
|
out_pipe.open();
|
2019-06-15 13:32:02 +00:00
|
|
|
}
|
2018-11-09 17:45:19 +00:00
|
|
|
|
|
|
|
child_pid = fork();
|
|
|
|
|
|
|
|
in_pipe.after_fork(child_pid);
|
|
|
|
out_pipe.after_fork(child_pid);
|
|
|
|
|
|
|
|
switch (child_pid) {
|
|
|
|
case -1:
|
2022-03-31 15:59:19 +00:00
|
|
|
retval = fmt::format(
|
|
|
|
FMT_STRING("error: unable to fork child process -- {}"),
|
|
|
|
strerror(errno));
|
2018-11-09 17:45:19 +00:00
|
|
|
break;
|
|
|
|
case 0: {
|
2022-03-16 22:38:08 +00:00
|
|
|
const char* args[action.ad_cmdline.size() + 1];
|
2022-03-31 15:59:19 +00:00
|
|
|
std::set<std::string> path_set(format->get_source_path());
|
2018-11-09 17:45:19 +00:00
|
|
|
char env_buffer[64];
|
|
|
|
int value_line;
|
2022-03-31 15:59:19 +00:00
|
|
|
std::string path;
|
2018-11-09 17:45:19 +00:00
|
|
|
|
2019-06-15 13:32:02 +00:00
|
|
|
dup2(STDOUT_FILENO, STDERR_FILENO);
|
2018-11-09 17:45:19 +00:00
|
|
|
setenv("LNAV_ACTION_FILE", lf->get_filename().c_str(), 1);
|
2022-03-16 22:38:08 +00:00
|
|
|
snprintf(env_buffer,
|
|
|
|
sizeof(env_buffer),
|
2018-11-09 17:45:19 +00:00
|
|
|
"%ld",
|
|
|
|
(ldh.ldh_line - lf->begin()) + 1);
|
|
|
|
setenv("LNAV_ACTION_FILE_LINE", env_buffer, 1);
|
2022-03-16 22:38:08 +00:00
|
|
|
snprintf(
|
|
|
|
env_buffer, sizeof(env_buffer), "%d", ldh.ldh_y_offset + 1);
|
2018-11-09 17:45:19 +00:00
|
|
|
setenv("LNAV_ACTION_MSG_LINE", env_buffer, 1);
|
2020-12-19 06:35:23 +00:00
|
|
|
setenv("LNAV_ACTION_VALUE_NAME", lv.lv_meta.lvm_name.get(), 1);
|
2018-11-09 17:45:19 +00:00
|
|
|
value_line = ldh.ldh_y_offset - ldh.get_value_line(lv) + 1;
|
|
|
|
snprintf(env_buffer, sizeof(env_buffer), "%d", value_line);
|
|
|
|
setenv("LNAV_ACTION_VALUE_LINE", env_buffer, 1);
|
|
|
|
|
2022-03-16 22:38:08 +00:00
|
|
|
for (const auto& path_iter : path_set) {
|
2018-11-09 17:45:19 +00:00
|
|
|
if (!path.empty()) {
|
|
|
|
path += ":";
|
|
|
|
}
|
|
|
|
path += path_iter;
|
|
|
|
}
|
2022-03-31 15:59:19 +00:00
|
|
|
path += ":" + std::string(getenv("PATH"));
|
2018-11-09 17:45:19 +00:00
|
|
|
setenv("PATH", path.c_str(), 1);
|
|
|
|
for (size_t lpc = 0; lpc < action.ad_cmdline.size(); lpc++) {
|
|
|
|
args[lpc] = action.ad_cmdline[lpc].c_str();
|
|
|
|
}
|
2020-11-15 05:39:12 +00:00
|
|
|
args[action.ad_cmdline.size()] = nullptr;
|
2022-03-16 22:38:08 +00:00
|
|
|
execvp(args[0], (char* const*) args);
|
2018-11-09 17:45:19 +00:00
|
|
|
fprintf(stderr,
|
|
|
|
"error: could not exec process -- %s:%s\n",
|
|
|
|
args[0],
|
|
|
|
strerror(errno));
|
|
|
|
_exit(0);
|
2022-03-16 22:38:08 +00:00
|
|
|
} break;
|
2018-11-09 17:45:19 +00:00
|
|
|
default: {
|
|
|
|
static int exec_count = 0;
|
|
|
|
|
2022-03-31 15:59:19 +00:00
|
|
|
const auto value = lv.to_string();
|
2018-11-09 17:45:19 +00:00
|
|
|
|
2022-03-13 22:49:41 +00:00
|
|
|
this->ad_child_cb(child_pid);
|
2018-11-09 17:45:19 +00:00
|
|
|
|
|
|
|
if (write(in_pipe.write_end(), value.c_str(), value.size()) == -1) {
|
|
|
|
perror("execute_action write");
|
|
|
|
}
|
|
|
|
in_pipe.close();
|
|
|
|
|
|
|
|
if (out_pipe.read_end() != -1) {
|
2022-03-31 15:59:19 +00:00
|
|
|
auto pp = std::make_shared<piper_proc>(
|
|
|
|
std::move(out_pipe.read_end()),
|
2019-07-30 05:18:32 +00:00
|
|
|
false,
|
2022-03-16 22:38:08 +00:00
|
|
|
lnav::filesystem::open_temp_file(
|
|
|
|
ghc::filesystem::temp_directory_path()
|
|
|
|
/ "lnav.action.XXXXXX")
|
2021-03-06 00:17:28 +00:00
|
|
|
.map([](auto pair) {
|
2020-10-21 05:55:46 +00:00
|
|
|
ghc::filesystem::remove(pair.first);
|
2021-03-06 00:17:28 +00:00
|
|
|
|
|
|
|
return pair;
|
2020-10-21 05:55:46 +00:00
|
|
|
})
|
2019-07-30 05:18:32 +00:00
|
|
|
.expect("Cannot create temporary file for action")
|
|
|
|
.second);
|
2022-03-29 05:00:49 +00:00
|
|
|
auto desc = fmt::format(FMT_STRING("[{}] Output of {}"),
|
|
|
|
exec_count++,
|
|
|
|
action.ad_cmdline[0]);
|
2022-03-13 22:49:41 +00:00
|
|
|
|
|
|
|
this->ad_piper_cb(desc, pp);
|
2018-11-09 17:45:19 +00:00
|
|
|
}
|
|
|
|
|
2019-06-15 13:32:02 +00:00
|
|
|
return "";
|
2022-03-16 22:38:08 +00:00
|
|
|
} break;
|
2018-11-09 17:45:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
2022-03-16 22:38:08 +00:00
|
|
|
bool
|
|
|
|
action_delegate::text_handle_mouse(textview_curses& tc, mouse_event& me)
|
2018-11-09 17:45:19 +00:00
|
|
|
{
|
|
|
|
bool retval = false;
|
|
|
|
|
2020-11-15 05:39:12 +00:00
|
|
|
if (me.me_button != mouse_button_t::BUTTON_LEFT) {
|
2018-11-09 17:45:19 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
vis_line_t mouse_line = vis_line_t(tc.get_top() + me.me_y);
|
|
|
|
int mouse_left = tc.get_left() + me.me_x;
|
|
|
|
|
|
|
|
switch (me.me_state) {
|
2020-11-15 05:39:12 +00:00
|
|
|
case mouse_button_state_t::BUTTON_STATE_PRESSED:
|
2022-06-22 18:25:11 +00:00
|
|
|
if (mouse_line >= 0_vl && mouse_line <= tc.get_bottom()) {
|
2018-11-09 17:45:19 +00:00
|
|
|
size_t line_end_index = 0;
|
|
|
|
int x_offset;
|
|
|
|
|
|
|
|
this->ad_press_line = mouse_line;
|
|
|
|
this->ad_log_helper.parse_line(mouse_line, true);
|
|
|
|
|
2022-03-16 22:38:08 +00:00
|
|
|
this->ad_log_helper.get_line_bounds(this->ad_line_index,
|
|
|
|
line_end_index);
|
2018-11-09 17:45:19 +00:00
|
|
|
|
|
|
|
struct line_range lr(this->ad_line_index, line_end_index);
|
|
|
|
|
|
|
|
this->ad_press_value = -1;
|
|
|
|
|
|
|
|
x_offset = this->ad_line_index + mouse_left;
|
|
|
|
if (lr.contains(x_offset)) {
|
|
|
|
for (size_t lpc = 0;
|
2022-07-25 06:29:46 +00:00
|
|
|
lpc < this->ad_log_helper.ldh_line_values.lvv_values
|
|
|
|
.size();
|
|
|
|
lpc++)
|
|
|
|
{
|
|
|
|
auto& lv = this->ad_log_helper.ldh_line_values
|
|
|
|
.lvv_values[lpc];
|
2018-11-09 17:45:19 +00:00
|
|
|
|
|
|
|
if (lv.lv_origin.contains(x_offset)) {
|
|
|
|
this->ad_press_value = lpc;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2020-11-15 05:39:12 +00:00
|
|
|
case mouse_button_state_t::BUTTON_STATE_DRAGGED:
|
2018-11-09 17:45:19 +00:00
|
|
|
if (mouse_line != this->ad_press_line) {
|
|
|
|
this->ad_press_value = -1;
|
|
|
|
}
|
|
|
|
if (this->ad_press_value != -1) {
|
|
|
|
retval = true;
|
|
|
|
}
|
|
|
|
break;
|
2020-11-15 05:39:12 +00:00
|
|
|
case mouse_button_state_t::BUTTON_STATE_RELEASED:
|
2022-03-16 22:38:08 +00:00
|
|
|
if (this->ad_press_value != -1 && this->ad_press_line == mouse_line)
|
|
|
|
{
|
2022-07-25 06:29:46 +00:00
|
|
|
auto& lv = this->ad_log_helper.ldh_line_values
|
|
|
|
.lvv_values[this->ad_press_value];
|
2018-11-09 17:45:19 +00:00
|
|
|
int x_offset = this->ad_line_index + mouse_left;
|
|
|
|
|
|
|
|
if (lv.lv_origin.contains(x_offset)) {
|
2022-03-31 15:59:19 +00:00
|
|
|
auto lf = this->ad_log_helper.ldh_file;
|
|
|
|
const std::vector<std::string>* actions;
|
2018-11-09 17:45:19 +00:00
|
|
|
|
|
|
|
actions = lf->get_format()->get_actions(lv);
|
2020-11-15 05:39:12 +00:00
|
|
|
if (actions != nullptr && !actions->empty()) {
|
2022-03-13 22:49:41 +00:00
|
|
|
const auto rc = execute_action(actions->at(0));
|
2018-11-09 17:45:19 +00:00
|
|
|
|
2022-03-13 22:49:41 +00:00
|
|
|
// lnav_data.ld_rl_view->set_value(rc);
|
2018-11-09 17:45:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
retval = true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|