// Copyright 2018 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "subprocess.h"

#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <launchpad/launchpad.h>
#include <poll.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <zircon/errors.h>
#include <zircon/process.h>
#include <zircon/syscalls.h>
#include <zircon/types.h>

extern char** environ;

#include "util.h"

Subprocess::Subprocess(bool use_console) : fd_(-1), handle_(ZX_HANDLE_INVALID),
                                           use_console_(use_console) {
}

Subprocess::~Subprocess() {
  if (fd_ >= 0)
    close(fd_);
  // Reap child if forgotten.
  if (handle_ != ZX_HANDLE_INVALID)
    Finish();
}

bool Subprocess::Start(SubprocessSet* set, const string& command) {
  printf("executing %s\n", command.c_str());

  int output_pipe[2];
  if (pipe(output_pipe) < 0)
    Fatal("pipe: %s", strerror(errno));
  fd_ = output_pipe[0];

  launchpad_t* lp = NULL;
  launchpad_create(ZX_HANDLE_INVALID, "sh", &lp);
  const char* args[] = { "/boot/bin/sh", "-c", command.c_str() };
  launchpad_load_from_file(lp, args[0]);
  launchpad_set_args(lp, 3, args);
  launchpad_clone(lp, LP_CLONE_ALL & (~LP_CLONE_FDIO_STDIO));

  if (!use_console_) {
    launchpad_clone_fd(lp, output_pipe[1], 1);
    launchpad_clone_fd(lp, output_pipe[1], 2);
  }

  const char *errmsg = NULL;
  if (launchpad_go(lp, &handle_, &errmsg) != ZX_OK)
    Fatal(errmsg);
  launchpad_destroy(lp);

  close(output_pipe[1]);
  return true;
}

void Subprocess::OnPipeReady() {
  char buf[4 << 10];
  ssize_t len = read(fd_, buf, sizeof(buf));
  if (len > 0) {
    buf_.append(buf, len);
  } else {
    if (len < 0)
      Fatal("read: %s", strerror(errno));
    close(fd_);
    fd_ = -1;
  }
}

ExitStatus Subprocess::Finish() {
  assert(handle_ != ZX_HANDLE_INVALID);
  zx_status_t status = zx_object_wait_one(handle_, ZX_PROCESS_TERMINATED, ZX_TIME_INFINITE, nullptr);
  if (status != ZX_OK)
    Fatal("zx_object_wait_one failed");

  zx_info_process_t info;
  status = zx_object_get_info(handle_, ZX_INFO_PROCESS, &info, sizeof(info), nullptr, nullptr);
  if (status != ZX_OK)
    Fatal("zx_object_get_info failed to get process status");

  zx_handle_close(handle_);
  handle_ = ZX_HANDLE_INVALID;

  if (info.exited) {
    if (info.return_code == 0)
      return ExitSuccess;
  }
  return ExitFailure;
}

bool Subprocess::Done() const {
  return fd_ == -1;
}

const string& Subprocess::GetOutput() const {
  return buf_;
}

SubprocessSet::SubprocessSet() {
}

SubprocessSet::~SubprocessSet() {
  Clear();
}

Subprocess *SubprocessSet::Add(const string& command, bool use_console) {
  Subprocess *subprocess = new Subprocess(use_console);
  if (!subprocess->Start(this, command)) {
    delete subprocess;
    return 0;
  }
  running_.push_back(subprocess);
  return subprocess;
}

bool SubprocessSet::DoWork() {
  vector<pollfd> fds;
  nfds_t nfds = 0;

  for (vector<Subprocess*>::iterator i = running_.begin();
       i != running_.end(); ++i) {
    int fd = (*i)->fd_;
    if (fd < 0)
      continue;
    pollfd pfd = { fd, POLLIN | POLLPRI, 0 };
    fds.push_back(pfd);
    ++nfds;
  }

  int ret = ppoll(&fds.front(), nfds, NULL, NULL);
  if (ret == -1) {
    perror("ninja: ppoll");
    return false;
  }

  nfds_t cur_nfd = 0;
  for (vector<Subprocess*>::iterator i = running_.begin();
       i != running_.end(); ) {
    int fd = (*i)->fd_;
    if (fd < 0)
      continue;
    assert(fd == fds[cur_nfd].fd);
    if (fds[cur_nfd++].revents) {
      (*i)->OnPipeReady();
      if ((*i)->Done()) {
        finished_.push(*i);
        i = running_.erase(i);
        continue;
      }
    }
    ++i;
  }

  return false;
}

Subprocess* SubprocessSet::NextFinished() {
  if (finished_.empty())
    return NULL;
  Subprocess* subproc = finished_.front();
  finished_.pop();
  return subproc;
}

void SubprocessSet::Clear() {
  for (vector<Subprocess*>::iterator i = running_.begin();
       i != running_.end(); ++i)
    // Since the foreground process is in our process group, it will receive
    // the interruption signal (i.e. SIGINT or SIGTERM) at the same time as us.
    if (!(*i)->use_console_)
      zx_task_kill((*i)->handle_);
  for (vector<Subprocess*>::iterator i = running_.begin();
       i != running_.end(); ++i)
    delete *i;
  running_.clear();
}
