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