#!/usr/local/bin/perl
;#
;# Copyright (c) 1995-1997
;#	Ikuo Nakagawa. All rights reserved.
;#
;# Redistribution and use in source and binary forms, with or without
;# modification, are permitted provided that the following conditions
;# are met:
;#
;# 1. Redistributions of source code must retain the above copyright
;#    notice unmodified, this list of conditions, and the following
;#    disclaimer.
;# 2. Redistributions in binary form must reproduce the above copyright
;#    notice, this list of conditions and the following disclaimer in the
;#    documentation and/or other materials provided with the distribution.
;#
;# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
;# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
;# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
;# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
;# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
;# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
;# OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
;# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
;# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
;# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
;# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
;#
;# $Id: run.pl,v 1.2 1997/09/16 15:35:51 ikuo Exp $
;#
use strict;
use vars qw($opt_d $opt_f $opt_l $opt_p $opt_v $todo $dir);

use Getopt::Std;

$dir = '/u/ftpadmin/run';
chdir($dir) or die("chdir: $!\n");

$todo = 'full-mirror';

getopts("df:l:p:v") or die("Usage: $0 [-v] [-p #] [archive...]\n");

if ($opt_l) {
	open(STDERR, '>>'.$opt_l) or die("open($opt_l): $!\n");
	open(STDOUT, '>&STDERR') or die("open(STDOUT): $!\n");
}

$opt_p = 1 if $opt_d || $opt_p < 1;

if ($opt_f) {
	local *FILE;

	-f $opt_f or die("$opt_f: file not found\n");
	open(FILE, $opt_f) or die("open($opt_f): $!\n");
	while (<FILE>) {
		s/^\s+//; s/\s+$//; next if /^$/ || /^#/;
		push(@ARGV, $_);
	}
	close(FILE);
}

if (@ARGV == 0) {
	warn("nothing to do, terminate\n");
} else {
	&loop(@ARGV);
}
exit;

sub loop {
	my %kids = ();
	my $n = 0;

	while (@_ || %kids) {
		while (@_ && $n < $opt_p) {
			my $x = shift;
			my $p = &run($x);
			warn("target \"$x\" [$p] started.\n");
			$kids{$p} = $x;
			$n++;
		}
		if ((my $kids = join(',', values %kids)) ne '') {
			warn("running: $kids\n");
		}
		if ((my $p = wait) >= 0) {
			warn("kid[$p] returns $?\n");
			if (exists($kids{$p})) {
				warn("target \"$kids{$p}\" [$p] done.\n");
				delete($kids{$p});
				$n--;
			}
		}
	}

	1;
}

sub run {
	my $pac = shift;
	my $log = "log/$pac.log";

	if (!defined(my $pid = fork)) {
		die("fork: $!\n");
	} elsif ($pid) {
		return $pid; # in parent...
	}

	if (!$opt_d && -e $log) {
		system 'rotate', $log, '3', '2', '1', '0';
		$? == 0 or warn("rotate($log): returns $?\n"), next;
		open(STDERR, '>'.$log)
			or warn("open($log): $!\n"), next;
		open(STDOUT, '>&STDERR')
			or warn("can't redirect stdout: $!\n"), next;
	}
	exec '/usr/bin/time', '-l', 'ftpmirror',
		'--todo='.$todo,
		'--ftp-list-method=LIST',
		'--load-config+=run.cf',
		'--log-mask=Fan=6,Fan::Farm=6',
		'--ftp-stats', $pac
		or die("exec: $!\n");
}
