From 0ea86494454476e633557916e8d6e9fc2ccbf3e7 Mon Sep 17 00:00:00 2001 From: eldritch horrors Date: Mon, 17 Mar 2025 15:45:27 +0100 Subject: [PATCH] libutil: add generic redirections runProgram2 explicit stderr redirection makes mergeStderrToStdout unnecessary also. Change-Id: I63de929e6dc53f6c5ceb2d43c2ce288bfc04d872 --- lix/libfetchers/git.cc | 5 +++-- lix/libstore/build/derivation-goal.cc | 2 +- lix/libstore/globals.cc | 3 ++- lix/libstore/ssh.cc | 4 +++- lix/libutil/processes.cc | 8 +++++--- lix/libutil/processes.hh | 7 ++++++- 6 files changed, 20 insertions(+), 9 deletions(-) diff --git a/lix/libfetchers/git.cc b/lix/libfetchers/git.cc index 5896e3a55..42c73c12c 100644 --- a/lix/libfetchers/git.cc +++ b/lix/libfetchers/git.cc @@ -20,6 +20,7 @@ #include #include #include +#include using namespace std::string_literals; @@ -166,7 +167,7 @@ WorkdirInfo getWorkdirInfo(const Input & input, const Path & workdir) .program = "git", .args = { "-C", workdir, "--git-dir", gitDir, "rev-parse", "--verify", "--no-revs", "HEAD^{commit}" }, .environment = env, - .mergeStderrToStdout = true + .redirections = {{.from = STDERR_FILENO, .to = STDOUT_FILENO}}, }); auto exitCode = WEXITSTATUS(result.first); auto errorMessage = result.second; @@ -694,7 +695,7 @@ struct GitInputScheme : InputScheme auto result = runProgram(RunOptions { .program = "git", .args = { "-C", repoDir, "--git-dir", gitDir, "cat-file", "commit", input.getRev()->gitRev() }, - .mergeStderrToStdout = true + .redirections = {{.from = STDERR_FILENO, .to = STDOUT_FILENO}}, }); if (WEXITSTATUS(result.first) == 128 && result.second.find("bad file") != std::string::npos) diff --git a/lix/libstore/build/derivation-goal.cc b/lix/libstore/build/derivation-goal.cc index c223b4cc9..c09b505a7 100644 --- a/lix/libstore/build/derivation-goal.cc +++ b/lix/libstore/build/derivation-goal.cc @@ -988,7 +988,7 @@ void runPostBuildHook( .program = settings.postBuildHook, .environment = hookEnvironment, .captureStdout = true, - .mergeStderrToStdout = true, + .redirections = {{.from = STDERR_FILENO, .to = STDOUT_FILENO}}, }); Finally const _wait([&] { proc.waitAndCheck(); }); diff --git a/lix/libstore/globals.cc b/lix/libstore/globals.cc index 6ecf65769..bbe397599 100644 --- a/lix/libstore/globals.cc +++ b/lix/libstore/globals.cc @@ -244,7 +244,8 @@ StringSet Settings::getDefaultExtraPlatforms() // x86_64 in aarch64 environments or vice versa since they can // always exec with their own binary preferences. if (std::string{SYSTEM} == "aarch64-darwin" && - runProgram(RunOptions {.program = "arch", .args = {"-arch", "x86_64", "/usr/bin/true"}, .mergeStderrToStdout = true}).first == 0) + runProgram(RunOptions {.program = "arch", .args = {"-arch", "x86_64", "/usr/bin/true"}, + .redirections = {{.from = STDERR_FILENO, .to = STDOUT_FILENO}}}).first == 0) extraPlatforms.insert("x86_64-darwin"); #endif diff --git a/lix/libstore/ssh.cc b/lix/libstore/ssh.cc index cbb7aa32a..68ca4854c 100644 --- a/lix/libstore/ssh.cc +++ b/lix/libstore/ssh.cc @@ -5,6 +5,7 @@ #include "lix/libutil/logging.hh" #include "lix/libutil/strings.hh" #include "lix/libstore/temporary-dir.hh" +#include namespace nix { @@ -50,7 +51,8 @@ bool SSHMaster::isMasterRunning() { Strings args = {"-O", "check", host}; addCommonSSHOpts(args); - auto res = runProgram(RunOptions {.program = "ssh", .args = args, .mergeStderrToStdout = true}); + auto res = runProgram(RunOptions {.program = "ssh", .args = args, + .redirections = {{.from = STDERR_FILENO, .to = STDOUT_FILENO}}}); return res.first == 0; } diff --git a/lix/libutil/processes.cc b/lix/libutil/processes.cc index bc4433c19..057eb29e0 100644 --- a/lix/libutil/processes.cc +++ b/lix/libutil/processes.cc @@ -330,9 +330,11 @@ RunningProgram runProgram2(const RunOptions & options) replaceEnv(*options.environment); if (options.captureStdout && dup2(out.writeSide.get(), STDOUT_FILENO) == -1) throw SysError("dupping stdout"); - if (options.mergeStderrToStdout) - if (dup2(STDOUT_FILENO, STDERR_FILENO) == -1) - throw SysError("cannot dup stdout into stderr"); + for (auto redirection : options.redirections) { + if (dup2(redirection.to, redirection.from) == -1) { + throw SysError("dupping fd %i to %i", redirection.from, redirection.to); + } + } if (options.chdir && chdir((*options.chdir).c_str()) == -1) throw SysError("chdir failed"); diff --git a/lix/libutil/processes.hh b/lix/libutil/processes.hh index 01c42b9fc..3311b8fb8 100644 --- a/lix/libutil/processes.hh +++ b/lix/libutil/processes.hh @@ -76,6 +76,11 @@ std::string runProgram(Path program, bool searchPath = false, struct RunOptions { + struct Redirection + { + int from, to; + }; + Path program; bool searchPath = true; Strings args = {}; @@ -84,8 +89,8 @@ struct RunOptions std::optional chdir = {}; std::optional> environment = {}; bool captureStdout = false; - bool mergeStderrToStdout = false; bool isInteractive = false; + std::vector redirections; }; struct [[nodiscard("you must call RunningProgram::wait()")]] RunningProgram