/******************************************************************************
 *                                                                            *
 *  Copyright (C) 2005 Volker Gropp (mail@gropp.org)                          *
 *                                                                            *
 *  This program is free software; you can redistribute it and/or modify      *
 *  it under the terms of the GNU General Public License as published by      *
 *  the Free Software Foundation; either version 2 of the License, or         *
 *  (at your option) any later version.                                       *
 *                                                                            *
 *  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 General Public License         *
 *  along with this program; if not, write to the Free Software               *
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA *
 *                                                                            *
 *****************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <time.h>
#include <string.h>

#define LOGFILE "/var/log/ppp-uptime-log"
#define PPP_PID "/var/run/pppoe.conf-adsl.pid.pppd"
#define MAX_SHOW 10
#define MAX_BUF 4096

struct dial_list {
   long dialin;
   long length;
   struct dial_list *next;
};

char *time2str(long timestamp) {
   static char time_str[255];
   struct tm *p_tm;
   p_tm=localtime(&timestamp);
   strftime(time_str,254,"%c",p_tm);
   return time_str;
}

char* dhms(long secs) {
 static char ttime[255];
 long days = 0,
   hours = 0,
   mins = 0;
 char sh[3],sm[3],ss[3];

 while ( secs >= 86400 ) {
   days++;
   secs -= 86400;
 }
 while ( secs >= 3600 ) {
    hours++;
    secs -= 3600;
   }
 while ( secs >= 60 ) {
    mins++;
    secs -= 60;
   }
 sprintf(sh,"%2li",hours);
 sprintf(sm,"%2li",mins);
 sprintf(ss,"%2li",secs);
 if (sh[0]==' ') sh[0]='0';
 if (sm[0]==' ') sm[0]='0';
 if (ss[0]==' ') ss[0]='0';

 sprintf(ttime, "%5li days, %s:%s:%s", (long)days,sh,sm,ss);
 return ttime;
}



int main(int argc,char **argv) {
   struct dial_list *first=NULL;
   struct dial_list *list_p=NULL;
   struct dial_list *tmp_p=NULL;
   FILE *fp;
   char buffer[MAX_BUF];
   long dialin,length,oneup,cur_pos;
   struct dial_list current,first_stat,last_stat;
   unsigned long count=0,out_done=0;
   struct stat cur_stat;
   char current_found=0;
   int max_show=MAX_SHOW;
   if (argc>1) max_show=atol(argv[1]);
   lstat(PPP_PID,&cur_stat);
   current.dialin=cur_stat.st_mtime;
   current.length=time(NULL)-cur_stat.st_mtime;
   if (!(fp=fopen(LOGFILE,"r"))) {
      printf("error open logfile: %s\n",strerror(errno));
      return 1;
   }
   dialin=length=0;
   while (fgets(buffer,MAX_BUF,fp)!=NULL) {
      dialin=length=0;
      sscanf(buffer,"%li|%li",&dialin,&length);
      if (dialin==0) continue;
      /* change current connection to exact length */
      if (dialin==current.dialin) length=current.length;
      if (first==NULL) {
         first=(struct dial_list*)malloc(sizeof(struct dial_list));
         first->next=NULL;
         first->dialin=dialin;
         first->length=length;
      } else {
         list_p=first;
         if (first->length<length) {
            list_p=first;
            first=(struct dial_list*)malloc(sizeof(struct dial_list));
            first->next=list_p;
            first->dialin=dialin;
            first->length=length;
         } else {
            while (list_p->next!=NULL && list_p->next->length>=length) {
               list_p=list_p->next;
            }
            tmp_p=(struct dial_list*)malloc(sizeof(struct dial_list));
            tmp_p->dialin=dialin;
            tmp_p->length=length;
            tmp_p->next=list_p->next;
            list_p->next=tmp_p;
         }
      }
   }
   fclose(fp);
   
   printf("      #          link-uptime |                   dialin at\n");
   printf("-----------------------------+----------------------------\n");
         
   list_p=first;
   first_stat=*first;
   while (list_p!=NULL) {
      count++;
      if (max_show>out_done) {
         if (list_p->dialin==current.dialin) {
            printf("\033[1m-> ");
            current_found=1;
         } else printf("   ");
         printf("%4li %s |    %s\n",out_done+1,dhms(list_p->length),time2str(list_p->dialin));
         if (list_p->dialin==current.dialin) printf("\033[0m");
         out_done++;
      }
      if (list_p->dialin==current.dialin) {
         oneup=last_stat.length-current.length;
         cur_pos=count;
      }
      last_stat=*list_p;
      first=list_p->next;
      free(list_p);
      list_p=first;
   }
   printf("-----------------------------+----------------------------\n");
   if (!current_found) {
      printf("\033[1m");
      printf("-> %4li %s |    %s\n",cur_pos,dhms(current.length),time2str(current.dialin));
      printf("\033[0m");
      printf("-----------------------------+----------------------------\n");
   }
   printf(" 1up in %s | at %s\n",dhms(oneup),time2str(time(NULL)+oneup));
   printf(" no1 in %s | at %s\n",dhms(first_stat.length-current.length),time2str(time(NULL)+first_stat.length-current.length));
   return 0;
}
