/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing for details.  */
#include "cmLoadCommandCommand.h"

#include <signal.h>
#include <sstream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "cmCPluginAPI.cxx"
#include "cmCPluginAPI.h"
#include "cmDynamicLoader.h"
#include "cmMakefile.h"
#include "cmState.h"
#include "cmSystemTools.h"

class cmExecutionStatus;

#ifdef __QNX__
#include <malloc.h> /* for malloc/free on QNX */
#endif

extern "C" void TrapsForSignalsCFunction(int sig);

// a class for loadabple commands
class cmLoadedCommand : public cmCommand
{
public:
  cmLoadedCommand()
  {
    memset(&this->info, 0, sizeof(this->info));
    this->info.CAPI = &cmStaticCAPI;
  }

  ///! clean up any memory allocated by the plugin
  ~cmLoadedCommand() override;

  /**
   * This is a virtual constructor for the command.
   */
  cmCommand* Clone() override
  {
    cmLoadedCommand* newC = new cmLoadedCommand;
    // we must copy when we clone
    memcpy(&newC->info, &this->info, sizeof(info));
    return newC;
  }

  /**
   * This is called when the command is first encountered in
   * the CMakeLists.txt file.
   */
  bool InitialPass(std::vector<std::string> const& args,
                   cmExecutionStatus&) override;

  /**
   * This is called at the end after all the information
   * specified by the command is accumulated. Most commands do
   * not implement this method.  At this point, reading and
   * writing to the cache can be done.
   */
  void FinalPass() override;
  bool HasFinalPass() const override
  {
    return this->info.FinalPass != nullptr;
  }

  static const char* LastName;
  static void TrapsForSignals(int sig)
  {
    fprintf(stderr, "CMake loaded command %s crashed with signal: %d.\n",
            cmLoadedCommand::LastName, sig);
  }
  static void InstallSignalHandlers(const char* name, int remove = 0)
  {
    cmLoadedCommand::LastName = name;
    if (!name) {
      cmLoadedCommand::LastName = "????";
    }

    if (!remove) {
      signal(SIGSEGV, TrapsForSignalsCFunction);
#ifdef SIGBUS
      signal(SIGBUS, TrapsForSignalsCFunction);
#endif
      signal(SIGILL, TrapsForSignalsCFunction);
    } else {
      signal(SIGSEGV, nullptr);
#ifdef SIGBUS
      signal(SIGBUS, nullptr);
#endif
      signal(SIGILL, nullptr);
    }
  }

  cmLoadedCommandInfo info;
};

extern "C" void TrapsForSignalsCFunction(int sig)
{
  cmLoadedCommand::TrapsForSignals(sig);
}

const char* cmLoadedCommand::LastName = nullptr;

bool cmLoadedCommand::InitialPass(std::vector<std::string> const& args,
                                  cmExecutionStatus&)
{
  if (!info.InitialPass) {
    return true;
  }

  // clear the error string
  if (this->info.Error) {
    free(this->info.Error);
  }

  // create argc and argv and then invoke the command
  int argc = static_cast<int>(args.size());
  char** argv = nullptr;
  if (argc) {
    argv = static_cast<char**>(malloc(argc * sizeof(char*)));
  }
  int i;
  for (i = 0; i < argc; ++i) {
    argv[i] = strdup(args[i].c_str());
  }
  cmLoadedCommand::InstallSignalHandlers(info.Name);
  int result = info.InitialPass(&info, this->Makefile, argc, argv);
  cmLoadedCommand::InstallSignalHandlers(info.Name, 1);
  cmFreeArguments(argc, argv);

  if (result) {
    return true;
  }

  /* Initial Pass must have failed so set the error string */
  if (this->info.Error) {
    this->SetError(this->info.Error);
  }
  return false;
}

void cmLoadedCommand::FinalPass()
{
  if (this->info.FinalPass) {
    cmLoadedCommand::InstallSignalHandlers(info.Name);
    this->info.FinalPass(&this->info, this->Makefile);
    cmLoadedCommand::InstallSignalHandlers(info.Name, 1);
  }
}

cmLoadedCommand::~cmLoadedCommand()
{
  if (this->info.Destructor) {
    cmLoadedCommand::InstallSignalHandlers(info.Name);
    this->info.Destructor(&this->info);
    cmLoadedCommand::InstallSignalHandlers(info.Name, 1);
  }
  if (this->info.Error) {
    free(this->info.Error);
  }
}

// cmLoadCommandCommand
bool cmLoadCommandCommand::InitialPass(std::vector<std::string> const& args,
                                       cmExecutionStatus&)
{
  if (args.empty()) {
    return true;
  }

  // Construct a variable to report what file was loaded, if any.
  // Start by removing the definition in case of failure.
  std::string reportVar = "CMAKE_LOADED_COMMAND_";
  reportVar += args[0];
  this->Makefile->RemoveDefinition(reportVar);

  // the file must exist
  std::string moduleName =
    this->Makefile->GetRequiredDefinition("CMAKE_SHARED_MODULE_PREFIX");
  moduleName += "cm" + args[0];
  moduleName +=
    this->Makefile->GetRequiredDefinition("CMAKE_SHARED_MODULE_SUFFIX");

  // search for the file
  std::vector<std::string> path;
  for (unsigned int j = 1; j < args.size(); j++) {
    // expand variables
    std::string exp = args[j];
    cmSystemTools::ExpandRegistryValues(exp);

    // Glob the entry in case of wildcards.
    cmSystemTools::GlobDirs(exp, path);
  }

  // Try to find the program.
  std::string fullPath = cmSystemTools::FindFile(moduleName, path);
  if (fullPath.empty()) {
    std::ostringstream e;
    e << "Attempt to load command failed from file \"" << moduleName << "\"";
    this->SetError(e.str());
    return false;
  }

  // try loading the shared library / dll
  cmsys::DynamicLoader::LibraryHandle lib =
    cmDynamicLoader::OpenLibrary(fullPath.c_str());
  if (!lib) {
    std::string err = "Attempt to load the library ";
    err += fullPath + " failed.";
    const char* error = cmsys::DynamicLoader::LastError();
    if (error) {
      err += " Additional error info is:\n";
      err += error;
    }
    this->SetError(err);
    return false;
  }

  // Report what file was loaded for this command.
  this->Makefile->AddDefinition(reportVar, fullPath.c_str());

  // find the init function
  std::string initFuncName = args[0] + "Init";
  CM_INIT_FUNCTION initFunction = reinterpret_cast<CM_INIT_FUNCTION>(
    cmsys::DynamicLoader::GetSymbolAddress(lib, initFuncName));
  if (!initFunction) {
    initFuncName = "_";
    initFuncName += args[0];
    initFuncName += "Init";
    initFunction = reinterpret_cast<CM_INIT_FUNCTION>(
      cmsys::DynamicLoader::GetSymbolAddress(lib, initFuncName));
  }
  // if the symbol is found call it to set the name on the
  // function blocker
  if (initFunction) {
    // create a function blocker and set it up
    cmLoadedCommand* f = new cmLoadedCommand();
    (*initFunction)(&f->info);
    this->Makefile->GetState()->AddScriptedCommand(args[0], f);
    return true;
  }
  this->SetError("Attempt to load command failed. "
                 "No init function found.");
  return false;
}
