/* loggrep.c by David N. Welton <davidw@efn.org> 
   http://www.efn.org/~davidw */ 
 
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>

#include <netdb.h>

#define POSFILE "/.posfile"

long getpos(char *);
void putpos(char *, long);
void usage();

int main (int argc, char *argv[])
{
    long pos = 0;

    char in[1000];
    char *lfname;
    char *unm;
    char *envhome;
    char *home;
    char *posfn;

    int o;
    int lookups = 0;		/* Do hostname lookups */

    struct stat logfilestat;
    FILE *logfile; 

    while ((o = getopt(argc, argv, "l")) != -1)
    {
	switch (o)
	{
	case 'l':
	    lookups = 1;
	    break;
	}
    }
	    
    if(argv[optind])
	lfname = (char *)strdup(argv[optind]);
    else
	usage();

    if (setpriority(PRIO_PROCESS, 0, 8))
	perror("Cannot set low priority");  
      
    unm = (char *)strdup(getlogin());
    if (unm == NULL)
	unm = (char *)strdup(getenv("LOGNAME"));
    fprintf(stderr, "Seeking logs for %s ...\n", unm);

    envhome = getenv("HOME");
    if (envhome != NULL)
	home = (char *)strdup(envhome);
    else 
	fputs("Problem with HOME env var", stderr);
    posfn = (char *)malloc(strlen(home) + strlen(POSFILE));
    strcpy(posfn, home);
    strncat(posfn, POSFILE, strlen(POSFILE) + 1);
    fprintf(stderr, "Storing results in %s ...\n", posfn);
  
    pos = getpos(posfn);

    logfile = fopen(lfname, "r");
    fstat(fileno(logfile), &logfilestat);
    
    if (logfilestat.st_size < pos)
    {
	fputs("Cannot start reading after end of file - changing Position to 0\n", stderr);
	pos = 0;
    }

    if (logfile == NULL)
    {
	perror("Cannot open logfile");
	exit (1);
    }
    fprintf(stderr, "File position = %ld\n", pos);
    if (pos > 0)
    {
	pos --;
	if(fseek(logfile, pos, SEEK_SET))
	{
	    perror("Cannot seek");
	    exit(1);
	}
    }

    while(fgets(in, 1000, logfile))
    {
	if (strstr(in, unm))
	{
	    if (lookups) 
	    {
		char *address;
		char *rest;
		char *result;
		struct hostent *clienthost;
		struct hostent *hostname;
		address = malloc(strlen(in));
		rest = in;
		sscanf(in, "%s ", address);
		rest += strlen(address) + 1;
		
		clienthost = gethostbyname(address);
		if (clienthost == NULL)
		{
		    result = address;
		} else {
		    result = clienthost->h_name;
		    hostname = gethostbyaddr(clienthost->h_addr, 4, AF_INET);
		    if (hostname != NULL)
			result = hostname->h_name;
		}
		
		printf("%s %s", result, rest);
	    } else {
		fputs(in, stdout);
	    }
	}
    }
    pos = ftell(logfile);
    fclose(logfile);
    putpos(posfn, pos);
    return 0;
}

long getpos(char *posfn)
{
    char poschar[20];

    long pos;

    FILE *posfile;
  
    posfile = fopen(posfn, "r");
    if (posfile == NULL)
    {
	fputs("Could not open position file - creating\n", stderr);
	posfile = fopen(posfn, "w");
	if (posfile == NULL)
	{
	    perror("Could not create position file - giving up");
	    exit (1);
	}
	pos = 0;
    }
    else
    {
	if(fgets(poschar, 20, posfile))
	    pos = strtol(poschar, NULL, 10);
	else
	    pos = 0;
    }

    fclose(posfile);
    return pos;
}

void putpos(char *posfn, long pos)
{

    FILE *posfile;

    posfile = fopen(posfn, "w");
    if (posfile == NULL)
    {
	perror("Could not open position file for write");
	exit (1);
    }
    fprintf(posfile, "%ld\n", pos);
    fclose(posfile);
}

void usage ()
{
    fprintf(stderr, "usage: loggrep logfilename\n");
    exit(1);
}

