/*
 * $Id: proc_uptime.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_uptime()
{

 int i,numfields;

 /* 
  * Open /proc/uptime.
  */
 stat_fd[PROC_UPTIME] = fopen("/proc/uptime","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}
  */

 /* PROC_UPTIME */
 if(stat_fd[PROC_UPTIME]){

   double total_secs,uptime_secs;
   int updays,uphours,upminutes;
   char upbuf[128];
   int pos = 0;

   /* Only contains one line, so not much to parse */
   fgets(statbuf,BUFLEN,stat_fd[PROC_UPTIME]);
   /* parse the line into fields */
   numfields = parse(statbuf,fields,MAXFIELDNUMBER,BUFLEN);

   total_secs = atof(fields[0]);

   /* 
    * read and calculate the amount of uptime.  This code was wholeheartedly
    * lifted from uptime itself.
    */

   updays = (int) total_secs / 86400;
   upminutes = (int) total_secs / 60;
   uphours = (int) upminutes / 60;
   uphours = uphours % 24;
   upminutes = upminutes % 60;
   uptime_secs = total_secs - updays*86400 - uphours*3600 - upminutes*60;

   /* Return the (string) data in the name label */
   /* JBP: removed equals-signs, used to be "uptime=%1dd:%1dh:%1dm:%1.2fs" */
   sprintf(stats[UPTIME].name, "uptime %1dd:%1dh:%1dm:%1.2fs",
       updays,uphours,upminutes,uptime_secs);
   stats[UPTIME].source = PROC_UPTIME;		/* Tag its source for xref */
   stats[UPTIME].avail = 1;			/* Yes, we found it */
   stats[UPTIME].current = total_secs;	/* Save uptime in seconds */
 }

} /* End init_proc_uptime() */

void get_proc_uptime()
{

 int i,numfields;

 /* 
  * Now, for a clever trick.  We'll reset the files without actually
  * closing or reopening them.  Perhaps we can save the overhead of
  * an open/close (presumed relatively large, as one has to stat the
  * files in question on EACH open).
  */

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

 {

   double total_secs,uptime_secs;
   int updays,uphours,upminutes;
   char upbuf[128];
   int pos = 0;

   /* Only contains one line, so not much to parse */
   total_secs = 0.0;
   fgets(statbuf,BUFLEN,stat_fd[PROC_UPTIME]);
   /* parse the line into fields */
   numfields = parse(statbuf,fields,MAXFIELDNUMBER,BUFLEN);

   total_secs = atof(fields[0]);

   /* 
    * read and calculate the amount of uptime.  This code was wholeheartedly
    * lifted from uptime itself.
    */

   updays = (int) total_secs / 86400;
   upminutes = (int) total_secs / 60;
   uphours = (int) upminutes / 60;
   uphours = uphours % 24;
   upminutes = upminutes % 60;
   uptime_secs = total_secs - updays*86400 - uphours*3600 - upminutes*60;

   /* Return the (string) data in the name label */
   sprintf(stats[UPTIME].name, "uptime %1dd:%1dh:%1dm:%1.2fs",
       updays,uphours,upminutes,uptime_secs);
   stats[UPTIME].current = total_secs;	/* Save uptime in seconds */
 }

}  /* End get_proc_uptime() */

void eval_proc_uptime()
{

 stats[UPTIME].rate = stats[UPTIME].current;

} /* End eval_proc_uptime() */
