Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 34 additions & 36 deletions src/process.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,15 @@ namespace proc {
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
Expand Down Expand Up @@ -97,24 +106,24 @@ namespace proc {
}

_app_id = app_id;
_app = *iter;
auto &proc = *iter;

_app_prep_begin = std::begin(_app.prep_cmds);
_app_prep_it = _app_prep_begin;
_undo_begin = std::begin(proc.prep_cmds);
_undo_it = _undo_begin;

if (!_app.output.empty() && _app.output != "null"sv) {
if (!proc.output.empty() && proc.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<std::codecvt_utf8_utf16<wchar_t>, wchar_t> converter;
auto woutput = converter.from_bytes(_app.output);
auto woutput = converter.from_bytes(proc.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(_app.output.c_str(), "a"));
_pipe.reset(fopen(proc.output.c_str(), "a"));
#endif
}

Expand All @@ -124,33 +133,27 @@ namespace proc {
terminate();
});

for (; _app_prep_it != std::end(_app.prep_cmds); ++_app_prep_it) {
auto &cmd = _app_prep_it->do_cmd;
for (; _undo_it != std::end(proc.prep_cmds); ++_undo_it) {
auto &cmd = _undo_it->do_cmd;

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);
BOOST_LOG(info) << "Executing: ["sv << cmd << ']';
auto ret = exe_with_full_privs(cmd, _env, _pipe, ec);

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 : _app.detached) {
boost::filesystem::path working_dir = _app.working_dir.empty() ?
for (auto &cmd : proc.detached) {
boost::filesystem::path working_dir = proc.working_dir.empty() ?
find_working_directory(cmd, _env) :
boost::filesystem::path(_app.working_dir);
boost::filesystem::path(proc.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) {
Expand All @@ -161,18 +164,18 @@ namespace proc {
}
}

if (_app.cmd.empty()) {
if (proc.cmd.empty()) {
BOOST_LOG(info) << "Executing [Desktop]"sv;
placebo = true;
}
else {
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);
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);
if (ec) {
BOOST_LOG(warning) << "Couldn't run ["sv << _app.cmd << "]: System: "sv << ec.message();
BOOST_LOG(warning) << "Couldn't run ["sv << proc.cmd << "]: System: "sv << ec.message();
return -1;
}
}
Expand Down Expand Up @@ -207,26 +210,21 @@ namespace proc {
_process_handle = bp::group();
_app_id = -1;

for (; _app_prep_it != _app_prep_begin; --_app_prep_it) {
auto &cmd = (_app_prep_it - 1)->undo_cmd;
for (; _undo_it != _undo_begin; --_undo_it) {
auto &cmd = (_undo_it - 1)->undo_cmd;

if (cmd.empty()) {
continue;
}

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);
BOOST_LOG(info) << "Executing: ["sv << cmd << ']';

auto ret = exe_with_full_privs(cmd, _env, _pipe, ec);

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 << ']';
}
Expand Down
5 changes: 2 additions & 3 deletions src/process.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,6 @@ namespace proc {

boost::process::environment _env;
std::vector<ctx_t> _apps;
ctx_t _app;

// If no command associated with _app_id, yet it's still running
bool placebo {};
Expand All @@ -96,8 +95,8 @@ namespace proc {
boost::process::group _process_handle;

file_t _pipe;
std::vector<cmd_t>::const_iterator _app_prep_it;
std::vector<cmd_t>::const_iterator _app_prep_begin;
std::vector<cmd_t>::const_iterator _undo_it;
std::vector<cmd_t>::const_iterator _undo_begin;
};

/**
Expand Down