1 //===-- Program.cpp - Implement OS Program Concept --------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file implements the operating system Program concept. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "llvm/Support/Program.h" 14 #include "llvm/ADT/StringRef.h" 15 #include "llvm/Config/llvm-config.h" 16 #include "llvm/Support/raw_ostream.h" 17 using namespace llvm; 18 using namespace sys; 19 20 //===----------------------------------------------------------------------===// 21 //=== WARNING: Implementation here must contain only TRULY operating system 22 //=== independent code. 23 //===----------------------------------------------------------------------===// 24 25 static bool Execute(ProcessInfo &PI, StringRef Program, 26 ArrayRef<StringRef> Args, 27 std::optional<ArrayRef<StringRef>> Env, 28 ArrayRef<std::optional<StringRef>> Redirects, 29 unsigned MemoryLimit, std::string *ErrMsg, 30 BitVector *AffinityMask); 31 32 int sys::ExecuteAndWait(StringRef Program, ArrayRef<StringRef> Args, 33 std::optional<ArrayRef<StringRef>> Env, 34 ArrayRef<std::optional<StringRef>> Redirects, 35 unsigned SecondsToWait, unsigned MemoryLimit, 36 std::string *ErrMsg, bool *ExecutionFailed, 37 std::optional<ProcessStatistics> *ProcStat, 38 BitVector *AffinityMask) { 39 assert(Redirects.empty() || Redirects.size() == 3); 40 ProcessInfo PI; 41 if (Execute(PI, Program, Args, Env, Redirects, MemoryLimit, ErrMsg, 42 AffinityMask)) { 43 if (ExecutionFailed) 44 *ExecutionFailed = false; 45 ProcessInfo Result = Wait( 46 PI, SecondsToWait == 0 ? std::nullopt : std::optional(SecondsToWait), 47 ErrMsg, ProcStat); 48 return Result.ReturnCode; 49 } 50 51 if (ExecutionFailed) 52 *ExecutionFailed = true; 53 54 return -1; 55 } 56 57 ProcessInfo sys::ExecuteNoWait(StringRef Program, ArrayRef<StringRef> Args, 58 std::optional<ArrayRef<StringRef>> Env, 59 ArrayRef<std::optional<StringRef>> Redirects, 60 unsigned MemoryLimit, std::string *ErrMsg, 61 bool *ExecutionFailed, BitVector *AffinityMask) { 62 assert(Redirects.empty() || Redirects.size() == 3); 63 ProcessInfo PI; 64 if (ExecutionFailed) 65 *ExecutionFailed = false; 66 if (!Execute(PI, Program, Args, Env, Redirects, MemoryLimit, ErrMsg, 67 AffinityMask)) 68 if (ExecutionFailed) 69 *ExecutionFailed = true; 70 71 return PI; 72 } 73 74 bool sys::commandLineFitsWithinSystemLimits(StringRef Program, 75 ArrayRef<const char *> Args) { 76 SmallVector<StringRef, 8> StringRefArgs; 77 StringRefArgs.reserve(Args.size()); 78 for (const char *A : Args) 79 StringRefArgs.emplace_back(A); 80 return commandLineFitsWithinSystemLimits(Program, StringRefArgs); 81 } 82 83 void sys::printArg(raw_ostream &OS, StringRef Arg, bool Quote) { 84 const bool Escape = Arg.find_first_of(" \"\\$") != StringRef::npos; 85 86 if (!Quote && !Escape) { 87 OS << Arg; 88 return; 89 } 90 91 // Quote and escape. This isn't really complete, but good enough. 92 OS << '"'; 93 for (const auto c : Arg) { 94 if (c == '"' || c == '\\' || c == '$') 95 OS << '\\'; 96 OS << c; 97 } 98 OS << '"'; 99 } 100 101 // Include the platform-specific parts of this class. 102 #ifdef LLVM_ON_UNIX 103 #include "Unix/Program.inc" 104 #endif 105 #ifdef _WIN32 106 #include "Windows/Program.inc" 107 #endif 108