// Copyright (c) 2011 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 "update_engine/subprocess.h"
#include <stdlib.h>
#include <string.h>
#include <string>
#include <unistd.h>
#include <vector>
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/string_util.h"

using std::string;
using std::tr1::shared_ptr;
using std::vector;

namespace chromeos_update_engine {

void Subprocess::GChildExitedCallback(GPid pid, gint status, gpointer data) {
  SubprocessRecord* record = reinterpret_cast<SubprocessRecord*>(data);

  // Make sure we read any remaining process output. Then close the pipe.
  GStdoutWatchCallback(record->gioout, G_IO_IN, &record->stdout);
  int fd = g_io_channel_unix_get_fd(record->gioout);
  g_source_remove(record->gioout_tag);
  g_io_channel_unref(record->gioout);
  close(fd);

  g_spawn_close_pid(pid);
  gint use_status = status;
  if (WIFEXITED(status))
    use_status = WEXITSTATUS(status);

  if (status) {
    LOG(INFO) << "Subprocess status: " << use_status;
  }
  if (!record->stdout.empty()) {
    LOG(INFO) << "Subprocess output:\n" << record->stdout;
  }
  if (record->callback) {
    record->callback(use_status, record->stdout, record->callback_data);
  }
  Get().subprocess_records_.erase(record->tag);
}

void Subprocess::GRedirectStderrToStdout(gpointer user_data) {
  dup2(1, 2);
}

gboolean Subprocess::GStdoutWatchCallback(GIOChannel* source,
                                          GIOCondition condition,
                                          gpointer data) {
  string* stdout = reinterpret_cast<string*>(data);
  char buf[1024];
  gsize bytes_read;
  while (g_io_channel_read_chars(source,
                                 buf,
                                 arraysize(buf),
                                 &bytes_read,
                                 NULL) == G_IO_STATUS_NORMAL &&
         bytes_read > 0) {
    stdout->append(buf, bytes_read);
  }
  return TRUE;  // Keep the callback source. It's freed in GChilExitedCallback.
}

namespace {
void FreeArgv(char** argv) {
  for (int i = 0; argv[i]; i++) {
    free(argv[i]);
    argv[i] = NULL;
  }
}

void FreeArgvInError(char** argv) {
  FreeArgv(argv);
  LOG(ERROR) << "Ran out of memory copying args.";
}

// Note: Caller responsible for free()ing the returned value!
// Will return NULL on failure and free any allocated memory.
char** ArgPointer() {
  const char* keys[] = {"LD_LIBRARY_PATH", "PATH"};
  char** ret = new char*[arraysize(keys) + 1];
  int pointer = 0;
  for (size_t i = 0; i < arraysize(keys); i++) {
    if (getenv(keys[i])) {
      ret[pointer] = strdup(StringPrintf("%s=%s", keys[i],
                                         getenv(keys[i])).c_str());
      if (!ret[pointer]) {
        FreeArgv(ret);
        delete [] ret;
        return NULL;
      }
      ++pointer;
    }
  }
  ret[pointer] = NULL;
  return ret;
}

class ScopedFreeArgPointer {
 public:
  ScopedFreeArgPointer(char** arr) : arr_(arr) {}
  ~ScopedFreeArgPointer() {
    if (!arr_)
      return;
    for (int i = 0; arr_[i]; i++)
      free(arr_[i]);
    delete[] arr_;
  }
 private:
  char** arr_;
  DISALLOW_COPY_AND_ASSIGN(ScopedFreeArgPointer);
};
}  // namespace {}

uint32_t Subprocess::Exec(const vector<string>& cmd,
                          ExecCallback callback,
                          void* p) {
  GPid child_pid;
  scoped_array<char*> argv(new char*[cmd.size() + 1]);
  for (unsigned int i = 0; i < cmd.size(); i++) {
    argv[i] = strdup(cmd[i].c_str());
    if (!argv[i]) {
      FreeArgvInError(argv.get());  // NULL in argv[i] terminates argv.
      return 0;
    }
  }
  argv[cmd.size()] = NULL;

  char** argp = ArgPointer();
  if (!argp) {
    FreeArgvInError(argv.get());  // NULL in argv[i] terminates argv.
    return 0;
  }
  ScopedFreeArgPointer argp_free(argp);

  shared_ptr<SubprocessRecord> record(new SubprocessRecord);
  record->callback = callback;
  record->callback_data = p;
  gint stdout_fd = -1;
  bool success = g_spawn_async_with_pipes(
      NULL,  // working directory
      argv.get(),
      argp,
      G_SPAWN_DO_NOT_REAP_CHILD,  // flags
      GRedirectStderrToStdout,  // child setup function
      NULL,  // child setup data pointer
      &child_pid,
      NULL,
      &stdout_fd,
      NULL,
      NULL);
  FreeArgv(argv.get());
  if (!success) {
    LOG(ERROR) << "g_spawn_async failed";
    return 0;
  }
  record->tag =
      g_child_watch_add(child_pid, GChildExitedCallback, record.get());
  subprocess_records_[record->tag] = record;

  // Capture the subprocess output.
  record->gioout = g_io_channel_unix_new(stdout_fd);
  g_io_channel_set_encoding(record->gioout, NULL, NULL);
  LOG_IF(WARNING,
         g_io_channel_set_flags(record->gioout, G_IO_FLAG_NONBLOCK, NULL) !=
         G_IO_STATUS_NORMAL) << "Unable to set non-blocking I/O mode.";
  record->gioout_tag = g_io_add_watch(
      record->gioout,
      static_cast<GIOCondition>(G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP),
      GStdoutWatchCallback,
      &record->stdout);
  return record->tag;
}

void Subprocess::CancelExec(uint32_t tag) {
  subprocess_records_[tag]->callback = NULL;
}

bool Subprocess::SynchronousExecFlags(const vector<string>& cmd,
                                      GSpawnFlags flags,
                                      int* return_code,
                                      string* stdout) {
  if (stdout) {
    *stdout = "";
  }
  GError* err = NULL;
  scoped_array<char*> argv(new char*[cmd.size() + 1]);
  for (unsigned int i = 0; i < cmd.size(); i++) {
    argv[i] = strdup(cmd[i].c_str());
    if (!argv[i]) {
      FreeArgvInError(argv.get());  // NULL in argv[i] terminates argv.
      return false;
    }
  }
  argv[cmd.size()] = NULL;

  char** argp = ArgPointer();
  if (!argp) {
    FreeArgvInError(argv.get());  // NULL in argv[i] terminates argv.
    return false;
  }
  ScopedFreeArgPointer argp_free(argp);

  char* child_stdout;
  bool success = g_spawn_sync(
      NULL,  // working directory
      argv.get(),
      argp,
      static_cast<GSpawnFlags>(G_SPAWN_STDERR_TO_DEV_NULL |
                               G_SPAWN_SEARCH_PATH | flags),  // flags
      GRedirectStderrToStdout,  // child setup function
      NULL,  // data for child setup function
      &child_stdout,
      NULL,
      return_code,
      &err);
  FreeArgv(argv.get());
  if (err) {
    LOG(INFO) << "err is: " << err->code << ", " << err->message;
    g_error_free(err);
  }
  if (child_stdout) {
    if (stdout) {
      *stdout = child_stdout;
    } else if (*child_stdout) {
      LOG(INFO) << "Subprocess output:\n" << child_stdout;
    }
    g_free(child_stdout);
  }
  return success;
}

bool Subprocess::SynchronousExec(const std::vector<std::string>& cmd,
                                 int* return_code,
                                 std::string* stdout) {
  return SynchronousExecFlags(cmd,
                              static_cast<GSpawnFlags>(0),
                              return_code,
                              stdout);
}

bool Subprocess::SubprocessInFlight() {
  for (std::map<int, shared_ptr<SubprocessRecord> >::iterator it =
           subprocess_records_.begin();
       it != subprocess_records_.end(); ++it) {
    if (it->second->callback)
      return true;
  }
  return false;
}

Subprocess* Subprocess::subprocess_singleton_ = NULL;

}  // namespace chromeos_update_engine
