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