#!/usr/local/bin/perl
#
############################################################################
# The origional of this script is kept under RCS control DO NOT EDIT until #
# you have checked out a locked copy of the script!!!                      #
############################################################################
#
# build - a perl script for automating the administration of ftp
# 	archives. Created by Mike Miller, September 1994.
# 	use the command `build help` to see the documentation.
#

# location of the gifs
$leftgif = "/pub/next/admin/a_left.gif";

# html information
$siteurl = "ftp://next-ftp.peak.org";

# site information
$sitetop = "/info/ftp/pub/next";
# the number of characters to strip off the path to translate it
# into a ftp directory
$ntrans = 9;

#location of executeables
$gzip = "/usr/local/gnu/bin/gzip";
$compress = "compress";

# first thing to do is to get the date of this whole darn thing
# since I timestamp a lot of stuff there isn't any sense in
# executing date over and over again since date doesn't need
# to be that accurate

$date = `date`;
chop $date;

# I leave most of my debug code in. It's done with if statements. It
# probably makes the code slower due to the increased number of if
# statements, but it's not such a pain in the butt to debug when
# something goes wrong...
$idescend_debug = 0;
$deep_debug = 0;
$diag = 0;

if (@ARGV == 0) {
# no arguments isn't very fun, tell the user about it.
	print STDERR "Usage: build option [option]\n";
	print STDERR "type `build help` for assistance\n";
	exit;
}

foreach $arg (@ARGV) {
# if we have some arguments then decide what to do based on those
# arguments. Here is a nice case statement to do the job
	print STDOUT "Inside the loop with $arg\n";
	CASE: {
		if ($arg =~ /^archive/) { &build_archive;last CASE; }
		if ($arg =~ /^index/) { &idecend("$sitetop");last CASE; }
		if ($arg =~ /^recents/) { &recents;last CASE; }
		if ($arg =~ /^sindex/) { &submission_index; last CASE; }
		if ($arg =~ /^.index/) { &refresh_index; last CASE; }
		if ($arg =~ /^modes/) { &odecend; last CASE; }
		if ($arg =~ /^misc/) { &misc; last CASE; }
		if ($arg =~ /^help/) { &help; last CASE; }
		print STDOUT "$arg is not a valid option for build.\n";
		print STDOUT "Type `build help` to get a list of valid choices and help\n";
	}
}
exit;

# That was the main body of the program. Below this point
# there are merely subroutines (and lots of them)

sub help {
# guess what? This is the big help stuff that we print to tell
# users all the wonderful things that this program can do.
	print STDOUT <<"end_of_help";

build 1.1ALPHA4						Sept 18, 1997

	A perl program designed to assist in the maintence of the
	next archive at next-ftp.peak.org. (previously at
	ftp.cs.orst.edu) It has several features:
		Recursive index building and maintance.
		Submission directory monitoring.
		Automatic change of permissions. *** Currently Broken ***

	There are currently 6 possible arguments that build takes.

	archive - This preforms a total reconstruction of the archive
		including indexing, linking, and creation of
		informational files.

	index - This recursivly builds up a index of the entire
		archive from the .index files that are also created
		or updated on the fly. The result is a .index file
		in every subdirectory with the contents of the
		subdirectory, and a index file with the contents
		of that subdirectory and the contents of all
		subdirectories underneath it. Also builds a cute
		little html document in each directory called
		files.html that is a html verison of the .index at
		each level.

	.index - This creates or updates a single .index file in
		the current directory. This file can have descriptions
		of the files added to it by leaving a space after
		the filename and adding text. The additional text
		is preserved through the indexing process providing
		that it is on the same line as a valid file, and 
		there is a space between the filename and the text. 

	modes - This changes the directories to be mode 775 and
		regular files to be 664. It is a recursive calling
		function that does not modify the current directory
		that it is in, only the subdirectories of itself.
		*** CURRENTLY BROKEN ***

	misc -  This just takes care of a couple little things.
		Compresses and gzips copies of the top level index
		file as well as ls-lR.

	recents - This creates a called Recent_Arrivals that finds
		all files that have a last modified date of 7 or
		less days.

	sindex - This creates a index file for the submissions
		directory that is diffrent from the standard
		index file in that it seperates out the files by
		arrival times. It also mails the file to the
		administrative alias.

	help - Creates this text and outputs it to standard output.

EXAMPLES
	Say you have just moved a lot of files around and you want
	to add descriptions to the .index files and update the
	archive because you had to reorganize some major areas.
	to get a new .index file in the directory you are in:
		build .index
	Now you can edit the .index file to add the descriptons
	Then maybe you want to update the entire index structure.
		build index
	Now that the index is cleared up you realize that you
	need to move a few more files around so you do that, and
	just to update everything you rebuild the entire archive
		build archive
	now everything is updated and everyone should be happy.

BUGS
	Plenty, it isn't very robust yet and does *very* little
	error checking. I wouldn't reccomend moving it off of
	next-ftp.peak.org unless you know perl pretty well.

HISTORY
	build was created by Mike Miller September 1994. It
	contains some stuff that is coded specifically to
	the next-ftp.peak.org archive. be careful if you try
	to use it elsewhere.

	Second Coding October 1995 by Mike Miller

	1.0ALPHA  - This version was a working prototype.
		parts of it don't even run to syntatcal errors
	1.1ALPHA  - Massive changes, it does different things
		and in diffrent ways...
	1.1ALPHA2 - Modifications to fix bugs and add html
		 features.
	1.1ALPHA3 - Moved the script to next-ftp.peak.org this
		 move required many little changes and caused
		 the creation of several global variables that
		 were specific to the site instead of hardcoding
		 imbedded in the code
        1.1ALPHA4 - Added '\' character to delimit @ in printed
		 email addresses. This makes the script Perl5
		 compatable

AUTHORS
	Just me so far. If you use this, write me mail and let
	me know what you think. This is version 1.1ALPHA so don't
	expect too much.

	millerm\@ece.orst.edu

end_of_help
}

sub build_archive {
# pretty self explanatory, it goes through and runs everything
	chdir "$sitetop";
#	&odecend; # IT IS BROKEN
	&idecend ("$sitetop");
	&recents;
	&submission_index;
	&misc;
}

sub misc {
# This takes the index file in the top directory and creates
# gziped and compressed versions of the index
	chdir "$sitetop";
	`cp index index.bak`;
	unlink ("index.gz");
	`$gzip -9 index`;
	`cp index.bak index`;
	unlink ("index.Z");
	`$compress index`;
	`mv index.bak index`;
	@listing = `ls -LlRF`;
	$pwd = `pwd`;
	print "$pwd";
	open (FILE, ">$sitetop/ls-lR") || die "Can't open the ls-lR file for some reason";
	foreach $file (@listing) {
		print FILE "$file"
	}
	close (FILE);
	chdir "$sitetop";
	`cp ls-lR ls-lR.bak`;
	unlink("ls-lR.gz");
	`$gzip -9 ls-lR`;
	`cp ls-lR.bak ls-lR`;
	unlink("ls-lR.Z");
	`$compress ls-lR`;
	`mv ls-lR.bak ls-lR`;
}

sub idecend {
# this builds all the .index and index files throughout the tree
# it gets passed the directory it has just entered
	local($thisdir, @junk) = @_;
	opendir(CDIR, ".");
	local(@filelist) = grep(!/^.\.?$/, readdir(CDIR));
	closedir(CDIR);
	local ($file);
	foreach $file (@filelist) {
		if($deep_debug){print STDOUT " the file is $file\n";}
		local ($todir) = "$thisdir/$file";
		if ( ($todir) && ( -d $todir ) )
		{
			chdir "$todir";
			if($idescend_debug){print("entering $todir\n");}
			&idecend ($todir);
			chdir "$thisdir";
			if($idescend_debug){print("entering $thisdir\n");}
		}
	}
	&refresh_index ($thisdir);  # updates the .index
	&build_index ($thisdir); # builds (destructivly) the index file from the
		                 # index files below (ain't recursion great?)
}

sub odecend {
# this bit of code is to change the ownership of the files to 664
# over the entire directory structure without moshing the permissions
# on the soft links and on the directories. If you know of a better
# way to do this please contact me. This method strikes me as messy
        local(@filelist) = `ls -1F`;
        local ($file);
        foreach $file (@filelist) {
                chop $file;
                #print STDOUT "This is the file at the top of odecend $file\n";
                if ( (-d $file) && ($file) && ($file !=~/submissions/) ) {
                        #print STDOUT "moving into $file\n";
                        chdir "$file";
                        &odecend;
			local (@listing) = `ls -1F`;
			if (-f ".index") {
				push (@listing, ".index\n");
			}
			local ($tobec);
			foreach $tobec (@listing) {
				chop $tobec;
				#print STDOUT "trying to change mode of $tobec\n";
				if ( -d $tobec ) {
					#print STDOUT "directory $tobec\n";
					local (@broke) = grep(!(chmod 0775, $_), $tobec);
					if (@broke) {
						$pwd = `pwd`;
						print STDOUT "$0: couldn't chmod @broke inside of $pwd";
					}
				}
				else {
					#print STDOUT "file $tobec\n";
					local (@broke) = grep(!(chmod 0664, $_), $tobec);
					if (@broke) {
						$pwd = `pwd`;
						print STDOUT "$0: couldn't chmod @broke inside of $pwd";
					}
				}
			}
                        local ($pwd) = `pwd`;
                        print STDOUT "moving out of $pwd";
                        chdir "..";
                }
        }
}

sub refresh_index {
# This little piece is responsible for updating/creating the .index
# files. There are one or two little tricks that you would need to
# change if you are using this at a site other than next-ftp.peak.org
	local($thisdir, @junk) = @_;
	if ( -e ".index" ) {
		open (ORIG, ".index") || die "Can't open .index, refresh_index";
		local (@origional);
		while (<ORIG>) {
# OK a word of explination, I'm going to build an associative array
# with the key being the (almost) full pathname of the file
# and the contents are the description.
			local ($name, $description) = split(' ',$_,2);
			chop $description;
			$origional{$name} = $description;
			#print "$name, $origional{$name}\n";
		}
		close ORIG;
	}
	substr ($thisdir,0,$ntrans) = ''; # this makes it so that "absolute" pathname
				  # matches in ftp and mosaic
	open (INDEX, ">.index") || print "Can't open .index for output while in $thisdir\n";
	open (HTML, ">files.html") || print "Can't open files.html for output while in $thisdir\n";
	print HTML "<title>Index for $siteurl$thisdir</title>\n";
	print HTML "<H4>Index for $siteurl$thisdir</H4>\n";
	print HTML "Last Updated $date<hr>\n";
	if ( -e "../files.html" )
	{
		print HTML "<img src=\"$leftgif\"><a href=\"../files.html\"><b> up one level</b></a><dl>";
	}
	else
	{
		print HTML "<img src=\"$leftgif\"><a href=\"../\"><b> up one level</b></a><dl>";
	}
	local (@filelist) = `ls -1`;
	local ($file);
	foreach $file (@filelist) {
		chop $file;
		$current = "$thisdir/$file";
		print INDEX "$current \t$origional{$current}\n";
		if( -d $file )
		{
			print HTML "<dt><b><a href=\"$file/files.html\">$file</a></b><dd> $origional{$current}<p>\n";
		}
		else
		{
			print HTML "<dt><a href=\"$file\">$file</a><dd> $origional{$current}<p>\n";
		}
	}
	print HTML "</dl>\n<hr><i>This list is automatically generated. If it appears to be out of date or corrupted please contact next-ftp\@mail.peak.org. Thank you</i>\n";
	close (INDEX);
	close (HTML);
}

sub build_index
{
# this piece of code builds the index file based on the index files
# in it's immedate subdirectories and the .index file in the current
# directory
	local ($thisdir, @junk) = @_;
	opendir(CDIR, ".");
	local(@filelist) = grep(!/^.\.?$/, readdir(CDIR));
	closedir(CDIR);
	open (INDEX, ">index") || print "Can't open index for output at $thisdir\n";
	substr($thisdir,0,$ntrans) = '';#here is "absolute" pathname mod.
	print INDEX "Index for $siteurl$thisdir\n";  #oohhh, a URL
	print INDEX "Last Updated $date\n\n";
	open (CINDEX, ".index") || print "Can't open .index for input to index";
	while (<CINDEX>)
	{
		print INDEX "$_";
	}
	close CINDEX;
	foreach $file (@filelist)
	{
		if (($file) && ( -r "$file/index" ))
		{
			print INDEX "\n";
			open (SINDEX, "$file/index") || die "Can't open index at $thisdir\n";
			while (<SINDEX>)
			{
				print INDEX "$_";
			}
			close (SINDEX);
		}
	}
	close (INDEX);
}

sub recents {
# more fun... This creates a file called Recent_Arrivals and puts the output
# of a find -type f -mtime +7 (and some greps) in the file all nice and
# pretty (including another one of those ftp style absolute filenames)
	open (FILE, ">$sitetop/Recent_Arrivals") || die "can't open recent\n";
	local (@list);
	local ($file);
	@list = `find $sitetop -follow -type f -mtime -7 -print | grep -v index | grep -v NextTrash | grep -v files.html`;
	print FILE "The following is a list of the files that have arrived in the past 7 days\n";
	print FILE "Last updated: $date\n\n";
	foreach $file (@list) {
		substr($file,0,$ntrans) = '';  # "absolute" pathname
		print FILE "$file";
	}
	close (FILE);
}

sub submission_index {
# This is pretty nice, it builds a special index for the submissions
# directory that breaks it down by arrival dates and then mails the
# file to our archive administration alias. Here we don't bother
# with changing the filenames around
	open (FILE, ">$sitetop/submissions/index") || die "Can't open the submissions index for some reason";
	local (@day1);
	local (@day2);
	local (@week);
	local (@forever);
	local ($file);
	print FILE "This is the submissions directory for the next archive at next-ftp.peak.org\n";
	print FILE "Regular daily report for $date\n\n";
	@day1 = `find $sitetop/submissions -type f -mtime 1 -print | grep -v index`;
	local ($inarray) = @day1;
	if ($inarray) {
		print FILE "Today's arrivals:\n\n";
		foreach $file (@day1) {
			print FILE "$file";
		}
		print FILE "\n";
	}
	@day2 = `find $sitetop/submissions -type f -mtime 2 -print | grep -v index`;
	$inarray = @day2;
	if ($inarray) {
		print FILE "Yesterday's arrivals:\n\n";
		foreach $file (@day2) {
			print FILE "$file";
		}
		print FILE "\n";
	}
	@week = `find $sitetop/submissions -type f -mtime -7 -a ! -mtime -2 -print | grep -v index`;
	$inarray = @week;
	if ($inarray) {
		print FILE "Week's arrivals:\n\n";
		foreach $file (@week) {
			print FILE "$file";
		}
		print FILE "\n";
	}
	@forever = `find $sitetop/submissions -type f -mtime +7 -print`;
	$inarray = @forever;
	if ($inarray) {
		print FILE "Files that have been here a long time:\n\n";
		foreach $file (@forever) {
			print FILE "$file";
		}
		print FILE "\n";
	}
	close (FILE);
	local ($tempval) = `/usr/bin/mail -s NeXT_FTP_Report next-ftp\@peak.org < $sitetop/submissions/index`;
	if($diag){print STDOUT "$tempval";}
}

# Congrats! You have reached the end of the perl script.
