require 'syslog.pl';
require 'errno.ph';

# $Header: /afs/gza.com/development/mail-server/RCS/mservlib.pl,v 1.27 1994/03/01 12:59:43 jik Exp $

package lib;

require 'mservconfig.pl';

$unique_number = 0;

sub db_init {
    local($now, $user);
    local($seconds_per_day) = 60 * 60 * 24;
    local(@times);
    local($logged);

    $request_db = $default_request_db if (! $request_db);

    if (! dbmopen(REQUEST_DB, $request_db, 0660)) {
	&main'syslog('err', "Opening DBM database $request_db: $!");
	die "Opening DBM database $request_db: $!.\n";
    }

    $now = time;

    for $user (keys %REQUEST_DB) {
	$logged = ($REQUEST_DB{$user} =~ s/L//);
	@times = split(' ', $REQUEST_DB{$user});
	while (@times && ($now - $times[0] > $seconds_per_day)) {
	    shift @times;
	}
	if (! @times) {
	    delete $REQUEST_DB{$user};
	}
	else {
	    if ($logged && (@times >= $max_daily_requests)) {
		$logged = "L";
	    }
	    else {
		$logged = "";
	    }
	    $REQUEST_DB{$user} = $logged . join(' ', @times);
	}
    }

    return;
}


sub db_close {
    dbmclose(REQUEST_DB);
}

sub check_db {
    local($user, $file) = @_;
    local($logged, $retval);

    $logged = ($REQUEST_DB{$user} =~ s/L//);
    
    $retval = ((! $REQUEST_DB{$user}) || 
	       ((split(' ', $REQUEST_DB{$user}) < $max_daily_requests)));

    if (! $retval) {
	if (! $logged) {
	    &main'syslog('info', 
			 "per-day limit reached (%s for %s); skipping message",
			 $file, $user);
	}
	$REQUEST_DB{$user} .= "L";
    }

    $retval;
}

sub add_db {
    local($user, $points) = @_;
    local($time) = time;

    for (1..$points) {
	$REQUEST_DB{$user} .= " $time";
    }
}

sub cleanup {
    &db_close();
    unlink(<$tempfile.*>);
    exit((@_ > 0) ? $_[0] : 0);
}

sub get_lock {
    local($file, $times) = @_;
    local($pid, $checkpid);

    open(LOCKFILE, ">$queuedir/$file") || die "Opening $queuedir/$file: $!";
    print LOCKFILE $$ || die;
    close(LOCKFILE);

    while (! link("$queuedir/$file", "$queuedir/$lockfile")) {
	if ($! != &main'EEXIST) {
	    &main'syslog('err', "linking to $queuedir/$lockfile: $!");
	    die "linking to $queuedir/$lockfile: $!";
	}
	$pid = do "$queuedir/$lockfile";
	if ($pid && (! kill(0, $pid)) && ($! == &main'ESRCH)) {
	    $checkpid = do "$queuedir/$lockfile";
	    if ($pid == $checkpid) {
		&main'syslog('notice', "process $pid appears to have died, " .
			     "removing $lockfile");
		if ((! unlink("$queuedir/$lockfile")) &&
		    ($! != &main'ENOENT)) {
		    &main'syslog('err', "error removing $lockfile: $!");
		    die "error removing $lockfile: $!";
		}
		next;
	    }
	}
	if (defined($times) && (--$times <= 0)) {
	    &main'syslog('notice', "giving up on getting lock");
	    unlink("$queuedir/$file");
	    return undef;
	}
	sleep 10;
    }
    return 1;
}

sub clear_lock {
    if (@_ == 1) {
	unlink("$queuedir/$_[0]");
    }
    unlink("$queuedir/$lockfile");
}

sub make_file_name {
    sprintf("%d.%d.%03d.%s", time, $$, $unique_number++, $_[0]);
}

sub make_file_pattern {
    sprintf("[0-9]*.[0-9]*.[0-9][0-9][0-9].%s", $_[0]);
}

sub make_file_regexp {
    sprintf("^[0-9]+\\.[0-9]+\\.[0-9]{3}\\.%s\$", $_[0]);
}

sub file_time {
    if ($_[0] =~ /^(.*\/|)([^\.]+)\.[^\/]*$/) {
	$2;
    }
    else {
	undef;
    }
}

sub file_process {
    if ($_[0] =~ /^(.*\/|)[^\.]+\.([^\.]+)\.[^\/]*$/) {
	$2;
    }
    else {
	undef;
    }
}

1;
