static char rcsid[]={"@(#) $Id: waitsize.c,v 1.1.1.1 2004/02/07 12:28:29 stewart Exp $"};
/*
 * waitsize 
 * Author: Stewart Gebbie
 * 1998 2010
 * Terms of use: availabe as-is with no restrictions on the use of the code
 *
 * monitors a file size, exiting when the given file size
 * is reached.
 */
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>

void usage(char* prg)
{
  fprintf(stdout,"usage: %s file size [pause millisec]\n",prg);
  exit(1);
};

#define HISTORY_LEN 10

int main(int argc, char* argv[])
{
  struct stat buf;

  char* fnm;
  off_t fsize=0, beginsize=0, newsize=0;
  struct timeval begintime, newtime;
  off_t size_history[HISTORY_LEN];
  long time_history[HISTORY_LEN];
  int history_pos=0;
  long pause=2000*1000;
  int retcode=1;
  double mult=8.0/1024.0;
  double speed=0, history_speed=0, begin_speed=0;
  long time_left=0, history_time_left=0, begin_time_left=0;
  long hours, all_minutes, minutes, seconds;
  int line_len=0;
  int update_old=0;

  if((argc<3)||(argc>4)) usage(argv[0]);

  fnm=argv[1];
  fsize=atol(argv[2]);
  if(argc==4) pause=1000*atoi(argv[3]);

  if(!stat(fnm,&buf)) beginsize=buf.st_size;
  gettimeofday(&begintime,NULL);

  for(history_pos=0;history_pos<HISTORY_LEN;history_pos++)
  {
      size_history[history_pos]=beginsize;
      time_history[history_pos]=begintime.tv_sec;
  }
  history_pos=0;

  usleep(pause);

  while(!stat(fnm,&buf))
  {
     if(buf.st_size>=fsize)
     { 
       retcode=0;
       fprintf(stdout,"%s [%ld>=%ld]\n",fnm,(long)(buf.st_size),(long)fsize);
       break;
     };
     newsize=buf.st_size; 
     gettimeofday(&newtime,NULL);
     /* update history */
     history_pos=(history_pos+1)%HISTORY_LEN;
     size_history[history_pos]=newsize;
     time_history[history_pos]=newtime.tv_sec;
     history_speed=(double)(size_history[history_pos]-
	     size_history[(history_pos+1)%HISTORY_LEN]) 
	 / (double)(time_history[history_pos]-
		    time_history[(history_pos+1)%HISTORY_LEN]); 
	 
     history_time_left=history_speed?
	 (long)(((double)(fsize-newsize))/(double)history_speed) : 0;
#if 0
     if(1)
     {
	 int i;
	 int j;
	 fprintf(stdout,"\nHISTORY [pos=%ld]\n",(long)history_pos);
	 for(i=0;i<HISTORY_LEN;i++)
	 {
	     j=(i+history_pos)%HISTORY_LEN;
	     fprintf(stdout,"j=%ld\t",(long)(j));
	     fprintf(stdout,"size=%ld\t",(long)(size_history[j]));
	     fprintf(stdout,"time=%ld\n",(long)(time_history[j]));
	 }
	 fprintf(stdout,"\nspeed=%g time left=%ld\n",
		 history_speed,history_time_left);
     }
#endif
     /* */
     begin_speed=(double)(newsize-beginsize) 
	 / (double)(newtime.tv_sec-begintime.tv_sec); 
     begin_time_left=begin_speed?
	 (long) (((double)(fsize-newsize))/(double)begin_speed) : 0;
     /* */

     time_left=history_time_left;
     speed=history_speed;

     all_minutes=time_left/60;
     hours=all_minutes/60;
     minutes=all_minutes%60;
     seconds=time_left%60;

     speed*=mult;
     for(;line_len;line_len--)
	 fwrite(" ",1,1,stdout);
     fprintf(stdout,"\r"); 
     line_len+=fprintf(stdout,"%s [%ld<%ld]",fnm,(long)(buf.st_size),(long)fsize); 
     line_len+=fprintf(stdout," <%2.0f%%>",
	                (double)(100*((double)buf.st_size/(double)fsize)));
     line_len+=fprintf(stdout," (%.3f Kbps)",speed); 
     if(speed)
     {
	 line_len+=fprintf(stdout," {");
	 if(hours)
	     line_len+=fprintf(stdout,"%ld hr, ", hours);
	 if(hours || minutes)
	     line_len+=fprintf(stdout,"%2.2ld min, ", minutes);
	 line_len+=fprintf(stdout,"%2.2ld sec", seconds); 
	 line_len+=fprintf(stdout,"}");
     }
     else
	 line_len+=fprintf(stdout," { stalled }");
     fprintf(stdout,"\r"); 
     fflush(stdout);

     usleep(pause);
  };

  return retcode;
};
