#!/usr/bin/perl
#
#NAME
#  rsdir - rsync directories on a list of mirror hosts
#  rsdrl - rsync directories on a list of mirror hosts and relink files
#
#SYNOPSIS
#  rsdir dir...
#  rsdrl dir...
#
#WARNING
#  This program MUST be run from $HOME! (Unless $base is changed below.) This
#  program  syncs  relative  to  the home directories on all remote machines,
#  using the same path there as on this machine.  It also  assumes  the  same
#  login  id  on all the machines.  If you need something more versatile, use
#  rsync directly.  The main purpose of this program is as a "wrapper" around
#  the rsync command to speed up some common uses.
#
#DESCRIPTION
#  This is how I synchronize my files with a number of machines  that
#  I use as mirrors.
#
#  This program uses rsync to synchronize  the  list  of  directories
#  with the corresponding directories on several other machines.
#
#OPTIONS
#
#EXAMPLES
#
#FILES
#
#BUGS
#  While the local directories will be rsync'd with  each  host,  the
#  remote hosts will not necessarily be rsync'd with each other. This
#  is order dependent:  host1's files will end up  on  with  all  the
#  hosts  (including  the  local  host).   But  host2's  files  won't
#  necessarily be on host1. To ensure completion, repeat the command.
#
#SEE ALSO
#
#AUTHOR
#  John Chambers <jc@trillian.mit.edu>
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #

$| = 1;	# Don't buffer stdio
($P = $0) =~ s".*/"";
$V = $ENV{"V_$P"} || 2;

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
#  I sometimes link this program to special names for these hosts:
	%names = (
		'jc'    => 'john-chambers.us',
		'trill' => 'trillian.mit.edu',
#		'rr'    => 'rudy-rucker.mit.edu',
		'jeffer'=> 'jeffer.john-chambers.us',
		'kendy' => 'kendy.john-chambers.us',
		'minya' => 'minya.john-chambers.us',
#		'test' => 'test.local',
	);

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
#  The list of mirror hosts:
if ($rhost = $names{$P}) {	# Are we named for a host?
	@hosts = ($rhost);		# If so, rsync to only that host
} else {					# Pick one of these, or make up your list:
	@hosts =  qw( john-chambers.us );
#	@hosts =  qw( gavving.home john-chambers.us rucker.mit.edu trillian.mit.edu );
#	@hosts =  qw( minya gavving kendy jeffer );
#	@hosts =  qw( minya );	# Just the one machine
#	@hosts =  qw( rudy );
#	@hosts =  qw( kendy minya trill rr );	# Closest first
#	@hosts =  qw( trill kendy minya rr );	# Most-public first
#	@hosts =  qw( kendy minya trill rr );	# Local server first
#	@hosts =  qw( trill kendy rr );		# Simple-name defaults
#	@hosts =  qw( trill jc );		# Simple-name defaults
#	@hosts =  qw( trill jc );		# Simple-name defaults
#	@hosts =  qw( john-chambers.us rucker.mit.edu );
#	@hosts =  qw( kendy );
#	@hosts =  qw( minya );
#	@hosts =  qw( jc.tzo.net trillian.mit.edu rucker.mit.edu );
}

#  The transport protocol is also fixed:
	$ENV{'RSYNC_RSH'} = 'ssh';

# Here is the base path on remote systems:
	$base = '';		# Null for home directory

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
$home = $ENV{'HOME'} || ".";
$rlflag = ($P eq 'rsdrl');	# Whether to relink after rsync
#rsOpts = 'CHvurptOz';		# rsync options (minya)
#rsOpts = 'CabvutOz';		# rsync options (kendy)
#rsOpts = 'CHlprtOuvz';		# rsync options with hard links preserved
$rsOpts = 'CHlprtOuvK';		# rsync options with hard and sym links preserved
#rsOpts = 'Clprtuvz';		# rsync options without hard links preserved
$cleanflag = 0;				# Whether to do a cleanup first
#print "Password:$pswd\n" if $V>5;

for $dir (@ARGV) {
	print "\n";
	print "==== $dir/\n";
#	$XF = "$dir/.rsExclude";
	$Xopt = '';
	if      (-f ($XF = "$dir/.rsExclude")) {
		$Xopt = "--exclude-from=$XF";
		print "\t$Xopt\n" if $V>1;
	} elsif (-f ($XF = ".rsExclude")) {
		$Xopt = "--exclude-from=$XF";
		print "\t$Xopt\n" if $V>1;
	} elsif (-f ($XF = "$home/.rsExclude")) {
		$Xopt = "--exclude-from=$XF";
		print "\t$Xopt\n" if $V>1;
	}
	for $hst (@hosts) {	# Load new files into local file system
		print "<=== $hst\n";
		$frcmd = "rsync -$rsOpts $Xopt $hst:$base$dir/ $dir/";
		print "cmd: $frcmd\n";
		system $frcmd;
	}
	for $hst (@hosts) {	# Sync remote file systems to ours
		print "===> $hst\n";
		$tocmd = "rsync -$rsOpts $Xopt $dir/ $hst:$base$dir/";
		print "cmd: $tocmd\n";
		system $tocmd;
	}
	if ($rlflag) {	# Are we starting a relink?
		$rlcmd = "relink +rv $dir";
		$rllog = "$dir/relink.log";
		unlink($rllog) if -f $rllog;
		print "	$rlcmd\n" if $V>1;
		system "$rlcmd >$rllog 2>&1 &";
	}
}
