/* $Copyright: $
 * Copyright (c) 1997 by Steve Baker (ice@mama.indstate.edu)
 * All Rights reserved
 *
 * This software is provided as is without any express or implied
 * warranties, including, without limitation, the implied warranties
 * of merchant-ability and fitness for a particular purpose.
 */
#include <stdio.h>
#include <unistd.h>
#include <sys/file.h>
#include <utmp.h>

/* Adjust the time quantum if your time corruption is finer grained
 * or you have infrequent logins
 */
#define FUDGEFACTOR	  60*60*24*30	/* 30 days */

char *prttime(time_t);

/* Fixtime:
 *
 * Fixes netdate time corruption, by resyncing time entries.
 * Use: fixtime <input wtmp> [<output wtmp> | -]
 * Use different output file to test if fixtime works for you,
 * then use the same input and output filename to update the file.
 * Example: fixtime /var/log/wtmp /var/log/wtmp
 *
 * THIS IS NOT A WTMP DE-CORRUPTOR.  YOUR WTMP MUST _NOT_ BE CORRUPT.
 * USE AT YOUR OWN RISK.  THIS IS NOT VERY WELL TESTED.
 *
 * Compile with: make fixtime
 */
int main(argc,argv)
int argc;
char **argv;
{
  struct utmp u;
  time_t prev = 0, factor = 0;
  int in, out, n, verbose = 0;

  if (argc < 3) {
    fprintf(stderr,"usage: %s [-v] <input> [<output> | -]\n",argv[0]);
    exit(1);
  }

  n = 1;
  if (!strcmp(argv[n],"-v")) {
    verbose = 1;
    n++;
  }
  if ((in = open(argv[n],O_RDONLY)) < 0) {
    fprintf(stderr,"error opening %s for reading.\n",argv[1]);
    exit(1);
  }
  n++;
  if (strcmp("-",argv[n])) {
    if ((out = open(argv[2],O_RDWR|O_CREAT)) < 0) {
      fprintf(stderr,"error opening %s for writing.\n",argv[1]);
      exit(1);
    }
  } else out = 1;

  n=read(in,&u,sizeof(struct utmp));
  prev = u.ut_time;
  write(out,&u,sizeof(struct utmp));

  while((n=read(in,&u,sizeof(struct utmp))) == sizeof(struct utmp)) {
    if (u.ut_time > (prev+FUDGEFACTOR) || u.ut_time < (prev-FUDGEFACTOR)) {
      if (!factor) {
	factor = u.ut_time - prev;
	if (verbose) fprintf(stderr,"Adusting time by %s",prttime(factor));
      }
      u.ut_time -= factor;
      if (verbose) fprintf(stderr,".");
    } else {
      if (factor && verbose) fprintf(stderr,"\n");
      factor = 0;
    }

    write(out,&u,sizeof(struct utmp));
    prev = u.ut_time;
  }
  exit(0);
}

char *prttime(time_t factor)
{
  static char buf[256];

  if (factor < 60) {
    sprintf(buf,"%ld seconds",factor);
  } if (factor < 3600) {
    sprintf(buf,"%ld:%02ld minutes",factor/60,factor%60);
  } if (factor < 86400) {
    sprintf(buf,"%ld:%ld:%ld hours",factor/3600,(factor%3600)/60,factor%60);
  } else {
    sprintf(buf,"%ld days, %ld:%ld:%ld hours",factor/86400,(factor%86400)/3600,(factor%3600)/60,factor%60);
  }

  return buf;
}
