//===-- ProcessLaunchInfo.cpp -----------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// C Includes
// C++ Includes
#include <climits>

// Other libraries and framework includes
// Project includes
#include "lldb/Core/Debugger.h"
#include "lldb/Host/Config.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Target/FileAction.h"
#include "lldb/Target/ProcessLaunchInfo.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/StreamString.h"

#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/FileSystem.h"

#if !defined(_WIN32)
#include <limits.h>
#endif

using namespace lldb;
using namespace lldb_private;

//----------------------------------------------------------------------------
// ProcessLaunchInfo member functions
//----------------------------------------------------------------------------

ProcessLaunchInfo::ProcessLaunchInfo()
    : ProcessInfo(), m_working_dir(), m_plugin_name(), m_flags(0),
      m_file_actions(), m_pty(new lldb_utility::PseudoTerminal),
      m_resume_count(0), m_monitor_callback(nullptr),
      m_monitor_callback_baton(nullptr), m_monitor_signals(false),
      m_listener_sp(), m_hijack_listener_sp() {}

ProcessLaunchInfo::ProcessLaunchInfo(const FileSpec &stdin_file_spec,
                                     const FileSpec &stdout_file_spec,
                                     const FileSpec &stderr_file_spec,
                                     const FileSpec &working_directory,
                                     uint32_t launch_flags)
    : ProcessInfo(), m_working_dir(), m_plugin_name(), m_flags(launch_flags),
      m_file_actions(), m_pty(new lldb_utility::PseudoTerminal),
      m_resume_count(0), m_monitor_callback(nullptr),
      m_monitor_callback_baton(nullptr), m_monitor_signals(false),
      m_listener_sp(), m_hijack_listener_sp() {
  if (stdin_file_spec) {
    FileAction file_action;
    const bool read = true;
    const bool write = false;
    if (file_action.Open(STDIN_FILENO, stdin_file_spec, read, write))
      AppendFileAction(file_action);
  }
  if (stdout_file_spec) {
    FileAction file_action;
    const bool read = false;
    const bool write = true;
    if (file_action.Open(STDOUT_FILENO, stdout_file_spec, read, write))
      AppendFileAction(file_action);
  }
  if (stderr_file_spec) {
    FileAction file_action;
    const bool read = false;
    const bool write = true;
    if (file_action.Open(STDERR_FILENO, stderr_file_spec, read, write))
      AppendFileAction(file_action);
  }
  if (working_directory)
    SetWorkingDirectory(working_directory);
}

bool ProcessLaunchInfo::AppendCloseFileAction(int fd) {
  FileAction file_action;
  if (file_action.Close(fd)) {
    AppendFileAction(file_action);
    return true;
  }
  return false;
}

bool ProcessLaunchInfo::AppendDuplicateFileAction(int fd, int dup_fd) {
  FileAction file_action;
  if (file_action.Duplicate(fd, dup_fd)) {
    AppendFileAction(file_action);
    return true;
  }
  return false;
}

bool ProcessLaunchInfo::AppendOpenFileAction(int fd, const FileSpec &file_spec,
                                             bool read, bool write) {
  FileAction file_action;
  if (file_action.Open(fd, file_spec, read, write)) {
    AppendFileAction(file_action);
    return true;
  }
  return false;
}

bool ProcessLaunchInfo::AppendSuppressFileAction(int fd, bool read,
                                                 bool write) {
  FileAction file_action;
  if (file_action.Open(fd, FileSpec{FileSystem::DEV_NULL, false}, read,
                       write)) {
    AppendFileAction(file_action);
    return true;
  }
  return false;
}

const FileAction *ProcessLaunchInfo::GetFileActionAtIndex(size_t idx) const {
  if (idx < m_file_actions.size())
    return &m_file_actions[idx];
  return nullptr;
}

const FileAction *ProcessLaunchInfo::GetFileActionForFD(int fd) const {
  for (size_t idx = 0, count = m_file_actions.size(); idx < count; ++idx) {
    if (m_file_actions[idx].GetFD() == fd)
      return &m_file_actions[idx];
  }
  return nullptr;
}

const FileSpec &ProcessLaunchInfo::GetWorkingDirectory() const {
  return m_working_dir;
}

void ProcessLaunchInfo::SetWorkingDirectory(const FileSpec &working_dir) {
  m_working_dir = working_dir;
}

const char *ProcessLaunchInfo::GetProcessPluginName() const {
  return (m_plugin_name.empty() ? nullptr : m_plugin_name.c_str());
}

void ProcessLaunchInfo::SetProcessPluginName(llvm::StringRef plugin) {
  m_plugin_name = plugin;
}

const FileSpec &ProcessLaunchInfo::GetShell() const { return m_shell; }

void ProcessLaunchInfo::SetShell(const FileSpec &shell) {
  m_shell = shell;
  if (m_shell) {
    m_shell.ResolveExecutableLocation();
    m_flags.Set(lldb::eLaunchFlagLaunchInShell);
  } else
    m_flags.Clear(lldb::eLaunchFlagLaunchInShell);
}

void ProcessLaunchInfo::SetLaunchInSeparateProcessGroup(bool separate) {
  if (separate)
    m_flags.Set(lldb::eLaunchFlagLaunchInSeparateProcessGroup);
  else
    m_flags.Clear(lldb::eLaunchFlagLaunchInSeparateProcessGroup);
}

void ProcessLaunchInfo::SetShellExpandArguments(bool expand) {
  if (expand)
    m_flags.Set(lldb::eLaunchFlagShellExpandArguments);
  else
    m_flags.Clear(lldb::eLaunchFlagShellExpandArguments);
}

void ProcessLaunchInfo::Clear() {
  ProcessInfo::Clear();
  m_working_dir.Clear();
  m_plugin_name.clear();
  m_shell.Clear();
  m_flags.Clear();
  m_file_actions.clear();
  m_resume_count = 0;
  m_listener_sp.reset();
  m_hijack_listener_sp.reset();
}

void ProcessLaunchInfo::SetMonitorProcessCallback(
    const Host::MonitorChildProcessCallback &callback, bool monitor_signals) {
  m_monitor_callback = callback;
  m_monitor_signals = monitor_signals;
}

bool ProcessLaunchInfo::MonitorProcess() const {
  if (m_monitor_callback && ProcessIDIsValid()) {
    Host::StartMonitoringChildProcess(m_monitor_callback, GetProcessID(),
                                      m_monitor_signals);
    return true;
  }
  return false;
}

void ProcessLaunchInfo::SetDetachOnError(bool enable) {
  if (enable)
    m_flags.Set(lldb::eLaunchFlagDetachOnError);
  else
    m_flags.Clear(lldb::eLaunchFlagDetachOnError);
}

void ProcessLaunchInfo::FinalizeFileActions(Target *target,
                                            bool default_to_use_pty) {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));

  // If nothing for stdin or stdout or stderr was specified, then check the
  // process for any default
  // settings that were set with "settings set"
  if (GetFileActionForFD(STDIN_FILENO) == nullptr ||
      GetFileActionForFD(STDOUT_FILENO) == nullptr ||
      GetFileActionForFD(STDERR_FILENO) == nullptr) {
    if (log)
      log->Printf("ProcessLaunchInfo::%s at least one of stdin/stdout/stderr "
                  "was not set, evaluating default handling",
                  __FUNCTION__);

    if (m_flags.Test(eLaunchFlagLaunchInTTY)) {
      // Do nothing, if we are launching in a remote terminal
      // no file actions should be done at all.
      return;
    }

    if (m_flags.Test(eLaunchFlagDisableSTDIO)) {
      if (log)
        log->Printf("ProcessLaunchInfo::%s eLaunchFlagDisableSTDIO set, adding "
                    "suppression action for stdin, stdout and stderr",
                    __FUNCTION__);
      AppendSuppressFileAction(STDIN_FILENO, true, false);
      AppendSuppressFileAction(STDOUT_FILENO, false, true);
      AppendSuppressFileAction(STDERR_FILENO, false, true);
    } else {
      // Check for any values that might have gotten set with any of:
      // (lldb) settings set target.input-path
      // (lldb) settings set target.output-path
      // (lldb) settings set target.error-path
      FileSpec in_file_spec;
      FileSpec out_file_spec;
      FileSpec err_file_spec;
      if (target) {
        // Only override with the target settings if we don't already have
        // an action for in, out or error
        if (GetFileActionForFD(STDIN_FILENO) == nullptr)
          in_file_spec = target->GetStandardInputPath();
        if (GetFileActionForFD(STDOUT_FILENO) == nullptr)
          out_file_spec = target->GetStandardOutputPath();
        if (GetFileActionForFD(STDERR_FILENO) == nullptr)
          err_file_spec = target->GetStandardErrorPath();
      }

      if (log)
        log->Printf("ProcessLaunchInfo::%s target stdin='%s', target "
                    "stdout='%s', stderr='%s'",
                    __FUNCTION__,
                    in_file_spec ? in_file_spec.GetCString() : "<null>",
                    out_file_spec ? out_file_spec.GetCString() : "<null>",
                    err_file_spec ? err_file_spec.GetCString() : "<null>");

      if (in_file_spec) {
        AppendOpenFileAction(STDIN_FILENO, in_file_spec, true, false);
        if (log)
          log->Printf(
              "ProcessLaunchInfo::%s appended stdin open file action for %s",
              __FUNCTION__, in_file_spec.GetCString());
      }

      if (out_file_spec) {
        AppendOpenFileAction(STDOUT_FILENO, out_file_spec, false, true);
        if (log)
          log->Printf(
              "ProcessLaunchInfo::%s appended stdout open file action for %s",
              __FUNCTION__, out_file_spec.GetCString());
      }

      if (err_file_spec) {
        AppendOpenFileAction(STDERR_FILENO, err_file_spec, false, true);
        if (log)
          log->Printf(
              "ProcessLaunchInfo::%s appended stderr open file action for %s",
              __FUNCTION__, err_file_spec.GetCString());
      }

      if (default_to_use_pty &&
          (!in_file_spec || !out_file_spec || !err_file_spec)) {
        if (log)
          log->Printf("ProcessLaunchInfo::%s default_to_use_pty is set, and at "
                      "least one stdin/stderr/stdout is unset, so generating a "
                      "pty to use for it",
                      __FUNCTION__);

        int open_flags = O_RDWR | O_NOCTTY;
#if !defined(_WIN32)
        // We really shouldn't be specifying platform specific flags
        // that are intended for a system call in generic code.  But
        // this will have to do for now.
        open_flags |= O_CLOEXEC;
#endif
        if (m_pty->OpenFirstAvailableMaster(open_flags, nullptr, 0)) {
          const FileSpec slave_file_spec{m_pty->GetSlaveName(nullptr, 0),
                                         false};

          // Only use the slave tty if we don't have anything specified for
          // input and don't have an action for stdin
          if (!in_file_spec && GetFileActionForFD(STDIN_FILENO) == nullptr) {
            AppendOpenFileAction(STDIN_FILENO, slave_file_spec, true, false);
          }

          // Only use the slave tty if we don't have anything specified for
          // output and don't have an action for stdout
          if (!out_file_spec && GetFileActionForFD(STDOUT_FILENO) == nullptr) {
            AppendOpenFileAction(STDOUT_FILENO, slave_file_spec, false, true);
          }

          // Only use the slave tty if we don't have anything specified for
          // error and don't have an action for stderr
          if (!err_file_spec && GetFileActionForFD(STDERR_FILENO) == nullptr) {
            AppendOpenFileAction(STDERR_FILENO, slave_file_spec, false, true);
          }
        }
      }
    }
  }
}

bool ProcessLaunchInfo::ConvertArgumentsForLaunchingInShell(
    Status &error, bool localhost, bool will_debug,
    bool first_arg_is_full_shell_command, int32_t num_resumes) {
  error.Clear();

  if (GetFlags().Test(eLaunchFlagLaunchInShell)) {
    if (m_shell) {
      std::string shell_executable = m_shell.GetPath();

      const char **argv = GetArguments().GetConstArgumentVector();
      if (argv == nullptr || argv[0] == nullptr)
        return false;
      Args shell_arguments;
      std::string safe_arg;
      shell_arguments.AppendArgument(shell_executable);
      const llvm::Triple &triple = GetArchitecture().GetTriple();
      if (triple.getOS() == llvm::Triple::Win32 &&
          !triple.isWindowsCygwinEnvironment())
        shell_arguments.AppendArgument(llvm::StringRef("/C"));
      else
        shell_arguments.AppendArgument(llvm::StringRef("-c"));

      StreamString shell_command;
      if (will_debug) {
        // Add a modified PATH environment variable in case argv[0]
        // is a relative path.
        const char *argv0 = argv[0];
        FileSpec arg_spec(argv0, false);
        if (arg_spec.IsRelative()) {
          // We have a relative path to our executable which may not work if
          // we just try to run "a.out" (without it being converted to
          // "./a.out")
          FileSpec working_dir = GetWorkingDirectory();
          // Be sure to put quotes around PATH's value in case any paths have
          // spaces...
          std::string new_path("PATH=\"");
          const size_t empty_path_len = new_path.size();

          if (working_dir) {
            new_path += working_dir.GetPath();
          } else {
            llvm::SmallString<64> cwd;
            if (! llvm::sys::fs::current_path(cwd))
              new_path += cwd;
          }
          std::string curr_path;
          if (HostInfo::GetEnvironmentVar("PATH", curr_path)) {
            if (new_path.size() > empty_path_len)
              new_path += ':';
            new_path += curr_path;
          }
          new_path += "\" ";
          shell_command.PutCString(new_path);
        }

        if (triple.getOS() != llvm::Triple::Win32 ||
            triple.isWindowsCygwinEnvironment())
          shell_command.PutCString("exec");

        // Only Apple supports /usr/bin/arch being able to specify the
        // architecture
        if (GetArchitecture().IsValid() && // Valid architecture
            GetArchitecture().GetTriple().getVendor() ==
                llvm::Triple::Apple && // Apple only
            GetArchitecture().GetCore() !=
                ArchSpec::eCore_x86_64_x86_64h) // Don't do this for x86_64h
        {
          shell_command.Printf(" /usr/bin/arch -arch %s",
                               GetArchitecture().GetArchitectureName());
          // Set the resume count to 2:
          // 1 - stop in shell
          // 2 - stop in /usr/bin/arch
          // 3 - then we will stop in our program
          SetResumeCount(num_resumes + 1);
        } else {
          // Set the resume count to 1:
          // 1 - stop in shell
          // 2 - then we will stop in our program
          SetResumeCount(num_resumes);
        }
      }

      if (first_arg_is_full_shell_command) {
        // There should only be one argument that is the shell command itself to
        // be used as is
        if (argv[0] && !argv[1])
          shell_command.Printf("%s", argv[0]);
        else
          return false;
      } else {
        for (size_t i = 0; argv[i] != nullptr; ++i) {
          const char *arg =
              Args::GetShellSafeArgument(m_shell, argv[i], safe_arg);
          shell_command.Printf(" %s", arg);
        }
      }
      shell_arguments.AppendArgument(shell_command.GetString());
      m_executable = m_shell;
      m_arguments = shell_arguments;
      return true;
    } else {
      error.SetErrorString("invalid shell path");
    }
  } else {
    error.SetErrorString("not launching in shell");
  }
  return false;
}

ListenerSP ProcessLaunchInfo::GetListenerForProcess(Debugger &debugger) {
  if (m_listener_sp)
    return m_listener_sp;
  else
    return debugger.GetListener();
}
