// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.

#include "spawn_sync.h"
#include "debug_utils-inl.h"
#include "env-inl.h"
#include "node_internals.h"
#include "string_bytes.h"
#include "util-inl.h"

#include <cstring>


namespace node {

using v8::Array;
using v8::Context;
using v8::EscapableHandleScope;
using v8::FunctionCallbackInfo;
using v8::HandleScope;
using v8::Int32;
using v8::Integer;
using v8::Isolate;
using v8::Just;
using v8::Local;
using v8::Maybe;
using v8::MaybeLocal;
using v8::Nothing;
using v8::Null;
using v8::Number;
using v8::Object;
using v8::String;
using v8::Value;

void SyncProcessOutputBuffer::OnAlloc(size_t suggested_size,
                                      uv_buf_t* buf) const {
  if (used() == kBufferSize)
    *buf = uv_buf_init(nullptr, 0);
  else
    *buf = uv_buf_init(data_ + used(), available());
}


void SyncProcessOutputBuffer::OnRead(const uv_buf_t* buf, size_t nread) {
  // If we hand out the same chunk twice, this should catch it.
  CHECK_EQ(buf->base, data_ + used());
  used_ += static_cast<unsigned int>(nread);
}


size_t SyncProcessOutputBuffer::Copy(char* dest) const {
  memcpy(dest, data_, used());
  return used();
}


unsigned int SyncProcessOutputBuffer::available() const {
  return sizeof data_ - used();
}


unsigned int SyncProcessOutputBuffer::used() const {
  return used_;
}


SyncProcessOutputBuffer* SyncProcessOutputBuffer::next() const {
  return next_;
}


void SyncProcessOutputBuffer::set_next(SyncProcessOutputBuffer* next) {
  next_ = next;
}


SyncProcessStdioPipe::SyncProcessStdioPipe(SyncProcessRunner* process_handler,
                                           bool readable,
                                           bool writable,
                                           uv_buf_t input_buffer)
    : process_handler_(process_handler),
      readable_(readable),
      writable_(writable),
      input_buffer_(input_buffer),

      first_output_buffer_(nullptr),
      last_output_buffer_(nullptr),

      uv_pipe_(),
      write_req_(),
      shutdown_req_(),

      lifecycle_(kUninitialized) {
  CHECK(readable || writable);
}


SyncProcessStdioPipe::~SyncProcessStdioPipe() {
  CHECK(lifecycle_ == kUninitialized || lifecycle_ == kClosed);

  SyncProcessOutputBuffer* buf;
  SyncProcessOutputBuffer* next;

  for (buf = first_output_buffer_; buf != nullptr; buf = next) {
    next = buf->next();
    delete buf;
  }
}


int SyncProcessStdioPipe::Initialize(uv_loop_t* loop) {
  CHECK_EQ(lifecycle_, kUninitialized);

  int r = uv_pipe_init(loop, uv_pipe(), 0);
  if (r < 0)
    return r;

  uv_pipe()->data = this;

  lifecycle_ = kInitialized;
  return 0;
}


int SyncProcessStdioPipe::Start() {
  CHECK_EQ(lifecycle_, kInitialized);

  // Set the busy flag already. If this function fails no recovery is
  // possible.
  lifecycle_ = kStarted;

  if (readable()) {
    if (input_buffer_.len > 0) {
      CHECK_NOT_NULL(input_buffer_.base);

      int r = uv_write(&write_req_,
                       uv_stream(),
                       &input_buffer_,
                       1,
                       WriteCallback);
      if (r < 0)
        return r;
    }

    int r = uv_shutdown(&shutdown_req_, uv_stream(), ShutdownCallback);
    if (r < 0)
      return r;
  }

  if (writable()) {
    int r = uv_read_start(uv_stream(), AllocCallback, ReadCallback);
    if (r < 0)
      return r;
  }

  return 0;
}


void SyncProcessStdioPipe::Close() {
  CHECK(lifecycle_ == kInitialized || lifecycle_ == kStarted);

  uv_close(uv_handle(), CloseCallback);

  lifecycle_ = kClosing;
}


Local<Object> SyncProcessStdioPipe::GetOutputAsBuffer(Environment* env) const {
  size_t length = OutputLength();
  Local<Object> js_buffer = Buffer::New(env, length).ToLocalChecked();
  CopyOutput(Buffer::Data(js_buffer));
  return js_buffer;
}


bool SyncProcessStdioPipe::readable() const {
  return readable_;
}


bool SyncProcessStdioPipe::writable() const {
  return writable_;
}


uv_stdio_flags SyncProcessStdioPipe::uv_flags() const {
  unsigned int flags;

  flags = UV_CREATE_PIPE;
  if (readable())
    flags |= UV_READABLE_PIPE;
  if (writable())
    flags |= UV_WRITABLE_PIPE;

  return static_cast<uv_stdio_flags>(flags);
}


uv_pipe_t* SyncProcessStdioPipe::uv_pipe() const {
  CHECK_LT(lifecycle_, kClosing);
  return &uv_pipe_;
}


uv_stream_t* SyncProcessStdioPipe::uv_stream() const {
  return reinterpret_cast<uv_stream_t*>(uv_pipe());
}


uv_handle_t* SyncProcessStdioPipe::uv_handle() const {
  return reinterpret_cast<uv_handle_t*>(uv_pipe());
}


size_t SyncProcessStdioPipe::OutputLength() const {
  SyncProcessOutputBuffer* buf;
  size_t size = 0;

  for (buf = first_output_buffer_; buf != nullptr; buf = buf->next())
    size += buf->used();

  return size;
}


void SyncProcessStdioPipe::CopyOutput(char* dest) const {
  SyncProcessOutputBuffer* buf;
  size_t offset = 0;

  for (buf = first_output_buffer_; buf != nullptr; buf = buf->next())
    offset += buf->Copy(dest + offset);
}


void SyncProcessStdioPipe::OnAlloc(size_t suggested_size, uv_buf_t* buf) {
  // This function assumes that libuv will never allocate two buffers for the
  // same stream at the same time. There's an assert in
  // SyncProcessOutputBuffer::OnRead that would fail if this assumption was
  // ever violated.

  if (last_output_buffer_ == nullptr) {
    // Allocate the first capture buffer.
    first_output_buffer_ = new SyncProcessOutputBuffer();
    last_output_buffer_ = first_output_buffer_;

  } else if (last_output_buffer_->available() == 0) {
    // The current capture buffer is full so get us a new one.
    SyncProcessOutputBuffer* buf = new SyncProcessOutputBuffer();
    last_output_buffer_->set_next(buf);
    last_output_buffer_ = buf;
  }

  last_output_buffer_->OnAlloc(suggested_size, buf);
}


void SyncProcessStdioPipe::OnRead(const uv_buf_t* buf, ssize_t nread) {
  if (nread == UV_EOF) {
    // Libuv implicitly stops reading on EOF.

  } else if (nread < 0) {
    SetError(static_cast<int>(nread));
    // At some point libuv should really implicitly stop reading on error.
    uv_read_stop(uv_stream());

  } else {
    last_output_buffer_->OnRead(buf, nread);
    process_handler_->IncrementBufferSizeAndCheckOverflow(nread);
  }
}


void SyncProcessStdioPipe::OnWriteDone(int result) {
  if (result < 0)
    SetError(result);
}


void SyncProcessStdioPipe::OnShutdownDone(int result) {
  if (result < 0)
    SetError(result);
}


void SyncProcessStdioPipe::OnClose() {
  lifecycle_ = kClosed;
}


void SyncProcessStdioPipe::SetError(int error) {
  CHECK_NE(error, 0);
  process_handler_->SetPipeError(error);
}


void SyncProcessStdioPipe::AllocCallback(uv_handle_t* handle,
                                         size_t suggested_size,
                                         uv_buf_t* buf) {
  SyncProcessStdioPipe* self =
      reinterpret_cast<SyncProcessStdioPipe*>(handle->data);
  self->OnAlloc(suggested_size, buf);
}


void SyncProcessStdioPipe::ReadCallback(uv_stream_t* stream,
                                        ssize_t nread,
                                        const uv_buf_t* buf) {
  SyncProcessStdioPipe* self =
        reinterpret_cast<SyncProcessStdioPipe*>(stream->data);
  self->OnRead(buf, nread);
}


void SyncProcessStdioPipe::WriteCallback(uv_write_t* req, int result) {
  SyncProcessStdioPipe* self =
      reinterpret_cast<SyncProcessStdioPipe*>(req->handle->data);
  self->OnWriteDone(result);
}


void SyncProcessStdioPipe::ShutdownCallback(uv_shutdown_t* req, int result) {
  SyncProcessStdioPipe* self =
      reinterpret_cast<SyncProcessStdioPipe*>(req->handle->data);

  // On AIX, OS X and the BSDs, calling shutdown() on one end of a pipe
  // when the other end has closed the connection fails with ENOTCONN.
  // Libuv is not the right place to handle that because it can't tell
  // if the error is genuine but we here can.
  if (result == UV_ENOTCONN)
    result = 0;

  self->OnShutdownDone(result);
}


void SyncProcessStdioPipe::CloseCallback(uv_handle_t* handle) {
  SyncProcessStdioPipe* self =
      reinterpret_cast<SyncProcessStdioPipe*>(handle->data);
  self->OnClose();
}


void SyncProcessRunner::Initialize(Local<Object> target,
                                   Local<Value> unused,
                                   Local<Context> context,
                                   void* priv) {
  Environment* env = Environment::GetCurrent(context);
  env->SetMethod(target, "spawn", Spawn);
}


void SyncProcessRunner::Spawn(const FunctionCallbackInfo<Value>& args) {
  Environment* env = Environment::GetCurrent(args);
  env->PrintSyncTrace();
  SyncProcessRunner p(env);
  Local<Value> result;
  if (!p.Run(args[0]).ToLocal(&result)) return;
  args.GetReturnValue().Set(result);
}


SyncProcessRunner::SyncProcessRunner(Environment* env)
    : max_buffer_(0),
      timeout_(0),
      kill_signal_(SIGTERM),

      uv_loop_(nullptr),

      stdio_count_(0),
      uv_stdio_containers_(nullptr),
      stdio_pipes_initialized_(false),

      uv_process_options_(),
      file_buffer_(nullptr),
      args_buffer_(nullptr),
      env_buffer_(nullptr),
      cwd_buffer_(nullptr),

      uv_process_(),
      killed_(false),

      buffered_output_size_(0),
      exit_status_(-1),
      term_signal_(-1),

      uv_timer_(),
      kill_timer_initialized_(false),

      error_(0),
      pipe_error_(0),

      lifecycle_(kUninitialized),

      env_(env) {
}


SyncProcessRunner::~SyncProcessRunner() {
  CHECK_EQ(lifecycle_, kHandlesClosed);

  stdio_pipes_.clear();
  delete[] file_buffer_;
  delete[] args_buffer_;
  delete[] cwd_buffer_;
  delete[] env_buffer_;
  delete[] uv_stdio_containers_;
}


Environment* SyncProcessRunner::env() const {
  return env_;
}

MaybeLocal<Object> SyncProcessRunner::Run(Local<Value> options) {
  EscapableHandleScope scope(env()->isolate());

  CHECK_EQ(lifecycle_, kUninitialized);

  Maybe<bool> r = TryInitializeAndRunLoop(options);
  CloseHandlesAndDeleteLoop();
  if (r.IsNothing()) return MaybeLocal<Object>();

  Local<Object> result = BuildResultObject();

  return scope.Escape(result);
}

Maybe<bool> SyncProcessRunner::TryInitializeAndRunLoop(Local<Value> options) {
  int r;

  // There is no recovery from failure inside TryInitializeAndRunLoop - the
  // only option we'd have is to close all handles and destroy the loop.
  CHECK_EQ(lifecycle_, kUninitialized);
  lifecycle_ = kInitialized;

  uv_loop_ = new uv_loop_t;
  if (uv_loop_ == nullptr) {
    SetError(UV_ENOMEM);
    return Just(false);
  }

  r = uv_loop_init(uv_loop_);
  if (r < 0) {
    delete uv_loop_;
    uv_loop_ = nullptr;
    SetError(r);
    return Just(false);
  }

  if (!ParseOptions(options).To(&r)) return Nothing<bool>();

  if (r < 0) {
    SetError(r);
    return Just(false);
  }

  if (timeout_ > 0) {
    r = uv_timer_init(uv_loop_, &uv_timer_);
    if (r < 0) {
      SetError(r);
      return Just(false);
    }

    uv_unref(reinterpret_cast<uv_handle_t*>(&uv_timer_));

    uv_timer_.data = this;
    kill_timer_initialized_ = true;

    // Start the timer immediately. If uv_spawn fails then
    // CloseHandlesAndDeleteLoop() will immediately close the timer handle
    // which implicitly stops it, so there is no risk that the timeout callback
    // runs when the process didn't start.
    r = uv_timer_start(&uv_timer_, KillTimerCallback, timeout_, 0);
    if (r < 0) {
      SetError(r);
      return Just(false);
    }
  }

  uv_process_options_.exit_cb = ExitCallback;
  r = uv_spawn(uv_loop_, &uv_process_, &uv_process_options_);
  if (r < 0) {
    SetError(r);
    return Just(false);
  }
  uv_process_.data = this;

  for (const auto& pipe : stdio_pipes_) {
    if (pipe != nullptr) {
      r = pipe->Start();
      if (r < 0) {
        SetPipeError(r);
        return Just(false);
      }
    }
  }

  r = uv_run(uv_loop_, UV_RUN_DEFAULT);
  if (r < 0)
    // We can't handle uv_run failure.
    ABORT();

  // If we get here the process should have exited.
  CHECK_GE(exit_status_, 0);
  return Just(true);
}


void SyncProcessRunner::CloseHandlesAndDeleteLoop() {
  CHECK_LT(lifecycle_, kHandlesClosed);

  if (uv_loop_ != nullptr) {
    CloseStdioPipes();
    CloseKillTimer();
    // Close the process handle when ExitCallback was not called.
    uv_handle_t* uv_process_handle =
        reinterpret_cast<uv_handle_t*>(&uv_process_);

    // Close the process handle if it is still open. The handle type also
    // needs to be checked because TryInitializeAndRunLoop() won't spawn a
    // process if input validation fails.
    if (uv_process_handle->type == UV_PROCESS &&
        !uv_is_closing(uv_process_handle))
      uv_close(uv_process_handle, nullptr);

    // Give closing watchers a chance to finish closing and get their close
    // callbacks called.
    int r = uv_run(uv_loop_, UV_RUN_DEFAULT);
    if (r < 0)
      ABORT();

    CheckedUvLoopClose(uv_loop_);
    delete uv_loop_;
    uv_loop_ = nullptr;

  } else {
    // If the loop doesn't exist, neither should any pipes or timers.
    CHECK_EQ(false, stdio_pipes_initialized_);
    CHECK_EQ(false, kill_timer_initialized_);
  }

  lifecycle_ = kHandlesClosed;
}


void SyncProcessRunner::CloseStdioPipes() {
  CHECK_LT(lifecycle_, kHandlesClosed);

  if (stdio_pipes_initialized_) {
    CHECK(!stdio_pipes_.empty());
    CHECK_NOT_NULL(uv_loop_);

    for (const auto& pipe : stdio_pipes_) {
      if (pipe)
        pipe->Close();
    }

    stdio_pipes_initialized_ = false;
  }
}


void SyncProcessRunner::CloseKillTimer() {
  CHECK_LT(lifecycle_, kHandlesClosed);

  if (kill_timer_initialized_) {
    CHECK_GT(timeout_, 0);
    CHECK_NOT_NULL(uv_loop_);

    uv_handle_t* uv_timer_handle = reinterpret_cast<uv_handle_t*>(&uv_timer_);
    uv_ref(uv_timer_handle);
    uv_close(uv_timer_handle, KillTimerCloseCallback);

    kill_timer_initialized_ = false;
  }
}


void SyncProcessRunner::Kill() {
  // Only attempt to kill once.
  if (killed_)
    return;
  killed_ = true;

  // We might get here even if the process we spawned has already exited. This
  // could happen when our child process spawned another process which
  // inherited (one of) the stdio pipes. In this case we won't attempt to send
  // a signal to the process, however we will still close our end of the stdio
  // pipes so this situation won't make us hang.
  if (exit_status_ < 0) {
    int r = uv_process_kill(&uv_process_, kill_signal_);

    // If uv_kill failed with an error that isn't ESRCH, the user probably
    // specified an invalid or unsupported signal. Signal this to the user as
    // and error and kill the process with SIGKILL instead.
    if (r < 0 && r != UV_ESRCH) {
      SetError(r);

      // Deliberately ignore the return value, we might not have
      // sufficient privileges to signal the child process.
      USE(uv_process_kill(&uv_process_, SIGKILL));
    }
  }

  // Close all stdio pipes.
  CloseStdioPipes();

  // Stop the timeout timer immediately.
  CloseKillTimer();
}


void SyncProcessRunner::IncrementBufferSizeAndCheckOverflow(ssize_t length) {
  buffered_output_size_ += length;

  if (max_buffer_ > 0 && buffered_output_size_ > max_buffer_) {
    SetError(UV_ENOBUFS);
    Kill();
  }
}


void SyncProcessRunner::OnExit(int64_t exit_status, int term_signal) {
  if (exit_status < 0)
    return SetError(static_cast<int>(exit_status));

  exit_status_ = exit_status;
  term_signal_ = term_signal;
}


void SyncProcessRunner::OnKillTimerTimeout() {
  SetError(UV_ETIMEDOUT);
  Kill();
}


int SyncProcessRunner::GetError() {
  if (error_ != 0)
    return error_;
  else
    return pipe_error_;
}


void SyncProcessRunner::SetError(int error) {
  if (error_ == 0)
    error_ = error;
}


void SyncProcessRunner::SetPipeError(int pipe_error) {
  if (pipe_error_ == 0)
    pipe_error_ = pipe_error;
}


Local<Object> SyncProcessRunner::BuildResultObject() {
  EscapableHandleScope scope(env()->isolate());
  Local<Context> context = env()->context();

  Local<Object> js_result = Object::New(env()->isolate());

  if (GetError() != 0) {
    js_result->Set(context, env()->error_string(),
                   Integer::New(env()->isolate(), GetError())).Check();
  }

  if (exit_status_ >= 0) {
    if (term_signal_ > 0) {
      js_result->Set(context, env()->status_string(),
                     Null(env()->isolate())).Check();
    } else {
      js_result->Set(context, env()->status_string(),
                     Number::New(env()->isolate(),
                                 static_cast<double>(exit_status_))).Check();
    }
  } else {
    // If exit_status_ < 0 the process was never started because of some error.
    js_result->Set(context, env()->status_string(),
                   Null(env()->isolate())).Check();
  }

  if (term_signal_ > 0)
    js_result->Set(context, env()->signal_string(),
                   String::NewFromUtf8(env()->isolate(),
                                       signo_string(term_signal_))
                       .ToLocalChecked())
        .Check();
  else
    js_result->Set(context, env()->signal_string(),
                   Null(env()->isolate())).Check();

  if (exit_status_ >= 0)
    js_result->Set(context, env()->output_string(),
                   BuildOutputArray()).Check();
  else
    js_result->Set(context, env()->output_string(),
                   Null(env()->isolate())).Check();

  js_result->Set(context, env()->pid_string(),
                 Number::New(env()->isolate(), uv_process_.pid)).Check();

  return scope.Escape(js_result);
}


Local<Array> SyncProcessRunner::BuildOutputArray() {
  CHECK_GE(lifecycle_, kInitialized);
  CHECK(!stdio_pipes_.empty());

  EscapableHandleScope scope(env()->isolate());
  MaybeStackBuffer<Local<Value>, 8> js_output(stdio_pipes_.size());

  for (uint32_t i = 0; i < stdio_pipes_.size(); i++) {
    SyncProcessStdioPipe* h = stdio_pipes_[i].get();
    if (h != nullptr && h->writable())
      js_output[i] = h->GetOutputAsBuffer(env());
    else
      js_output[i] = Null(env()->isolate());
  }

  return scope.Escape(
      Array::New(env()->isolate(), js_output.out(), js_output.length()));
}

Maybe<int> SyncProcessRunner::ParseOptions(Local<Value> js_value) {
  Isolate* isolate = env()->isolate();
  HandleScope scope(isolate);
  int r;

  if (!js_value->IsObject()) return Just<int>(UV_EINVAL);

  Local<Context> context = env()->context();
  Local<Object> js_options = js_value.As<Object>();

  Local<Value> js_file =
      js_options->Get(context, env()->file_string()).ToLocalChecked();
  if (!CopyJsString(js_file, &file_buffer_).To(&r)) return Nothing<int>();
  if (r < 0) return Just(r);
  uv_process_options_.file = file_buffer_;

  Local<Value> js_args =
      js_options->Get(context, env()->args_string()).ToLocalChecked();
  if (!CopyJsStringArray(js_args, &args_buffer_).To(&r)) return Nothing<int>();
  if (r < 0) return Just(r);
  uv_process_options_.args = reinterpret_cast<char**>(args_buffer_);

  Local<Value> js_cwd =
      js_options->Get(context, env()->cwd_string()).ToLocalChecked();
  if (IsSet(js_cwd)) {
    if (!CopyJsString(js_cwd, &cwd_buffer_).To(&r)) return Nothing<int>();
    if (r < 0) return Just(r);
    uv_process_options_.cwd = cwd_buffer_;
  }

  Local<Value> js_env_pairs =
      js_options->Get(context, env()->env_pairs_string()).ToLocalChecked();
  if (IsSet(js_env_pairs)) {
    if (!CopyJsStringArray(js_env_pairs, &env_buffer_).To(&r))
      return Nothing<int>();
    if (r < 0) return Just(r);

    uv_process_options_.env = reinterpret_cast<char**>(env_buffer_);
  }
  Local<Value> js_uid =
      js_options->Get(context, env()->uid_string()).ToLocalChecked();
  if (IsSet(js_uid)) {
    CHECK(js_uid->IsInt32());
    const int32_t uid = js_uid.As<Int32>()->Value();
    uv_process_options_.uid = static_cast<uv_uid_t>(uid);
    uv_process_options_.flags |= UV_PROCESS_SETUID;
  }

  Local<Value> js_gid =
      js_options->Get(context, env()->gid_string()).ToLocalChecked();
  if (IsSet(js_gid)) {
    CHECK(js_gid->IsInt32());
    const int32_t gid = js_gid.As<Int32>()->Value();
    uv_process_options_.gid = static_cast<uv_gid_t>(gid);
    uv_process_options_.flags |= UV_PROCESS_SETGID;
  }

  Local<Value> js_detached =
      js_options->Get(context, env()->detached_string()).ToLocalChecked();
  if (js_detached->BooleanValue(isolate))
    uv_process_options_.flags |= UV_PROCESS_DETACHED;

  Local<Value> js_win_hide =
      js_options->Get(context, env()->windows_hide_string()).ToLocalChecked();
  if (js_win_hide->BooleanValue(isolate))
    uv_process_options_.flags |= UV_PROCESS_WINDOWS_HIDE;

  Local<Value> js_wva =
      js_options->Get(context, env()->windows_verbatim_arguments_string())
          .ToLocalChecked();

  if (js_wva->BooleanValue(isolate))
    uv_process_options_.flags |= UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS;

  Local<Value> js_timeout =
      js_options->Get(context, env()->timeout_string()).ToLocalChecked();
  if (IsSet(js_timeout)) {
    CHECK(js_timeout->IsNumber());
    int64_t timeout = js_timeout->IntegerValue(context).FromJust();
    timeout_ = static_cast<uint64_t>(timeout);
  }

  Local<Value> js_max_buffer =
      js_options->Get(context, env()->max_buffer_string()).ToLocalChecked();
  if (IsSet(js_max_buffer)) {
    CHECK(js_max_buffer->IsNumber());
    max_buffer_ = js_max_buffer->NumberValue(context).FromJust();
  }

  Local<Value> js_kill_signal =
      js_options->Get(context, env()->kill_signal_string()).ToLocalChecked();
  if (IsSet(js_kill_signal)) {
    CHECK(js_kill_signal->IsInt32());
    kill_signal_ = js_kill_signal.As<Int32>()->Value();
  }

  Local<Value> js_stdio =
      js_options->Get(context, env()->stdio_string()).ToLocalChecked();
  r = ParseStdioOptions(js_stdio);
  if (r < 0) return Just(r);

  return Just(0);
}


int SyncProcessRunner::ParseStdioOptions(Local<Value> js_value) {
  HandleScope scope(env()->isolate());
  Local<Array> js_stdio_options;

  if (!js_value->IsArray())
    return UV_EINVAL;

  Local<Context> context = env()->context();
  js_stdio_options = js_value.As<Array>();

  stdio_count_ = js_stdio_options->Length();
  uv_stdio_containers_ = new uv_stdio_container_t[stdio_count_];

  stdio_pipes_.clear();
  stdio_pipes_.resize(stdio_count_);
  stdio_pipes_initialized_ = true;

  for (uint32_t i = 0; i < stdio_count_; i++) {
    Local<Value> js_stdio_option =
        js_stdio_options->Get(context, i).ToLocalChecked();

    if (!js_stdio_option->IsObject())
      return UV_EINVAL;

    int r = ParseStdioOption(i, js_stdio_option.As<Object>());
    if (r < 0)
      return r;
  }

  uv_process_options_.stdio = uv_stdio_containers_;
  uv_process_options_.stdio_count = stdio_count_;

  return 0;
}


int SyncProcessRunner::ParseStdioOption(int child_fd,
                                        Local<Object> js_stdio_option) {
  Local<Context> context = env()->context();
  Local<Value> js_type =
      js_stdio_option->Get(context, env()->type_string()).ToLocalChecked();

  if (js_type->StrictEquals(env()->ignore_string())) {
    return AddStdioIgnore(child_fd);

  } else if (js_type->StrictEquals(env()->pipe_string())) {
    Isolate* isolate = env()->isolate();
    Local<String> rs = env()->readable_string();
    Local<String> ws = env()->writable_string();

    bool readable = js_stdio_option->Get(context, rs)
        .ToLocalChecked()->BooleanValue(isolate);
    bool writable =
        js_stdio_option->Get(context, ws)
        .ToLocalChecked()->BooleanValue(isolate);

    uv_buf_t buf = uv_buf_init(nullptr, 0);

    if (readable) {
      Local<Value> input =
          js_stdio_option->Get(context, env()->input_string()).ToLocalChecked();
      if (Buffer::HasInstance(input)) {
        buf = uv_buf_init(Buffer::Data(input),
                          static_cast<unsigned int>(Buffer::Length(input)));
      } else if (!input->IsUndefined() && !input->IsNull()) {
        // Strings, numbers etc. are currently unsupported. It's not possible
        // to create a buffer for them here because there is no way to free
        // them afterwards.
        return UV_EINVAL;
      }
    }

    return AddStdioPipe(child_fd, readable, writable, buf);

  } else if (js_type->StrictEquals(env()->inherit_string()) ||
             js_type->StrictEquals(env()->fd_string())) {
    int inherit_fd = js_stdio_option->Get(context, env()->fd_string())
        .ToLocalChecked()->Int32Value(context).FromJust();
    return AddStdioInheritFD(child_fd, inherit_fd);

  } else {
    CHECK(0 && "invalid child stdio type");
    return UV_EINVAL;
  }
}


int SyncProcessRunner::AddStdioIgnore(uint32_t child_fd) {
  CHECK_LT(child_fd, stdio_count_);
  CHECK(!stdio_pipes_[child_fd]);

  uv_stdio_containers_[child_fd].flags = UV_IGNORE;

  return 0;
}


int SyncProcessRunner::AddStdioPipe(uint32_t child_fd,
                                    bool readable,
                                    bool writable,
                                    uv_buf_t input_buffer) {
  CHECK_LT(child_fd, stdio_count_);
  CHECK(!stdio_pipes_[child_fd]);

  std::unique_ptr<SyncProcessStdioPipe> h(
      new SyncProcessStdioPipe(this, readable, writable, input_buffer));

  int r = h->Initialize(uv_loop_);
  if (r < 0) {
    h.reset();
    return r;
  }

  uv_stdio_containers_[child_fd].flags = h->uv_flags();
  uv_stdio_containers_[child_fd].data.stream = h->uv_stream();

  stdio_pipes_[child_fd] = std::move(h);

  return 0;
}


int SyncProcessRunner::AddStdioInheritFD(uint32_t child_fd, int inherit_fd) {
  CHECK_LT(child_fd, stdio_count_);
  CHECK(!stdio_pipes_[child_fd]);

  uv_stdio_containers_[child_fd].flags = UV_INHERIT_FD;
  uv_stdio_containers_[child_fd].data.fd = inherit_fd;

  return 0;
}


bool SyncProcessRunner::IsSet(Local<Value> value) {
  return !value->IsUndefined() && !value->IsNull();
}

Maybe<int> SyncProcessRunner::CopyJsString(Local<Value> js_value,
                                           const char** target) {
  Isolate* isolate = env()->isolate();
  Local<String> js_string;
  size_t size, written;
  char* buffer;

  if (js_value->IsString())
    js_string = js_value.As<String>();
  else if (!js_value->ToString(env()->isolate()->GetCurrentContext())
                .ToLocal(&js_string))
    return Nothing<int>();

  // Include space for null terminator byte.
  if (!StringBytes::StorageSize(isolate, js_string, UTF8).To(&size))
    return Nothing<int>();
  size += 1;

  buffer = new char[size];

  written = StringBytes::Write(isolate, buffer, -1, js_string, UTF8);
  buffer[written] = '\0';

  *target = buffer;
  return Just(0);
}

Maybe<int> SyncProcessRunner::CopyJsStringArray(Local<Value> js_value,
                                                char** target) {
  Isolate* isolate = env()->isolate();
  Local<Array> js_array;
  uint32_t length;
  size_t list_size, data_size, data_offset;
  char** list;
  char* buffer;

  if (!js_value->IsArray()) return Just<int>(UV_EINVAL);

  Local<Context> context = env()->context();
  js_array = js_value.As<Array>()->Clone().As<Array>();
  length = js_array->Length();
  data_size = 0;

  // Index has a pointer to every string element, plus one more for a final
  // null pointer.
  list_size = (length + 1) * sizeof *list;

  // Convert all array elements to string. Modify the js object itself if
  // needed - it's okay since we cloned the original object. Also compute the
  // length of all strings, including room for a null terminator after every
  // string. Align strings to cache lines.
  for (uint32_t i = 0; i < length; i++) {
    auto value = js_array->Get(context, i).ToLocalChecked();

    if (!value->IsString()) {
      Local<String> string;
      if (!value->ToString(env()->isolate()->GetCurrentContext())
               .ToLocal(&string))
        return Nothing<int>();
      js_array
          ->Set(context,
                i,
                string)
          .Check();
    }

    Maybe<size_t> maybe_size = StringBytes::StorageSize(isolate, value, UTF8);
    if (maybe_size.IsNothing()) return Nothing<int>();
    data_size += maybe_size.FromJust() + 1;
    data_size = RoundUp(data_size, sizeof(void*));
  }

  buffer = new char[list_size + data_size];

  list = reinterpret_cast<char**>(buffer);
  data_offset = list_size;

  for (uint32_t i = 0; i < length; i++) {
    list[i] = buffer + data_offset;
    auto value = js_array->Get(context, i).ToLocalChecked();
    data_offset += StringBytes::Write(isolate,
                                      buffer + data_offset,
                                      -1,
                                      value,
                                      UTF8);
    buffer[data_offset++] = '\0';
    data_offset = RoundUp(data_offset, sizeof(void*));
  }

  list[length] = nullptr;

  *target = buffer;
  return Just(0);
}


void SyncProcessRunner::ExitCallback(uv_process_t* handle,
                                     int64_t exit_status,
                                     int term_signal) {
  SyncProcessRunner* self = reinterpret_cast<SyncProcessRunner*>(handle->data);
  uv_close(reinterpret_cast<uv_handle_t*>(handle), nullptr);
  self->OnExit(exit_status, term_signal);
}


void SyncProcessRunner::KillTimerCallback(uv_timer_t* handle) {
  SyncProcessRunner* self = reinterpret_cast<SyncProcessRunner*>(handle->data);
  self->OnKillTimerTimeout();
}


void SyncProcessRunner::KillTimerCloseCallback(uv_handle_t* handle) {
  // No-op.
}

}  // namespace node

NODE_MODULE_CONTEXT_AWARE_INTERNAL(spawn_sync,
  node::SyncProcessRunner::Initialize)
