From 6a914f70168b8b276b861edbafee0d75e86b3699 Mon Sep 17 00:00:00 2001 From: pgrunzjr Date: Mon, 27 Mar 2023 09:15:35 -0500 Subject: [PATCH] Execute do/undo commands non-elevated (#1022) --- src/process.cpp | 71 ++++++++++++++++++++++++++----------------------- src/process.h | 5 ++-- 2 files changed, 40 insertions(+), 36 deletions(-) diff --git a/src/process.cpp b/src/process.cpp index 9a6c9253..000329e1 100644 --- a/src/process.cpp +++ b/src/process.cpp @@ -49,14 +49,6 @@ void process_end(bp::child &proc, bp::group &proc_handle) { proc.wait(); } -int exe_with_full_privs(const std::string &cmd, bp::environment &env, file_t &file, std::error_code &ec) { - if(!file) { - return bp::system(cmd, env, bp::std_out > bp::null, bp::std_err > bp::null, ec); - } - - return bp::system(cmd, env, bp::std_out > file.get(), bp::std_err > file.get(), ec); -} - boost::filesystem::path find_working_directory(const std::string &cmd, bp::environment &env) { // Parse the raw command string into parts to get the actual command portion #ifdef _WIN32 @@ -100,25 +92,25 @@ int proc_t::execute(int app_id) { return 404; } - _app_id = app_id; - auto &proc = *iter; + _app_id = app_id; + _app = *iter; - _undo_begin = std::begin(proc.prep_cmds); - _undo_it = _undo_begin; + _app_prep_begin = std::begin(_app.prep_cmds); + _app_prep_it = _app_prep_begin; - if(!proc.output.empty() && proc.output != "null"sv) { + if(!_app.output.empty() && _app.output != "null"sv) { #ifdef _WIN32 // fopen() interprets the filename as an ANSI string on Windows, so we must convert it // to UTF-16 and use the wchar_t variants for proper Unicode log file path support. std::wstring_convert, wchar_t> converter; - auto woutput = converter.from_bytes(proc.output); + auto woutput = converter.from_bytes(_app.output); // Use _SH_DENYNO to allow us to open this log file again for writing even if it is // still open from a previous execution. This is required to handle the case of a // detached process executing again while the previous process is still running. _pipe.reset(_wfsopen(woutput.c_str(), L"a", _SH_DENYNO)); #else - _pipe.reset(fopen(proc.output.c_str(), "a")); + _pipe.reset(fopen(_app.output.c_str(), "a")); #endif } @@ -128,27 +120,33 @@ int proc_t::execute(int app_id) { terminate(); }); - for(; _undo_it != std::end(proc.prep_cmds); ++_undo_it) { - auto &cmd = _undo_it->do_cmd; + for(; _app_prep_it != std::end(_app.prep_cmds); ++_app_prep_it) { + auto &cmd = _app_prep_it->do_cmd; - BOOST_LOG(info) << "Executing: ["sv << cmd << ']'; - auto ret = exe_with_full_privs(cmd, _env, _pipe, ec); + boost::filesystem::path working_dir = _app.working_dir.empty() ? + find_working_directory(cmd, _env) : + boost::filesystem::path(_app.working_dir); + BOOST_LOG(info) << "Executing Do Cmd: ["sv << cmd << ']'; + auto child = platf::run_unprivileged(cmd, working_dir, _env, _pipe.get(), ec, nullptr); if(ec) { BOOST_LOG(error) << "Couldn't run ["sv << cmd << "]: System: "sv << ec.message(); return -1; } + child.wait(); + auto ret = child.exit_code(); + if(ret != 0) { BOOST_LOG(error) << '[' << cmd << "] failed with code ["sv << ret << ']'; return -1; } } - for(auto &cmd : proc.detached) { - boost::filesystem::path working_dir = proc.working_dir.empty() ? + for(auto &cmd : _app.detached) { + boost::filesystem::path working_dir = _app.working_dir.empty() ? find_working_directory(cmd, _env) : - boost::filesystem::path(proc.working_dir); + boost::filesystem::path(_app.working_dir); BOOST_LOG(info) << "Spawning ["sv << cmd << "] in ["sv << working_dir << ']'; auto child = platf::run_unprivileged(cmd, working_dir, _env, _pipe.get(), ec, nullptr); if(ec) { @@ -159,18 +157,18 @@ int proc_t::execute(int app_id) { } } - if(proc.cmd.empty()) { + if(_app.cmd.empty()) { BOOST_LOG(info) << "Executing [Desktop]"sv; placebo = true; } else { - boost::filesystem::path working_dir = proc.working_dir.empty() ? - find_working_directory(proc.cmd, _env) : - boost::filesystem::path(proc.working_dir); - BOOST_LOG(info) << "Executing: ["sv << proc.cmd << "] in ["sv << working_dir << ']'; - _process = platf::run_unprivileged(proc.cmd, working_dir, _env, _pipe.get(), ec, &_process_handle); + boost::filesystem::path working_dir = _app.working_dir.empty() ? + find_working_directory(_app.cmd, _env) : + boost::filesystem::path(_app.working_dir); + BOOST_LOG(info) << "Executing: ["sv << _app.cmd << "] in ["sv << working_dir << ']'; + _process = platf::run_unprivileged(_app.cmd, working_dir, _env, _pipe.get(), ec, &_process_handle); if(ec) { - BOOST_LOG(warning) << "Couldn't run ["sv << proc.cmd << "]: System: "sv << ec.message(); + BOOST_LOG(warning) << "Couldn't run ["sv << _app.cmd << "]: System: "sv << ec.message(); return -1; } } @@ -203,21 +201,26 @@ void proc_t::terminate() { _process_handle = bp::group(); _app_id = -1; - for(; _undo_it != _undo_begin; --_undo_it) { - auto &cmd = (_undo_it - 1)->undo_cmd; + for(; _app_prep_it != _app_prep_begin; --_app_prep_it) { + auto &cmd = (_app_prep_it - 1)->undo_cmd; if(cmd.empty()) { continue; } - BOOST_LOG(info) << "Executing: ["sv << cmd << ']'; - - auto ret = exe_with_full_privs(cmd, _env, _pipe, ec); + boost::filesystem::path working_dir = _app.working_dir.empty() ? + find_working_directory(cmd, _env) : + boost::filesystem::path(_app.working_dir); + BOOST_LOG(info) << "Executing Undo Cmd: ["sv << cmd << ']'; + auto child = platf::run_unprivileged(cmd, working_dir, _env, _pipe.get(), ec, nullptr); if(ec) { BOOST_LOG(warning) << "System: "sv << ec.message(); } + child.wait(); + auto ret = child.exit_code(); + if(ret != 0) { BOOST_LOG(warning) << "Return code ["sv << ret << ']'; } diff --git a/src/process.h b/src/process.h index e4bd0170..99af563d 100644 --- a/src/process.h +++ b/src/process.h @@ -87,6 +87,7 @@ private: boost::process::environment _env; std::vector _apps; + ctx_t _app; // If no command associated with _app_id, yet it's still running bool placebo {}; @@ -95,8 +96,8 @@ private: boost::process::group _process_handle; file_t _pipe; - std::vector::const_iterator _undo_it; - std::vector::const_iterator _undo_begin; + std::vector::const_iterator _app_prep_it; + std::vector::const_iterator _app_prep_begin; }; /**