/// \file ProgramRunner.cpp /// A program runner is used to invoke external programs a bit more safelly than /// to compose a string and invoke system. // // This file is distributed under the MIT License. See LICENSE.md for details. // #include #include "llvm/ADT/ArrayRef.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" #include "llvm/Support/Program.h" #include "revng/Support/Assert.h" #include "revng/Support/Debug.h" #include "revng/Support/PathList.h" #include "revng/Support/ProgramRunner.h" using namespace llvm; static Logger<> DILogger("program-runner"); ProgramRunner Runner; ProgramRunner::ProgramRunner() { using namespace llvm::sys::path; llvm::SmallString<128> BinPath; append(BinPath, getCurrentRoot(), "bin"); Paths = { BinPath.str().str() }; // Append PATH char *Path = getenv("PATH"); if (Path == nullptr) return; llvm::SmallVector BasePaths; StringRef(Path).split(BasePaths, ":"); for (llvm::StringRef BasePath : BasePaths) Paths.push_back(BasePath.str()); } bool ProgramRunner::isProgramAvailable(llvm::StringRef ProgramName) { llvm::SmallVector PathsRef; for (const std::string &Path : Paths) PathsRef.push_back(llvm::StringRef(Path)); auto MaybeProgramPath = llvm::sys::findProgramByName(ProgramName, PathsRef); if (!MaybeProgramPath) return false; return true; } int ProgramRunner::run(llvm::StringRef ProgramName, ArrayRef Args) { llvm::SmallVector PathsRef; for (const std::string &Path : Paths) PathsRef.push_back(llvm::StringRef(Path)); auto MaybeProgramPath = llvm::sys::findProgramByName(ProgramName, PathsRef); revng_assert(not Paths.empty()); revng_assert(MaybeProgramPath, (ProgramName + " was not found in " + getenv("PATH")) .str() .c_str()); // Prepare actual arguments std::vector StringRefs{ *MaybeProgramPath }; DILogger << "Running " << StringRefs[0].str() << " with the following arguments:\n"; for (const std::string &Arg : Args) { StringRefs.push_back(Arg); DILogger << " " << Arg << "\n"; } DILogger << DoLog; int ExitCode = llvm::sys::ExecuteAndWait(StringRefs[0], StringRefs); return ExitCode; }