/*
 * $Id: proc_stat.c,v 1.1 2001/03/15 22:16:13 jpormann Exp jpormann $
 *
 * procstatd - Copyright (c) 1999 by Robert G. Brown, rgb@phy.duke.edu
 *         GPL version 2b (b for beverage) granted.
 *
 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 * PERFORMANCE OF THIS SOFTWARE.
 *
 * procstatd - A daemon to extract statistics from /proc/stat and publish them
 *         on demand via a socket connection or broadcast.
 */

#include "procstatd.h"

void init_proc_stat()
{

 int i,numfields;


 /* 
  * Open /proc/stat.
  */
 stat_fd[PROC_STAT] = fopen("/proc/stat","r");

 /*
  * If the open succeeded, the file descriptor is nonzero.  We then
  * initialize all stats derived from /proc/stat.  Put values into
  * stats[FIELD].{name,source,avail,current,previous,rate}
  */

 if(stat_fd[PROC_STAT]){
   while(TRUE){
     /* Normal EOF causes break from while loop */
     if((fgets(statbuf,BUFLEN,stat_fd[PROC_STAT]) == NULL)) break;
     /* parse the line into fields */
     numfields = parse(statbuf,fields,MAXFIELDNUMBER,BUFLEN);

     /*
      * Now we go down a simple lookup table to assemble each statistic
      * by name.  fields[] now contains the parsed fields from a line of
      * /proc/stat.  We identify the line by its first entry (the name
      * of the /proc/stat entity) and use the following values to build 
      * one or more statistics.
      */
     /* CPU (but NOT cpu[0,1,2,3]) */
     if((strlen(fields[0]) == 3) && strncmp(fields[0],"cpu",3) == 0){
       /* CPU_USER */
       sprintf(stats[CPU_USER].name,"cpu_user");	/* Label it. */
       stats[CPU_USER].source = PROC_STAT;		/* Tag its source for xref */
       stats[CPU_USER].avail = 1;			/* Yes, we found it */
       stats[CPU_USER].current = atof(fields[1]);		/* current value */
       /* CPU_NICE */
       sprintf(stats[CPU_NICE].name,"cpu_nice");	/* Label it. */
       stats[CPU_NICE].source = PROC_STAT;		/* Tag its source for xref */
       stats[CPU_NICE].avail = 1;			/* Yes, we found it */
       stats[CPU_NICE].current = atof(fields[2]);		/* current value */
       /* CPU_SYS */
       sprintf(stats[CPU_SYS].name,"cpu_sys");		/* Label it. */
       stats[CPU_SYS].source = PROC_STAT;		/* Tag its source for xref */
       stats[CPU_SYS].avail = 1;			/* Yes, we found it */
       stats[CPU_SYS].current = atof(fields[3]);		/* current value */
       /* CPU_IDLE */
       sprintf(stats[CPU_IDLE].name,"cpu_idle");	/* Label it. */
       stats[CPU_IDLE].source = PROC_STAT;		/* Tag its source for xref */
       stats[CPU_IDLE].avail = 1;			/* Yes, we found it */
       stats[CPU_IDLE].current = atof(fields[4]);		/* current value */
       /* CPU */
       sprintf(stats[CPU].name,"cpu");		/* Label it. */
       stats[CPU].source = PROC_STAT;		/* Tag its source for xref */
       stats[CPU].avail = 1;			/* Yes, we found it */
       stats[CPU].current = atof(fields[4]);	/* current value */
     } /* end cpu */

     /* CPU0 */
     if(strncmp(fields[0],"cpu0",4) == 0){
       /* CPU0_USER */
       sprintf(stats[CPU0_USER].name,"cpu0_user");	/* Label it. */
       stats[CPU0_USER].source = PROC_STAT;		/* Tag its source for xref */
       stats[CPU0_USER].avail = 1;			/* Yes, we found it */
       stats[CPU0_USER].current = atof(fields[1]);	/* current value */
       /* CPU0_NICE */
       sprintf(stats[CPU0_NICE].name,"cpu0_nice");	/* Label it. */
       stats[CPU0_NICE].source = PROC_STAT;		/* Tag its source for xref */
       stats[CPU0_NICE].avail = 1;			/* Yes, we found it */
       stats[CPU0_NICE].current = atof(fields[2]);		/* current value */
       /* CPU0_SYS */
       sprintf(stats[CPU0_SYS].name,"cpu0_sys");		/* Label it. */
       stats[CPU0_SYS].source = PROC_STAT;		/* Tag its source for xref */
       stats[CPU0_SYS].avail = 1;			/* Yes, we found it */
       stats[CPU0_SYS].current = atof(fields[3]);		/* current value */
       /* CPU0_IDLE */
       sprintf(stats[CPU0_IDLE].name,"cpu0_idle");	/* Label it. */
       stats[CPU0_IDLE].source = PROC_STAT;		/* Tag its source for xref */
       stats[CPU0_IDLE].avail = 1;			/* Yes, we found it */
       stats[CPU0_IDLE].current = atof(fields[4]);		/* current value */
       /* CPU0 */
       sprintf(stats[CPU0].name,"cpu0");	/* Label it. */
       stats[CPU0].source = PROC_STAT;		/* Tag its source for xref */
       stats[CPU0].avail = 1;			/* Yes, we found it */
       stats[CPU0].current = atof(fields[4]);	/* current value */
     } /* end cpu0 */

     /* CPU1 */
     if(strncmp(fields[0],"cpu1",4) == 0){
       /* CPU1_USER */
       sprintf(stats[CPU1_USER].name,"cpu1_user");	/* Label it. */
       stats[CPU1_USER].source = PROC_STAT;		/* Tag its source for xref */
       stats[CPU1_USER].avail = 1;			/* Yes, we found it */
       stats[CPU1_USER].current = atof(fields[1]);		/* current value */
       /* CPU1_NICE */
       sprintf(stats[CPU1_NICE].name,"cpu1_nice");	/* Label it. */
       stats[CPU1_NICE].source = PROC_STAT;		/* Tag its source for xref */
       stats[CPU1_NICE].avail = 1;			/* Yes, we found it */
       stats[CPU1_NICE].current = atof(fields[2]);		/* current value */
       /* CPU1_SYS */
       sprintf(stats[CPU1_SYS].name,"cpu1_sys");		/* Label it. */
       stats[CPU1_SYS].source = PROC_STAT;		/* Tag its source for xref */
       stats[CPU1_SYS].avail = 1;			/* Yes, we found it */
       stats[CPU1_SYS].current = atof(fields[3]);		/* current value */
       /* CPU1_IDLE */
       sprintf(stats[CPU1_IDLE].name,"cpu1_idle");	/* Label it. */
       stats[CPU1_IDLE].source = PROC_STAT;		/* Tag its source for xref */
       stats[CPU1_IDLE].avail = 1;			/* Yes, we found it */
       stats[CPU1_IDLE].current = atof(fields[4]);		/* current value */
       /* CPU1 */
       sprintf(stats[CPU1].name,"cpu1");	/* Label it. */
       stats[CPU1].source = PROC_STAT;		/* Tag its source for xref */
       stats[CPU1].avail = 1;			/* Yes, we found it */
       stats[CPU1].current = atof(fields[4]);	/* current value */
     } /* end cpu1 */

     /* CPU2 */
     if(strncmp(fields[0],"cpu2",4) == 0){
       /* CPU2_USER */
       sprintf(stats[CPU2_USER].name,"cpu2_user");	/* Label it. */
       stats[CPU2_USER].source = PROC_STAT;		/* Tag its source for xref */
       stats[CPU2_USER].avail = 1;			/* Yes, we found it */
       stats[CPU2_USER].current = atof(fields[1]);		/* current value */
       /* CPU2_NICE */
       sprintf(stats[CPU2_NICE].name,"cpu2_nice");	/* Label it. */
       stats[CPU2_NICE].source = PROC_STAT;		/* Tag its source for xref */
       stats[CPU2_NICE].avail = 1;			/* Yes, we found it */
       stats[CPU2_NICE].current = atof(fields[2]);		/* current value */
       /* CPU2_SYS */
       sprintf(stats[CPU2_SYS].name,"cpu2_sys");		/* Label it. */
       stats[CPU2_SYS].source = PROC_STAT;		/* Tag its source for xref */
       stats[CPU2_SYS].avail = 1;			/* Yes, we found it */
       stats[CPU2_SYS].current = atof(fields[3]);		/* current value */
       /* CPU2_IDLE */
       sprintf(stats[CPU2_IDLE].name,"cpu2_idle");	/* Label it. */
       stats[CPU2_IDLE].source = PROC_STAT;		/* Tag its source for xref */
       stats[CPU2_IDLE].avail = 1;			/* Yes, we found it */
       stats[CPU2_IDLE].current = atof(fields[4]);		/* current value */
       /* CPU2 */
       sprintf(stats[CPU2].name,"cpu2");	/* Label it. */
       stats[CPU2].source = PROC_STAT;		/* Tag its source for xref */
       stats[CPU2].avail = 1;			/* Yes, we found it */
       stats[CPU2].current = atof(fields[4]);	/* current value */
     } /* end cpu2 */

     /* CPU3 */
     if(strncmp(fields[0],"cpu3",4) == 0){
       /* CPU3_USER */
       sprintf(stats[CPU3_USER].name,"cpu3_user");	/* Label it. */
       stats[CPU3_USER].source = PROC_STAT;		/* Tag its source for xref */
       stats[CPU3_USER].avail = 1;			/* Yes, we found it */
       stats[CPU3_USER].current = atof(fields[1]);		/* current value */
       /* CPU3_NICE */
       sprintf(stats[CPU3_NICE].name,"cpu3_nice");	/* Label it. */
       stats[CPU3_NICE].source = PROC_STAT;		/* Tag its source for xref */
       stats[CPU3_NICE].avail = 1;			/* Yes, we found it */
       stats[CPU3_NICE].current = atof(fields[2]);		/* current value */
       /* CPU3_SYS */
       sprintf(stats[CPU3_SYS].name,"cpu3_sys");		/* Label it. */
       stats[CPU3_SYS].source = PROC_STAT;		/* Tag its source for xref */
       stats[CPU3_SYS].avail = 1;			/* Yes, we found it */
       stats[CPU3_SYS].current = atof(fields[3]);		/* current value */
       /* CPU3_IDLE */
       sprintf(stats[CPU3_IDLE].name,"cpu3_idle");	/* Label it. */
       stats[CPU3_IDLE].source = PROC_STAT;		/* Tag its source for xref */
       stats[CPU3_IDLE].avail = 1;			/* Yes, we found it */
       stats[CPU3_IDLE].current = atof(fields[4]);	/* current value */
       /* CPU3 */
       sprintf(stats[CPU3].name,"cpu3");	/* Label it. */
       stats[CPU3].source = PROC_STAT;		/* Tag its source for xref */
       stats[CPU3].avail = 1;			/* Yes, we found it */
       stats[CPU3].current = atof(fields[4]);	/* current value */
     } /* end cpu3 */

     /* DISK */
     if((strlen(fields[0]) == 4) && strncmp(fields[0],"disk",4) == 0){
       sprintf(stats[DISK].name,"disk");	/* Label it. */
       stats[DISK].source = PROC_STAT;		/* Tag its source for xref */
       stats[DISK].avail = 1;			/* Yes, we found it */
       /* Sum the four fields for disk activity */
       stats[DISK].current = 0;
       for(i = 1;i<=4; i++){
         stats[DISK].current += atof(fields[i]);
       }
     } /* end DISK */

     /* 
      * rgb note:  Skipping the rest of the disk stats, but they could
      * easily be added by an intrepid soul who wanted them.
      * Just block copy the DISK entry and morph it to DISK_RIO, etc.
      * Don't forget to add a DISK_RIO enum entry in procd.h, too.
      */

     /* PAGE */
     if(strncmp(fields[0],"page",4) == 0){
       /* PAGE_IN */
       sprintf(stats[PAGE_IN].name,"page_in");		/* Label it. */
       stats[PAGE_IN].source = PROC_STAT;		/* Tag its source for xref */
       stats[PAGE_IN].avail = 1;			/* Yes, we found it */
       stats[PAGE_IN].current = atof(fields[1]);	/* current value */
       /* PAGE_OUT */
       sprintf(stats[PAGE_OUT].name,"page_out");	/* Label it. */
       stats[PAGE_OUT].source = PROC_STAT;		/* Tag its source for xref */
       stats[PAGE_OUT].avail = 1;			/* Yes, we found it */
       stats[PAGE_OUT].current = atof(fields[2]);		/* current value */
       /* PAGE (total) */
       sprintf(stats[PAGE].name,"page");	/* Label it. */
       stats[PAGE].source = PROC_STAT;		/* Tag its source for xref */
       stats[PAGE].avail = 1;			/* Yes, we found it */
       stats[PAGE].current = stats[PAGE_IN].current+stats[PAGE_OUT].current;		/* current value */
     } /* end PAGE */

     /* SWAP */
     if(strncmp(fields[0],"swap",4) == 0){
       /* SWAP_IN */
       sprintf(stats[SWAP_IN].name,"swap_in");		/* Label it. */
       stats[SWAP_IN].source = PROC_STAT;		/* Tag its source for xref */
       stats[SWAP_IN].avail = 1;			/* Yes, we found it */
       stats[SWAP_IN].current = atof(fields[1]);	/* current value */
       /* SWAP_OUT */
       sprintf(stats[SWAP_OUT].name,"swap_out");	/* Label it. */
       stats[SWAP_OUT].source = PROC_STAT;		/* Tag its source for xref */
       stats[SWAP_OUT].avail = 1;			/* Yes, we found it */
       stats[SWAP_OUT].current = atof(fields[2]);		/* current value */
       /* SWAP (total) */
       sprintf(stats[SWAP].name,"swap");	/* Label it. */
       stats[SWAP].source = PROC_STAT;		/* Tag its source for xref */
       stats[SWAP].avail = 1;			/* Yes, we found it */
       stats[SWAP].current = stats[SWAP_IN].current+stats[SWAP_OUT].current;		/* current value */
     } /* end SWAP */

     /* INTR */
     if(strncmp(fields[0],"intr",4) == 0){
       /* INTR */
       sprintf(stats[INTR].name,"intr");	/* Label it. */
       stats[INTR].source = PROC_STAT;		/* Tag its source for xref */
       stats[INTR].avail = 1;			/* Yes, we found it */
       stats[INTR].current = atof(fields[1]);		/* current value */
     } /* end INTR */

     /* PROC */
     if(strncmp(fields[0],"processes",9) == 0){
       /* PROC */
       sprintf(stats[PROC].name,"proc");	/* Label it. */
       stats[PROC].source = PROC_STAT;		/* Tag its source for xref */
       stats[PROC].avail = 1;			/* Yes, we found it */
       stats[PROC].current = atof(fields[1]);		/* current value */
     } /* end PROC */

     /* CONTEXT */
     if(strncmp(fields[0],"ctxt",4) == 0){
       /* CONTEXT */
       sprintf(stats[CONTEXT].name,"ctxt");	/* Label it. */
       stats[CONTEXT].source = PROC_STAT;		/* Tag its source for xref */
       stats[CONTEXT].avail = 1;			/* Yes, we found it */
       stats[CONTEXT].current = atof(fields[1]);		/* current value */
     } /* end CONTEXT */

   }	/* End while(TRUE) loop */

 }

} /* End init_proc_stat().  We leave stat_fd[PROC_STAT] open. */

void get_proc_stat()
{

 int i,numfields;
 static int cur_time,prev_time;
 /* 
  * Set the global interval for use in evaluating rates below. 
  */
 cur_time = (long) time(NULL);
 interval=(cur_time - prev_time);
 prev_time = cur_time;

 /* 
  * Now, for a clever trick.  We RESET the files without actually
  * closing or reopening them.  This should save the overhead of
  * an open/close (presumed relatively large, as one has to 
  * allocate/free certain kernel structures and stat the file in question 
  * on EACH open/close).
  */

 /* PROC_STAT */
 errno = 0;
 if(stat_fd[PROC_STAT]){
   rewind(stat_fd[PROC_STAT]);	/* void, so tough to check errors */
 } else {
   return;
 }
 if(errno == EBADF){
   fprintf(stderr,"Error: The /proc/stat file descriptor/stream is not seekable.\n");
   fclose(stat_fd[PROC_STAT]); 
   fprintf(stderr,"Closing and reopening /proc/stat.\n");
   stat_fd[PROC_STAT] = fopen("/proc/stat","r");
 }

 while(TRUE){

   /* Normal EOF causes break from while loop */
   if((fgets(statbuf,BUFLEN,stat_fd[PROC_STAT]) == NULL)) break;

   /* parse the line into fields */
   numfields = parse(statbuf,fields,MAXFIELDNUMBER,BUFLEN);

   /*
    * Now we go down a simple lookup table to assemble each statistic
    * by name.  fields[] now contains the parsed fields from a line of
    * /proc/stat.  We identify the line by its first entry (the name
    * of the /proc/stat entity) and use the following values to build 
    * one or more statistics.
    */

   /* CPU (but NOT cpu[0,1,2,3]) */
   if((strlen(fields[0]) == 3) && strncmp(fields[0],"cpu",3) == 0){
     /* CPU_USER */
     stats[CPU_USER].previous = stats[CPU_USER].current;/* previous value */
     stats[CPU_USER].current = atof(fields[1]);		/* current value */
     /* CPU_NICE */
     stats[CPU_NICE].previous = stats[CPU_NICE].current;/* previous value */
     stats[CPU_NICE].current = atof(fields[2]);		/* current value */
     /* CPU_SYS */
     stats[CPU_SYS].previous = stats[CPU_SYS].current;	/* previous value */
     stats[CPU_SYS].current = atof(fields[3]);		/* current value */
     /* CPU_IDLE */
     stats[CPU_IDLE].previous = stats[CPU_IDLE].current;/* previous value */
     stats[CPU_IDLE].current = atof(fields[4]);		/* current value */
     /* CPU */
     stats[CPU].previous = stats[CPU].current;		/* previous value */
     stats[CPU].current = stats[CPU_USER].current + stats[CPU_NICE].current 
                          + stats[CPU_SYS].current;	/* current value */
   } /* end cpu */

   /* CPU0 */
   if(strncmp(fields[0],"cpu0",4) == 0){
     /* CPU0_USER */
     stats[CPU0_USER].previous = stats[CPU0_USER].current;	/* previous value */
     stats[CPU0_USER].current = atof(fields[1]);		/* current value */
     /* CPU0_NICE */
     stats[CPU0_NICE].previous = stats[CPU0_NICE].current;	/* previous value */
     stats[CPU0_NICE].current = atof(fields[2]);		/* current value */
     /* CPU0_SYS */
     stats[CPU0_SYS].previous = stats[CPU0_SYS].current;	/* previous value */
     stats[CPU0_SYS].current = atof(fields[3]);		/* current value */
     /* CPU0_IDLE */
     stats[CPU0_IDLE].previous = stats[CPU0_IDLE].current;	/* previous value */
     stats[CPU0_IDLE].current = atof(fields[4]);		/* current value */
     /* CPU0 */
     stats[CPU0].previous = stats[CPU0].current;	/* previous value */
     stats[CPU0].current = stats[CPU0_USER].current + stats[CPU0_NICE].current + stats[CPU0_SYS].current;	/* current value */
   } /* end cpu0 */

   /* CPU1 */
   if(strncmp(fields[0],"cpu1",4) == 0){
     /* CPU1_USER */
     stats[CPU1_USER].previous = stats[CPU1_USER].current;	/* previous value */
     stats[CPU1_USER].current = atof(fields[1]);		/* current value */
     /* CPU1_NICE */
     stats[CPU1_NICE].previous = stats[CPU1_NICE].current;	/* previous value */
     stats[CPU1_NICE].current = atof(fields[2]);		/* current value */
     /* CPU1_SYS */
     stats[CPU1_SYS].previous = stats[CPU1_SYS].current;	/* previous value */
     stats[CPU1_SYS].current = atof(fields[3]);		/* current value */
     /* CPU1_IDLE */
     stats[CPU1_IDLE].previous = stats[CPU1_IDLE].current;	/* previous value */
     stats[CPU1_IDLE].current = atof(fields[4]);		/* current value */
     /* CPU1 */
     stats[CPU1].previous = stats[CPU1].current;	/* previous value */
     stats[CPU1].current = stats[CPU1_USER].current + stats[CPU1_NICE].current + stats[CPU1_SYS].current;	/* current value */
   } /* end cpu1 */

   /* CPU2 */
   if(strncmp(fields[0],"cpu2",4) == 0){
     /* CPU2_USER */
     stats[CPU2_USER].previous = stats[CPU2_USER].current;	/* previous value */
     stats[CPU2_USER].current = atof(fields[1]);		/* current value */
     /* CPU2_NICE */
     stats[CPU2_NICE].previous = stats[CPU2_NICE].current;	/* previous value */
     stats[CPU2_NICE].current = atof(fields[2]);		/* current value */
     /* CPU2_SYS */
     stats[CPU2_SYS].previous = stats[CPU2_SYS].current;	/* previous value */
     stats[CPU2_SYS].current = atof(fields[3]);		/* current value */
     /* CPU2_IDLE */
     stats[CPU2_IDLE].previous = stats[CPU2_IDLE].current;	/* previous value */
     stats[CPU2_IDLE].current = atof(fields[4]);		/* current value */
     /* CPU2 */
     stats[CPU2].previous = stats[CPU2].current;	/* previous value */
     stats[CPU2].current = stats[CPU2_USER].current + stats[CPU2_NICE].current + stats[CPU2_SYS].current;	/* current value */
   } /* end cpu2 */

   /* CPU3 */
   if(strncmp(fields[0],"cpu3",4) == 0){
     /* CPU3_USER */
     stats[CPU3_USER].previous = stats[CPU3_USER].current;	/* previous value */
     stats[CPU3_USER].current = atof(fields[1]);		/* current value */
     /* CPU3_NICE */
     stats[CPU3_NICE].previous = stats[CPU3_NICE].current;	/* previous value */
     stats[CPU3_NICE].current = atof(fields[2]);		/* current value */
     /* CPU3_SYS */
     stats[CPU3_SYS].previous = stats[CPU3_SYS].current;	/* previous value */
     stats[CPU3_SYS].current = atof(fields[3]);		/* current value */
     /* CPU3_IDLE */
     stats[CPU3_IDLE].previous = stats[CPU3_IDLE].current;	/* previous value */
     stats[CPU3_IDLE].current = atof(fields[4]);		/* current value */
     /* CPU3 */
     stats[CPU3].previous = stats[CPU3].current;	/* previous value */
     stats[CPU3].current = stats[CPU3_USER].current + stats[CPU3_NICE].current + stats[CPU3_SYS].current;	/* current value */
   } /* end cpu3 */

   /* DISK */
   if((strlen(fields[0]) == 4) && strncmp(fields[0],"disk",4) == 0){
     stats[DISK].previous = stats[DISK].current;	/* previous value */
     /* Sum the four fields for disk activity */
     stats[DISK].current = 0;
     for(i = 1;i<=4; i++){
       stats[DISK].current += atof(fields[i]);
     }
   } /* end DISK */

   /* 
    * rgb note:  Skipping the rest of the disk stats, but they could
    * easily be added by an intrepid soul who wanted them.
    * Just block copy the DISK entry and morph it to DISK_RIO, etc.
    * Don't forget to add a DISK_RIO enum entry in procd.h, too.
    */

   /* PAGE */
   if(strncmp(fields[0],"page",4) == 0){
     /* PAGE_IN */
     stats[PAGE_IN].previous = stats[PAGE_IN].current;	/* previous value */
     stats[PAGE_IN].current = atof(fields[1]);	/* current value */
     /* PAGE_OUT */
     stats[PAGE_OUT].previous = stats[PAGE_OUT].current;	/* previous value */
     stats[PAGE_OUT].current = atof(fields[2]);		/* current value */
     /* PAGE (total) */
     stats[PAGE].previous = stats[PAGE].current;	/* previous value */
     stats[PAGE].current = stats[PAGE_IN].current+stats[PAGE_OUT].current;		/* current value */
   } /* end PAGE */

   /* SWAP */
   if(strncmp(fields[0],"swap",4) == 0){
     /* SWAP_IN */
     stats[SWAP_IN].previous = stats[SWAP_IN].current;	/* previous value */
     stats[SWAP_IN].current = atof(fields[1]);	/* current value */
     /* SWAP_OUT */
     stats[SWAP_OUT].previous = stats[SWAP_OUT].current;	/* previous value */
     stats[SWAP_OUT].current = atof(fields[2]);		/* current value */
     /* SWAP (total) */
     stats[SWAP].previous = stats[SWAP].current;	/* previous value */
     stats[SWAP].current = stats[SWAP_IN].current+stats[SWAP_OUT].current;		/* current value */
   } /* end SWAP */

   /* INTR */
   if(strncmp(fields[0],"intr",4) == 0){
     /* INTR */
     stats[INTR].previous = stats[INTR].current;	/* previous value */
     stats[INTR].current = atof(fields[1]);		/* current value */
   } /* end INTR */

   /* PROC */
   if(strncmp(fields[0],"processes",9) == 0){
     /* PROC */
     stats[PROC].previous = stats[PROC].current;	/* previous value */
     stats[PROC].current = atof(fields[1]);		/* current value */
   } /* end PROC */

   /* CONTEXT */
   if(strncmp(fields[0],"ctxt",4) == 0){
     /* CONTEXT */
     stats[CONTEXT].previous = stats[CONTEXT].current;	/* previous value */
     stats[CONTEXT].current = atof(fields[1]);		/* current value */
   } /* end CONTEXT */

 } /* End while(TRUE) loop */

 /* End of get_proc_stat() */

}


void eval_proc_stat()
{

 int i,numfields;

 for(i=0;i<N_STATS;i++){
   switch(i) {
     /* CPU */
     case CPU:
     case CPU_USER:
     case CPU_NICE:
     case CPU_SYS:
     case CPU_IDLE:
       stats[i].rate=100.0*(stats[i].current-stats[i].previous)/
                    (stats[CPU].current + stats[CPU_IDLE].current
                      - stats[CPU].previous - stats[CPU_IDLE].previous);
       if(stats[i].rate > 100.0) stats[i].rate = 100.0;
       if(stats[i].rate < 0.0) stats[i].rate = 0.0;
       break;
     /* CPU0 */
     case CPU0:
     case CPU0_USER:
     case CPU0_NICE:
     case CPU0_SYS:
     case CPU0_IDLE:
       stats[i].rate=100.0*(stats[i].current-stats[i].previous)/
                    (stats[CPU0].current + stats[CPU0_IDLE].current
                      - stats[CPU0].previous - stats[CPU0_IDLE].previous);
       if(stats[i].rate > 100.0) stats[i].rate = 100.0;
       if(stats[i].rate < 0.0) stats[i].rate = 0.0;
       break;
     /* CPU1 */
     case CPU1:
     case CPU1_USER:
     case CPU1_NICE:
     case CPU1_SYS:
     case CPU1_IDLE:
       stats[i].rate=100.0*(stats[i].current-stats[i].previous)/
                    (stats[CPU1].current + stats[CPU1_IDLE].current
                      - stats[CPU1].previous - stats[CPU1_IDLE].previous);
       if(stats[i].rate > 100.0) stats[i].rate = 100.0;
       if(stats[i].rate < 0.0) stats[i].rate = 0.0;
       break;
     /* CPU2 */
     case CPU2:
     case CPU2_USER:
     case CPU2_NICE:
     case CPU2_SYS:
     case CPU2_IDLE:
       stats[i].rate=100.0*(stats[i].current-stats[i].previous)/
                    (stats[CPU2].current + stats[CPU2_IDLE].current
                      - stats[CPU2].previous - stats[CPU2_IDLE].previous);
       if(stats[i].rate > 100.0) stats[i].rate = 100.0;
       if(stats[i].rate < 0.0) stats[i].rate = 0.0;
       break;
     /* CPU3 */
     case CPU3:
     case CPU3_USER:
     case CPU3_NICE:
     case CPU3_SYS:
     case CPU3_IDLE:
       stats[i].rate=100.0*(stats[i].current-stats[i].previous)/
                    (stats[CPU3].current + stats[CPU3_IDLE].current
                      - stats[CPU3].previous - stats[CPU3_IDLE].previous);
       if(stats[i].rate > 100.0) stats[i].rate = 100.0;
       if(stats[i].rate < 0.0) stats[i].rate = 0.0;
       break;
     /* 
      * DISK, PAGE, PAGE_IN, PAGE_OUT, SWAP, SWAP_IN, SWAP_OUT, INTR, CONTEXT
      * and PROC are all RATES.
      */
     case DISK:
     case PAGE:
     case PAGE_IN:
     case PAGE_OUT:
     case SWAP:
     case SWAP_IN:
     case SWAP_OUT:
     case INTR:
     case PROC:
     case CONTEXT:
       stats[i].rate = (stats[i].current - stats[i].previous)/interval;
       if(stats[i].rate < 0.0) stats[i].rate = 0.0;
       break;
     default:
       break;
   } /* End case switch */
 } /* End loop through enumerated types */

} /* End eval_proc_stat */

