text: #include "tsar.h"
  
  /*
   * Structure for Proc infomation.
   */
  struct stats_proc {
      unsigned long long user_cpu;
      unsigned long long sys_cpu;
      unsigned long long total_cpu;
      unsigned long long mem;
      unsigned long long total_mem;
      unsigned long long read_bytes;
      unsigned long long write_bytes;
  };
  
  #define PID_IO          "/proc/%u/io"
  #define PID_STAT        "/proc/%u/stat"
  #define PID_STATUS      "/proc/%u/status"
  #define STATS_PROC_SIZE (sizeof(struct stats_proc))
  
  static char *proc_usage = "    --proc              PROC info (mem cpu usage & io/fd info)";
  
  
  static void
  read_proc_stats(struct module *mod, char *parameter)
  {
      int     nb = 0, pid[16];
      char    buf[LEN_4096];
      char    filename[128], line[256];
      FILE   *fp;
      struct  stats_proc st_proc;
  
      memset(&st_proc, 0, sizeof(struct stats_proc));
  
      /* get pid by proc name */
      if (strlen(parameter) > 20) {
          return;
      }
      char cmd[32] = "/sbin/pidof ";
      strncat(cmd, parameter, sizeof(cmd) - strlen(cmd) -1);
      char  spid[256];
      fp = popen(cmd, "r");
      if (fp == NULL) {
          return;
      }
      if(fscanf(fp, "%s", spid) == EOF) {
          pclose(fp);
          return;
      }
      pclose(fp);
      /* split pidof into array pid */
      char *p;
      p = strtok(spid, " ");
      while (p) {
          pid[nb] = atoi(p);
          if (pid[nb++] <= 0) {
              return;
          }
          if (nb >= 16) {
              return;
          }
          p = strtok(NULL, " ");
      }
      /* get all pid's info */
      while (--nb >= 0) {
          unsigned long long data;
          /* read values from /proc/pid/stat */
          sprintf(filename, PID_STAT, pid[nb]);
          if ((fp = fopen(filename, "r")) == NULL) {
              return;
          }
          unsigned long long cpudata[4];
          if (fgets(line, 256, fp) == NULL) {
              fclose(fp);
              return;
          }
  
          if ((p = strstr(line, ")")) == NULL) {
              fclose(fp);
              return;
          }
          if (sscanf(p, "%*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %llu %llu %llu %llu",
                      &cpudata[0], &cpudata[1], &cpudata[2], &cpudata[3]) == EOF) {
              fclose(fp);
              return;
          }
          st_proc.user_cpu += cpudata[0];
          st_proc.user_cpu += cpudata[2];
          st_proc.sys_cpu += cpudata[1];
          st_proc.sys_cpu += cpudata[3];
          fclose(fp);
          /* get cpu&mem info from /proc/pid/status */
          sprintf(filename, PID_STATUS, pid[nb]);
          if ((fp = fopen(filename, "r")) == NULL) {
              return;
          }
          while (fgets(line, 256, fp) != NULL) {
              if (!strncmp(line, "VmRSS:", 6)) {
                  sscanf(line + 6, "%llu", &data);
                  st_proc.mem += data * 1024;
              }
          }
          fclose(fp);
          /* get io info from /proc/pid/io */
          sprintf(filename, PID_IO, pid[nb]);
          if ((fp = fopen(filename, "r")) == NULL) {
              return;
          }
          while (fgets(line, 256, fp) != NULL) {
              if (!strncmp(line, "read_bytes:", 11)) {
                  sscanf(line + 11, "%llu", &data);
                  st_proc.read_bytes += data;
              }
              else if (!strncmp(line, "write_bytes:", 12)) {
                  sscanf(line + 12, "%llu", &data);
                  st_proc.write_bytes += data;
              }
          }
          fclose(fp);
      }
  
      /* read+calc cpu total time from /proc/stat */
      fp = fopen("/proc/stat", "r");
      if (fp == NULL) {
          fclose(fp);
          return;
      }
      unsigned long long cpu_time[10];
      bzero(cpu_time, sizeof(cpu_time));
      if (fscanf(fp, "%*s %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu",
                  &cpu_time[0], &cpu_time[1], &cpu_time[2], &cpu_time[3],
                  &cpu_time[4], &cpu_time[5], &cpu_time[6], &cpu_time[7],
                  &cpu_time[8], &cpu_time[9]) == EOF) {
          fclose(fp);
          return;
      }
      fclose(fp);
      int i;
      for(i=0; i < 10;i++) {
          st_proc.total_cpu += cpu_time[i];
      }
      /* read total mem from /proc/meminfo */
      fp = fopen("/proc/meminfo", "r");
      if (fp == NULL) {
          fclose(fp);
          return;
      }
      if (fscanf(fp, "MemTotal:      %llu kB", &st_proc.total_mem) == EOF) {
          fclose(fp);
          return;
      }
      st_proc.total_mem *= 1024;
      fclose(fp);
      /* store data to tsar */
      int pos = sprintf(buf, "%lld,%lld,%lld,%lld,%lld,%lld,%lld",
              st_proc.user_cpu,
              st_proc.sys_cpu,
              st_proc.total_cpu,
              st_proc.total_mem,
              st_proc.mem,
              st_proc.read_bytes,
              st_proc.write_bytes
              );
      if (pos >= 0) buf[pos] = '\0';
      set_mod_record(mod, buf);
  }
  
  static void
  set_proc_record(struct module *mod, double st_array[],
      U_64 pre_array[], U_64 cur_array[], int inter)
  {
      if (cur_array[2] > pre_array[2]) {
          st_array[2] = cur_array[2] - pre_array[2];
      } else {
          st_array[2] = 0;
          return;
      }
      if (cur_array[0] >= pre_array[0]) {
          st_array[0] = (cur_array[0] - pre_array[0]) * 100.0 / st_array[2];
      } else {
          st_array[0] = 0;
      }
      if (cur_array[1] >= pre_array[1]) {
          st_array[1] = (cur_array[1] - pre_array[1]) * 100.0 / st_array[2];
      } else {
          st_array[1] = 0;
      }
      st_array[3] = cur_array[4] * 100.0 / cur_array[3];
      st_array[4] = cur_array[4];
      if (cur_array[5] >= pre_array[5]) {
          st_array[5] = (cur_array[5] - pre_array[5]) * 1.0 / inter;
      } else {
          st_array[5] = 0;
      }
      if (cur_array[6] >= pre_array[6]) {
          st_array[6] = (cur_array[6] - pre_array[6]) * 1.0 / inter;
      } else {
          st_array[5] = 0;
      }
  }
  
  static struct mod_info proc_info[] = {
      {"  user", SUMMARY_BIT,  0,  STATS_NULL},
      {"   sys", SUMMARY_BIT,  0,  STATS_NULL},
      {" total", HIDE_BIT,  0,  STATS_NULL},
      {"   mem", SUMMARY_BIT,  0,  STATS_NULL},
      {"   RSS", DETAIL_BIT,  0,  STATS_NULL},
      {"  read", DETAIL_BIT,  0,  STATS_NULL},
      {" write", DETAIL_BIT,  0,  STATS_NULL},
  };
  
  void
  mod_register(struct module *mod)
  {
      register_mod_fields(mod, "--proc", proc_usage, proc_info, 7, read_proc_stats, set_proc_record);
  }
  