// Copyright (c) 2012 The Chromium OS 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 "debugd/src/process_with_output.h"

#include <signal.h>

#include <base/files/file_util.h>
#include <base/strings/string_split.h>

#include "debugd/src/error_utils.h"

namespace debugd {

namespace {

const char kDBusErrorString[] = "org.chromium.debugd.error.RunProcess";
const char kInitErrorString[] = "Process initialization failure.";
const char kStartErrorString[] = "Process start failure.";
const char kInputErrorString[] = "Process input write failure.";
const char kPathLengthErrorString[] = "Path length is too long.";

}  // namespace

ProcessWithOutput::ProcessWithOutput()
    : separate_stderr_(false), use_minijail_(true) {
}

ProcessWithOutput::~ProcessWithOutput() {
  outfile_.reset();
  errfile_.reset();

  if (!outfile_path_.empty())
    base::DeleteFile(outfile_path_, false);  // not recursive
  if (!errfile_path_.empty())
    base::DeleteFile(errfile_path_, false);
}

bool ProcessWithOutput::Init() {
  if (use_minijail_) {
    if (!SandboxedProcess::Init())
      return false;
  }

  outfile_.reset(base::CreateAndOpenTemporaryFile(&outfile_path_));
  if (!outfile_.get()) {
    return false;
  }
  if (separate_stderr_) {
    errfile_.reset(base::CreateAndOpenTemporaryFile(&errfile_path_));
    if (!errfile_.get()) {
      return false;
    }
  }

  // We can't just RedirectOutput to the file we just created, since
  // RedirectOutput uses O_CREAT | O_EXCL to open the target file (i.e., it'll
  // fail if the file already exists). We can't CreateTemporaryFile() and then
  // use that filename, since we'd have to remove it before using
  // RedirectOutput, which exposes us to a /tmp race. Instead, bind outfile_'s
  // fd to the subprocess's stdout and stderr.
  BindFd(fileno(outfile_.get()), STDOUT_FILENO);
  BindFd(fileno(separate_stderr_ ? errfile_.get() : outfile_.get()),
         STDERR_FILENO);
  return true;
}

bool ProcessWithOutput::GetOutputLines(std::vector<std::string>* output) {
  std::string contents;
  if (!base::ReadFileToString(outfile_path_, &contents))
    return false;

  *output = base::SplitString(contents, "\n", base::KEEP_WHITESPACE,
                              base::SPLIT_WANT_ALL);
  return true;
}

bool ProcessWithOutput::GetOutput(std::string* output) {
  return base::ReadFileToString(outfile_path_, output);
}

bool ProcessWithOutput::GetError(std::string* error) {
  return base::ReadFileToString(errfile_path_, error);
}

int ProcessWithOutput::RunProcess(const std::string& command,
                                  const ArgList& arguments,
                                  bool requires_root,
                                  const std::string* stdin,
                                  std::string* stdout,
                                  std::string* stderr,
                                  brillo::ErrorPtr* error) {
  ProcessWithOutput process;
  if (requires_root) {
    process.SandboxAs("root", "root");
  }
  return DoRunProcess(
      command, arguments, stdin, stdout, stderr, error, &process);
}

int ProcessWithOutput::RunHelper(const std::string& helper,
                                 const ArgList& arguments,
                                 bool requires_root,
                                 const std::string* stdin,
                                 std::string* stdout,
                                 std::string* stderr,
                                 brillo::ErrorPtr* error) {
  std::string helper_path;
  if (!SandboxedProcess::GetHelperPath(helper, &helper_path)) {
    DEBUGD_ADD_ERROR(error, kDBusErrorString, kPathLengthErrorString);
    return kRunError;
  }
  return RunProcess(
      helper_path, arguments, requires_root, stdin, stdout, stderr, error);
}

int ProcessWithOutput::RunProcessFromHelper(const std::string& command,
                                            const ArgList& arguments,
                                            const std::string* stdin,
                                            std::string* stdout,
                                            std::string* stderr) {
  ProcessWithOutput process;
  process.set_use_minijail(false);
  process.SetSearchPath(true);
  return DoRunProcess(
      command, arguments, stdin, stdout, stderr, nullptr, &process);
}

int ProcessWithOutput::DoRunProcess(const std::string& command,
                                    const ArgList& arguments,
                                    const std::string* stdin,
                                    std::string* stdout,
                                    std::string* stderr,
                                    brillo::ErrorPtr* error,
                                    ProcessWithOutput* process) {
  process->set_separate_stderr(true);
  if (!process->Init()) {
    DEBUGD_ADD_ERROR(error, kDBusErrorString, kInitErrorString);
    return kRunError;
  }

  process->AddArg(command);
  for (const auto& argument : arguments) {
    process->AddArg(argument);
  }

  int result = kRunError;
  if (stdin) {
    process->RedirectUsingPipe(STDIN_FILENO, true);
    if (process->Start()) {
      int stdin_fd = process->GetPipe(STDIN_FILENO);
      // Kill the process if writing to or closing the pipe fails.
      if (!base::WriteFileDescriptor(stdin_fd, stdin->c_str(),
                                     stdin->length()) ||
          IGNORE_EINTR(close(stdin_fd)) < 0) {
        process->Kill(SIGKILL, 0);
        DEBUGD_ADD_ERROR(error, kDBusErrorString, kInputErrorString);
      }
      result = process->Wait();
    } else {
      DEBUGD_ADD_ERROR(error, kDBusErrorString, kStartErrorString);
    }
  } else {
    result = process->Run();
  }

  if (stdout)
    process->GetOutput(stdout);

  if (stderr)
    process->GetError(stderr);

  return result;
}

}  // namespace debugd
