#!/usr/bin/perl

eval 'exec /usr/bin/perl  -S $0 ${1+"$@"}'
    if 0; # not running under some shell
##!~_~perlpath~_~
#
# MiniVend session expiration
#
# $Id: expire,v 1.3 2000/02/06 01:53:00 mike Exp mike $
#
# Copyright 1996-2000 by Michael J. Heins <mikeh@minivend.com>
#
# This program was originally based on Vend 0.2
# Copyright 1995 by Andrew M. Wilcox <awilcox@world.std.com>
#
# Portions from Vend 0.3
# Copyright 1995 by Andrew M. Wilcox <awilcox@world.std.com>
#
# See the file 'Changes' for information.
#
# 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., 59 Temple Place, Suite 330, Boston,
# MA  02111-1307  USA.

use lib '/usr/local/minivend/lib';
#use lib '~_~INSTALLPRIVLIB~_~';
use lib '/usr/local/minivend';
#use lib '~_~INSTALLARCHLIB~_~';

BEGIN {

	($Global::VendRoot = $ENV{MINIVEND_ROOT})
		if defined $ENV{MINIVEND_ROOT};
$Global::VendRoot = $Global::VendRoot || '/usr/local/minivend';
#$Global::VendRoot = $Global::VendRoot || '~_~INSTALLARCHLIB~_~';
	$ENV{MINIVEND_STORABLE} = 1
		if -f "$Global::VendRoot/_session_storable";
	$ENV{MINIVEND_STORABLE_DB} = 1
		if -f "$Global::VendRoot/_db_storable";
	
}
### END CONFIGURABLE VARIABLES

sub dontwarn { $FindBin::RealBin; }

$Global::ConfigFile = 'minivend.cfg';
$Global::HammerLock = 20;
$Global::ErrorFile = 'error.log';

use strict;
use Fcntl;

$Vend::ExternalProgram = 1;
$Vend::SessionName = 'utility';

#select a DBM

BEGIN {
	$Global::GDBM = $Global::DB_File = 0;
    AUTO: {
        last AUTO if
            (defined $ENV{MINIVEND_DBFILE} and $Global::DB_File = 1);
        last AUTO if
            (defined $ENV{MINIVEND_NODBM});
        eval {require GDBM_File and $Global::GDBM = 1} ||
        eval {require DB_File and $Global::DB_File = 1};
    }
	if($Global::GDBM) {
		require Vend::Table::GDBM;
		import GDBM_File;
		$Global::GDBM = 1;
	}
	elsif($Global::DB_File) {
		require Vend::Table::DB_File;
		import DB_File;
		$Global::DB_File = 1;
	}
	else {
		die "Can't use expire without DBM sessions.\n";
	}
}

use Vend::Session;
use Vend::Config qw(get_catalog_default parse_time);
use vars qw/$opt_c $opt_r $opt_e/;

my $USAGE = <<EOF;
usage: expire [-r] -c catalog [-e 'SessionExpire']
           or
       expire [-r] [-e 'SessionExpire'] sessionfile [sessionfile.lock]

 OPTIONS
      -c catalog  specify a catalog from minivend.cfg

      -e time     vary expire time from default in catalog.cfg.
                  time is a string like '4 hours' or '2 days'

      -r          reorganize database and recover lost disk space
EOF

my $catalog;
my $expiretime;
my $reorg;

$Vend::Cfg = { FileCreationMask => 0600 };

use Getopt::Std;

getopts('c:e:r') or die "$@\n$USAGE\n";

$catalog    = $opt_c || undef;
$expiretime = $opt_e || undef;
$reorg      = $opt_r;

GETOPT: {

	last GETOPT if $catalog;
	$Vend::Cfg->{SessionDatabase} = shift
		|| die $USAGE;
	$Vend::Cfg->{SessionDatabase} =~ s/\.(gdbm|db)$//;
	$Vend::Cfg->{SessionLockFile} = shift;
	if (defined $Vend::Cfg->{SessionLockFile}) { 
		die <<EOF unless -f $Vend::Cfg->{SessionLockFile};
Session lock file '$Vend::Cfg->{SessionLockFile}' doesn't exist.
Create one if you are sure the MiniVend server is down, then try
again.
EOF
	}
	elsif (-f "$Vend::Cfg->{SessionDatabase}.lock") {
		$Vend::Cfg->{SessionLockFile} = 
				"$Vend::Cfg->{SessionDatabase}.lock";
	}
	else {
		my $dir = $Vend::Cfg->{SessionDatabase};
		$dir = s:/?([^/]+)$::;
		my $file = $1 || die $USAGE;
		die "Aborting, no lock files found!\n"
			unless -f "$dir/$file.lock";
	}

} # END GETOPT

die "too many args, aborting.\n" 
		if @ARGV;
my (%wanted) = qw(	sessionexpire	SessionExpire
					sessiondatabase SessionDatabase
					sessionlockfile SessionLockFile
					scratchdir		ScratchDir
					errorfile       ErrorFile);

if(defined $catalog) {
	my($name,$dir,$param);
	chdir $Global::VendRoot;
	open(GLOBAL, $Global::ConfigFile) or
		die "No global configuration file? Aborting.\n";
	while(<GLOBAL>) {
		next unless /^\s*catalog\s+$catalog\s+/i;
		chomp;
		s/^\s+//;
		(undef,$name,$dir,$param) = split /\s+/, $_, 4;
		last;
	}
	close GLOBAL;
	die "Catalog $catalog not found in $Global::ConfigFile.\n"
		unless defined $name;
	chdir $dir or die "chdir to $dir: $!\n";
	open(CATALOG, 'catalog.cfg') or
		die "No catalog configuration file? Aborting.\n";
	my (%seen);
	while(<CATALOG>) {
		next unless /\S/;
		next if /^\s*#/;
		chomp;
		s/^\s+//;
		s/\s+$//;
		($name,$param) = split /\s+/, $_, 2;
		next unless defined $wanted{lc $name};
		$seen{$wanted{lc $name}} = $param;
	}
	close CATALOG;
	for(values %wanted) {
		next if defined $seen{$_};
		$seen{$_} = get_catalog_default($_);
	}
	for(keys %seen) {
		$Vend::Cfg->{$_} = $seen{$_};
	}
	$expiretime = $Vend::Cfg->{SessionExpire} unless defined $expiretime;
}
else {
	$Vend::Cfg->{ScratchDir} = '/tmp';
	$Vend::Cfg->{ErrorFile} = $Global::ErrorFile;
	$expiretime = '1 day' unless defined $expiretime;
}

$Vend::Cfg->{SessionExpire} = parse_time('SessionExpire', $expiretime);

die $USAGE unless defined $Vend::Cfg->{SessionLockFile};

my $db_reorg = $Global::DB_File ? $reorg : undef;

undef $reorg unless $Global::GDBM;

get_session() unless $reorg;
expire_sessions($reorg);
release_session() unless $reorg;

system "compact ." if $db_reorg;

=head1 NAME

expire -- expire Minivend session files and databases

=head1 VERSION

1.0

=head1 SYNOPSIS

   expire [-ra] [-e expr] [-c catalog] [-d dir] [sessiondb]

=head1 DESCRIPTION

Minivend's C<expire> expires the various session database and temporary
files used by the MiniVend daemon.

If the program C<tmpwatch> is available, it is called with the appropriate 
arguments. Otherwise, MiniVend will remove all files itself with a recursive
routine.

=head1 OPTIONS

=over 4

=item -c name

Expires the catalog C<name> according to its settings. Removes all temporary
files that are in a subdirectory one level below the directory itself.

=item -d dir

Sets the directory that will be checked for session files and/or temporary
files.

=item -e spec

Accepts a Minivend expire time setting like "6 hours", "3 days", etc.
The expire time is applied directly to sessions, and may be padded for
temporary files.

=back

=head1 SEE ALSO

mvdocs(8), expireall(1), http://www.minivend.com

=head1 AUTHOR

Mike Heins, <mikeh@minivend.com>


