#! /usr/bin/perl

#
#   Copyright (C) Heinz-Josef Claes (2000)
#                 hjclaes@web.de
#   
#   This program is free software; you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation; either version 2 of the License, or
#   (at your option) any later version.
#   
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#   
#   You should have received a copy of the GNU General Public License
#   along with this program; if not, write to the Free Software
#   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#



push @VERSION, '$Id: multitail.pl 330 2004-04-18 07:39:13Z hjc $ ';

sub libPath
{
    my $file = shift;

    my $dir;

    # Falls Datei selbst ein symlink ist, solange folgen, bis aufgelöst
    if (-f $file)
    {
	while (-l $file)
	{
	    my $link = readlink($file);

	    if (substr($link, 0, 1) ne "/")
	    {
		$file =~ s/[^\/]+$/$link/;
	    }
	    else
	    {
		$file = $link;
	    }
	}

	($dir, $file) = &splitFileDir($file);
	$file = "/$file";
    }
    else
    {
	print STDERR "<$file> does not exist!\n";
	exit 1;
    }

    $dir .= "/../lib";           # Pfad zu den Bibliotheken
    my $oldDir = `/bin/pwd`;
    chomp $oldDir;
    if (chdir $dir)
    {
	my $absDir = `/bin/pwd`;
	chop $absDir;
	chdir $oldDir;

	return (&splitFileDir("$absDir$file"));
    }
    else
    {
	print STDERR "<$dir> does not exist, exiting\n";
    }
}
sub splitFileDir
{
    my $name = shift;

    return ('.', $name) unless ($name =~/\//);    # nur einfacher Dateiname

    my ($dir, $file) = $name =~ /^(.*)\/(.*)$/s;
    $dir = '/' if ($dir eq '');                   # gilt, falls z.B. /filename
    return ($dir, $file);
}
my ($req, $prog) = &libPath($0);
push @INC, "$req";

require "checkParam.pl";
require "tail.pl";
require "prLog.pl";
require 'version.pl';


$Help = <<EOH;
	Read multiple log files. The log files can be written round.
Usage:
	$0 [-a] [-d delay] [-p begin|end] [-t]
                [-o outFile [-m max] [-P]
		 [[-n noFiles] | [-s yes|no [-c compressprog]]  ]
		] files...

-a --addName      add filename to the output at the beginning of each line
-d --delay        delay in sec. between checking the files (default 5 sec)
-p --position     read from begin or end of file (default = begin)
-t --withTime     add current time and date to the output
-o --out          write output to file
-m --maxFilelen   maximal len of file written round (default = 1e6)
-n --noOldFiles   number of old files to store
-P --withPID	  write pid to log file (default is not)
-H --withHostname write hostname to log file (default is not)
-l --maxlines     maximal number of lines to read per second in one chunk
		  from a log file (default = 100)
		  this value multiplied with [-d] is the number read at once

-s --saveLogs	  save log files with date and time instead of deleting the
		  old (with [-noOldFiles]): 'yes' or 'no'
-c --compressWith compress saved log files (e.g. with -c 'gzip -9')

-V		  print version(s)

Copyright (c) 2001-2004 by Heinz-Josef Claes
Published under the GNU General Public License
EOH

&printVersions(\@ARGV, '-V');

$CheckPar = CheckParam->new('-allowLists' => 'yes',
			    '-list' => [
					Option->new('-option' => '-a',
						    '-alias' => '--addName'),
					Option->new('-option' => '-d',
						    '-alias' => '--delay',
						    '-default' => 5),
					Option->new('-option' => '-p',
						    '-alias' => '--position',
						    '-default' => 'begin',
						    '-pattern' =>
						    '^begin$|^end$' # '
						    ),
					Option->new('-option' => '-t',
						    '-alias' => '--withTime'),
					Option->new('-option' => '-o',
						    '-alias' => '--out',
						    '-param' => 'yes'),
					Option->new('-option' => '-m',
						    '-alias' => '--maxFilelen',
						    '-default' => 1e6),
					Option->new('-option' => '-n',
						    '-alias' => '--noOldFiles',
						    '-param' => 'yes',
						    '-only_if' =>
						    '[-o] and not ( [-s] or [-c])'),
					Option->new('-option' => '-P',
						    '-alias' => '--withPID'),
					Option->new('-option' => '-H',
						    '-alias' => '--withHostname'),
					Option->new('-option' => '-l',
						    '-alias' => '--maxlines',
						    '-default' => 100,
						    '-pattern' => '^\d+$' # '
						    ),
					Option->new('-option' => '-s',
						    '-alias' => '--saveLogs',
						    '-param' => 'yes',
						    '-pattern' =>
						    '^yes$|^no$', #'
						    '-only_if' =>
						    '[-o] and not [-n]'),
					Option->new('-option' => '-c',
						    '-alias' => '--compressWith',
						    '-param' => 'yes',
						    '-only_if' =>
						    '[-o] and not [-n]')
					]
			    );

$CheckPar->check('-argv' => \@ARGV,
                 '-help' => $Help
                 );

$delay = $CheckPar->getOptWithPar('-d');
$addName = 1 if ($CheckPar->getOptWithoutPar('-a'));
$position = $CheckPar->getOptWithPar('-p');
$withTime = ($CheckPar->getOptWithoutPar('-t')) ? 'yes' : 'no';
$out = $CheckPar->getOptWithPar('-o');
$maxFilelen = $CheckPar->getOptWithPar('-m');
$noOldFiles = $CheckPar->getOptWithPar('-n');
$withPID = $CheckPar->getOptWithoutPar('-P') ? 'yes' : 'no';
$hostname = $CheckPar->getOptWithoutPar('-H') ? `hostname -f` : '';
chomp $hostname;
$maxlines = $CheckPar->getOptWithPar('-l');
$saveLogs = $CheckPar->getOptWithPar('-s');
$compressWith = $CheckPar->getOptWithPar('-c');

unless ($CheckPar->getNoListPar())
{
    print "$Help";
    exit 1;
}

# Initialisierung
my @files;
my $file;
my $iter = Iter_ParList->new($CheckPar);
while ($file = $iter->next())
{
    my $f = ($addName) ? "$file " : '';
    push @files, tailOneFile->new('-filename' => $file,
				  '-position' => $position,
				  '-prefix' => $f,
				  '-maxlines' => $maxlines * $d)
}


# Ausgabeobjekt erzeugen
@fileout = ('-file' => $out) if ($out);
$prLog = printLog->new(@fileout,
		       '-withTime' => $withTime,
		       '-maxFilelen' => $maxFilelen,
		       '-noOfOldFiles' => $noOldFiles,
		       '-saveLogs' => $saveLogs,
		       '-compressWith' => $compressWith,
		       '-withPID' => $withPID,
		       '-hostname' => $hostname
		       );


my $i = 0;
while (42)
{
    my $l = $files[$i]->read();
    chop @$l;
#    print "@$l\n";
    $prLog->pr(@$l);

    ++$i;
    $i %= @files;
    select(undef, undef, undef, $delay / @files); # sleep in seconds
}

