// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "bin/process.h"

#include "bin/dartutils.h"
#include "bin/io_buffer.h"
#include "bin/namespace.h"
#include "bin/platform.h"
#include "bin/socket.h"
#include "bin/utils.h"
#include "platform/syslog.h"

#include "include/dart_api.h"

namespace dart {
namespace bin {

static const int kProcessIdNativeField = 0;

// Extract an array of C strings from a list of Dart strings.
static char** ExtractCStringList(Dart_Handle strings,
                                 Dart_Handle status_handle,
                                 const char* error_msg,
                                 intptr_t* length) {
  static const intptr_t kMaxArgumentListLength = 1024 * 1024;
  ASSERT(Dart_IsList(strings));
  intptr_t len = 0;
  Dart_Handle result = Dart_ListLength(strings, &len);
  ThrowIfError(result);
  // Protect against user-defined list implementations that can have
  // arbitrary length.
  if ((len < 0) || (len > kMaxArgumentListLength)) {
    result = DartUtils::SetIntegerField(status_handle, "_errorCode", 0);
    ThrowIfError(result);
    result = DartUtils::SetStringField(status_handle, "_errorMessage",
                                       "Max argument list length exceeded");
    ThrowIfError(result);
    return NULL;
  }
  *length = len;
  char** string_args;
  string_args =
      reinterpret_cast<char**>(Dart_ScopeAllocate(len * sizeof(*string_args)));
  for (int i = 0; i < len; i++) {
    Dart_Handle arg = Dart_ListGetAt(strings, i);
    ThrowIfError(arg);
    if (!Dart_IsString(arg)) {
      result = DartUtils::SetIntegerField(status_handle, "_errorCode", 0);
      ThrowIfError(result);
      result =
          DartUtils::SetStringField(status_handle, "_errorMessage", error_msg);
      ThrowIfError(result);
      return NULL;
    }
    string_args[i] = const_cast<char*>(DartUtils::GetStringValue(arg));
  }
  return string_args;
}

bool Process::ModeIsAttached(ProcessStartMode mode) {
  return (mode == kNormal) || (mode == kInheritStdio);
}

bool Process::ModeHasStdio(ProcessStartMode mode) {
  return (mode == kNormal) || (mode == kDetachedWithStdio);
}

void Process::ClearAllSignalHandlers() {
  for (intptr_t i = 1; i <= kLastSignal; i++) {
    ClearSignalHandler(i, ILLEGAL_PORT);
  }
}

void FUNCTION_NAME(Process_Start)(Dart_NativeArguments args) {
  Dart_Handle process = Dart_GetNativeArgument(args, 0);
  intptr_t process_stdin;
  intptr_t process_stdout;
  intptr_t process_stderr;
  intptr_t exit_event;
  Namespace* namespc = Namespace::GetNamespace(args, 1);
  Dart_Handle status_handle = Dart_GetNativeArgument(args, 11);
  Dart_Handle path_handle = Dart_GetNativeArgument(args, 2);
  // The Dart code verifies that the path implements the String
  // interface. However, only builtin Strings are handled by
  // GetStringValue.
  Dart_Handle result;
  if (!Dart_IsString(path_handle)) {
    result = DartUtils::SetIntegerField(status_handle, "_errorCode", 0);
    ThrowIfError(result);
    result = DartUtils::SetStringField(status_handle, "_errorMessage",
                                       "Path must be a builtin string");
    ThrowIfError(result);
    Dart_SetBooleanReturnValue(args, false);
    return;
  }
  const char* path = DartUtils::GetStringValue(path_handle);
  Dart_Handle arguments = Dart_GetNativeArgument(args, 3);
  intptr_t args_length = 0;
  char** string_args =
      ExtractCStringList(arguments, status_handle,
                         "Arguments must be builtin strings", &args_length);
  if (string_args == NULL) {
    Dart_SetBooleanReturnValue(args, false);
    return;
  }
  Dart_Handle working_directory_handle = Dart_GetNativeArgument(args, 4);
  // Defaults to the current working directoy.
  const char* working_directory = NULL;
  if (Dart_IsString(working_directory_handle)) {
    working_directory = DartUtils::GetStringValue(working_directory_handle);
  } else if (!Dart_IsNull(working_directory_handle)) {
    result = DartUtils::SetIntegerField(status_handle, "_errorCode", 0);
    ThrowIfError(result);
    result =
        DartUtils::SetStringField(status_handle, "_errorMessage",
                                  "WorkingDirectory must be a builtin string");
    ThrowIfError(result);
    Dart_SetBooleanReturnValue(args, false);
    return;
  }
  Dart_Handle environment = Dart_GetNativeArgument(args, 5);
  intptr_t environment_length = 0;
  char** string_environment = NULL;
  if (!Dart_IsNull(environment)) {
    string_environment = ExtractCStringList(
        environment, status_handle,
        "Environment values must be builtin strings", &environment_length);
    if (string_environment == NULL) {
      Dart_SetBooleanReturnValue(args, false);
      return;
    }
  }
  int64_t mode =
      DartUtils::GetInt64ValueCheckRange(Dart_GetNativeArgument(args, 6), 0, 3);
  Dart_Handle stdin_handle = Dart_GetNativeArgument(args, 7);
  Dart_Handle stdout_handle = Dart_GetNativeArgument(args, 8);
  Dart_Handle stderr_handle = Dart_GetNativeArgument(args, 9);
  Dart_Handle exit_handle = Dart_GetNativeArgument(args, 10);
  intptr_t pid = -1;
  char* os_error_message = NULL;  // Scope allocated by Process::Start.

  int error_code = Process::Start(
      namespc, path, string_args, args_length, working_directory,
      string_environment, environment_length,
      static_cast<ProcessStartMode>(mode), &process_stdout, &process_stdin,
      &process_stderr, &pid, &exit_event, &os_error_message);
  if (error_code == 0) {
    if (Process::ModeHasStdio(static_cast<ProcessStartMode>(mode))) {
      Socket::SetSocketIdNativeField(stdin_handle, process_stdin,
                                     Socket::kFinalizerNormal);
      Socket::SetSocketIdNativeField(stdout_handle, process_stdout,
                                     Socket::kFinalizerNormal);
      Socket::SetSocketIdNativeField(stderr_handle, process_stderr,
                                     Socket::kFinalizerNormal);
    }
    if (Process::ModeIsAttached(static_cast<ProcessStartMode>(mode))) {
      Socket::SetSocketIdNativeField(exit_handle, exit_event,
                                     Socket::kFinalizerNormal);
    }
    Process::SetProcessIdNativeField(process, pid);
  } else {
    result =
        DartUtils::SetIntegerField(status_handle, "_errorCode", error_code);
    ThrowIfError(result);

    const char* error_message = (os_error_message != NULL)
                                    ? os_error_message
                                    : "Failed to get error message";
    Dart_Handle val = DartUtils::NewString(error_message);
    if (Dart_IsError(val)) {
      // Try to clean the message from non-ASCII characters.
      const intptr_t len = strlen(error_message);
      char* ascii_message =
          reinterpret_cast<char*>(Dart_ScopeAllocate(len + 1));
      for (intptr_t i = 0; i < len; i++) {
        if (static_cast<uint8_t>(error_message[i]) < 0x80) {
          ascii_message[i] = error_message[i];
        } else {
          ascii_message[i] = '?';
        }
      }
      ascii_message[len] = '\0';

      val = DartUtils::NewStringFormatted(
          "Failed to start %s. OS returned an error (code %d) which can't be "
          "fully converted to Dart string (%s): %s",
          path, error_code, Dart_GetError(val), ascii_message);
    }
    result = Dart_SetField(status_handle, DartUtils::NewString("_errorMessage"),
                           val);
    ThrowIfError(result);
  }
  Dart_SetBooleanReturnValue(args, error_code == 0);
}

void FUNCTION_NAME(Process_Wait)(Dart_NativeArguments args) {
  Dart_Handle process = Dart_GetNativeArgument(args, 0);
  Socket* process_stdin =
      Socket::GetSocketIdNativeField(Dart_GetNativeArgument(args, 1));
  Socket* process_stdout =
      Socket::GetSocketIdNativeField(Dart_GetNativeArgument(args, 2));
  Socket* process_stderr =
      Socket::GetSocketIdNativeField(Dart_GetNativeArgument(args, 3));
  Socket* exit_event =
      Socket::GetSocketIdNativeField(Dart_GetNativeArgument(args, 4));
  ProcessResult result;
  intptr_t pid;
  Process::GetProcessIdNativeField(process, &pid);
  bool success = Process::Wait(pid, process_stdin->fd(), process_stdout->fd(),
                               process_stderr->fd(), exit_event->fd(), &result);
  // Process::Wait() closes the file handles, so blow away the fds in the
  // Sockets so that they don't get picked up by the finalizer on _NativeSocket.
  process_stdin->CloseFd();
  process_stdout->CloseFd();
  process_stderr->CloseFd();
  exit_event->CloseFd();
  if (success) {
    Dart_Handle out = result.stdout_data();
    ThrowIfError(out);
    Dart_Handle err = result.stderr_data();
    ThrowIfError(err);
    Dart_Handle list = Dart_NewList(4);
    Dart_ListSetAt(list, 0, Dart_NewInteger(pid));
    Dart_ListSetAt(list, 1, Dart_NewInteger(result.exit_code()));
    Dart_ListSetAt(list, 2, out);
    Dart_ListSetAt(list, 3, err);
    Dart_SetReturnValue(args, list);
  } else {
    Dart_Handle error = DartUtils::NewDartOSError();
    Process::Kill(pid, 9);
    Dart_ThrowException(error);
  }
}

void FUNCTION_NAME(Process_KillPid)(Dart_NativeArguments args) {
  intptr_t pid = DartUtils::GetIntptrValue(Dart_GetNativeArgument(args, 0));
  intptr_t signal = DartUtils::GetIntptrValue(Dart_GetNativeArgument(args, 1));
  bool success = Process::Kill(pid, signal);
  Dart_SetBooleanReturnValue(args, success);
}

void FUNCTION_NAME(Process_Exit)(Dart_NativeArguments args) {
  int64_t status = 0;
  // Ignore result if passing invalid argument and just exit 0.
  DartUtils::GetInt64Value(Dart_GetNativeArgument(args, 0), &status);
  Process::RunExitHook(status);
  Dart_ExitIsolate();
  Platform::Exit(static_cast<int>(status));
}

void FUNCTION_NAME(Process_SetExitCode)(Dart_NativeArguments args) {
  int64_t status = 0;
  // Ignore result if passing invalid argument and just set exit code to 0.
  DartUtils::GetInt64Value(Dart_GetNativeArgument(args, 0), &status);
  Process::SetGlobalExitCode(status);
}

void FUNCTION_NAME(Process_GetExitCode)(Dart_NativeArguments args) {
  Dart_SetIntegerReturnValue(args, Process::GlobalExitCode());
}

void FUNCTION_NAME(Process_Sleep)(Dart_NativeArguments args) {
  ScopedBlockingCall blocker;
  int64_t milliseconds = 0;
  // Ignore result if passing invalid argument and just set exit code to 0.
  DartUtils::GetInt64Value(Dart_GetNativeArgument(args, 0), &milliseconds);
  TimerUtils::Sleep(milliseconds);
}

void FUNCTION_NAME(Process_Pid)(Dart_NativeArguments args) {
  // Ignore result if passing invalid argument and just set exit code to 0.
  intptr_t pid = -1;
  Dart_Handle process = Dart_GetNativeArgument(args, 0);
  if (Dart_IsNull(process)) {
    pid = Process::CurrentProcessId();
  } else {
    Process::GetProcessIdNativeField(process, &pid);
  }
  Dart_SetIntegerReturnValue(args, pid);
}

void FUNCTION_NAME(Process_SetSignalHandler)(Dart_NativeArguments args) {
  intptr_t signal = DartUtils::GetIntptrValue(Dart_GetNativeArgument(args, 0));
  intptr_t id = Process::SetSignalHandler(signal);
  if (id == -1) {
    Dart_SetReturnValue(args, DartUtils::NewDartOSError());
  } else {
    Dart_SetIntegerReturnValue(args, id);
  }
}

void FUNCTION_NAME(Process_ClearSignalHandler)(Dart_NativeArguments args) {
  intptr_t signal = DartUtils::GetIntptrValue(Dart_GetNativeArgument(args, 0));
  Process::ClearSignalHandler(signal, Dart_GetMainPortId());
}

Dart_Handle Process::GetProcessIdNativeField(Dart_Handle process,
                                             intptr_t* pid) {
  return Dart_GetNativeInstanceField(process, kProcessIdNativeField, pid);
}

Dart_Handle Process::SetProcessIdNativeField(Dart_Handle process,
                                             intptr_t pid) {
  return Dart_SetNativeInstanceField(process, kProcessIdNativeField, pid);
}

void FUNCTION_NAME(SystemEncodingToString)(Dart_NativeArguments args) {
  Dart_Handle bytes = Dart_GetNativeArgument(args, 0);
  intptr_t bytes_length = 0;
  Dart_Handle result = Dart_ListLength(bytes, &bytes_length);
  ThrowIfError(result);
  uint8_t* buffer = Dart_ScopeAllocate(bytes_length + 1);
  result = Dart_ListGetAsBytes(bytes, 0, buffer, bytes_length);
  buffer[bytes_length] = '\0';
  ThrowIfError(result);
  intptr_t len;
  char* str = StringUtils::ConsoleStringToUtf8(reinterpret_cast<char*>(buffer),
                                               bytes_length, &len);
  if (str == NULL) {
    Dart_ThrowException(DartUtils::NewDartUnsupportedError(
        "SystemEncodingToString not supported on this operating system"));
  }
  result = Dart_NewStringFromUTF8(reinterpret_cast<const uint8_t*>(str), len);
  ThrowIfError(result);
  Dart_SetReturnValue(args, result);
}

void FUNCTION_NAME(StringToSystemEncoding)(Dart_NativeArguments args) {
  Dart_Handle str = Dart_GetNativeArgument(args, 0);
  char* utf8;
  intptr_t utf8_len;
  Dart_Handle result =
      Dart_StringToUTF8(str, reinterpret_cast<uint8_t**>(&utf8), &utf8_len);
  ThrowIfError(result);
  intptr_t system_len;
  const char* system_string =
      StringUtils::Utf8ToConsoleString(utf8, utf8_len, &system_len);
  if (system_string == NULL) {
    Dart_ThrowException(DartUtils::NewDartUnsupportedError(
        "StringToSystemEncoding not supported on this operating system"));
  }
  uint8_t* buffer = NULL;
  Dart_Handle external_array = IOBuffer::Allocate(system_len, &buffer);
  if (Dart_IsNull(external_array)) {
    Dart_SetReturnValue(args, DartUtils::NewDartOSError());
    return;
  }
  if (!Dart_IsError(external_array)) {
    memmove(buffer, system_string, system_len);
  }
  Dart_SetReturnValue(args, external_array);
}

void FUNCTION_NAME(ProcessInfo_CurrentRSS)(Dart_NativeArguments args) {
  int64_t current_rss = Process::CurrentRSS();
  if (current_rss < 0) {
    Dart_SetReturnValue(args, DartUtils::NewDartOSError());
    return;
  }
  Dart_SetIntegerReturnValue(args, current_rss);
}

void FUNCTION_NAME(ProcessInfo_MaxRSS)(Dart_NativeArguments args) {
  int64_t max_rss = Process::MaxRSS();
  if (max_rss < 0) {
    Dart_SetReturnValue(args, DartUtils::NewDartOSError());
    return;
  }
  Dart_SetIntegerReturnValue(args, max_rss);
}

void Process::GetRSSInformation(int64_t* max_rss, int64_t* current_rss) {
  ASSERT(max_rss != NULL);
  ASSERT(current_rss != NULL);
  // Max RSS should be queried after current RSS to produce
  // consistent values as current RSS can grow beyond max RSS which
  // was queried before.
  *current_rss = Process::CurrentRSS();
  *max_rss = Process::MaxRSS();
}

}  // namespace bin
}  // namespace dart
