Home | History | Annotate | Line # | Download | only in Support
      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 #include <system_error>
     18 using namespace llvm;
     19 using namespace sys;
     20 
     21 //===----------------------------------------------------------------------===//
     22 //=== WARNING: Implementation here must contain only TRULY operating system
     23 //===          independent code.
     24 //===----------------------------------------------------------------------===//
     25 
     26 static bool Execute(ProcessInfo &PI, StringRef Program,
     27                     ArrayRef<StringRef> Args, Optional<ArrayRef<StringRef>> Env,
     28                     ArrayRef<Optional<StringRef>> Redirects,
     29                     unsigned MemoryLimit, std::string *ErrMsg,
     30                     BitVector *AffinityMask);
     31 
     32 int sys::ExecuteAndWait(StringRef Program, ArrayRef<StringRef> Args,
     33                         Optional<ArrayRef<StringRef>> Env,
     34                         ArrayRef<Optional<StringRef>> Redirects,
     35                         unsigned SecondsToWait, unsigned MemoryLimit,
     36                         std::string *ErrMsg, bool *ExecutionFailed,
     37                         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)) {
     43     if (ExecutionFailed)
     44       *ExecutionFailed = false;
     45     ProcessInfo Result =
     46         Wait(PI, SecondsToWait, /*WaitUntilTerminates=*/SecondsToWait == 0,
     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                                Optional<ArrayRef<StringRef>> Env,
     59                                ArrayRef<Optional<StringRef>> Redirects,
     60                                unsigned MemoryLimit, std::string *ErrMsg,
     61                                bool *ExecutionFailed, BitVector *AffinityMask) {
     62   assert(Redirects.empty() || Redirects.size() == 3);
     63   ProcessInfo PI;
     64   if (ExecutionFailed)
     65     *ExecutionFailed = false;
     66   if (!Execute(PI, Program, Args, Env, Redirects, MemoryLimit, ErrMsg,
     67                AffinityMask))
     68     if (ExecutionFailed)
     69       *ExecutionFailed = true;
     70 
     71   return PI;
     72 }
     73 
     74 bool sys::commandLineFitsWithinSystemLimits(StringRef Program,
     75                                             ArrayRef<const char *> Args) {
     76   SmallVector<StringRef, 8> StringRefArgs;
     77   StringRefArgs.reserve(Args.size());
     78   for (const char *A : Args)
     79     StringRefArgs.emplace_back(A);
     80   return commandLineFitsWithinSystemLimits(Program, StringRefArgs);
     81 }
     82 
     83 void sys::printArg(raw_ostream &OS, StringRef Arg, bool Quote) {
     84   const bool Escape = Arg.find_first_of(" \"\\$") != StringRef::npos;
     85 
     86   if (!Quote && !Escape) {
     87     OS << Arg;
     88     return;
     89   }
     90 
     91   // Quote and escape. This isn't really complete, but good enough.
     92   OS << '"';
     93   for (const auto c : Arg) {
     94     if (c == '"' || c == '\\' || c == '$')
     95       OS << '\\';
     96     OS << c;
     97   }
     98   OS << '"';
     99 }
    100 
    101 // Include the platform-specific parts of this class.
    102 #ifdef LLVM_ON_UNIX
    103 #include "Unix/Program.inc"
    104 #endif
    105 #ifdef _WIN32
    106 #include "Windows/Program.inc"
    107 #endif
    108