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