// 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 "chromeos/process_proxy/process_proxy.h"

#include <fcntl.h>
#include <stdlib.h>
#include <sys/ioctl.h>

#include "base/bind.h"
#include "base/command_line.h"
#include "base/file_util.h"
#include "base/logging.h"
#include "base/posix/eintr_wrapper.h"
#include "base/process/kill.h"
#include "base/process/launch.h"
#include "base/threading/thread.h"
#include "chromeos/process_proxy/process_output_watcher.h"

namespace {

enum PipeEnd {
  PIPE_END_READ,
  PIPE_END_WRITE
};

enum PseudoTerminalFd {
  PT_MASTER_FD,
  PT_SLAVE_FD
};

const int kInvalidFd = -1;

}  // namespace

namespace chromeos {

ProcessProxy::ProcessProxy(): process_launched_(false),
                              callback_set_(false),
                              watcher_started_(false) {
  // Set pipes to initial, invalid value so we can easily know if a pipe was
  // opened by us.
  ClearAllFdPairs();
};

bool ProcessProxy::Open(const std::string& command, pid_t* pid) {
  if (process_launched_)
    return false;

  if (!CreatePseudoTerminalPair(pt_pair_)) {
    return false;
  }

  process_launched_ = LaunchProcess(command, pt_pair_[PT_SLAVE_FD], &pid_);

  if (process_launched_) {
    // We won't need these anymore. These will be used by the launched process.
    CloseFd(&pt_pair_[PT_SLAVE_FD]);
    *pid = pid_;
    LOG(WARNING) << "Process launched: " << pid_;
  } else {
    CloseFdPair(pt_pair_);
  }
  return process_launched_;
}

bool ProcessProxy::StartWatchingOnThread(
    base::Thread* watch_thread,
    const ProcessOutputCallback& callback) {
  DCHECK(process_launched_);
  if (watcher_started_)
    return false;
  if (pipe(shutdown_pipe_))
    return false;

  // We give ProcessOutputWatcher a copy of master to make life easier during
  // tear down.
  // TODO(tbarzic): improve fd managment.
  int master_copy = HANDLE_EINTR(dup(pt_pair_[PT_MASTER_FD]));
  if (master_copy == -1)
    return false;

  callback_set_ = true;
  callback_ = callback;
  callback_runner_ = base::MessageLoopProxy::current();

  // This object will delete itself once watching is stopped.
  // It also takes ownership of the passed fds.
  ProcessOutputWatcher* output_watcher =
      new ProcessOutputWatcher(master_copy,
                               shutdown_pipe_[PIPE_END_READ],
                               base::Bind(&ProcessProxy::OnProcessOutput,
                                          this));

  // Output watcher took ownership of the read end of shutdown pipe.
  shutdown_pipe_[PIPE_END_READ] = -1;

  // |watch| thread is blocked by |output_watcher| from now on.
  watch_thread->message_loop()->PostTask(FROM_HERE,
      base::Bind(&ProcessOutputWatcher::Start,
                 base::Unretained(output_watcher)));
  watcher_started_ = true;
  return true;
}

void ProcessProxy::OnProcessOutput(ProcessOutputType type,
                                   const std::string& output) {
  if (!callback_runner_.get())
    return;

  callback_runner_->PostTask(
      FROM_HERE,
      base::Bind(&ProcessProxy::CallOnProcessOutputCallback,
                 this, type, output));
}

void ProcessProxy::CallOnProcessOutputCallback(ProcessOutputType type,
                                               const std::string& output) {
  // We may receive some output even after Close was called (crosh process does
  // not have to quit instantly, or there may be some trailing data left in
  // output stream fds). In that case owner of the callback may be gone so we
  // don't want to send it anything. |callback_set_| is reset when this gets
  // closed.
  if (callback_set_)
    callback_.Run(type, output);
}

bool ProcessProxy::StopWatching() {
  if (!watcher_started_)
    return true;
  // Signal Watcher that we are done. We use self-pipe trick to unblock watcher.
  // Anything may be written to the pipe.
  const char message[] = "q";
  return file_util::WriteFileDescriptor(shutdown_pipe_[PIPE_END_WRITE],
                                        message, sizeof(message));
}

void ProcessProxy::Close() {
  if (!process_launched_)
    return;

  process_launched_ = false;
  callback_set_ = false;
  callback_ = ProcessOutputCallback();
  callback_runner_ = NULL;

  base::KillProcess(pid_, 0, true /* wait */);

  // TODO(tbarzic): What if this fails?
  StopWatching();

  CloseAllFdPairs();
}

bool ProcessProxy::Write(const std::string& text) {
  if (!process_launched_)
    return false;

  // We don't want to write '\0' to the pipe.
  size_t data_size = text.length() * sizeof(*text.c_str());
  int bytes_written =
      file_util::WriteFileDescriptor(pt_pair_[PT_MASTER_FD],
                                     text.c_str(), data_size);
  return (bytes_written == static_cast<int>(data_size));
}

bool ProcessProxy::OnTerminalResize(int width, int height) {
  if (width < 0 || height < 0)
    return false;

  winsize ws;
  // Number of rows.
  ws.ws_row = height;
  // Number of columns.
  ws.ws_col = width;

  return (HANDLE_EINTR(ioctl(pt_pair_[PT_MASTER_FD], TIOCSWINSZ, &ws)) != -1);
}

ProcessProxy::~ProcessProxy() {
  // In case watcher did not started, we may get deleted without calling Close.
  // In that case we have to clean up created pipes. If watcher had been
  // started, there will be a callback with our reference owned by
  // process_output_watcher until Close is called, so we know Close has been
  // called  by now (and pipes have been cleaned).
  if (!watcher_started_)
    CloseAllFdPairs();
}

bool ProcessProxy::CreatePseudoTerminalPair(int *pt_pair) {
  ClearFdPair(pt_pair);

  // Open Master.
  pt_pair[PT_MASTER_FD] = HANDLE_EINTR(posix_openpt(O_RDWR | O_NOCTTY));
  if (pt_pair[PT_MASTER_FD] == -1)
    return false;

  if (grantpt(pt_pair_[PT_MASTER_FD]) != 0 ||
      unlockpt(pt_pair_[PT_MASTER_FD]) != 0) {
    CloseFd(&pt_pair[PT_MASTER_FD]);
    return false;
  }
  char* slave_name = NULL;
  // Per man page, slave_name must not be freed.
  slave_name = ptsname(pt_pair_[PT_MASTER_FD]);
  if (slave_name)
    pt_pair_[PT_SLAVE_FD] = HANDLE_EINTR(open(slave_name, O_RDWR | O_NOCTTY));

  if (pt_pair_[PT_SLAVE_FD] == -1) {
    CloseFdPair(pt_pair);
    return false;
  }

  return true;
}

bool ProcessProxy::LaunchProcess(const std::string& command, int slave_fd,
                                 pid_t* pid) {
  // Redirect crosh  process' output and input so we can read it.
  base::FileHandleMappingVector fds_mapping;
  fds_mapping.push_back(std::make_pair(slave_fd, STDIN_FILENO));
  fds_mapping.push_back(std::make_pair(slave_fd, STDOUT_FILENO));
  fds_mapping.push_back(std::make_pair(slave_fd, STDERR_FILENO));
  base::LaunchOptions options;
  options.fds_to_remap = &fds_mapping;
  options.ctrl_terminal_fd = slave_fd;
  options.environ["TERM"] = "xterm";

  // Launch the process.
  return base::LaunchProcess(CommandLine(base::FilePath(command)), options,
                             pid);
}

void ProcessProxy::CloseAllFdPairs() {
  CloseFdPair(pt_pair_);
  CloseFdPair(shutdown_pipe_);
}

void ProcessProxy::CloseFdPair(int* pipe) {
  CloseFd(&(pipe[PIPE_END_READ]));
  CloseFd(&(pipe[PIPE_END_WRITE]));
}

void ProcessProxy::CloseFd(int* fd) {
  if (*fd != kInvalidFd) {
    if (IGNORE_EINTR(close(*fd)) != 0)
      DPLOG(WARNING) << "close fd failed.";
  }
  *fd = kInvalidFd;
}

void ProcessProxy::ClearAllFdPairs() {
  ClearFdPair(pt_pair_);
  ClearFdPair(shutdown_pipe_);
}

void ProcessProxy::ClearFdPair(int* pipe) {
  pipe[PIPE_END_READ] = kInvalidFd;
  pipe[PIPE_END_WRITE] = kInvalidFd;
}

}  // namespace chromeos
