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, bool DetachProcess); |
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, /*DetachProcess=*/false)) { |
43 | if (ExecutionFailed) |
44 | *ExecutionFailed = false; |
45 | ProcessInfo Result = Wait( |
46 | PI, SecondsToWait: 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 | bool DetachProcess) { |
63 | assert(Redirects.empty() || Redirects.size() == 3); |
64 | ProcessInfo PI; |
65 | if (ExecutionFailed) |
66 | *ExecutionFailed = false; |
67 | if (!Execute(PI, Program, Args, Env, Redirects, MemoryLimit, ErrMsg, |
68 | AffinityMask, DetachProcess)) |
69 | if (ExecutionFailed) |
70 | *ExecutionFailed = true; |
71 | |
72 | return PI; |
73 | } |
74 | |
75 | bool sys::commandLineFitsWithinSystemLimits(StringRef Program, |
76 | ArrayRef<const char *> Args) { |
77 | SmallVector<StringRef, 8> StringRefArgs; |
78 | StringRefArgs.reserve(N: Args.size()); |
79 | for (const char *A : Args) |
80 | StringRefArgs.emplace_back(Args&: A); |
81 | return commandLineFitsWithinSystemLimits(Program, Args: StringRefArgs); |
82 | } |
83 | |
84 | void sys::printArg(raw_ostream &OS, StringRef Arg, bool Quote) { |
85 | const bool Escape = Arg.find_first_of(Chars: " \"\\$" ) != StringRef::npos; |
86 | |
87 | if (!Quote && !Escape) { |
88 | OS << Arg; |
89 | return; |
90 | } |
91 | |
92 | // Quote and escape. This isn't really complete, but good enough. |
93 | OS << '"'; |
94 | for (const auto c : Arg) { |
95 | if (c == '"' || c == '\\' || c == '$') |
96 | OS << '\\'; |
97 | OS << c; |
98 | } |
99 | OS << '"'; |
100 | } |
101 | |
102 | // Include the platform-specific parts of this class. |
103 | #ifdef LLVM_ON_UNIX |
104 | #include "Unix/Program.inc" |
105 | #endif |
106 | #ifdef _WIN32 |
107 | #include "Windows/Program.inc" |
108 | #endif |
109 | |