xref: /freebsd-src/contrib/llvm-project/llvm/lib/Support/Program.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===-- Program.cpp - Implement OS Program Concept --------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric //  This file implements the operating system Program concept.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "llvm/Support/Program.h"
140b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
150b57cec5SDimitry Andric #include "llvm/Config/llvm-config.h"
165ffd83dbSDimitry Andric #include "llvm/Support/raw_ostream.h"
170b57cec5SDimitry Andric using namespace llvm;
180b57cec5SDimitry Andric using namespace sys;
190b57cec5SDimitry Andric 
200b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
210b57cec5SDimitry Andric //=== WARNING: Implementation here must contain only TRULY operating system
220b57cec5SDimitry Andric //===          independent code.
230b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric static bool Execute(ProcessInfo &PI, StringRef Program,
26bdd1243dSDimitry Andric                     ArrayRef<StringRef> Args,
27bdd1243dSDimitry Andric                     std::optional<ArrayRef<StringRef>> Env,
28bdd1243dSDimitry Andric                     ArrayRef<std::optional<StringRef>> Redirects,
29e8d8bef9SDimitry Andric                     unsigned MemoryLimit, std::string *ErrMsg,
30*0fca6ea1SDimitry Andric                     BitVector *AffinityMask, bool DetachProcess);
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric int sys::ExecuteAndWait(StringRef Program, ArrayRef<StringRef> Args,
33bdd1243dSDimitry Andric                         std::optional<ArrayRef<StringRef>> Env,
34bdd1243dSDimitry Andric                         ArrayRef<std::optional<StringRef>> Redirects,
350b57cec5SDimitry Andric                         unsigned SecondsToWait, unsigned MemoryLimit,
365ffd83dbSDimitry Andric                         std::string *ErrMsg, bool *ExecutionFailed,
37bdd1243dSDimitry Andric                         std::optional<ProcessStatistics> *ProcStat,
38e8d8bef9SDimitry Andric                         BitVector *AffinityMask) {
390b57cec5SDimitry Andric   assert(Redirects.empty() || Redirects.size() == 3);
400b57cec5SDimitry Andric   ProcessInfo PI;
41e8d8bef9SDimitry Andric   if (Execute(PI, Program, Args, Env, Redirects, MemoryLimit, ErrMsg,
42*0fca6ea1SDimitry Andric               AffinityMask, /*DetachProcess=*/false)) {
430b57cec5SDimitry Andric     if (ExecutionFailed)
440b57cec5SDimitry Andric       *ExecutionFailed = false;
45bdd1243dSDimitry Andric     ProcessInfo Result = Wait(
46bdd1243dSDimitry Andric         PI, SecondsToWait == 0 ? std::nullopt : std::optional(SecondsToWait),
475ffd83dbSDimitry Andric         ErrMsg, ProcStat);
480b57cec5SDimitry Andric     return Result.ReturnCode;
490b57cec5SDimitry Andric   }
500b57cec5SDimitry Andric 
510b57cec5SDimitry Andric   if (ExecutionFailed)
520b57cec5SDimitry Andric     *ExecutionFailed = true;
530b57cec5SDimitry Andric 
540b57cec5SDimitry Andric   return -1;
550b57cec5SDimitry Andric }
560b57cec5SDimitry Andric 
570b57cec5SDimitry Andric ProcessInfo sys::ExecuteNoWait(StringRef Program, ArrayRef<StringRef> Args,
58bdd1243dSDimitry Andric                                std::optional<ArrayRef<StringRef>> Env,
59bdd1243dSDimitry Andric                                ArrayRef<std::optional<StringRef>> Redirects,
600b57cec5SDimitry Andric                                unsigned MemoryLimit, std::string *ErrMsg,
61*0fca6ea1SDimitry Andric                                bool *ExecutionFailed, BitVector *AffinityMask,
62*0fca6ea1SDimitry Andric                                bool DetachProcess) {
630b57cec5SDimitry Andric   assert(Redirects.empty() || Redirects.size() == 3);
640b57cec5SDimitry Andric   ProcessInfo PI;
650b57cec5SDimitry Andric   if (ExecutionFailed)
660b57cec5SDimitry Andric     *ExecutionFailed = false;
67e8d8bef9SDimitry Andric   if (!Execute(PI, Program, Args, Env, Redirects, MemoryLimit, ErrMsg,
68*0fca6ea1SDimitry Andric                AffinityMask, DetachProcess))
690b57cec5SDimitry Andric     if (ExecutionFailed)
700b57cec5SDimitry Andric       *ExecutionFailed = true;
710b57cec5SDimitry Andric 
720b57cec5SDimitry Andric   return PI;
730b57cec5SDimitry Andric }
740b57cec5SDimitry Andric 
750b57cec5SDimitry Andric bool sys::commandLineFitsWithinSystemLimits(StringRef Program,
760b57cec5SDimitry Andric                                             ArrayRef<const char *> Args) {
770b57cec5SDimitry Andric   SmallVector<StringRef, 8> StringRefArgs;
780b57cec5SDimitry Andric   StringRefArgs.reserve(Args.size());
790b57cec5SDimitry Andric   for (const char *A : Args)
800b57cec5SDimitry Andric     StringRefArgs.emplace_back(A);
810b57cec5SDimitry Andric   return commandLineFitsWithinSystemLimits(Program, StringRefArgs);
820b57cec5SDimitry Andric }
830b57cec5SDimitry Andric 
845ffd83dbSDimitry Andric void sys::printArg(raw_ostream &OS, StringRef Arg, bool Quote) {
855ffd83dbSDimitry Andric   const bool Escape = Arg.find_first_of(" \"\\$") != StringRef::npos;
865ffd83dbSDimitry Andric 
875ffd83dbSDimitry Andric   if (!Quote && !Escape) {
885ffd83dbSDimitry Andric     OS << Arg;
895ffd83dbSDimitry Andric     return;
905ffd83dbSDimitry Andric   }
915ffd83dbSDimitry Andric 
925ffd83dbSDimitry Andric   // Quote and escape. This isn't really complete, but good enough.
935ffd83dbSDimitry Andric   OS << '"';
945ffd83dbSDimitry Andric   for (const auto c : Arg) {
955ffd83dbSDimitry Andric     if (c == '"' || c == '\\' || c == '$')
965ffd83dbSDimitry Andric       OS << '\\';
975ffd83dbSDimitry Andric     OS << c;
985ffd83dbSDimitry Andric   }
995ffd83dbSDimitry Andric   OS << '"';
1005ffd83dbSDimitry Andric }
1015ffd83dbSDimitry Andric 
1020b57cec5SDimitry Andric // Include the platform-specific parts of this class.
1030b57cec5SDimitry Andric #ifdef LLVM_ON_UNIX
1040b57cec5SDimitry Andric #include "Unix/Program.inc"
1050b57cec5SDimitry Andric #endif
1060b57cec5SDimitry Andric #ifdef _WIN32
1070b57cec5SDimitry Andric #include "Windows/Program.inc"
1080b57cec5SDimitry Andric #endif
109