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, Optional<ArrayRef<StringRef>> Env, 27 ArrayRef<Optional<StringRef>> Redirects, 28 unsigned MemoryLimit, std::string *ErrMsg, 29 BitVector *AffinityMask); 30 31 int sys::ExecuteAndWait(StringRef Program, ArrayRef<StringRef> Args, 32 Optional<ArrayRef<StringRef>> Env, 33 ArrayRef<Optional<StringRef>> Redirects, 34 unsigned SecondsToWait, unsigned MemoryLimit, 35 std::string *ErrMsg, bool *ExecutionFailed, 36 Optional<ProcessStatistics> *ProcStat, 37 BitVector *AffinityMask) { 38 assert(Redirects.empty() || Redirects.size() == 3); 39 ProcessInfo PI; 40 if (Execute(PI, Program, Args, Env, Redirects, MemoryLimit, ErrMsg, 41 AffinityMask)) { 42 if (ExecutionFailed) 43 *ExecutionFailed = false; 44 ProcessInfo Result = 45 Wait(PI, SecondsToWait, /*WaitUntilTerminates=*/SecondsToWait == 0, 46 ErrMsg, ProcStat); 47 return Result.ReturnCode; 48 } 49 50 if (ExecutionFailed) 51 *ExecutionFailed = true; 52 53 return -1; 54 } 55 56 ProcessInfo sys::ExecuteNoWait(StringRef Program, ArrayRef<StringRef> Args, 57 Optional<ArrayRef<StringRef>> Env, 58 ArrayRef<Optional<StringRef>> Redirects, 59 unsigned MemoryLimit, std::string *ErrMsg, 60 bool *ExecutionFailed, BitVector *AffinityMask) { 61 assert(Redirects.empty() || Redirects.size() == 3); 62 ProcessInfo PI; 63 if (ExecutionFailed) 64 *ExecutionFailed = false; 65 if (!Execute(PI, Program, Args, Env, Redirects, MemoryLimit, ErrMsg, 66 AffinityMask)) 67 if (ExecutionFailed) 68 *ExecutionFailed = true; 69 70 return PI; 71 } 72 73 bool sys::commandLineFitsWithinSystemLimits(StringRef Program, 74 ArrayRef<const char *> Args) { 75 SmallVector<StringRef, 8> StringRefArgs; 76 StringRefArgs.reserve(Args.size()); 77 for (const char *A : Args) 78 StringRefArgs.emplace_back(A); 79 return commandLineFitsWithinSystemLimits(Program, StringRefArgs); 80 } 81 82 void sys::printArg(raw_ostream &OS, StringRef Arg, bool Quote) { 83 const bool Escape = Arg.find_first_of(" \"\\$") != StringRef::npos; 84 85 if (!Quote && !Escape) { 86 OS << Arg; 87 return; 88 } 89 90 // Quote and escape. This isn't really complete, but good enough. 91 OS << '"'; 92 for (const auto c : Arg) { 93 if (c == '"' || c == '\\' || c == '$') 94 OS << '\\'; 95 OS << c; 96 } 97 OS << '"'; 98 } 99 100 // Include the platform-specific parts of this class. 101 #ifdef LLVM_ON_UNIX 102 #include "Unix/Program.inc" 103 #endif 104 #ifdef _WIN32 105 #include "Windows/Program.inc" 106 #endif 107