// Copyright (c) 2013 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 "shill/external_task.h"

#include <signal.h>
#include <sys/prctl.h>

#include <base/bind.h>
#include <base/bind_helpers.h>

#include "shill/error.h"
#include "shill/event_dispatcher.h"
#include "shill/process_killer.h"

namespace shill {

using base::FilePath;
using std::map;
using std::string;
using std::vector;

ExternalTask::ExternalTask(
    ControlInterface *control,
    GLib *glib,
    const base::WeakPtr<RPCTaskDelegate> &task_delegate,
    const base::Callback<void(pid_t, int)> &death_callback)
    : control_(control),
      glib_(glib),
      process_killer_(ProcessKiller::GetInstance()),
      task_delegate_(task_delegate),
      death_callback_(death_callback),
      pid_(0),
      child_watch_tag_(0) {
  CHECK(task_delegate_);
}

ExternalTask::~ExternalTask() {
  ExternalTask::Stop();
}

void ExternalTask::DestroyLater(EventDispatcher *dispatcher) {
  // Passes ownership of |this| to Destroy.
  dispatcher->PostTask(base::Bind(&Destroy, this));
}

bool ExternalTask::Start(const FilePath &program,
                         const vector<string> &arguments,
                         const map<string, string> &environment,
                         bool terminate_with_parent,
                         Error *error) {
  CHECK(!pid_);
  CHECK(!child_watch_tag_);
  CHECK(!rpc_task_);

  scoped_ptr<RPCTask> local_rpc_task(new RPCTask(control_, this));

  // const_cast is safe here, because exec*() (and SpawnAsync) do not
  // modify the strings passed to them. This isn't captured in the
  // exec*() prototypes, due to limitations in ISO C.
  // http://pubs.opengroup.org/onlinepubs/009695399/functions/exec.html
  vector<char *> process_args;
  process_args.push_back(const_cast<char *>(program.value().c_str()));
  for (const auto &option : arguments) {
    process_args.push_back(const_cast<char *>(option.c_str()));
  }
  process_args.push_back(NULL);

  vector<char *> process_env;
  vector<string> env_vars(local_rpc_task->GetEnvironment());
  for (const auto &env_pair : environment) {
    env_vars.push_back(string(env_pair.first + "=" + env_pair.second));
  }
  for (const auto &env_var : env_vars) {
    // See above regarding const_cast.
    process_env.push_back(const_cast<char *>(env_var.c_str()));
  }
  process_env.push_back(NULL);

  GSpawnChildSetupFunc child_setup_func =
      terminate_with_parent ? SetupTermination : NULL;

  if (!glib_->SpawnAsync(NULL,
                         process_args.data(),
                         process_env.data(),
                         G_SPAWN_DO_NOT_REAP_CHILD,
                         child_setup_func,
                         NULL,
                         &pid_,
                         NULL)) {
    Error::PopulateAndLog(error, Error::kInternalError,
                          string("Unable to spawn: ") + process_args[0]);
    return false;
  }
  child_watch_tag_ = glib_->ChildWatchAdd(pid_, OnTaskDied, this);
  rpc_task_.reset(local_rpc_task.release());
  return true;
}

void ExternalTask::Stop() {
  if (child_watch_tag_) {
    glib_->SourceRemove(child_watch_tag_);
    child_watch_tag_ = 0;
  }
  if (pid_) {
    process_killer_->Kill(pid_, base::Closure());
    pid_ = 0;
  }
  rpc_task_.reset();
}

void ExternalTask::GetLogin(string *user, string *password) {
  return task_delegate_->GetLogin(user, password);
}

void ExternalTask::Notify(const string &event,
                          const map<string, string> &details) {
  return task_delegate_->Notify(event, details);
}

// static
void ExternalTask::OnTaskDied(GPid pid, gint status, gpointer data) {
  LOG(INFO) << __func__ << "(" << pid << ", "  << status << ")";
  ExternalTask *me = reinterpret_cast<ExternalTask *>(data);
  me->child_watch_tag_ = 0;
  CHECK_EQ(pid, me->pid_);
  me->pid_ = 0;
  me->death_callback_.Run(pid, status);
}

// static
void ExternalTask::Destroy(ExternalTask *task) {
  delete task;
}

// static
void ExternalTask::SetupTermination(gpointer /*glib_user_data*/) {
  prctl(PR_SET_PDEATHSIG, SIGTERM);
}

}  // namespace shill
