10b57cec5SDimitry Andric//===- llvm/Support/Unix/Program.cpp -----------------------------*- 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 Unix specific portion of the Program class.
100b57cec5SDimitry Andric//
110b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric
130b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
140b57cec5SDimitry Andric//=== WARNING: Implementation here must contain only generic UNIX code that
150b57cec5SDimitry Andric//===          is guaranteed to work on *all* UNIX variants.
160b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
170b57cec5SDimitry Andric
180b57cec5SDimitry Andric#include "Unix.h"
190b57cec5SDimitry Andric#include "llvm/ADT/StringExtras.h"
200b57cec5SDimitry Andric#include "llvm/Config/config.h"
210b57cec5SDimitry Andric#include "llvm/Support/Compiler.h"
220b57cec5SDimitry Andric#include "llvm/Support/Errc.h"
230b57cec5SDimitry Andric#include "llvm/Support/FileSystem.h"
240b57cec5SDimitry Andric#include "llvm/Support/Path.h"
250b57cec5SDimitry Andric#include "llvm/Support/StringSaver.h"
260b57cec5SDimitry Andric#include "llvm/Support/raw_ostream.h"
270b57cec5SDimitry Andric#if HAVE_SYS_STAT_H
280b57cec5SDimitry Andric#include <sys/stat.h>
290b57cec5SDimitry Andric#endif
300b57cec5SDimitry Andric#if HAVE_SYS_RESOURCE_H
310b57cec5SDimitry Andric#include <sys/resource.h>
320b57cec5SDimitry Andric#endif
330b57cec5SDimitry Andric#if HAVE_SIGNAL_H
340b57cec5SDimitry Andric#include <signal.h>
350b57cec5SDimitry Andric#endif
360b57cec5SDimitry Andric#if HAVE_FCNTL_H
370b57cec5SDimitry Andric#include <fcntl.h>
380b57cec5SDimitry Andric#endif
390b57cec5SDimitry Andric#if HAVE_UNISTD_H
400b57cec5SDimitry Andric#include <unistd.h>
410b57cec5SDimitry Andric#endif
420b57cec5SDimitry Andric#ifdef HAVE_POSIX_SPAWN
430b57cec5SDimitry Andric#include <spawn.h>
440b57cec5SDimitry Andric
450b57cec5SDimitry Andric#if defined(__APPLE__)
460b57cec5SDimitry Andric#include <TargetConditionals.h>
470b57cec5SDimitry Andric#endif
480b57cec5SDimitry Andric
490b57cec5SDimitry Andric#if defined(__APPLE__) && !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE)
500b57cec5SDimitry Andric#define USE_NSGETENVIRON 1
510b57cec5SDimitry Andric#else
520b57cec5SDimitry Andric#define USE_NSGETENVIRON 0
530b57cec5SDimitry Andric#endif
540b57cec5SDimitry Andric
550b57cec5SDimitry Andric#if !USE_NSGETENVIRON
560b57cec5SDimitry Andric  extern char **environ;
570b57cec5SDimitry Andric#else
580b57cec5SDimitry Andric#include <crt_externs.h> // _NSGetEnviron
590b57cec5SDimitry Andric#endif
600b57cec5SDimitry Andric#endif
610b57cec5SDimitry Andric
620b57cec5SDimitry Andricnamespace llvm {
630b57cec5SDimitry Andric
640b57cec5SDimitry Andricusing namespace sys;
650b57cec5SDimitry Andric
660b57cec5SDimitry AndricProcessInfo::ProcessInfo() : Pid(0), ReturnCode(0) {}
670b57cec5SDimitry Andric
680b57cec5SDimitry AndricErrorOr<std::string> sys::findProgramByName(StringRef Name,
690b57cec5SDimitry Andric                                            ArrayRef<StringRef> Paths) {
700b57cec5SDimitry Andric  assert(!Name.empty() && "Must have a name!");
710b57cec5SDimitry Andric  // Use the given path verbatim if it contains any slashes; this matches
720b57cec5SDimitry Andric  // the behavior of sh(1) and friends.
730b57cec5SDimitry Andric  if (Name.find('/') != StringRef::npos)
740b57cec5SDimitry Andric    return std::string(Name);
750b57cec5SDimitry Andric
760b57cec5SDimitry Andric  SmallVector<StringRef, 16> EnvironmentPaths;
770b57cec5SDimitry Andric  if (Paths.empty())
780b57cec5SDimitry Andric    if (const char *PathEnv = std::getenv("PATH")) {
790b57cec5SDimitry Andric      SplitString(PathEnv, EnvironmentPaths, ":");
800b57cec5SDimitry Andric      Paths = EnvironmentPaths;
810b57cec5SDimitry Andric    }
820b57cec5SDimitry Andric
830b57cec5SDimitry Andric  for (auto Path : Paths) {
840b57cec5SDimitry Andric    if (Path.empty())
850b57cec5SDimitry Andric      continue;
860b57cec5SDimitry Andric
870b57cec5SDimitry Andric    // Check to see if this first directory contains the executable...
880b57cec5SDimitry Andric    SmallString<128> FilePath(Path);
890b57cec5SDimitry Andric    sys::path::append(FilePath, Name);
900b57cec5SDimitry Andric    if (sys::fs::can_execute(FilePath.c_str()))
910b57cec5SDimitry Andric      return std::string(FilePath.str()); // Found the executable!
920b57cec5SDimitry Andric  }
930b57cec5SDimitry Andric  return errc::no_such_file_or_directory;
940b57cec5SDimitry Andric}
950b57cec5SDimitry Andric
960b57cec5SDimitry Andricstatic bool RedirectIO(Optional<StringRef> Path, int FD, std::string* ErrMsg) {
970b57cec5SDimitry Andric  if (!Path) // Noop
980b57cec5SDimitry Andric    return false;
990b57cec5SDimitry Andric  std::string File;
1000b57cec5SDimitry Andric  if (Path->empty())
1010b57cec5SDimitry Andric    // Redirect empty paths to /dev/null
1020b57cec5SDimitry Andric    File = "/dev/null";
1030b57cec5SDimitry Andric  else
1040b57cec5SDimitry Andric    File = *Path;
1050b57cec5SDimitry Andric
1060b57cec5SDimitry Andric  // Open the file
1070b57cec5SDimitry Andric  int InFD = open(File.c_str(), FD == 0 ? O_RDONLY : O_WRONLY|O_CREAT, 0666);
1080b57cec5SDimitry Andric  if (InFD == -1) {
1090b57cec5SDimitry Andric    MakeErrMsg(ErrMsg, "Cannot open file '" + File + "' for "
1100b57cec5SDimitry Andric              + (FD == 0 ? "input" : "output"));
1110b57cec5SDimitry Andric    return true;
1120b57cec5SDimitry Andric  }
1130b57cec5SDimitry Andric
1140b57cec5SDimitry Andric  // Install it as the requested FD
1150b57cec5SDimitry Andric  if (dup2(InFD, FD) == -1) {
1160b57cec5SDimitry Andric    MakeErrMsg(ErrMsg, "Cannot dup2");
1170b57cec5SDimitry Andric    close(InFD);
1180b57cec5SDimitry Andric    return true;
1190b57cec5SDimitry Andric  }
1200b57cec5SDimitry Andric  close(InFD);      // Close the original FD
1210b57cec5SDimitry Andric  return false;
1220b57cec5SDimitry Andric}
1230b57cec5SDimitry Andric
1240b57cec5SDimitry Andric#ifdef HAVE_POSIX_SPAWN
1250b57cec5SDimitry Andricstatic bool RedirectIO_PS(const std::string *Path, int FD, std::string *ErrMsg,
1260b57cec5SDimitry Andric                          posix_spawn_file_actions_t *FileActions) {
1270b57cec5SDimitry Andric  if (!Path) // Noop
1280b57cec5SDimitry Andric    return false;
1290b57cec5SDimitry Andric  const char *File;
1300b57cec5SDimitry Andric  if (Path->empty())
1310b57cec5SDimitry Andric    // Redirect empty paths to /dev/null
1320b57cec5SDimitry Andric    File = "/dev/null";
1330b57cec5SDimitry Andric  else
1340b57cec5SDimitry Andric    File = Path->c_str();
1350b57cec5SDimitry Andric
1360b57cec5SDimitry Andric  if (int Err = posix_spawn_file_actions_addopen(
1370b57cec5SDimitry Andric          FileActions, FD, File,
1380b57cec5SDimitry Andric          FD == 0 ? O_RDONLY : O_WRONLY | O_CREAT, 0666))
1390b57cec5SDimitry Andric    return MakeErrMsg(ErrMsg, "Cannot dup2", Err);
1400b57cec5SDimitry Andric  return false;
1410b57cec5SDimitry Andric}
1420b57cec5SDimitry Andric#endif
1430b57cec5SDimitry Andric
1440b57cec5SDimitry Andricstatic void TimeOutHandler(int Sig) {
1450b57cec5SDimitry Andric}
1460b57cec5SDimitry Andric
1470b57cec5SDimitry Andricstatic void SetMemoryLimits(unsigned size) {
1480b57cec5SDimitry Andric#if HAVE_SYS_RESOURCE_H && HAVE_GETRLIMIT && HAVE_SETRLIMIT
1490b57cec5SDimitry Andric  struct rlimit r;
1500b57cec5SDimitry Andric  __typeof__ (r.rlim_cur) limit = (__typeof__ (r.rlim_cur)) (size) * 1048576;
1510b57cec5SDimitry Andric
1520b57cec5SDimitry Andric  // Heap size
1530b57cec5SDimitry Andric  getrlimit (RLIMIT_DATA, &r);
1540b57cec5SDimitry Andric  r.rlim_cur = limit;
1550b57cec5SDimitry Andric  setrlimit (RLIMIT_DATA, &r);
1560b57cec5SDimitry Andric#ifdef RLIMIT_RSS
1570b57cec5SDimitry Andric  // Resident set size.
1580b57cec5SDimitry Andric  getrlimit (RLIMIT_RSS, &r);
1590b57cec5SDimitry Andric  r.rlim_cur = limit;
1600b57cec5SDimitry Andric  setrlimit (RLIMIT_RSS, &r);
1610b57cec5SDimitry Andric#endif
1620b57cec5SDimitry Andric#endif
1630b57cec5SDimitry Andric}
1640b57cec5SDimitry Andric
1650b57cec5SDimitry Andric}
1660b57cec5SDimitry Andric
1670b57cec5SDimitry Andricstatic std::vector<const char *>
1680b57cec5SDimitry AndrictoNullTerminatedCStringArray(ArrayRef<StringRef> Strings, StringSaver &Saver) {
1690b57cec5SDimitry Andric  std::vector<const char *> Result;
1700b57cec5SDimitry Andric  for (StringRef S : Strings)
1710b57cec5SDimitry Andric    Result.push_back(Saver.save(S).data());
1720b57cec5SDimitry Andric  Result.push_back(nullptr);
1730b57cec5SDimitry Andric  return Result;
1740b57cec5SDimitry Andric}
1750b57cec5SDimitry Andric
1760b57cec5SDimitry Andricstatic bool Execute(ProcessInfo &PI, StringRef Program,
1770b57cec5SDimitry Andric                    ArrayRef<StringRef> Args, Optional<ArrayRef<StringRef>> Env,
1780b57cec5SDimitry Andric                    ArrayRef<Optional<StringRef>> Redirects,
1790b57cec5SDimitry Andric                    unsigned MemoryLimit, std::string *ErrMsg) {
1800b57cec5SDimitry Andric  if (!llvm::sys::fs::exists(Program)) {
1810b57cec5SDimitry Andric    if (ErrMsg)
1820b57cec5SDimitry Andric      *ErrMsg = std::string("Executable \"") + Program.str() +
1830b57cec5SDimitry Andric                std::string("\" doesn't exist!");
1840b57cec5SDimitry Andric    return false;
1850b57cec5SDimitry Andric  }
1860b57cec5SDimitry Andric
1870b57cec5SDimitry Andric  BumpPtrAllocator Allocator;
1880b57cec5SDimitry Andric  StringSaver Saver(Allocator);
1890b57cec5SDimitry Andric  std::vector<const char *> ArgVector, EnvVector;
1900b57cec5SDimitry Andric  const char **Argv = nullptr;
1910b57cec5SDimitry Andric  const char **Envp = nullptr;
1920b57cec5SDimitry Andric  ArgVector = toNullTerminatedCStringArray(Args, Saver);
1930b57cec5SDimitry Andric  Argv = ArgVector.data();
1940b57cec5SDimitry Andric  if (Env) {
1950b57cec5SDimitry Andric    EnvVector = toNullTerminatedCStringArray(*Env, Saver);
1960b57cec5SDimitry Andric    Envp = EnvVector.data();
1970b57cec5SDimitry Andric  }
1980b57cec5SDimitry Andric
1990b57cec5SDimitry Andric  // If this OS has posix_spawn and there is no memory limit being implied, use
2000b57cec5SDimitry Andric  // posix_spawn.  It is more efficient than fork/exec.
2010b57cec5SDimitry Andric#ifdef HAVE_POSIX_SPAWN
2020b57cec5SDimitry Andric  if (MemoryLimit == 0) {
2030b57cec5SDimitry Andric    posix_spawn_file_actions_t FileActionsStore;
2040b57cec5SDimitry Andric    posix_spawn_file_actions_t *FileActions = nullptr;
2050b57cec5SDimitry Andric
2060b57cec5SDimitry Andric    // If we call posix_spawn_file_actions_addopen we have to make sure the
2070b57cec5SDimitry Andric    // c strings we pass to it stay alive until the call to posix_spawn,
2080b57cec5SDimitry Andric    // so we copy any StringRefs into this variable.
2090b57cec5SDimitry Andric    std::string RedirectsStorage[3];
2100b57cec5SDimitry Andric
2110b57cec5SDimitry Andric    if (!Redirects.empty()) {
2120b57cec5SDimitry Andric      assert(Redirects.size() == 3);
2130b57cec5SDimitry Andric      std::string *RedirectsStr[3] = {nullptr, nullptr, nullptr};
2140b57cec5SDimitry Andric      for (int I = 0; I < 3; ++I) {
2150b57cec5SDimitry Andric        if (Redirects[I]) {
2160b57cec5SDimitry Andric          RedirectsStorage[I] = *Redirects[I];
2170b57cec5SDimitry Andric          RedirectsStr[I] = &RedirectsStorage[I];
2180b57cec5SDimitry Andric        }
2190b57cec5SDimitry Andric      }
2200b57cec5SDimitry Andric
2210b57cec5SDimitry Andric      FileActions = &FileActionsStore;
2220b57cec5SDimitry Andric      posix_spawn_file_actions_init(FileActions);
2230b57cec5SDimitry Andric
2240b57cec5SDimitry Andric      // Redirect stdin/stdout.
2250b57cec5SDimitry Andric      if (RedirectIO_PS(RedirectsStr[0], 0, ErrMsg, FileActions) ||
2260b57cec5SDimitry Andric          RedirectIO_PS(RedirectsStr[1], 1, ErrMsg, FileActions))
2270b57cec5SDimitry Andric        return false;
2280b57cec5SDimitry Andric      if (!Redirects[1] || !Redirects[2] || *Redirects[1] != *Redirects[2]) {
2290b57cec5SDimitry Andric        // Just redirect stderr
2300b57cec5SDimitry Andric        if (RedirectIO_PS(RedirectsStr[2], 2, ErrMsg, FileActions))
2310b57cec5SDimitry Andric          return false;
2320b57cec5SDimitry Andric      } else {
2330b57cec5SDimitry Andric        // If stdout and stderr should go to the same place, redirect stderr
2340b57cec5SDimitry Andric        // to the FD already open for stdout.
2350b57cec5SDimitry Andric        if (int Err = posix_spawn_file_actions_adddup2(FileActions, 1, 2))
2360b57cec5SDimitry Andric          return !MakeErrMsg(ErrMsg, "Can't redirect stderr to stdout", Err);
2370b57cec5SDimitry Andric      }
2380b57cec5SDimitry Andric    }
2390b57cec5SDimitry Andric
2400b57cec5SDimitry Andric    if (!Envp)
2410b57cec5SDimitry Andric#if !USE_NSGETENVIRON
2420b57cec5SDimitry Andric      Envp = const_cast<const char **>(environ);
2430b57cec5SDimitry Andric#else
2440b57cec5SDimitry Andric      // environ is missing in dylibs.
2450b57cec5SDimitry Andric      Envp = const_cast<const char **>(*_NSGetEnviron());
2460b57cec5SDimitry Andric#endif
2470b57cec5SDimitry Andric
2480b57cec5SDimitry Andric    constexpr int maxRetries = 8;
2490b57cec5SDimitry Andric    int retries = 0;
2500b57cec5SDimitry Andric    pid_t PID;
2510b57cec5SDimitry Andric    int Err;
2520b57cec5SDimitry Andric    do {
2530b57cec5SDimitry Andric      PID = 0; // Make Valgrind happy.
2540b57cec5SDimitry Andric      Err = posix_spawn(&PID, Program.str().c_str(), FileActions,
2550b57cec5SDimitry Andric                        /*attrp*/ nullptr, const_cast<char **>(Argv),
2560b57cec5SDimitry Andric                        const_cast<char **>(Envp));
2570b57cec5SDimitry Andric    } while (Err == EINTR && ++retries < maxRetries);
2580b57cec5SDimitry Andric
2590b57cec5SDimitry Andric    if (FileActions)
2600b57cec5SDimitry Andric      posix_spawn_file_actions_destroy(FileActions);
2610b57cec5SDimitry Andric
2620b57cec5SDimitry Andric    if (Err)
2630b57cec5SDimitry Andric     return !MakeErrMsg(ErrMsg, "posix_spawn failed", Err);
2640b57cec5SDimitry Andric
2650b57cec5SDimitry Andric    PI.Pid = PID;
2660b57cec5SDimitry Andric    PI.Process = PID;
2670b57cec5SDimitry Andric
2680b57cec5SDimitry Andric    return true;
2690b57cec5SDimitry Andric  }
2700b57cec5SDimitry Andric#endif
2710b57cec5SDimitry Andric
2720b57cec5SDimitry Andric  // Create a child process.
2730b57cec5SDimitry Andric  int child = fork();
2740b57cec5SDimitry Andric  switch (child) {
2750b57cec5SDimitry Andric    // An error occurred:  Return to the caller.
2760b57cec5SDimitry Andric    case -1:
2770b57cec5SDimitry Andric      MakeErrMsg(ErrMsg, "Couldn't fork");
2780b57cec5SDimitry Andric      return false;
2790b57cec5SDimitry Andric
2800b57cec5SDimitry Andric    // Child process: Execute the program.
2810b57cec5SDimitry Andric    case 0: {
2820b57cec5SDimitry Andric      // Redirect file descriptors...
2830b57cec5SDimitry Andric      if (!Redirects.empty()) {
2840b57cec5SDimitry Andric        // Redirect stdin
2850b57cec5SDimitry Andric        if (RedirectIO(Redirects[0], 0, ErrMsg)) { return false; }
2860b57cec5SDimitry Andric        // Redirect stdout
2870b57cec5SDimitry Andric        if (RedirectIO(Redirects[1], 1, ErrMsg)) { return false; }
2880b57cec5SDimitry Andric        if (Redirects[1] && Redirects[2] && *Redirects[1] == *Redirects[2]) {
2890b57cec5SDimitry Andric          // If stdout and stderr should go to the same place, redirect stderr
2900b57cec5SDimitry Andric          // to the FD already open for stdout.
2910b57cec5SDimitry Andric          if (-1 == dup2(1,2)) {
2920b57cec5SDimitry Andric            MakeErrMsg(ErrMsg, "Can't redirect stderr to stdout");
2930b57cec5SDimitry Andric            return false;
2940b57cec5SDimitry Andric          }
2950b57cec5SDimitry Andric        } else {
2960b57cec5SDimitry Andric          // Just redirect stderr
2970b57cec5SDimitry Andric          if (RedirectIO(Redirects[2], 2, ErrMsg)) { return false; }
2980b57cec5SDimitry Andric        }
2990b57cec5SDimitry Andric      }
3000b57cec5SDimitry Andric
3010b57cec5SDimitry Andric      // Set memory limits
3020b57cec5SDimitry Andric      if (MemoryLimit!=0) {
3030b57cec5SDimitry Andric        SetMemoryLimits(MemoryLimit);
3040b57cec5SDimitry Andric      }
3050b57cec5SDimitry Andric
3060b57cec5SDimitry Andric      // Execute!
3070b57cec5SDimitry Andric      std::string PathStr = Program;
3080b57cec5SDimitry Andric      if (Envp != nullptr)
3090b57cec5SDimitry Andric        execve(PathStr.c_str(), const_cast<char **>(Argv),
3100b57cec5SDimitry Andric               const_cast<char **>(Envp));
3110b57cec5SDimitry Andric      else
3120b57cec5SDimitry Andric        execv(PathStr.c_str(), const_cast<char **>(Argv));
3130b57cec5SDimitry Andric      // If the execve() failed, we should exit. Follow Unix protocol and
3140b57cec5SDimitry Andric      // return 127 if the executable was not found, and 126 otherwise.
3150b57cec5SDimitry Andric      // Use _exit rather than exit so that atexit functions and static
3160b57cec5SDimitry Andric      // object destructors cloned from the parent process aren't
3170b57cec5SDimitry Andric      // redundantly run, and so that any data buffered in stdio buffers
3180b57cec5SDimitry Andric      // cloned from the parent aren't redundantly written out.
3190b57cec5SDimitry Andric      _exit(errno == ENOENT ? 127 : 126);
3200b57cec5SDimitry Andric    }
3210b57cec5SDimitry Andric
3220b57cec5SDimitry Andric    // Parent process: Break out of the switch to do our processing.
3230b57cec5SDimitry Andric    default:
3240b57cec5SDimitry Andric      break;
3250b57cec5SDimitry Andric  }
3260b57cec5SDimitry Andric
3270b57cec5SDimitry Andric  PI.Pid = child;
3280b57cec5SDimitry Andric  PI.Process = child;
3290b57cec5SDimitry Andric
3300b57cec5SDimitry Andric  return true;
3310b57cec5SDimitry Andric}
3320b57cec5SDimitry Andric
3330b57cec5SDimitry Andricnamespace llvm {
3340b57cec5SDimitry Andric
3350b57cec5SDimitry AndricProcessInfo sys::Wait(const ProcessInfo &PI, unsigned SecondsToWait,
3360b57cec5SDimitry Andric                      bool WaitUntilTerminates, std::string *ErrMsg) {
3370b57cec5SDimitry Andric  struct sigaction Act, Old;
3380b57cec5SDimitry Andric  assert(PI.Pid && "invalid pid to wait on, process not started?");
3390b57cec5SDimitry Andric
3400b57cec5SDimitry Andric  int WaitPidOptions = 0;
3410b57cec5SDimitry Andric  pid_t ChildPid = PI.Pid;
3420b57cec5SDimitry Andric  if (WaitUntilTerminates) {
3430b57cec5SDimitry Andric    SecondsToWait = 0;
3440b57cec5SDimitry Andric  } else if (SecondsToWait) {
3450b57cec5SDimitry Andric    // Install a timeout handler.  The handler itself does nothing, but the
3460b57cec5SDimitry Andric    // simple fact of having a handler at all causes the wait below to return
3470b57cec5SDimitry Andric    // with EINTR, unlike if we used SIG_IGN.
3480b57cec5SDimitry Andric    memset(&Act, 0, sizeof(Act));
3490b57cec5SDimitry Andric    Act.sa_handler = TimeOutHandler;
3500b57cec5SDimitry Andric    sigemptyset(&Act.sa_mask);
3510b57cec5SDimitry Andric    sigaction(SIGALRM, &Act, &Old);
3520b57cec5SDimitry Andric    alarm(SecondsToWait);
3530b57cec5SDimitry Andric  } else if (SecondsToWait == 0)
3540b57cec5SDimitry Andric    WaitPidOptions = WNOHANG;
3550b57cec5SDimitry Andric
3560b57cec5SDimitry Andric  // Parent process: Wait for the child process to terminate.
3570b57cec5SDimitry Andric  int status;
3580b57cec5SDimitry Andric  ProcessInfo WaitResult;
3590b57cec5SDimitry Andric
3600b57cec5SDimitry Andric  do {
3610b57cec5SDimitry Andric    WaitResult.Pid = waitpid(ChildPid, &status, WaitPidOptions);
3620b57cec5SDimitry Andric  } while (WaitUntilTerminates && WaitResult.Pid == -1 && errno == EINTR);
3630b57cec5SDimitry Andric
3640b57cec5SDimitry Andric  if (WaitResult.Pid != PI.Pid) {
3650b57cec5SDimitry Andric    if (WaitResult.Pid == 0) {
3660b57cec5SDimitry Andric      // Non-blocking wait.
3670b57cec5SDimitry Andric      return WaitResult;
3680b57cec5SDimitry Andric    } else {
3690b57cec5SDimitry Andric      if (SecondsToWait && errno == EINTR) {
3700b57cec5SDimitry Andric        // Kill the child.
3710b57cec5SDimitry Andric        kill(PI.Pid, SIGKILL);
3720b57cec5SDimitry Andric
3730b57cec5SDimitry Andric        // Turn off the alarm and restore the signal handler
3740b57cec5SDimitry Andric        alarm(0);
3750b57cec5SDimitry Andric        sigaction(SIGALRM, &Old, nullptr);
3760b57cec5SDimitry Andric
3770b57cec5SDimitry Andric        // Wait for child to die
3780b57cec5SDimitry Andric        if (wait(&status) != ChildPid)
3790b57cec5SDimitry Andric          MakeErrMsg(ErrMsg, "Child timed out but wouldn't die");
3800b57cec5SDimitry Andric        else
3810b57cec5SDimitry Andric          MakeErrMsg(ErrMsg, "Child timed out", 0);
3820b57cec5SDimitry Andric
3830b57cec5SDimitry Andric        WaitResult.ReturnCode = -2; // Timeout detected
3840b57cec5SDimitry Andric        return WaitResult;
3850b57cec5SDimitry Andric      } else if (errno != EINTR) {
3860b57cec5SDimitry Andric        MakeErrMsg(ErrMsg, "Error waiting for child process");
3870b57cec5SDimitry Andric        WaitResult.ReturnCode = -1;
3880b57cec5SDimitry Andric        return WaitResult;
3890b57cec5SDimitry Andric      }
3900b57cec5SDimitry Andric    }
3910b57cec5SDimitry Andric  }
3920b57cec5SDimitry Andric
3930b57cec5SDimitry Andric  // We exited normally without timeout, so turn off the timer.
3940b57cec5SDimitry Andric  if (SecondsToWait && !WaitUntilTerminates) {
3950b57cec5SDimitry Andric    alarm(0);
3960b57cec5SDimitry Andric    sigaction(SIGALRM, &Old, nullptr);
3970b57cec5SDimitry Andric  }
3980b57cec5SDimitry Andric
3990b57cec5SDimitry Andric  // Return the proper exit status. Detect error conditions
4000b57cec5SDimitry Andric  // so we can return -1 for them and set ErrMsg informatively.
4010b57cec5SDimitry Andric  int result = 0;
4020b57cec5SDimitry Andric  if (WIFEXITED(status)) {
4030b57cec5SDimitry Andric    result = WEXITSTATUS(status);
4040b57cec5SDimitry Andric    WaitResult.ReturnCode = result;
4050b57cec5SDimitry Andric
4060b57cec5SDimitry Andric    if (result == 127) {
4070b57cec5SDimitry Andric      if (ErrMsg)
4080b57cec5SDimitry Andric        *ErrMsg = llvm::sys::StrError(ENOENT);
4090b57cec5SDimitry Andric      WaitResult.ReturnCode = -1;
4100b57cec5SDimitry Andric      return WaitResult;
4110b57cec5SDimitry Andric    }
4120b57cec5SDimitry Andric    if (result == 126) {
4130b57cec5SDimitry Andric      if (ErrMsg)
4140b57cec5SDimitry Andric        *ErrMsg = "Program could not be executed";
4150b57cec5SDimitry Andric      WaitResult.ReturnCode = -1;
4160b57cec5SDimitry Andric      return WaitResult;
4170b57cec5SDimitry Andric    }
4180b57cec5SDimitry Andric  } else if (WIFSIGNALED(status)) {
4190b57cec5SDimitry Andric    if (ErrMsg) {
4200b57cec5SDimitry Andric      *ErrMsg = strsignal(WTERMSIG(status));
4210b57cec5SDimitry Andric#ifdef WCOREDUMP
4220b57cec5SDimitry Andric      if (WCOREDUMP(status))
4230b57cec5SDimitry Andric        *ErrMsg += " (core dumped)";
4240b57cec5SDimitry Andric#endif
4250b57cec5SDimitry Andric    }
4260b57cec5SDimitry Andric    // Return a special value to indicate that the process received an unhandled
4270b57cec5SDimitry Andric    // signal during execution as opposed to failing to execute.
4280b57cec5SDimitry Andric    WaitResult.ReturnCode = -2;
4290b57cec5SDimitry Andric  }
4300b57cec5SDimitry Andric  return WaitResult;
4310b57cec5SDimitry Andric}
4320b57cec5SDimitry Andric
4330b57cec5SDimitry Andricstd::error_code sys::ChangeStdinToBinary() {
4340b57cec5SDimitry Andric  // Do nothing, as Unix doesn't differentiate between text and binary.
4350b57cec5SDimitry Andric  return std::error_code();
4360b57cec5SDimitry Andric}
4370b57cec5SDimitry Andric
4380b57cec5SDimitry Andricstd::error_code sys::ChangeStdoutToBinary() {
4390b57cec5SDimitry Andric  // Do nothing, as Unix doesn't differentiate between text and binary.
4400b57cec5SDimitry Andric  return std::error_code();
4410b57cec5SDimitry Andric}
4420b57cec5SDimitry Andric
4430b57cec5SDimitry Andricstd::error_code
4440b57cec5SDimitry Andricllvm::sys::writeFileWithEncoding(StringRef FileName, StringRef Contents,
4450b57cec5SDimitry Andric                                 WindowsEncodingMethod Encoding /*unused*/) {
4460b57cec5SDimitry Andric  std::error_code EC;
4470b57cec5SDimitry Andric  llvm::raw_fd_ostream OS(FileName, EC, llvm::sys::fs::OpenFlags::F_Text);
4480b57cec5SDimitry Andric
4490b57cec5SDimitry Andric  if (EC)
4500b57cec5SDimitry Andric    return EC;
4510b57cec5SDimitry Andric
4520b57cec5SDimitry Andric  OS << Contents;
4530b57cec5SDimitry Andric
4540b57cec5SDimitry Andric  if (OS.has_error())
4550b57cec5SDimitry Andric    return make_error_code(errc::io_error);
4560b57cec5SDimitry Andric
4570b57cec5SDimitry Andric  return EC;
4580b57cec5SDimitry Andric}
4590b57cec5SDimitry Andric
4600b57cec5SDimitry Andricbool llvm::sys::commandLineFitsWithinSystemLimits(StringRef Program,
4610b57cec5SDimitry Andric                                                  ArrayRef<StringRef> Args) {
4620b57cec5SDimitry Andric  static long ArgMax = sysconf(_SC_ARG_MAX);
4630b57cec5SDimitry Andric  // POSIX requires that _POSIX_ARG_MAX is 4096, which is the lowest possible
4640b57cec5SDimitry Andric  // value for ARG_MAX on a POSIX compliant system.
4650b57cec5SDimitry Andric  static long ArgMin = _POSIX_ARG_MAX;
4660b57cec5SDimitry Andric
4670b57cec5SDimitry Andric  // This the same baseline used by xargs.
4680b57cec5SDimitry Andric  long EffectiveArgMax = 128 * 1024;
4690b57cec5SDimitry Andric
4700b57cec5SDimitry Andric  if (EffectiveArgMax > ArgMax)
4710b57cec5SDimitry Andric    EffectiveArgMax = ArgMax;
4720b57cec5SDimitry Andric  else if (EffectiveArgMax < ArgMin)
4730b57cec5SDimitry Andric    EffectiveArgMax = ArgMin;
4740b57cec5SDimitry Andric
4750b57cec5SDimitry Andric  // System says no practical limit.
4760b57cec5SDimitry Andric  if (ArgMax == -1)
4770b57cec5SDimitry Andric    return true;
4780b57cec5SDimitry Andric
4790b57cec5SDimitry Andric  // Conservatively account for space required by environment variables.
4800b57cec5SDimitry Andric  long HalfArgMax = EffectiveArgMax / 2;
4810b57cec5SDimitry Andric
4820b57cec5SDimitry Andric  size_t ArgLength = Program.size() + 1;
4830b57cec5SDimitry Andric  for (StringRef Arg : Args) {
4840b57cec5SDimitry Andric    // Ensure that we do not exceed the MAX_ARG_STRLEN constant on Linux, which
4850b57cec5SDimitry Andric    // does not have a constant unlike what the man pages would have you
4860b57cec5SDimitry Andric    // believe. Since this limit is pretty high, perform the check
4870b57cec5SDimitry Andric    // unconditionally rather than trying to be aggressive and limiting it to
4880b57cec5SDimitry Andric    // Linux only.
4890b57cec5SDimitry Andric    if (Arg.size() >= (32 * 4096))
4900b57cec5SDimitry Andric      return false;
4910b57cec5SDimitry Andric
4920b57cec5SDimitry Andric    ArgLength += Arg.size() + 1;
4930b57cec5SDimitry Andric    if (ArgLength > size_t(HalfArgMax)) {
4940b57cec5SDimitry Andric      return false;
4950b57cec5SDimitry Andric    }
4960b57cec5SDimitry Andric  }
4970b57cec5SDimitry Andric
4980b57cec5SDimitry Andric  return true;
4990b57cec5SDimitry Andric}
5000b57cec5SDimitry Andric}
501