#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifdef WIN32
#include <windows.h>
#endif
#ifdef VMS
char *strdup(char *s);
#endif
int lib_length(FILE *h);

static char *lines[100000];
static int nlines;
void tail_file(char *fname, int wanted);
int lib_sleep(int x);
void line_add(char *s);
void do_follow(char *fname, int upto);
void line_send(char *s);
static int isfollow,ispage;
static int upto;
int main(int argc, char *argv[])
{
	int wanted = 24;
	int i;
	char fname[200];

	if (argc<2) {
		printf("Usage: dtail xxxx.log -f -p -nn\n");
		printf("  -f = Follow log file, keep showing new data as it arrives\n");
		printf("  -p = Show output one page at a time\n");
		printf("  -nn = Show last nn lines of log file\n");
	}
	strcpy(fname,"");
	for (i=1; i<argc; i++) {
		if (strncmp(argv[i],"-f",2)==0) isfollow = TRUE;
		else if (strncmp(argv[i],"-p",2)==0) ispage = TRUE;
		else if (strncmp(argv[i],"-",1)==0) wanted =- atoi(argv[i]);
		else strcpy(fname,argv[i]);
	}
	if (strlen(fname)==0) return 0;
	tail_file(fname,wanted);
	if (isfollow) do_follow(fname,upto);
	return 0;
}
int lib_sleep(int x)
{
	Sleep(x*1000);
	return TRUE;
}
void do_follow(char *fname, int upto)
{
	char *s;
	FILE *f;
	char bf[3000];

	for (;;) {
		f = fopen(fname,"rb");
		if (f==NULL) goto sleep;		
		if (lib_length(f)>upto) {
			fseek(f,upto,SEEK_SET);
			for (;!feof(f);) {
			        if (fgets(bf,2000,f)==NULL) break;
				s = strchr(bf,'\r');
				if (s!=NULL) *s = 0;
				s = strchr(bf,'\n');
				if (s!=NULL) *s = 0;
				line_send(bf);		
			}
			upto = ftell(f);
		}
sleep:		
		fclose(f);
		lib_sleep(1);
	}
	
}
void line_send(char *s)
{
	static int i;
	char bf[200];
	i++;
	printf("%s\n",s);
	if (ispage) if (i==23) {
		printf("Press any key to continue, press any other key to abort...");
		fgets(bf,100,stdin);
		i = 0;
	}
}
void tail_file(char *fname, int wanted)
{
	int start;
	char *s;
	FILE *f;
	int i;
	int rest;
	char bf[3000];
 	f = fopen(fname,"rb");
	if (f==NULL) {perror(fname); return;}
	rest = wanted*160;
	if (rest>lib_length(f)) rest = lib_length(f);
	fseek(f,-wanted*160,SEEK_END);
 	if (fgets(bf,2000,f)!=NULL) line_add(bf);
	for (;!feof(f);) {
	  if (fgets(bf,2000,f)!=NULL) {
		s = strchr(bf,'\r');
		if (s!=NULL) *s = 0;
		s = strchr(bf,'\n');
		if (s!=NULL) *s = 0;
		line_add(bf);
	  }
	}
	upto = ftell(f);
	fclose(f);
	
	
	start = nlines-wanted;
	if (start<0) start = 0;
	for (i=start;i<nlines; i++) {
		line_send(lines[i]);
	}
}
void line_add(char *s)
{
 	lines[nlines++] = strdup(s);
}
#ifdef VMS
char *strdup(char *s)
{
	char *n = malloc(strlen(s)+1);
	strcpy(n,s);
	return n;
}
#endif
int lib_length(FILE *h)
{
	int f = fileno(h);
	struct stat bf;
        if (fstat(f,&bf)!=0) {printf("FATAL Could not get file length\n"); return 0;}
        return bf.st_size;
}