//===-- 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/Core/Log.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 "llvm/Support/ConvertUTF.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(
    Error &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 {
            char current_working_dir[PATH_MAX];
            const char *cwd =
                getcwd(current_working_dir, sizeof(current_working_dir));
            if (cwd && cwd[0])
              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();
}
