#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <fcntl.h>
#include <linux/acct.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

static char *Version = "$Id: accttrim.c,v 1.2 1995/07/09 21:30:00 jiivee Exp jiivee $";

void usage()
{
   fprintf(stderr, "Usage: accttrim [-n number] acctfile\n");
   exit(1);
}

int main(int argc, char **argv)
{
   int ch, nr, bytes, cnt = 0;
   int fdin, fdout;
   struct acct ac;
   struct stat st;
   char buf[BUFSIZ];
   char tmpfile[256];
   extern int optind;
   extern char *optarg;

   while ((ch = getopt(argc, argv, "n:")) != EOF) {
      switch (ch)
      {
         case 'n':
            cnt = atoi(optarg);
            break;
         default:
            usage();
      }
   }
   argc -= optind;
   argv += optind;

   if (!argc)
      usage();

   /* Turn accounting off for now */
   acct(NULL);

   if ((fdin = open(*argv, O_RDWR)) < 0) {
      perror("open");
      exit(1);
   }

   if (fstat(fdin, &st)) {
      perror("Cannot stat accountingfile");
      exit(1);
   }

   if (st.st_size < (cnt * sizeof(struct acct))) {
      fprintf(stderr, "Not that many entries in accounting file\n");
      exit(1);
   }

   sprintf(tmpfile, "%s.lck", *argv);
   if ((fdout = creat(tmpfile, 0600)) < 0) {
      perror("creat");
      exit(1);
   }

   /*
    * Dump the time we stripped it and write that as the first entry
    * in the accountingfile.
    */
   memset(&ac, 0, sizeof(struct acct));
   strcpy(ac.ac_comm, "STRIPPED");
   time(&ac.ac_etime);
   write(fdout, &ac, sizeof(struct acct));

   bytes = (cnt * sizeof(struct acct));
   if (lseek(fdin, st.st_size - (sizeof(struct acct) * cnt), SEEK_SET) == -1) {
      perror("lseek");
      exit(1);
   }

   /*
    * Try to read large chunks if possible, speeds up thing a bit.
    */
   while (bytes > 0) {
      if (bytes > BUFSIZ) {
         nr = read(fdin, buf, BUFSIZ);
         write(fdout, buf, nr);
         bytes -= BUFSIZ;
      } else {
         nr = read(fdin, buf, bytes);
         write(fdout, buf, nr);
         bytes = 0;
      }
   }
   close(fdout);
   close(fdin);

   /*
    * Ok relink the tempfile to the original accountingfile.
    */
   unlink(*argv);
   rename(tmpfile, *argv);

   /* Ok turn accounting on again */
   acct(*argv);

   return (0);
}
