// Copyright 2009 the V8 project 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 <errno.h>
#include <fcntl.h>
#include <netinet/ip.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

#include "src/d8.h"

namespace v8 {


// If the buffer ends in the middle of a UTF-8 sequence then we return
// the length of the string up to but not including the incomplete UTF-8
// sequence.  If the buffer ends with a valid UTF-8 sequence then we
// return the whole buffer.
static int LengthWithoutIncompleteUtf8(char* buffer, int len) {
  int answer = len;
  // 1-byte encoding.
  static const int kUtf8SingleByteMask = 0x80;
  static const int kUtf8SingleByteValue = 0x00;
  // 2-byte encoding.
  static const int kUtf8TwoByteMask = 0xE0;
  static const int kUtf8TwoByteValue = 0xC0;
  // 3-byte encoding.
  static const int kUtf8ThreeByteMask = 0xF0;
  static const int kUtf8ThreeByteValue = 0xE0;
  // 4-byte encoding.
  static const int kUtf8FourByteMask = 0xF8;
  static const int kUtf8FourByteValue = 0xF0;
  // Subsequent bytes of a multi-byte encoding.
  static const int kMultiByteMask = 0xC0;
  static const int kMultiByteValue = 0x80;
  int multi_byte_bytes_seen = 0;
  while (answer > 0) {
    int c = buffer[answer - 1];
    // Ends in valid single-byte sequence?
    if ((c & kUtf8SingleByteMask) == kUtf8SingleByteValue) return answer;
    // Ends in one or more subsequent bytes of a multi-byte value?
    if ((c & kMultiByteMask) == kMultiByteValue) {
      multi_byte_bytes_seen++;
      answer--;
    } else {
      if ((c & kUtf8TwoByteMask) == kUtf8TwoByteValue) {
        if (multi_byte_bytes_seen >= 1) {
          return answer + 2;
        }
        return answer - 1;
      } else if ((c & kUtf8ThreeByteMask) == kUtf8ThreeByteValue) {
        if (multi_byte_bytes_seen >= 2) {
          return answer + 3;
        }
        return answer - 1;
      } else if ((c & kUtf8FourByteMask) == kUtf8FourByteValue) {
        if (multi_byte_bytes_seen >= 3) {
          return answer + 4;
        }
        return answer - 1;
      } else {
        return answer;  // Malformed UTF-8.
      }
    }
  }
  return 0;
}


// Suspends the thread until there is data available from the child process.
// Returns false on timeout, true on data ready.
static bool WaitOnFD(int fd,
                     int read_timeout,
                     int total_timeout,
                     const struct timeval& start_time) {
  fd_set readfds, writefds, exceptfds;
  struct timeval timeout;
  int gone = 0;
  if (total_timeout != -1) {
    struct timeval time_now;
    gettimeofday(&time_now, nullptr);
    time_t seconds = time_now.tv_sec - start_time.tv_sec;
    gone = static_cast<int>(seconds * 1000 +
                            (time_now.tv_usec - start_time.tv_usec) / 1000);
    if (gone >= total_timeout) return false;
  }
  FD_ZERO(&readfds);
  FD_ZERO(&writefds);
  FD_ZERO(&exceptfds);
  FD_SET(fd, &readfds);
  FD_SET(fd, &exceptfds);
  if (read_timeout == -1 ||
      (total_timeout != -1 && total_timeout - gone < read_timeout)) {
    read_timeout = total_timeout - gone;
  }
  timeout.tv_usec = (read_timeout % 1000) * 1000;
  timeout.tv_sec = read_timeout / 1000;
  int number_of_fds_ready = select(fd + 1, &readfds, &writefds, &exceptfds,
                                   read_timeout != -1 ? &timeout : nullptr);
  return number_of_fds_ready == 1;
}


// Checks whether we ran out of time on the timeout.  Returns true if we ran out
// of time, false if we still have time.
static bool TimeIsOut(const struct timeval& start_time, const int& total_time) {
  if (total_time == -1) return false;
  struct timeval time_now;
  gettimeofday(&time_now, nullptr);
  // Careful about overflow.
  int seconds = static_cast<int>(time_now.tv_sec - start_time.tv_sec);
  if (seconds > 100) {
    if (seconds * 1000 > total_time) return true;
    return false;
  }
  int useconds = static_cast<int>(time_now.tv_usec - start_time.tv_usec);
  if (seconds * 1000000 + useconds > total_time * 1000) {
    return true;
  }
  return false;
}


// A utility class that does a non-hanging waitpid on the child process if we
// bail out of the System() function early.  If you don't ever do a waitpid on
// a subprocess then it turns into one of those annoying 'zombie processes'.
class ZombieProtector {
 public:
  explicit ZombieProtector(int pid): pid_(pid) { }
  ~ZombieProtector() {
    if (pid_ != 0) waitpid(pid_, nullptr, 0);
  }
  void ChildIsDeadNow() { pid_ = 0; }
 private:
  int pid_;
};


// A utility class that closes a file descriptor when it goes out of scope.
class OpenFDCloser {
 public:
  explicit OpenFDCloser(int fd): fd_(fd) { }
  ~OpenFDCloser() { close(fd_); }
 private:
  int fd_;
};


// A utility class that takes the array of command arguments and puts then in an
// array of new[]ed UTF-8 C strings.  Deallocates them again when it goes out of
// scope.
class ExecArgs {
 public:
  ExecArgs() { exec_args_[0] = nullptr; }
  bool Init(Isolate* isolate, Local<Value> arg0, Local<Array> command_args) {
    String::Utf8Value prog(isolate, arg0);
    if (*prog == nullptr) {
      const char* message =
          "os.system(): String conversion of program name failed";
      isolate->ThrowException(
          String::NewFromUtf8(isolate, message, NewStringType::kNormal)
              .ToLocalChecked());
      return false;
    }
    int len = prog.length() + 3;
    char* c_arg = new char[len];
    snprintf(c_arg, len, "%s", *prog);
    exec_args_[0] = c_arg;
    int i = 1;
    for (unsigned j = 0; j < command_args->Length(); i++, j++) {
      Local<Value> arg(
          command_args->Get(isolate->GetCurrentContext(),
                            Integer::New(isolate, j)).ToLocalChecked());
      String::Utf8Value utf8_arg(isolate, arg);
      if (*utf8_arg == nullptr) {
        exec_args_[i] = nullptr;  // Consistent state for destructor.
        const char* message =
            "os.system(): String conversion of argument failed.";
        isolate->ThrowException(
            String::NewFromUtf8(isolate, message, NewStringType::kNormal)
                .ToLocalChecked());
        return false;
      }
      int len = utf8_arg.length() + 1;
      char* c_arg = new char[len];
      snprintf(c_arg, len, "%s", *utf8_arg);
      exec_args_[i] = c_arg;
    }
    exec_args_[i] = nullptr;
    return true;
  }
  ~ExecArgs() {
    for (unsigned i = 0; i < kMaxArgs; i++) {
      if (exec_args_[i] == nullptr) {
        return;
      }
      delete [] exec_args_[i];
      exec_args_[i] = 0;
    }
  }
  static const unsigned kMaxArgs = 1000;
  char* const* arg_array() const { return exec_args_; }
  const char* arg0() const { return exec_args_[0]; }

 private:
  char* exec_args_[kMaxArgs + 1];
};


// Gets the optional timeouts from the arguments to the system() call.
static bool GetTimeouts(const v8::FunctionCallbackInfo<v8::Value>& args,
                        int* read_timeout,
                        int* total_timeout) {
  if (args.Length() > 3) {
    if (args[3]->IsNumber()) {
      *total_timeout = args[3]
                           ->Int32Value(args.GetIsolate()->GetCurrentContext())
                           .FromJust();
    } else {
      args.GetIsolate()->ThrowException(
          String::NewFromUtf8(args.GetIsolate(),
                              "system: Argument 4 must be a number",
                              NewStringType::kNormal).ToLocalChecked());
      return false;
    }
  }
  if (args.Length() > 2) {
    if (args[2]->IsNumber()) {
      *read_timeout = args[2]
                          ->Int32Value(args.GetIsolate()->GetCurrentContext())
                          .FromJust();
    } else {
      args.GetIsolate()->ThrowException(
          String::NewFromUtf8(args.GetIsolate(),
                              "system: Argument 3 must be a number",
                              NewStringType::kNormal).ToLocalChecked());
      return false;
    }
  }
  return true;
}


static const int kReadFD = 0;
static const int kWriteFD = 1;


// This is run in the child process after fork() but before exec().  It normally
// ends with the child process being replaced with the desired child program.
// It only returns if an error occurred.
static void ExecSubprocess(int* exec_error_fds,
                           int* stdout_fds,
                           const ExecArgs& exec_args) {
  close(exec_error_fds[kReadFD]);  // Don't need this in the child.
  close(stdout_fds[kReadFD]);      // Don't need this in the child.
  close(1);                        // Close stdout.
  dup2(stdout_fds[kWriteFD], 1);   // Dup pipe fd to stdout.
  close(stdout_fds[kWriteFD]);     // Don't need the original fd now.
  fcntl(exec_error_fds[kWriteFD], F_SETFD, FD_CLOEXEC);
  execvp(exec_args.arg0(), exec_args.arg_array());
  // Only get here if the exec failed.  Write errno to the parent to tell
  // them it went wrong.  If it went well the pipe is closed.
  int err = errno;
  ssize_t bytes_written;
  do {
    bytes_written = write(exec_error_fds[kWriteFD], &err, sizeof(err));
  } while (bytes_written == -1 && errno == EINTR);
  // Return (and exit child process).
}


// Runs in the parent process.  Checks that the child was able to exec (closing
// the file desriptor), or reports an error if it failed.
static bool ChildLaunchedOK(Isolate* isolate, int* exec_error_fds) {
  ssize_t bytes_read;
  int err;
  do {
    bytes_read = read(exec_error_fds[kReadFD], &err, sizeof(err));
  } while (bytes_read == -1 && errno == EINTR);
  if (bytes_read != 0) {
    isolate->ThrowException(
        String::NewFromUtf8(isolate, strerror(err), NewStringType::kNormal)
            .ToLocalChecked());
    return false;
  }
  return true;
}


// Accumulates the output from the child in a string handle.  Returns true if it
// succeeded or false if an exception was thrown.
static Local<Value> GetStdout(Isolate* isolate, int child_fd,
                              const struct timeval& start_time,
                              int read_timeout, int total_timeout) {
  Local<String> accumulator = String::Empty(isolate);

  int fullness = 0;
  static const int kStdoutReadBufferSize = 4096;
  char buffer[kStdoutReadBufferSize];

  if (fcntl(child_fd, F_SETFL, O_NONBLOCK) != 0) {
    return isolate->ThrowException(
        String::NewFromUtf8(isolate, strerror(errno), NewStringType::kNormal)
            .ToLocalChecked());
  }

  int bytes_read;
  do {
    bytes_read = static_cast<int>(
        read(child_fd, buffer + fullness, kStdoutReadBufferSize - fullness));
    if (bytes_read == -1) {
      if (errno == EAGAIN) {
        if (!WaitOnFD(child_fd,
                      read_timeout,
                      total_timeout,
                      start_time) ||
            (TimeIsOut(start_time, total_timeout))) {
          return isolate->ThrowException(
              String::NewFromUtf8(isolate, "Timed out waiting for output",
                                  NewStringType::kNormal).ToLocalChecked());
        }
        continue;
      } else if (errno == EINTR) {
        continue;
      } else {
        break;
      }
    }
    if (bytes_read + fullness > 0) {
      int length = bytes_read == 0 ?
                   bytes_read + fullness :
                   LengthWithoutIncompleteUtf8(buffer, bytes_read + fullness);
      Local<String> addition =
          String::NewFromUtf8(isolate, buffer, NewStringType::kNormal, length)
              .ToLocalChecked();
      accumulator = String::Concat(accumulator, addition);
      fullness = bytes_read + fullness - length;
      memcpy(buffer, buffer + length, fullness);
    }
  } while (bytes_read != 0);
  return accumulator;
}


// Modern Linux has the waitid call, which is like waitpid, but more useful
// if you want a timeout.  If we don't have waitid we can't limit the time
// waiting for the process to exit without losing the information about
// whether it exited normally.  In the common case this doesn't matter because
// we don't get here before the child has closed stdout and most programs don't
// do that before they exit.
//
// We're disabling usage of waitid in Mac OS X because it doesn't work for us:
// a parent process hangs on waiting while a child process is already a zombie.
// See http://code.google.com/p/v8/issues/detail?id=401.
#if defined(WNOWAIT) && !defined(ANDROID) && !defined(__APPLE__) \
    && !defined(__NetBSD__)
#if !defined(__FreeBSD__)
#define HAS_WAITID 1
#endif
#endif


// Get exit status of child.
static bool WaitForChild(Isolate* isolate,
                         int pid,
                         ZombieProtector& child_waiter,  // NOLINT
                         const struct timeval& start_time,
                         int read_timeout,
                         int total_timeout) {
#ifdef HAS_WAITID

  siginfo_t child_info;
  child_info.si_pid = 0;
  int useconds = 1;
  // Wait for child to exit.
  while (child_info.si_pid == 0) {
    waitid(P_PID, pid, &child_info, WEXITED | WNOHANG | WNOWAIT);
    usleep(useconds);
    if (useconds < 1000000) useconds <<= 1;
    if ((read_timeout != -1 && useconds / 1000 > read_timeout) ||
        (TimeIsOut(start_time, total_timeout))) {
      isolate->ThrowException(
          String::NewFromUtf8(isolate,
                              "Timed out waiting for process to terminate",
                              NewStringType::kNormal).ToLocalChecked());
      kill(pid, SIGINT);
      return false;
    }
  }
  if (child_info.si_code == CLD_KILLED) {
    char message[999];
    snprintf(message,
             sizeof(message),
             "Child killed by signal %d",
             child_info.si_status);
    isolate->ThrowException(
        String::NewFromUtf8(isolate, message, NewStringType::kNormal)
            .ToLocalChecked());
    return false;
  }
  if (child_info.si_code == CLD_EXITED && child_info.si_status != 0) {
    char message[999];
    snprintf(message,
             sizeof(message),
             "Child exited with status %d",
             child_info.si_status);
    isolate->ThrowException(
        String::NewFromUtf8(isolate, message, NewStringType::kNormal)
            .ToLocalChecked());
    return false;
  }

#else  // No waitid call.

  int child_status;
  waitpid(pid, &child_status, 0);  // We hang here if the child doesn't exit.
  child_waiter.ChildIsDeadNow();
  if (WIFSIGNALED(child_status)) {
    char message[999];
    snprintf(message,
             sizeof(message),
             "Child killed by signal %d",
             WTERMSIG(child_status));
    isolate->ThrowException(
        String::NewFromUtf8(isolate, message, NewStringType::kNormal)
            .ToLocalChecked());
    return false;
  }
  if (WEXITSTATUS(child_status) != 0) {
    char message[999];
    int exit_status = WEXITSTATUS(child_status);
    snprintf(message,
             sizeof(message),
             "Child exited with status %d",
             exit_status);
    isolate->ThrowException(
        String::NewFromUtf8(isolate, message, NewStringType::kNormal)
            .ToLocalChecked());
    return false;
  }

#endif  // No waitid call.

  return true;
}


// Implementation of the system() function (see d8.h for details).
void Shell::System(const v8::FunctionCallbackInfo<v8::Value>& args) {
  HandleScope scope(args.GetIsolate());
  int read_timeout = -1;
  int total_timeout = -1;
  if (!GetTimeouts(args, &read_timeout, &total_timeout)) return;
  Local<Array> command_args;
  if (args.Length() > 1) {
    if (!args[1]->IsArray()) {
      args.GetIsolate()->ThrowException(
          String::NewFromUtf8(args.GetIsolate(),
                              "system: Argument 2 must be an array",
                              NewStringType::kNormal).ToLocalChecked());
      return;
    }
    command_args = Local<Array>::Cast(args[1]);
  } else {
    command_args = Array::New(args.GetIsolate(), 0);
  }
  if (command_args->Length() > ExecArgs::kMaxArgs) {
    args.GetIsolate()->ThrowException(
        String::NewFromUtf8(args.GetIsolate(), "Too many arguments to system()",
                            NewStringType::kNormal).ToLocalChecked());
    return;
  }
  if (args.Length() < 1) {
    args.GetIsolate()->ThrowException(
        String::NewFromUtf8(args.GetIsolate(), "Too few arguments to system()",
                            NewStringType::kNormal).ToLocalChecked());
    return;
  }

  struct timeval start_time;
  gettimeofday(&start_time, nullptr);

  ExecArgs exec_args;
  if (!exec_args.Init(args.GetIsolate(), args[0], command_args)) {
    return;
  }
  int exec_error_fds[2];
  int stdout_fds[2];

  if (pipe(exec_error_fds) != 0) {
    args.GetIsolate()->ThrowException(
        String::NewFromUtf8(args.GetIsolate(), "pipe syscall failed.",
                            NewStringType::kNormal).ToLocalChecked());
    return;
  }
  if (pipe(stdout_fds) != 0) {
    args.GetIsolate()->ThrowException(
        String::NewFromUtf8(args.GetIsolate(), "pipe syscall failed.",
                            NewStringType::kNormal).ToLocalChecked());
    return;
  }

  pid_t pid = fork();
  if (pid == 0) {  // Child process.
    ExecSubprocess(exec_error_fds, stdout_fds, exec_args);
    exit(1);
  }

  // Parent process.  Ensure that we clean up if we exit this function early.
  ZombieProtector child_waiter(pid);
  close(exec_error_fds[kWriteFD]);
  close(stdout_fds[kWriteFD]);
  OpenFDCloser error_read_closer(exec_error_fds[kReadFD]);
  OpenFDCloser stdout_read_closer(stdout_fds[kReadFD]);

  Isolate* isolate = args.GetIsolate();
  if (!ChildLaunchedOK(isolate, exec_error_fds)) return;

  Local<Value> accumulator = GetStdout(isolate, stdout_fds[kReadFD], start_time,
                                       read_timeout, total_timeout);
  if (accumulator->IsUndefined()) {
    kill(pid, SIGINT);  // On timeout, kill the subprocess.
    args.GetReturnValue().Set(accumulator);
    return;
  }

  if (!WaitForChild(isolate, pid, child_waiter, start_time, read_timeout,
                    total_timeout)) {
    return;
  }

  args.GetReturnValue().Set(accumulator);
}


void Shell::ChangeDirectory(const v8::FunctionCallbackInfo<v8::Value>& args) {
  if (args.Length() != 1) {
    const char* message = "chdir() takes one argument";
    args.GetIsolate()->ThrowException(
        String::NewFromUtf8(args.GetIsolate(), message, NewStringType::kNormal)
            .ToLocalChecked());
    return;
  }
  String::Utf8Value directory(args.GetIsolate(), args[0]);
  if (*directory == nullptr) {
    const char* message = "os.chdir(): String conversion of argument failed.";
    args.GetIsolate()->ThrowException(
        String::NewFromUtf8(args.GetIsolate(), message, NewStringType::kNormal)
            .ToLocalChecked());
    return;
  }
  if (chdir(*directory) != 0) {
    args.GetIsolate()->ThrowException(
        String::NewFromUtf8(args.GetIsolate(), strerror(errno),
                            NewStringType::kNormal).ToLocalChecked());
    return;
  }
}


void Shell::SetUMask(const v8::FunctionCallbackInfo<v8::Value>& args) {
  if (args.Length() != 1) {
    const char* message = "umask() takes one argument";
    args.GetIsolate()->ThrowException(
        String::NewFromUtf8(args.GetIsolate(), message, NewStringType::kNormal)
            .ToLocalChecked());
    return;
  }
  if (args[0]->IsNumber()) {
    int previous = umask(
        args[0]->Int32Value(args.GetIsolate()->GetCurrentContext()).FromJust());
    args.GetReturnValue().Set(previous);
    return;
  } else {
    const char* message = "umask() argument must be numeric";
    args.GetIsolate()->ThrowException(
        String::NewFromUtf8(args.GetIsolate(), message, NewStringType::kNormal)
            .ToLocalChecked());
    return;
  }
}


static bool CheckItsADirectory(Isolate* isolate, char* directory) {
  struct stat stat_buf;
  int stat_result = stat(directory, &stat_buf);
  if (stat_result != 0) {
    isolate->ThrowException(
        String::NewFromUtf8(isolate, strerror(errno), NewStringType::kNormal)
            .ToLocalChecked());
    return false;
  }
  if ((stat_buf.st_mode & S_IFDIR) != 0) return true;
  isolate->ThrowException(
      String::NewFromUtf8(isolate, strerror(EEXIST), NewStringType::kNormal)
          .ToLocalChecked());
  return false;
}


// Returns true for success.  Creates intermediate directories as needed.  No
// error if the directory exists already.
static bool mkdirp(Isolate* isolate, char* directory, mode_t mask) {
  int result = mkdir(directory, mask);
  if (result == 0) return true;
  if (errno == EEXIST) {
    return CheckItsADirectory(isolate, directory);
  } else if (errno == ENOENT) {  // Intermediate path element is missing.
    char* last_slash = strrchr(directory, '/');
    if (last_slash == nullptr) {
      isolate->ThrowException(
          String::NewFromUtf8(isolate, strerror(errno), NewStringType::kNormal)
              .ToLocalChecked());
      return false;
    }
    *last_slash = 0;
    if (!mkdirp(isolate, directory, mask)) return false;
    *last_slash = '/';
    result = mkdir(directory, mask);
    if (result == 0) return true;
    if (errno == EEXIST) {
      return CheckItsADirectory(isolate, directory);
    }
    isolate->ThrowException(
        String::NewFromUtf8(isolate, strerror(errno), NewStringType::kNormal)
            .ToLocalChecked());
    return false;
  } else {
    isolate->ThrowException(
        String::NewFromUtf8(isolate, strerror(errno), NewStringType::kNormal)
            .ToLocalChecked());
    return false;
  }
}


void Shell::MakeDirectory(const v8::FunctionCallbackInfo<v8::Value>& args) {
  mode_t mask = 0777;
  if (args.Length() == 2) {
    if (args[1]->IsNumber()) {
      mask = args[1]
                 ->Int32Value(args.GetIsolate()->GetCurrentContext())
                 .FromJust();
    } else {
      const char* message = "mkdirp() second argument must be numeric";
      args.GetIsolate()->ThrowException(
          String::NewFromUtf8(args.GetIsolate(), message,
                              NewStringType::kNormal).ToLocalChecked());
      return;
    }
  } else if (args.Length() != 1) {
    const char* message = "mkdirp() takes one or two arguments";
    args.GetIsolate()->ThrowException(
        String::NewFromUtf8(args.GetIsolate(), message, NewStringType::kNormal)
            .ToLocalChecked());
    return;
  }
  String::Utf8Value directory(args.GetIsolate(), args[0]);
  if (*directory == nullptr) {
    const char* message = "os.mkdirp(): String conversion of argument failed.";
    args.GetIsolate()->ThrowException(
        String::NewFromUtf8(args.GetIsolate(), message, NewStringType::kNormal)
            .ToLocalChecked());
    return;
  }
  mkdirp(args.GetIsolate(), *directory, mask);
}


void Shell::RemoveDirectory(const v8::FunctionCallbackInfo<v8::Value>& args) {
  if (args.Length() != 1) {
    const char* message = "rmdir() takes one or two arguments";
    args.GetIsolate()->ThrowException(
        String::NewFromUtf8(args.GetIsolate(), message, NewStringType::kNormal)
            .ToLocalChecked());
    return;
  }
  String::Utf8Value directory(args.GetIsolate(), args[0]);
  if (*directory == nullptr) {
    const char* message = "os.rmdir(): String conversion of argument failed.";
    args.GetIsolate()->ThrowException(
        String::NewFromUtf8(args.GetIsolate(), message, NewStringType::kNormal)
            .ToLocalChecked());
    return;
  }
  rmdir(*directory);
}


void Shell::SetEnvironment(const v8::FunctionCallbackInfo<v8::Value>& args) {
  if (args.Length() != 2) {
    const char* message = "setenv() takes two arguments";
    args.GetIsolate()->ThrowException(
        String::NewFromUtf8(args.GetIsolate(), message, NewStringType::kNormal)
            .ToLocalChecked());
    return;
  }
  String::Utf8Value var(args.GetIsolate(), args[0]);
  String::Utf8Value value(args.GetIsolate(), args[1]);
  if (*var == nullptr) {
    const char* message =
        "os.setenv(): String conversion of variable name failed.";
    args.GetIsolate()->ThrowException(
        String::NewFromUtf8(args.GetIsolate(), message, NewStringType::kNormal)
            .ToLocalChecked());
    return;
  }
  if (*value == nullptr) {
    const char* message =
        "os.setenv(): String conversion of variable contents failed.";
    args.GetIsolate()->ThrowException(
        String::NewFromUtf8(args.GetIsolate(), message, NewStringType::kNormal)
            .ToLocalChecked());
    return;
  }
  setenv(*var, *value, 1);
}


void Shell::UnsetEnvironment(const v8::FunctionCallbackInfo<v8::Value>& args) {
  if (args.Length() != 1) {
    const char* message = "unsetenv() takes one argument";
    args.GetIsolate()->ThrowException(
        String::NewFromUtf8(args.GetIsolate(), message, NewStringType::kNormal)
            .ToLocalChecked());
    return;
  }
  String::Utf8Value var(args.GetIsolate(), args[0]);
  if (*var == nullptr) {
    const char* message =
        "os.setenv(): String conversion of variable name failed.";
    args.GetIsolate()->ThrowException(
        String::NewFromUtf8(args.GetIsolate(), message, NewStringType::kNormal)
            .ToLocalChecked());
    return;
  }
  unsetenv(*var);
}

char* Shell::ReadCharsFromTcpPort(const char* name, int* size_out) {
  DCHECK_GE(Shell::options.read_from_tcp_port, 0);

  int sockfd = socket(PF_INET, SOCK_STREAM, 0);
  if (sockfd < 0) {
    fprintf(stderr, "Failed to create IPv4 socket\n");
    return nullptr;
  }

  // Create an address for localhost:PORT where PORT is specified by the shell
  // option --read-from-tcp-port.
  sockaddr_in serv_addr;
  memset(&serv_addr, 0, sizeof(sockaddr_in));
  serv_addr.sin_family = AF_INET;
  serv_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
  serv_addr.sin_port = htons(Shell::options.read_from_tcp_port);

  if (connect(sockfd, reinterpret_cast<sockaddr*>(&serv_addr),
              sizeof(serv_addr)) < 0) {
    fprintf(stderr, "Failed to connect to localhost:%d\n",
            Shell::options.read_from_tcp_port);
    close(sockfd);
    return nullptr;
  }

  // The file server follows the simple protocol for requesting and receiving
  // a file with a given filename:
  //
  //   REQUEST client -> server: {filename}"\0"
  //   RESPONSE server -> client: {4-byte file-length}{file contents}
  //
  // i.e. the request sends the filename with a null terminator, and response
  // sends the file contents by sending the length (as a 4-byte big-endian
  // value) and the contents.

  // If the file length is <0, there was an error sending the file, and the
  // rest of the response is undefined (and may, in the future, contain an error
  // message). The socket should be closed to avoid trying to interpret the
  // undefined data.

  // REQUEST
  // Send the filename.
  size_t sent_len = 0;
  size_t name_len = strlen(name) + 1;  // Includes the null terminator
  while (sent_len < name_len) {
    ssize_t sent_now = send(sockfd, name + sent_len, name_len - sent_len, 0);
    if (sent_now < 0) {
      fprintf(stderr, "Failed to send %s to localhost:%d\n", name,
              Shell::options.read_from_tcp_port);
      close(sockfd);
      return nullptr;
    }
    sent_len += sent_now;
  }

  // RESPONSE
  // Receive the file.
  ssize_t received = 0;

  // First, read the (zero-terminated) file length.
  uint32_t big_endian_file_length;
  received = recv(sockfd, &big_endian_file_length, 4, 0);
  // We need those 4 bytes to read off the file length.
  if (received < 4) {
    fprintf(stderr, "Failed to receive %s's length from localhost:%d\n", name,
            Shell::options.read_from_tcp_port);
    close(sockfd);
    return nullptr;
  }
  // Reinterpretet the received file length as a signed big-endian integer.
  int32_t file_length = bit_cast<int32_t>(htonl(big_endian_file_length));

  if (file_length < 0) {
    fprintf(stderr, "Received length %d for %s from localhost:%d\n",
            file_length, name, Shell::options.read_from_tcp_port);
    close(sockfd);
    return nullptr;
  }

  // Allocate the output array.
  char* chars = new char[file_length];

  // Now keep receiving and copying until the whole file is received.
  ssize_t total_received = 0;
  while (total_received < file_length) {
    received =
        recv(sockfd, chars + total_received, file_length - total_received, 0);
    if (received < 0) {
      fprintf(stderr, "Failed to receive %s from localhost:%d\n", name,
              Shell::options.read_from_tcp_port);
      close(sockfd);
      delete[] chars;
      return nullptr;
    }
    total_received += received;
  }

  close(sockfd);
  *size_out = file_length;
  return chars;
}

void Shell::AddOSMethods(Isolate* isolate, Local<ObjectTemplate> os_templ) {
  if (options.enable_os_system) {
    os_templ->Set(String::NewFromUtf8(isolate, "system", NewStringType::kNormal)
                      .ToLocalChecked(),
                  FunctionTemplate::New(isolate, System));
  }
  os_templ->Set(String::NewFromUtf8(isolate, "chdir", NewStringType::kNormal)
                    .ToLocalChecked(),
                FunctionTemplate::New(isolate, ChangeDirectory));
  os_templ->Set(String::NewFromUtf8(isolate, "setenv", NewStringType::kNormal)
                    .ToLocalChecked(),
                FunctionTemplate::New(isolate, SetEnvironment));
  os_templ->Set(String::NewFromUtf8(isolate, "unsetenv", NewStringType::kNormal)
                    .ToLocalChecked(),
                FunctionTemplate::New(isolate, UnsetEnvironment));
  os_templ->Set(String::NewFromUtf8(isolate, "umask", NewStringType::kNormal)
                    .ToLocalChecked(),
                FunctionTemplate::New(isolate, SetUMask));
  os_templ->Set(String::NewFromUtf8(isolate, "mkdirp", NewStringType::kNormal)
                    .ToLocalChecked(),
                FunctionTemplate::New(isolate, MakeDirectory));
  os_templ->Set(String::NewFromUtf8(isolate, "rmdir", NewStringType::kNormal)
                    .ToLocalChecked(),
                FunctionTemplate::New(isolate, RemoveDirectory));
}

void Shell::Exit(int exit_code) {
  // Use _exit instead of exit to avoid races between isolate
  // threads and static destructors.
  fflush(stdout);
  fflush(stderr);
  _exit(exit_code);
}

}  // namespace v8
