/* tail.c - print the last few lines in a file.  If count is specified, *
 *	that many lines are printed instead of the default value of	*
 *	ten lines.  If no files are specified, head reads standard	*
 *	input.								*
 *									*
 * tail [-<count>] [<file> ...] 					*
 *									*
 * tail (C) 1988 by Gary L. Brant					*
 *									*
 * :ts=8								*/

#include <stdio.h>
#define   MAXLINE   1000

void fputs ();
int default_lines = 10; /* default number of lines to list */
int headlin = 0;

typedef struct list {
   struct list *nxt;
   char line[MAXLINE];
};


main (argc, argv)	/* list 1st n lines of a file */
int  argc;
char *argv[];
{
   FILE *input, *fopen ();
   void fclose ();
   int i = 0, rval;
   long maxlines, convert ();
   char ch;

   maxlines = default_lines;
   while (++i < argc) {
      if (argv [i][0] == '-') { 	/* process line count argument */
	 maxlines = convert (argv[i]);
	 default_lines = maxlines;
      } else if (argv [i][0] == '+') {
	 maxlines = -convert (argv[i]);
	 default_lines = maxlines;
      } else {
	 ++headlin;
	 if ((input = fopen (argv[i], "r")) == NULL) {
	    fputs ("tail: can't open ", stderr);
	    fputs (argv[i], stderr);
	    putc ('\n', stderr);
	    break;
	 } else {
	    rval = list (input, argv[i], maxlines);
	    fclose (input);
	    if (rval)
               quit (rval);
	 }
      }
   }
   if (!headlin)
      quit (list (stdin, "", maxlines));
   quit (0);
}


list (fp, fn, maxlines) 	/* list tail of a file */
FILE *fp;
char *fn;
register long maxlines;
{
   int n;
   char line[MAXLINE];
   char *c, *fgets (), *alloc ();

   if (maxlines < 0) {		/* +n, head relative list */
      while (maxlines++ < 0 && (c = fgets (line, MAXLINE, fp)) != NULL);
      if (c != NULL) {
	 heading (fn);
	 while ((fgets (line, MAXLINE, fp)) != NULL)
	    fputs (line, stdout);
      }
   } else {			/* -n, tail relative list */
      register struct list *head = NULL, *curr, *next, *p;
      register long nlin = 0;

      while ((fgets (line, MAXLINE, fp)) != NULL) {
         n = strlen (line);
	 if (++nlin > maxlines) {	/* de-link 1st line */
	    p = head;
	    head = head->nxt;
	    freeit (p);
	 }
	 if ((next = (struct list *) alloc (n+5)) == NULL) {
	    fputs ("not enough memory for list\n", stderr);
	    while (head != NULL) {
	       p = head;
	       head = head->nxt;
	       freeit (p);
	    }
	    return (20);
	 }
	 if (head == NULL)
	    head = next;
	 else
	    curr->nxt = next;
	 curr = next;
	 strcpy (next->line, line);
	 next->nxt = NULL;
      }
      heading (fn);

      /* now print the lines in the list, deallocating as we go */

      while (head != NULL) {
         fputs (head->line, stdout);
	 p = head;
	 head = head->nxt;
	 freeit (p);
      }
   }
   return (0);
}


heading (filename)
char *filename;
{
   if (headlin) {
      fputs ("==> ", stdout);
      fputs (filename, stdout);
      fputs (" <==\n", stdout);
   }
}


long convert (string)
char string[];
{
   register long maxlines = 0;
   register int j;
   register char ch;

   for (j = 1; (ch = string[j]) != '\0'; j++)
   if (ch >= '0' && ch <= '9') {
      maxlines *= 10;
      maxlines += ch - '0';
   } else {
      maxlines = default_lines;
      break;
   }
   return (maxlines);
}


void _wb_parse ()
{
}
