/*
 * Copyright (C) Tildeslash Ltd. All rights reserved.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License version 3.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * In addition, as a special exception, the copyright holders give
 * permission to link the code of portions of this program with the
 * OpenSSL library under certain conditions as described in each
 * individual source file, and distribute linked combinations
 * including the two.
 *
 * You must obey the GNU Affero General Public License in all respects
 * for all of the code used other than OpenSSL.  
 */

#include "config.h"

#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif

#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif

#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif

#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif

#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif

#ifdef HAVE_TIME_H
#include <time.h>
#endif

#ifdef HAVE_STRING_H
#include <string.h>
#endif

#include <stdio.h>

#include "monit.h"
#include "process.h"
#include "process_sysdep.h"

/**
 *  General purpose /proc methods.
 *
 *  @file
 */


/* ------------------------------------------------------------------ Public */


/**
 * Initialize the proc information code
 * @return TRUE if succeeded otherwise FALSE.
 */
int init_process_info(void) {
  memset(&systeminfo, 0, sizeof(SystemInfo_T));
  gettimeofday(&systeminfo.collected, NULL);
  if(uname(&systeminfo.uname) < 0) {
    LogError("'%s' resource monitoring initialization error -- uname failed: %s\n", Run.system->name, STRERROR);
    return FALSE;
  }

  systeminfo.total_cpu_user_percent = -10;
  systeminfo.total_cpu_syst_percent = -10;
  systeminfo.total_cpu_wait_percent = -10;

  return (init_process_info_sysdep());

}


/**
 * Get the proc infomation (CPU percentage, MEM in MByte and percent,
 * status), enduser version. 
 * @param p A Service object
 * @param pid The process id
 * @return TRUE if succeeded otherwise FALSE.
 */
int update_process_data(Service_T s, ProcessTree_T *pt, int treesize, pid_t pid) {
  int leaf;

  ASSERT(s);
  ASSERT(systeminfo.mem_kbyte_max > 0);

  /* save the previous pid and set actual one */
  s->inf->priv.process._pid = s->inf->priv.process.pid;
  s->inf->priv.process.pid  = pid;

  if ((leaf = findprocess(pid, pt, treesize)) != -1) {
 
    /* save the previous ppid and set actual one */
    s->inf->priv.process._ppid             = s->inf->priv.process.ppid;
    s->inf->priv.process.ppid              = pt[leaf].ppid;
    s->inf->priv.process.uptime            = time(NULL) - pt[leaf].starttime;
    s->inf->priv.process.children          = pt[leaf].children_sum;
    s->inf->priv.process.mem_kbyte         = pt[leaf].mem_kbyte;
    s->inf->priv.process.status_flag       = pt[leaf].status_flag;
    s->inf->priv.process.total_mem_kbyte   = pt[leaf].mem_kbyte_sum;
    s->inf->priv.process.cpu_percent       = pt[leaf].cpu_percent;
    s->inf->priv.process.total_cpu_percent = pt[leaf].cpu_percent_sum;

    if (systeminfo.mem_kbyte_max == 0) {
      s->inf->priv.process.total_mem_percent = 0;
      s->inf->priv.process.mem_percent       = 0;
    } else {
      s->inf->priv.process.total_mem_percent = (int)((double)pt[leaf].mem_kbyte_sum * 1000.0 / systeminfo.mem_kbyte_max);
      s->inf->priv.process.mem_percent       = (int)((double)pt[leaf].mem_kbyte * 1000.0 / systeminfo.mem_kbyte_max);
    }

  } else {
    s->inf->priv.process.ppid              = 0;
    s->inf->priv.process.uptime            = 0;
    s->inf->priv.process.children          = 0;
    s->inf->priv.process.total_mem_kbyte   = 0;
    s->inf->priv.process.total_mem_percent = 0;
    s->inf->priv.process.mem_kbyte         = 0;
    s->inf->priv.process.mem_percent       = 0;
    s->inf->priv.process.cpu_percent       = 0;
    s->inf->priv.process.total_cpu_percent = 0;
  }
  
  return TRUE;
}


/**
 * Updates the system wide statistic
 * @return TRUE if successful, otherwise FALSE
 */
int update_system_load() {

  if (Run.doprocess) {

    ASSERT(systeminfo.mem_kbyte_max > 0);

    /** Get load average triplet */
    if (-1 == getloadavg_sysdep(systeminfo.loadavg, 3)) {
      LogError("'%s' statistic error -- load average gathering failed\n", Run.system->name);
      goto error1;
    }

    /** Get memory usage statistic */
    if (! used_system_memory_sysdep(&systeminfo)) {
      LogError("'%s' statistic error -- memory usage gathering failed\n", Run.system->name);
      goto error2;
    }
    systeminfo.total_mem_percent  = (int)(1000 * (double)systeminfo.total_mem_kbyte / (double)systeminfo.mem_kbyte_max);
    systeminfo.total_swap_percent = systeminfo.swap_kbyte_max ? (int)(1000 * (double)systeminfo.total_swap_kbyte / (double)systeminfo.swap_kbyte_max) : 0;

    /** Get CPU usage statistic */
    if (! used_system_cpu_sysdep(&systeminfo)) {
      LogError("'%s' statistic error -- cpu usage gathering failed\n", Run.system->name);
      goto error3;
    }

    return TRUE;
  }

error1:
  systeminfo.loadavg[0] = 0;
  systeminfo.loadavg[1] = 0;
  systeminfo.loadavg[2] = 0;
error2:
  systeminfo.total_mem_kbyte   = 0;
  systeminfo.total_mem_percent = 0;
error3:
  systeminfo.total_cpu_user_percent = 0;
  systeminfo.total_cpu_syst_percent = 0;  
  systeminfo.total_cpu_wait_percent = 0;  

  return FALSE;
}


/**
 * Initialize the process tree 
 * @return treesize >= 0 if succeeded otherwise < 0
 */
int initprocesstree(ProcessTree_T **pt_r, int *size_r, ProcessTree_T **oldpt_r, int *oldsize_r) {
  int i;
  int oldentry;
  ProcessTree_T *pt;
  ProcessTree_T *oldpt;
  int root = -1;

  if (*pt_r != NULL) {  
    if (oldpt_r && *oldpt_r != NULL)
      delprocesstree(oldpt_r, oldsize_r);
    *oldpt_r   = *pt_r; 
    *oldsize_r = *size_r; 
  }
  
  if ((*size_r = initprocesstree_sysdep(pt_r)) <= 0) {
    DEBUG("system statistic error -- cannot initialize the process tree => process resource monitoring disabled\n");
    Run.doprocess = FALSE;
    return -1;
  } else if (Run.doprocess == FALSE) {
    DEBUG("system statistic -- initialization of the process tree succeeded => process resource monitoring enabled\n");
    Run.doprocess = TRUE;
  }

  pt    = *pt_r;
  oldpt = *oldpt_r;

  if (pt == NULL)
    return 0;

  for (i = 0; i < (volatile int)*size_r; i ++) {
    if (oldpt && ((oldentry = findprocess(pt[i].pid, oldpt, *oldsize_r)) != -1)) {
      pt[i].cputime_prev = oldpt[oldentry].cputime;
      pt[i].time_prev    = oldpt[oldentry].time;
 
      /* The cpu_percent may be set already (for example by HPUX module) */
      if (pt[i].cpu_percent  == 0 && pt[i].cputime_prev != 0 && pt[i].cputime != 0 && pt[i].cputime > pt[i].cputime_prev) {
        pt[i].cpu_percent = (int)((1000 * (double)(pt[i].cputime - pt[i].cputime_prev) / (pt[i].time - pt[i].time_prev)) / systeminfo.cpus);
        if (pt[i].cpu_percent > 1000)
          pt[i].cpu_percent = 1000;
      }
    } else {
      pt[i].cputime_prev = 0;
      pt[i].time_prev    = 0.0;
      pt[i].cpu_percent  = 0;
    }
        
    if (pt[i].pid == pt[i].ppid) {
      pt[i].parent = i;
      continue;
    }

    if ((pt[i].parent = findprocess(pt[i].ppid, pt, *size_r)) == -1) {
      /* Parent process wasn't found - on Linux this is normal: main process with PID 0 is not listed, similarly in FreeBSD jail.
       * We create virtual process entry for missing parent so we can have full tree-like structure with root. */
      int j = (*size_r)++;

      pt = RESIZE(*pt_r, *size_r * sizeof(ProcessTree_T));
      memset(&pt[j], 0, sizeof(ProcessTree_T));
      pt[j].ppid = pt[j].pid  = pt[i].ppid;
      pt[i].parent = j;
    }
    
    if (! connectchild(pt, pt[i].parent, i)) {
      /* connection to parent process has failed, this is usually caused in the part above */
      DEBUG("system statistic error -- cannot connect process id %d to its parent %d\n", pt[i].pid, pt[i].ppid);
      pt[i].pid = 0;
      continue;
    }
  }

  /* The main process in Solaris zones and FreeBSD host doesn't have pid 1, so try to find process which is parent of itself */
  for (i = 0; i < *size_r; i++) {
    if (pt[i].pid == pt[i].ppid) {
      root = i;
      break;
    }
  }

  if (root == -1) {
    DEBUG("system statistic error -- cannot find root process id\n");
    return -1;
  }

  fillprocesstree(pt, root);

  return *size_r;
}


/**
 * Search a leaf in the processtree
 * @param pid  pid of the process
 * @param pt  processtree
 * @param treesize  size of the processtree
 * @return process index if succeeded otherwise -1
 */
int findprocess(int pid, ProcessTree_T *pt, int size) {
  int i;

  ASSERT(pt);

  if (size <= 0)
    return -1;

  for (i = 0; i < size; i++)
    if (pid == pt[i].pid)
      return i;

  return -1;
}

/**
 * Delete the process tree 
 */
void delprocesstree(ProcessTree_T **reference, int *size) {
  int i;
  ProcessTree_T *pt = *reference;
  if (pt) {
    for (i = 0; i < *size; i++) {
      FREE(pt[i].cmdline);
      FREE(pt[i].children);
    }
    FREE(pt);
    *reference = NULL;
    *size = 0;
  }
  return;
}


void process_testmatch(char *pattern) {
#ifdef HAVE_REGEX_H
  regex_t *regex_comp;
  int reg_return;
#endif

#ifdef HAVE_REGEX_H
  NEW(regex_comp);
  if ((reg_return = regcomp(regex_comp, pattern, REG_NOSUB|REG_EXTENDED))) {
    char errbuf[STRLEN];
    regerror(reg_return, regex_comp, errbuf, STRLEN);
    regfree(regex_comp);
    FREE(regex_comp);
    printf("Regex %s parsing error: %s\n", pattern, errbuf);
    exit(1);
  }
#endif
  initprocesstree(&ptree, &ptreesize, &oldptree, &oldptreesize);
  if (Run.doprocess) {
    int i, count = 0;
    printf("List of processes matching pattern \"%s\":\n", pattern);
    printf("------------------------------------------\n");
    for (i = 0; i < ptreesize; i++) {
      int match = FALSE;
      if (ptree[i].cmdline && ! strstr(ptree[i].cmdline, "procmatch")) {
#ifdef HAVE_REGEX_H
        match = regexec(regex_comp, ptree[i].cmdline, 0, NULL, 0) ? FALSE : TRUE;
#else
        match = strstr(ptree[i].cmdline, pattern) ? TRUE : FALSE;
#endif
        if (match) {
          printf("\t%s\n", ptree[i].cmdline);
          count++;
        }
      }
    }
    printf("------------------------------------------\n");
    printf("Total matches: %d\n", count);
    if (count > 1)
      printf("WARNING: multiple processes matched the pattern. The check is FIRST-MATCH based, please refine the pattern\n");
  }
}


