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