10b57cec5SDimitry Andric //===-- Program.cpp - Implement OS Program Concept --------------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file implements the operating system Program concept. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "llvm/Support/Program.h" 140b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 150b57cec5SDimitry Andric #include "llvm/Config/llvm-config.h" 165ffd83dbSDimitry Andric #include "llvm/Support/raw_ostream.h" 170b57cec5SDimitry Andric using namespace llvm; 180b57cec5SDimitry Andric using namespace sys; 190b57cec5SDimitry Andric 200b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 210b57cec5SDimitry Andric //=== WARNING: Implementation here must contain only TRULY operating system 220b57cec5SDimitry Andric //=== independent code. 230b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 240b57cec5SDimitry Andric 250b57cec5SDimitry Andric static bool Execute(ProcessInfo &PI, StringRef Program, 26bdd1243dSDimitry Andric ArrayRef<StringRef> Args, 27bdd1243dSDimitry Andric std::optional<ArrayRef<StringRef>> Env, 28bdd1243dSDimitry Andric ArrayRef<std::optional<StringRef>> Redirects, 29e8d8bef9SDimitry Andric unsigned MemoryLimit, std::string *ErrMsg, 30*0fca6ea1SDimitry Andric BitVector *AffinityMask, bool DetachProcess); 310b57cec5SDimitry Andric 320b57cec5SDimitry Andric int sys::ExecuteAndWait(StringRef Program, ArrayRef<StringRef> Args, 33bdd1243dSDimitry Andric std::optional<ArrayRef<StringRef>> Env, 34bdd1243dSDimitry Andric ArrayRef<std::optional<StringRef>> Redirects, 350b57cec5SDimitry Andric unsigned SecondsToWait, unsigned MemoryLimit, 365ffd83dbSDimitry Andric std::string *ErrMsg, bool *ExecutionFailed, 37bdd1243dSDimitry Andric std::optional<ProcessStatistics> *ProcStat, 38e8d8bef9SDimitry Andric BitVector *AffinityMask) { 390b57cec5SDimitry Andric assert(Redirects.empty() || Redirects.size() == 3); 400b57cec5SDimitry Andric ProcessInfo PI; 41e8d8bef9SDimitry Andric if (Execute(PI, Program, Args, Env, Redirects, MemoryLimit, ErrMsg, 42*0fca6ea1SDimitry Andric AffinityMask, /*DetachProcess=*/false)) { 430b57cec5SDimitry Andric if (ExecutionFailed) 440b57cec5SDimitry Andric *ExecutionFailed = false; 45bdd1243dSDimitry Andric ProcessInfo Result = Wait( 46bdd1243dSDimitry Andric PI, SecondsToWait == 0 ? std::nullopt : std::optional(SecondsToWait), 475ffd83dbSDimitry Andric ErrMsg, ProcStat); 480b57cec5SDimitry Andric return Result.ReturnCode; 490b57cec5SDimitry Andric } 500b57cec5SDimitry Andric 510b57cec5SDimitry Andric if (ExecutionFailed) 520b57cec5SDimitry Andric *ExecutionFailed = true; 530b57cec5SDimitry Andric 540b57cec5SDimitry Andric return -1; 550b57cec5SDimitry Andric } 560b57cec5SDimitry Andric 570b57cec5SDimitry Andric ProcessInfo sys::ExecuteNoWait(StringRef Program, ArrayRef<StringRef> Args, 58bdd1243dSDimitry Andric std::optional<ArrayRef<StringRef>> Env, 59bdd1243dSDimitry Andric ArrayRef<std::optional<StringRef>> Redirects, 600b57cec5SDimitry Andric unsigned MemoryLimit, std::string *ErrMsg, 61*0fca6ea1SDimitry Andric bool *ExecutionFailed, BitVector *AffinityMask, 62*0fca6ea1SDimitry Andric bool DetachProcess) { 630b57cec5SDimitry Andric assert(Redirects.empty() || Redirects.size() == 3); 640b57cec5SDimitry Andric ProcessInfo PI; 650b57cec5SDimitry Andric if (ExecutionFailed) 660b57cec5SDimitry Andric *ExecutionFailed = false; 67e8d8bef9SDimitry Andric if (!Execute(PI, Program, Args, Env, Redirects, MemoryLimit, ErrMsg, 68*0fca6ea1SDimitry Andric AffinityMask, DetachProcess)) 690b57cec5SDimitry Andric if (ExecutionFailed) 700b57cec5SDimitry Andric *ExecutionFailed = true; 710b57cec5SDimitry Andric 720b57cec5SDimitry Andric return PI; 730b57cec5SDimitry Andric } 740b57cec5SDimitry Andric 750b57cec5SDimitry Andric bool sys::commandLineFitsWithinSystemLimits(StringRef Program, 760b57cec5SDimitry Andric ArrayRef<const char *> Args) { 770b57cec5SDimitry Andric SmallVector<StringRef, 8> StringRefArgs; 780b57cec5SDimitry Andric StringRefArgs.reserve(Args.size()); 790b57cec5SDimitry Andric for (const char *A : Args) 800b57cec5SDimitry Andric StringRefArgs.emplace_back(A); 810b57cec5SDimitry Andric return commandLineFitsWithinSystemLimits(Program, StringRefArgs); 820b57cec5SDimitry Andric } 830b57cec5SDimitry Andric 845ffd83dbSDimitry Andric void sys::printArg(raw_ostream &OS, StringRef Arg, bool Quote) { 855ffd83dbSDimitry Andric const bool Escape = Arg.find_first_of(" \"\\$") != StringRef::npos; 865ffd83dbSDimitry Andric 875ffd83dbSDimitry Andric if (!Quote && !Escape) { 885ffd83dbSDimitry Andric OS << Arg; 895ffd83dbSDimitry Andric return; 905ffd83dbSDimitry Andric } 915ffd83dbSDimitry Andric 925ffd83dbSDimitry Andric // Quote and escape. This isn't really complete, but good enough. 935ffd83dbSDimitry Andric OS << '"'; 945ffd83dbSDimitry Andric for (const auto c : Arg) { 955ffd83dbSDimitry Andric if (c == '"' || c == '\\' || c == '$') 965ffd83dbSDimitry Andric OS << '\\'; 975ffd83dbSDimitry Andric OS << c; 985ffd83dbSDimitry Andric } 995ffd83dbSDimitry Andric OS << '"'; 1005ffd83dbSDimitry Andric } 1015ffd83dbSDimitry Andric 1020b57cec5SDimitry Andric // Include the platform-specific parts of this class. 1030b57cec5SDimitry Andric #ifdef LLVM_ON_UNIX 1040b57cec5SDimitry Andric #include "Unix/Program.inc" 1050b57cec5SDimitry Andric #endif 1060b57cec5SDimitry Andric #ifdef _WIN32 1070b57cec5SDimitry Andric #include "Windows/Program.inc" 1080b57cec5SDimitry Andric #endif 109