// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/process/launch.h"

#include <crt_externs.h>
#include <mach/mach.h>
#include <spawn.h>
#include <string.h>
#include <sys/syscall.h>
#include <sys/wait.h>

#include "base/command_line.h"
#include "base/files/scoped_file.h"
#include "base/logging.h"
#include "base/mac/availability.h"
#include "base/posix/eintr_wrapper.h"
#include "base/process/environment_internal.h"
#include "base/threading/scoped_blocking_call.h"
#include "base/threading/thread_restrictions.h"
#include "base/trace_event/trace_event.h"

// Changes the current thread's directory to a path or directory file
// descriptor. libpthread only exposes a syscall wrapper starting in
// macOS 10.12, but the system call dates back to macOS 10.5. On older OSes,
// the syscall is issued directly.
extern "C" {
int pthread_chdir_np(const char*) API_AVAILABLE(macosx(10.12));
int pthread_fchdir_np(int fd) API_AVAILABLE(macosx(10.12));
}

namespace base {

// Friend and derived class of ScopedAllowBaseSyncPrimitives which allows
// GetAppOutputInternal() to join a process. GetAppOutputInternal() can't itself
// be a friend of ScopedAllowBaseSyncPrimitives because it is in the anonymous
// namespace.
class GetAppOutputScopedAllowBaseSyncPrimitives
    : public base::ScopedAllowBaseSyncPrimitives {};

namespace {

// DPSXCHECK is a Debug Posix Spawn Check macro. The posix_spawn* family of
// functions return an errno value, as opposed to setting errno directly. This
// macro emulates a DPCHECK().
#define DPSXCHECK(expr)                                              \
  do {                                                               \
    int rv = (expr);                                                 \
    DCHECK_EQ(rv, 0) << #expr << ": -" << rv << " " << strerror(rv); \
  } while (0)

class PosixSpawnAttr {
 public:
  PosixSpawnAttr() { DPSXCHECK(posix_spawnattr_init(&attr_)); }

  ~PosixSpawnAttr() { DPSXCHECK(posix_spawnattr_destroy(&attr_)); }

  posix_spawnattr_t* get() { return &attr_; }

 private:
  posix_spawnattr_t attr_;
};

class PosixSpawnFileActions {
 public:
  PosixSpawnFileActions() {
    DPSXCHECK(posix_spawn_file_actions_init(&file_actions_));
  }

  ~PosixSpawnFileActions() {
    DPSXCHECK(posix_spawn_file_actions_destroy(&file_actions_));
  }

  void Open(int filedes, const char* path, int mode) {
    DPSXCHECK(posix_spawn_file_actions_addopen(&file_actions_, filedes, path,
                                               mode, 0));
  }

  void Dup2(int filedes, int newfiledes) {
    DPSXCHECK(
        posix_spawn_file_actions_adddup2(&file_actions_, filedes, newfiledes));
  }

  void Inherit(int filedes) {
    DPSXCHECK(posix_spawn_file_actions_addinherit_np(&file_actions_, filedes));
  }

  const posix_spawn_file_actions_t* get() const { return &file_actions_; }

 private:
  posix_spawn_file_actions_t file_actions_;

  DISALLOW_COPY_AND_ASSIGN(PosixSpawnFileActions);
};

int ChangeCurrentThreadDirectory(const char* path) {
  if (__builtin_available(macOS 10.12, *)) {
    return pthread_chdir_np(path);
  } else {
    return syscall(SYS___pthread_chdir, path);
  }
}

// The recommended way to unset a per-thread cwd is to set a new value to an
// invalid file descriptor, per libpthread-218.1.3/private/private.h.
int ResetCurrentThreadDirectory() {
  if (__builtin_available(macOS 10.12, *)) {
    return pthread_fchdir_np(-1);
  } else {
    return syscall(SYS___pthread_fchdir, -1);
  }
}

struct GetAppOutputOptions {
  // Whether to pipe stderr to stdout in |output|.
  bool include_stderr = false;
  // Caller-supplied string poiter for the output.
  std::string* output = nullptr;
  // Result exit code of Process::Wait().
  int exit_code = 0;
};

bool GetAppOutputInternal(const std::vector<std::string>& argv,
                          GetAppOutputOptions* gao_options) {
  ScopedFD read_fd, write_fd;
  {
    int pipefds[2];
    if (pipe(pipefds) != 0) {
      DPLOG(ERROR) << "pipe";
      return false;
    }
    read_fd.reset(pipefds[0]);
    write_fd.reset(pipefds[1]);
  }

  LaunchOptions launch_options;
  launch_options.fds_to_remap.emplace_back(write_fd.get(), STDOUT_FILENO);
  if (gao_options->include_stderr) {
    launch_options.fds_to_remap.emplace_back(write_fd.get(), STDERR_FILENO);
  }

  Process process = LaunchProcess(argv, launch_options);

  // Close the parent process' write descriptor, so that EOF is generated in
  // read loop below.
  write_fd.reset();

  // Read the child's output before waiting for its exit, otherwise the pipe
  // buffer may fill up if the process is producing a lot of output.
  std::string* output = gao_options->output;
  output->clear();

  const size_t kBufferSize = 1024;
  size_t total_bytes_read = 0;
  ssize_t read_this_pass = 0;
  do {
    output->resize(output->size() + kBufferSize);
    read_this_pass = HANDLE_EINTR(
        read(read_fd.get(), &(*output)[total_bytes_read], kBufferSize));
    if (read_this_pass >= 0) {
      total_bytes_read += read_this_pass;
      output->resize(total_bytes_read);
    }
  } while (read_this_pass > 0);

  // Reap the child process.
  GetAppOutputScopedAllowBaseSyncPrimitives allow_wait;
  if (!process.WaitForExit(&gao_options->exit_code)) {
    return false;
  }

  return read_this_pass == 0;
}

}  // namespace

Process LaunchProcess(const CommandLine& cmdline,
                      const LaunchOptions& options) {
  return LaunchProcess(cmdline.argv(), options);
}

Process LaunchProcess(const std::vector<std::string>& argv,
                      const LaunchOptions& options) {
  TRACE_EVENT0("base", "LaunchProcess");

  PosixSpawnAttr attr;

  short flags = POSIX_SPAWN_CLOEXEC_DEFAULT;
  if (options.new_process_group) {
    flags |= POSIX_SPAWN_SETPGROUP;
    DPSXCHECK(posix_spawnattr_setpgroup(attr.get(), 0));
  }
  DPSXCHECK(posix_spawnattr_setflags(attr.get(), flags));

  PosixSpawnFileActions file_actions;

  // Process file descriptors for the child. By default, LaunchProcess will
  // open stdin to /dev/null and inherit stdout and stderr.
  bool inherit_stdout = true, inherit_stderr = true;
  bool null_stdin = true;
  for (const auto& dup2_pair : options.fds_to_remap) {
    if (dup2_pair.second == STDIN_FILENO) {
      null_stdin = false;
    } else if (dup2_pair.second == STDOUT_FILENO) {
      inherit_stdout = false;
    } else if (dup2_pair.second == STDERR_FILENO) {
      inherit_stderr = false;
    }

    if (dup2_pair.first == dup2_pair.second) {
      file_actions.Inherit(dup2_pair.second);
    } else {
      file_actions.Dup2(dup2_pair.first, dup2_pair.second);
    }
  }

  if (null_stdin) {
    file_actions.Open(STDIN_FILENO, "/dev/null", O_RDONLY);
  }
  if (inherit_stdout) {
    file_actions.Inherit(STDOUT_FILENO);
  }
  if (inherit_stderr) {
    file_actions.Inherit(STDERR_FILENO);
  }

  std::vector<char*> argv_cstr;
  argv_cstr.reserve(argv.size() + 1);
  for (const auto& arg : argv)
    argv_cstr.push_back(const_cast<char*>(arg.c_str()));
  argv_cstr.push_back(nullptr);

  std::unique_ptr<char*[]> owned_environ;
  char* empty_environ = nullptr;
  char** new_environ =
      options.clear_environment ? &empty_environ : *_NSGetEnviron();
  if (!options.environment.empty()) {
    owned_environ =
        internal::AlterEnvironment(new_environ, options.environment);
    new_environ = owned_environ.get();
  }

  const char* executable_path = !options.real_path.empty()
                                    ? options.real_path.value().c_str()
                                    : argv_cstr[0];

  // If the new program has specified its PWD, change the thread-specific
  // working directory. The new process will inherit it during posix_spawnp().
  if (!options.current_directory.empty()) {
    int rv =
        ChangeCurrentThreadDirectory(options.current_directory.value().c_str());
    if (rv != 0) {
      DPLOG(ERROR) << "pthread_chdir_np";
      return Process();
    }
  }

  int rv;
  pid_t pid;
  {
    // If |options.mach_ports_for_rendezvous| is specified : the server's lock
    // must be held for the duration of posix_spawnp() so that new child's PID
    // can be recorded with the set of ports.
    const bool has_mac_ports_for_rendezvous =
        !options.mach_ports_for_rendezvous.empty();
    AutoLockMaybe rendezvous_lock(
        has_mac_ports_for_rendezvous
            ? &MachPortRendezvousServer::GetInstance()->GetLock()
            : nullptr);

    // Use posix_spawnp as some callers expect to have PATH consulted.
    rv = posix_spawnp(&pid, executable_path, file_actions.get(), attr.get(),
                      &argv_cstr[0], new_environ);

    if (has_mac_ports_for_rendezvous) {
      auto* rendezvous = MachPortRendezvousServer::GetInstance();
      if (rv == 0) {
        rendezvous->RegisterPortsForPid(pid, options.mach_ports_for_rendezvous);
      } else {
        // Because |options| is const-ref, the collection has to be copied here.
        // The caller expects to relinquish ownership of any strong rights if
        // LaunchProcess() were to succeed, so these rights should be manually
        // destroyed on failure.
        MachPortsForRendezvous ports = options.mach_ports_for_rendezvous;
        for (auto& port : ports) {
          port.second.Destroy();
        }
      }
    }
  }

  // Restore the thread's working directory if it was changed.
  if (!options.current_directory.empty()) {
    ResetCurrentThreadDirectory();
  }

  if (rv != 0) {
    DLOG(ERROR) << "posix_spawnp(" << executable_path << "): -" << rv << " "
                << strerror(rv);
    return Process();
  }

  if (options.wait) {
    // While this isn't strictly disk IO, waiting for another process to
    // finish is the sort of thing ThreadRestrictions is trying to prevent.
    ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK);
    pid_t ret = HANDLE_EINTR(waitpid(pid, nullptr, 0));
    DPCHECK(ret > 0);
  }

  return Process(pid);
}

bool GetAppOutput(const CommandLine& cl, std::string* output) {
  return GetAppOutput(cl.argv(), output);
}

bool GetAppOutputAndError(const CommandLine& cl, std::string* output) {
  return GetAppOutputAndError(cl.argv(), output);
}

bool GetAppOutputWithExitCode(const CommandLine& cl,
                              std::string* output,
                              int* exit_code) {
  GetAppOutputOptions options;
  options.output = output;
  bool rv = GetAppOutputInternal(cl.argv(), &options);
  *exit_code = options.exit_code;
  return rv;
}

bool GetAppOutput(const std::vector<std::string>& argv, std::string* output) {
  GetAppOutputOptions options;
  options.output = output;
  return GetAppOutputInternal(argv, &options) &&
         options.exit_code == EXIT_SUCCESS;
}

bool GetAppOutputAndError(const std::vector<std::string>& argv,
                          std::string* output) {
  GetAppOutputOptions options;
  options.include_stderr = true;
  options.output = output;
  return GetAppOutputInternal(argv, &options) &&
         options.exit_code == EXIT_SUCCESS;
}

void RaiseProcessToHighPriority() {
  // Historically this has not been implemented on POSIX and macOS. This could
  // influence the Mach task policy in the future.
}

}  // namespace base
