//===-- source/Host/netbsd/Host.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
#include <dlfcn.h>
#include <execinfo.h>
#include <stdio.h>
#include <sys/proc.h>
#include <sys/sysctl.h>
#include <sys/types.h>

#include <limits.h>

#include <elf.h>
#include <kvm.h>
#include <sys/exec.h>
#include <sys/ptrace.h>

// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Target/Process.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Endian.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/NameMatches.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StreamString.h"

#include "llvm/Support/Host.h"

extern "C" {
extern char **environ;
}

using namespace lldb;
using namespace lldb_private;

Environment Host::GetEnvironment() { return Environment(environ); }

static bool GetNetBSDProcessArgs(const ProcessInstanceInfoMatch *match_info_ptr,
                                 ProcessInstanceInfo &process_info) {
  if (!process_info.ProcessIDIsValid())
    return false;

  int pid = process_info.GetProcessID();

  int mib[4] = {CTL_KERN, KERN_PROC_ARGS, pid, KERN_PROC_ARGV};

  char arg_data[8192];
  size_t arg_data_size = sizeof(arg_data);
  if (::sysctl(mib, 4, arg_data, &arg_data_size, NULL, 0) != 0)
    return false;

  DataExtractor data(arg_data, arg_data_size, endian::InlHostByteOrder(),
                     sizeof(void *));
  lldb::offset_t offset = 0;
  const char *cstr;

  cstr = data.GetCStr(&offset);
  if (!cstr)
    return false;

  process_info.GetExecutableFile().SetFile(cstr, false,
                                           FileSpec::Style::native);

  if (!(match_info_ptr == NULL ||
        NameMatches(process_info.GetExecutableFile().GetFilename().GetCString(),
                    match_info_ptr->GetNameMatchType(),
                    match_info_ptr->GetProcessInfo().GetName())))
    return false;

  Args &proc_args = process_info.GetArguments();
  while (1) {
    const uint8_t *p = data.PeekData(offset, 1);
    while ((p != NULL) && (*p == '\0') && offset < arg_data_size) {
      ++offset;
      p = data.PeekData(offset, 1);
    }
    if (p == NULL || offset >= arg_data_size)
      break;

    cstr = data.GetCStr(&offset);
    if (!cstr)
      break;

    proc_args.AppendArgument(llvm::StringRef(cstr));
  }

  return true;
}

static bool GetNetBSDProcessCPUType(ProcessInstanceInfo &process_info) {
  if (process_info.ProcessIDIsValid()) {
    process_info.GetArchitecture() =
        HostInfo::GetArchitecture(HostInfo::eArchKindDefault);
    return true;
  }
  process_info.GetArchitecture().Clear();
  return false;
}

static bool GetNetBSDProcessUserAndGroup(ProcessInstanceInfo &process_info) {
  ::kvm_t *kdp;
  char errbuf[_POSIX2_LINE_MAX]; /* XXX: error string unused */

  struct ::kinfo_proc2 *proc_kinfo;
  const int pid = process_info.GetProcessID();
  int nproc;

  if (!process_info.ProcessIDIsValid())
    goto error;

  if ((kdp = ::kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf)) == NULL)
    goto error;

  if ((proc_kinfo = ::kvm_getproc2(kdp, KERN_PROC_PID, pid,
                                   sizeof(struct ::kinfo_proc2), &nproc)) ==
      NULL) {
    ::kvm_close(kdp);
    goto error;
  }

  if (nproc < 1) {
    ::kvm_close(kdp); /* XXX: we don't check for error here */
    goto error;
  }

  process_info.SetParentProcessID(proc_kinfo->p_ppid);
  process_info.SetUserID(proc_kinfo->p_ruid);
  process_info.SetGroupID(proc_kinfo->p_rgid);
  process_info.SetEffectiveUserID(proc_kinfo->p_uid);
  process_info.SetEffectiveGroupID(proc_kinfo->p_gid);

  ::kvm_close(kdp); /* XXX: we don't check for error here */

  return true;

error:
  process_info.SetParentProcessID(LLDB_INVALID_PROCESS_ID);
  process_info.SetUserID(UINT32_MAX);
  process_info.SetGroupID(UINT32_MAX);
  process_info.SetEffectiveUserID(UINT32_MAX);
  process_info.SetEffectiveGroupID(UINT32_MAX);
  return false;
}

uint32_t Host::FindProcesses(const ProcessInstanceInfoMatch &match_info,
                             ProcessInstanceInfoList &process_infos) {
  const ::pid_t our_pid = ::getpid();
  const ::uid_t our_uid = ::getuid();

  const bool all_users =
      match_info.GetMatchAllUsers() ||
      // Special case, if lldb is being run as root we can attach to anything
      (our_uid == 0);

  kvm_t *kdp;
  char errbuf[_POSIX2_LINE_MAX]; /* XXX: error string unused */
  if ((kdp = ::kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf)) == NULL)
    return 0;

  struct ::kinfo_proc2 *proc_kinfo;
  int nproc;
  if ((proc_kinfo = ::kvm_getproc2(kdp, KERN_PROC_ALL, 0,
                                   sizeof(struct ::kinfo_proc2), &nproc)) ==
      NULL) {
    ::kvm_close(kdp);
    return 0;
  }

  for (int i = 0; i < nproc; i++) {
    if (proc_kinfo[i].p_pid < 1)
      continue; /* not valid */
    /* Make sure the user is acceptable */
    if (!all_users && proc_kinfo[i].p_ruid != our_uid)
      continue;

    if (proc_kinfo[i].p_pid == our_pid ||  // Skip this process
        proc_kinfo[i].p_pid == 0 ||        // Skip kernel (kernel pid is 0)
        proc_kinfo[i].p_stat == LSZOMB ||  // Zombies are bad
        proc_kinfo[i].p_flag & P_TRACED || // Being debugged?
        proc_kinfo[i].p_flag & P_WEXIT)    // Working on exiting
      continue;

    // Every thread is a process in NetBSD, but all the threads of a single
    // process have the same pid. Do not store the process info in the result
    // list if a process with given identifier is already registered there.
    if (proc_kinfo[i].p_nlwps > 1) {
      bool already_registered = false;
      for (size_t pi = 0; pi < process_infos.GetSize(); pi++) {
        if (process_infos.GetProcessIDAtIndex(pi) == proc_kinfo[i].p_pid) {
          already_registered = true;
          break;
        }
      }

      if (already_registered)
        continue;
    }
    ProcessInstanceInfo process_info;
    process_info.SetProcessID(proc_kinfo[i].p_pid);
    process_info.SetParentProcessID(proc_kinfo[i].p_ppid);
    process_info.SetUserID(proc_kinfo[i].p_ruid);
    process_info.SetGroupID(proc_kinfo[i].p_rgid);
    process_info.SetEffectiveUserID(proc_kinfo[i].p_uid);
    process_info.SetEffectiveGroupID(proc_kinfo[i].p_gid);
    // Make sure our info matches before we go fetch the name and cpu type
    if (match_info.Matches(process_info) &&
        GetNetBSDProcessArgs(&match_info, process_info)) {
      GetNetBSDProcessCPUType(process_info);
      if (match_info.Matches(process_info))
        process_infos.Append(process_info);
    }
  }

  kvm_close(kdp); /* XXX: we don't check for error here */

  return process_infos.GetSize();
}

bool Host::GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &process_info) {
  process_info.SetProcessID(pid);

  if (GetNetBSDProcessArgs(NULL, process_info)) {
    GetNetBSDProcessCPUType(process_info);
    GetNetBSDProcessUserAndGroup(process_info);
    return true;
  }

  process_info.Clear();
  return false;
}

Status Host::ShellExpandArguments(ProcessLaunchInfo &launch_info) {
  return Status("unimplemented");
}
