/*  tail.c -- UTOOL. Print last n lines of file.

     author: David H. Wolen
     last change: 01/25/83

     usage:  tail  [n]

     options:  n  number of lines to print.  Range
                  1--1000.  Default 32.

     input:  STDIN
     output: STDOUT

     linkage:  a:clink tail -f dio -ca (uses deff3.crl)
*/

#include "a:bdscio.h"
#include "dio.h"

#define  STDIN  0
#define  STDOUT 1
#define  LINES  1000     /* max lines to display */
#define  OS1LINES  32    /* default lines to display */
#define  SIZECP  2        /* size of pointer to char in bytes */

main(argc,argv)
int  argc;
char *argv[];
{
     int  ntail, nsave, i;
     char *linbuf[LINES], line[MAXLINE];

     dioinit(&argc,argv);
     _allocp=NULL;
     nsave=0;

     if(argc > 1)   /* number of lines to print given on command line */
          {ntail=atoi(*++argv);
          if(ntail < 1 || ntail > LINES)
               error("tail: lines to print must be 1--1000");
          }
     else           /* use default */
          ntail=OS1LINES;

     while(fgets(line,STDIN))
          saveline(line,linbuf,&nsave,ntail);

     if(nsave <= 0)
          error("tail: empty input");

     for(i=0; i < nsave; i++)
          fputs(linbuf[i],STDOUT);

     dioflush();
}



/* saveline -- store lines and save pointers to them */
saveline(line,linbuf,nsave,ntail)
char *line, *linbuf[];
int  *nsave, ntail;
{
     char *alloc(), *p;

     if(*nsave < ntail)
          {if((p=alloc(strlen(line)+1)) == NULL)
               error("tail: out of room in saveline #1");
          strcpy(p,line);
          linbuf[(*nsave)++]=p;
          }
     else
          {free(linbuf[0]);
          movmem(&linbuf[1],&linbuf[0],(ntail-1)*SIZECP);
          if((p=alloc(strlen(line)+1)) == NULL)
               error("tail: out of room in saveline #2");
          strcpy(p,line);
          linbuf[ntail-1]=p;
          }
}
