#!/usr/bin/perl

# Scott Harrison
# November 2000
# 12/5/2000,12/7,12/8,12/9,12/10,12/11,12/12,12/13,12/14,12/21 Scott Harrison
# 1/8/2001,1/10/2001,1/13/2001,1/16/2001,1/18/2001,1/23/2001 Scott Harrison
# 2/26/2001,2/27/2001,3/5/2001,4/10/2001,4/11,2001,4/13,2001 Scott Harrison
# 4/17/2001 Scott Harrison

# Read in loncapa tags and metagroup tags.  Output various
# useful files for viewing, compiling, monitoring, updating,
# and installing.

# This code works well.  HOWEVER, I was in a rush when I
# wrote it.  Future plans are that the parsing should be
# much more event-state based and the input should be
# more XML-ish. -Scott

# ---------------------------------------------- Read in command line arguments
my ($file,$mode)=@ARGV;

# ---------------------------------------------------- Read in master data file
open IN,"<$file";
my @lines=<IN>;
close IN;
my $info1=join('',@lines);
my $info2=$info1; # value to allow for meta data group retrieval

# ------------------------------------------------------- Make default settings
my $distribution="redhat6.2";
my $date=`date +'%B %e, %Y'`; chop $date;
my $buildhost=`hostname`; chop $buildhost;
# file category mappings
my %fcm=(
	 'conf' => 'configurable',
	 'graphic file' => 'graphicfile',
	 'handler' => 'handler',
	 'interface file' => 'interfacefile',
	 'symbolic link' => 'link',
	 'root script' => 'rootscript',
	 'script' => 'script',
	 'setuid script' => 'setuid',
	 'static conf' => 'static',
	 'system file' => 'systemfile',
	 );

# ---------------------------------------------------- Parse the marked up data
my %info; # big data storage object
while ($info1=~/\<loncapa\s+(.*?)\>/isg) {
    my $keystring=$1;
    # In the parsing of LON-CAPA tags, remove boundary white-space,
    # and handle quotation commands.
    my %hash=map {my ($key,$value)=split(/\=(?!")|\=(?=\s*"[^"]*"[^"]*$)/);
                                   $value=~s/^"//;
 				   $value=~s/"$//;
                                   (uc($key),$value);}
             split(/\s+(?=\w+\s*\=)/,$keystring);
    # Handle the different types of commands
    if (uc($hash{'TYPE'}) eq "OWNERSHIP") {
        $info{$hash{'TYPE'}}{$hash{'CATEGORY'}}{'CHMOD'}=$hash{'CHMOD'};
        $info{$hash{'TYPE'}}{$hash{'CATEGORY'}}{'CHOWN'}=$hash{'CHOWN'};
    }
    elsif (uc($hash{'TYPE'}) eq "DEVOWNERSHIP") {
        $info{$hash{'TYPE'}}{$hash{'CATEGORY'}}{'CHMOD'}=$hash{'CHMOD'};
        $info{$hash{'TYPE'}}{$hash{'CATEGORY'}}{'CHOWN'}=$hash{'CHOWN'};
    }
    elsif (uc($hash{'TYPE'}) eq "RPM") {
        $hash{'VALUE'}=~s/\\n/\n/g;
        $info{$hash{'TYPE'}}{$hash{'NAME'}}=$hash{'VALUE'};
    }
    elsif (uc($hash{'TYPE'}) eq "DIRECTORY") {
        $info{$hash{'TYPE'}}{$hash{'DIST'}}{$hash{'TARGET'}}{'CATEGORY'}=
                                                       $hash{'CATEGORY'};
        $info{$hash{'TYPE'}}{$hash{'DIST'}}{$hash{'TARGET'}}{'DESCRIPTION'}=
                               $hash{'DESCRIPTION'} if $hash{'DESCRIPTION'};
    }
    elsif (uc($hash{'TYPE'}) eq "LOCATION") {
        $info{$hash{'TYPE'}}{$hash{'DIST'}}{$hash{'TARGET'}}{'CATEGORY'}=                               $hash{'CATEGORY'};
        $info{$hash{'TYPE'}}{$hash{'DIST'}}{$hash{'TARGET'}}{'LINKTO'}=                               $hash{'LINKTO'};
        $info{$hash{'TYPE'}}{$hash{'DIST'}}{$hash{'TARGET'}}{'SOURCE'}=                                               $hash{'SOURCE'};
        # get surrounding metagroup information
        my $ckeystring=$keystring; $ckeystring=~s/(SOURCE\=\"[^"]*)\*/$1\\\*/g;
        $ckeystring=~s/(TARGET\=\"[^"]*)\*/$1\\\*/g;
        $info2=~/.*\<(?:metagroup|metasupergroup)\>(.*?)\<loncapa\s+$ckeystring\>(.*?)\<\/(?:metagroup|metasupergroup)\>/is;
	my $data=$1.$2;
        my @meta=('description','build','dependencies','files','note');
        foreach my $m (@meta) {
	    if ($data=~/\<($m)\>(.*?)\<\/$m\>/sgi) {
		my ($key,$value)=($1,$2);
		$info{$hash{'TYPE'}}{$hash{'DIST'}}{$hash{'TARGET'}}{uc($key)}=
		                                                    $value;
	    }
        }
    }
    else {
        warn("WARNING: this tag text will be ignored since it cannot be understood\n---> $keystring\n");
    }
}

my $a;
my @directories;
if ($mode eq "HTML") {
    $a=&begin_description_page;
    print $a;
    $a=&make_rpm_description_block;
    print $a;
    @directories=&determine_directory_structure;
    $a=&make_directory_structure_description_block(\@directories);
    print $a;
    $a=&make_file_type_ownership_and_permissions_description_block;
    print $a;
    $a=&make_directory_and_file_structure_description_block(\@directories);
    print $a;
    $a=&end_description_page;
    print $a;
}
elsif ($mode eq "SPEC") {
    my $out=$info{'RPM'}{'Name'} . '-' . $info{'RPM'}{'Version'} . '.spec';
    open OUT,">$out";
    $a=&make_rpm_spec_block;
    print OUT $a;
    $a=&make_rpm_build_block;
    print OUT $a;
    @directories=&determine_directory_structure;
    $a=&make_directory_structure_spec_block(\@directories);
    print OUT $a;
    $a=&make_directory_and_file_structure_spec_block(\@directories);
    print OUT $a;
    $a=&end_spec_page;
    print OUT $a;
    close OUT;
}
elsif ($mode eq "LCMakefile") {
    @directories=&determine_directory_structure;
    $a=&make_directory_LCMakefile_segment(\@directories);
    print $a;
    $a=&make_files_LCMakefile_segment(\@directories);
    print $a;
    $a=&make_links_LCMakefile_segment(\@directories);
    print $a;
}
elsif ($mode eq "BinaryRoot") {
    mkdir "BinaryRoot",0755;
    open OUT,">Makefile.BinaryRoot";
    @directories=&determine_directory_structure;
    $a=&make_directory_binaryroot_segment(\@directories);
    print OUT $a;
    $a=&make_files_binaryroot_segment(\@directories);
    print OUT $a;
    $a=&make_links_binaryroot_segment(\@directories);
    print OUT $a;
    close OUT;
    print `make -f Makefile.BinaryRoot TARGET='BinaryRoot' SOURCE='../..' directories`;
    print `make -f Makefile.BinaryRoot TARGET='BinaryRoot' SOURCE='../..' files`;
    print `make -f Makefile.BinaryRoot TARGET='BinaryRoot' SOURCE='../..' links`;
    open OUT,">base_file_list.txt";
    $a=&make_file_list(\@directories);
    print OUT $a;
    close OUT;
    open OUT,">setup_file_list.txt";
    print OUT "BinaryRoot/etc/passwd\n";
    close OUT;
    open OUT,">BinaryRoot/etc/passwd";
    print OUT<<END;
root::0:0:root:/root:/bin/bash
bin:!!:1:1:bin:/bin:
daemon:!!:2:2:daemon:/sbin:
adm:!!:3:4:adm:/var/adm:
lp:!!:4:7:lp:/var/spool/lpd:
sync:!!:5:0:sync:/sbin:/bin/sync
shutdown:!!:6:0:shutdown:/sbin:/sbin/shutdown
halt:!!:7:0:halt:/sbin:/sbin/halt
mail:!!:8:12:mail:/var/spool/mail:
news:!!:9:13:news:/var/spool/news:
uucp:!!:10:14:uucp:/var/spool/uucp:
operator:!!:11:0:operator:/root:
games:!!:12:100:games:/usr/games:
gopher:!!:13:30:gopher:/usr/lib/gopher-data:
ftp:!!:14:50:FTP User:/home/ftp:
nobody:!!:99:99:Nobody:/:
www:!!:500:500:www:/home/www:/bin/bash
END
close OUT;
    open OUT,">>setup_file_list.txt";
    print OUT "BinaryRoot/etc/group\n";
    close OUT;
    open OUT,">BinaryRoot/etc/group";
    print OUT<<END;
root::0:root
bin::1:root,bin,daemon
daemon::2:root,bin,daemon
sys::3:root,bin,adm
adm::4:root,adm,daemon
tty::5:
disk::6:root
lp::7:daemon,lp
mem::8:
kmem::9:
wheel::10:root
mail::12:mail
news::13:news
uucp::14:uucp
man::15:
games::20:
gopher::30:
dip::40:
ftp::50:
nobody::99:
users::100:
www::500:
END
close OUT;
    open OUT,">>setup_file_list.txt";
    print OUT "BinaryRoot/etc/hosts.deny\n";
    close OUT;
    open OUT,">BinaryRoot/etc/hosts.deny";
    print OUT<<END;
ALL: ALL
END
close OUT;
    
    `install -o www -g users -m 0700 -d BinaryRoot/home/www`;
    open OUT,">>setup_file_list.txt";
    print OUT "BinaryRoot/home/www\n";
    close OUT;
    `install -d BinaryRoot/etc/pam.d`;
    open OUT,">>setup_file_list.txt";
    print OUT "BinaryRoot/etc/pam.d/passwd\n";
    close OUT;
    open OUT,">BinaryRoot/etc/pam.d/passwd";
    print OUT<<END;
#%PAM-1.0
auth       required     /lib/security/pam_pwdb.so shadow nullok
account    required     /lib/security/pam_pwdb.so
password   required     /lib/security/pam_cracklib.so retry=3
password   required     /lib/security/pam_pwdb.so use_authtok nullok
END
close OUT;
    open OUT,">>setup_file_list.txt";
    print OUT "BinaryRoot/etc/pam.d/login\n";
    close OUT;
    open OUT,">BinaryRoot/etc/pam.d/login";
    print OUT<<END;
#%PAM-1.0
auth       required     /lib/security/pam_securetty.so
auth       required     /lib/security/pam_pwdb.so shadow nullok
auth       required     /lib/security/pam_nologin.so
account    required     /lib/security/pam_pwdb.so
password   required     /lib/security/pam_cracklib.so
password   required     /lib/security/pam_pwdb.so nullok use_authtok
session    required     /lib/security/pam_pwdb.so
session    optional     /lib/security/pam_console.so
END
close OUT;

}
elsif ($mode eq "status") {
    $a=&begin_description_page('status');
    print $a;
    $a=&make_rpm_description_block('status');
    print $a;
    @directories=&determine_directory_structure('status');
    $a=&make_directory_structure_description_block(\@directories,'status');
    print $a;
    $a=&make_file_type_ownership_and_permissions_description_block('status');
    print $a;
    $a=&make_directory_and_file_structure_description_block(\@directories,'status');
    print $a;
    $a=&end_description_page('status');
    print $a;
}
elsif ($mode eq "update") {
}
elsif ($mode eq "configinstall") {
    @directories=&determine_directory_structure;
    $a=&make_files_configinstall_segment(\@directories);
    print $a;
    $a=&make_files_configpermissions_segment(\@directories);
    print $a;
}
elsif ($mode eq "install") {
    @directories=&determine_directory_structure;
    $a=&make_directory_install_segment(\@directories);
    print $a;
    $a=&make_files_install_segment(\@directories);
    print $a;
    $a=&make_links_install_segment(\@directories);
    print $a;
}
elsif ($mode eq "build") {
    @directories=&determine_directory_structure;
    $a=&make_files_build_segment(\@directories);
    print $a;
}

# ------------------------------------------------------ a list of file targets
sub make_file_list {
    my ($dirs)=@_;
    my $description;
    my @allfiles=keys %{$info{'LOCATION'}{$distribution}};
    foreach my $d (@$dirs) {
	# set other values
	$description.=<<END;
BinaryRoot/$d
END
	my $dirdescription=$info{'DIRECTORY'}{$distribution}{$d}{'DESCRIPTION'};
	$dirdescription="(" . $dirdescription . ")" if $dirdescription;
	# find files that are contained in this directory
	my @files;
	my @filesfull;
	foreach my $f (@allfiles) {
	    if ($f=~/^$d\/([^\/]+)$/) {
		push @files,$1;
		push @filesfull,$f;
	    }
	}
	# render starting HTML formatting elements
	if (@files) {
        }
	my $pwd=`pwd`; chop $pwd;
	if (@files) {
            foreach my $i (0..$#files) {
		my $category=$info{'LOCATION'}{$distribution}{$filesfull[$i]}{'CATEGORY'};
		my $chown=$info{'OWNERSHIP'}{$category}{'CHOWN'};
		my $chmod=$info{'OWNERSHIP'}{$category}{'CHMOD'};
		my $devchown=$info{'DEVOWNERSHIP'}{$category}{'CHOWN'};
		my $devchmod=$info{'DEVOWNERSHIP'}{$category}{'CHMOD'};
		my $source=$info{'LOCATION'}{$distribution}{$filesfull[$i]}{'SOURCE'};
		my $rot="/".$filesfull[$i];
		if ($rot=~/\*/) {
		    $rot=~s/[^\/]+$// if $rot=~/\*/;
		    my $listing=$info{'LOCATION'}{$distribution}{$filesfull[$i]}{'FILES'};
		    chop $listing;
		    my @list=split(/\s+/,$listing);
		    my $rot2;
		    foreach my $l (@list) {
			$l=~s/^\s*//; $l=~s/\s*$//;
			$rot2.="BinaryRoot$rot$l\n" if length($l);
		    }
		    chop $rot2;
		    $rot=$rot2;
		}
		else {
		    $rot="BinaryRoot$rot";
		}
		if ($category eq "conf") {
		    $rot.=" # config";
		}
		$description.=<<END;
$rot
END
	    }
	}
    }
    $description.=<<END;

END
    return $description;
}

# --------------------------------- Commands to make BinaryRoot directories
sub make_directory_binaryroot_segment {
    my ($dirs)=@_;
    my $description=<<END;
directories:
END
    foreach my $d (@$dirs) {
	my $category=$info{'DIRECTORY'}{$distribution}{$d}{'CATEGORY'};
	my $chown=$info{'OWNERSHIP'}{$category}{'CHOWN'};
	my $chmod=$info{'OWNERSHIP'}{$category}{'CHMOD'};
	my $devchown=$info{'DEVOWNERSHIP'}{$category}{'CHOWN'};
	my $devchmod=$info{'DEVOWNERSHIP'}{$category}{'CHMOD'};
	my ($owner,$group)=split(/\:/,$devchown);
	my $own=$devchown; $own=~s/\:/\,/;
	$description.=<<END;
\tinstall -o $owner -g $group -m $devchmod -d \$(TARGET)/$d
END
    }
    $description.=<<END;

END
    return $description;
}

# --------------------------------------- Commands to make BinaryRoot files
sub make_files_binaryroot_segment {
    my ($dirs)=@_;
    my $description=<<END;
files:
END
    my @allfiles=keys %{$info{'LOCATION'}{$distribution}};
    foreach my $d (@$dirs) {
	# set other values
	my $dirdescription=$info{'DIRECTORY'}{$distribution}{$d}{'DESCRIPTION'};
	$dirdescription="(" . $dirdescription . ")" if $dirdescription;
	# find files that are contained in this directory
	my @files;
	my @filesfull;
	foreach my $f (@allfiles) {
	    if ($f=~/^$d\/([^\/]+)$/) {
		push @files,$1;
		push @filesfull,$f;
	    }
	}
	# render starting HTML formatting elements
	if (@files) {
	    $description.=<<END;
\t# $d $dirdescription
END
        }
	if (@files) {
            foreach my $i (0..$#files) {
		my $category=$info{'LOCATION'}{$distribution}{$filesfull[$i]}{'CATEGORY'};
		my $chown=$info{'OWNERSHIP'}{$category}{'CHOWN'};
		my $chmod=$info{'OWNERSHIP'}{$category}{'CHMOD'};
		my $devchown=$info{'DEVOWNERSHIP'}{$category}{'CHOWN'};
		my $devchmod=$info{'DEVOWNERSHIP'}{$category}{'CHMOD'};
		my $source=$info{'LOCATION'}{$distribution}{$filesfull[$i]}{'SOURCE'};
		my $rot=$filesfull[$i];
		$rot=~s/[^\/]+$/\./ if $rot=~/\*/;
		my ($owner,$group)=split(/\:/,$devchown);
		$description.=<<END if $category ne 'symbolic link';
\tinstall -o $owner -g $group -m $devchmod \$(SOURCE)/$source \$(TARGET)/$rot
END
	    }
	}
    }
    $description.=<<END;

END
    return $description;
}

# ------------------------------ Commands to make BinaryRoot symbolic links
sub make_links_binaryroot_segment {
    my ($dirs)=@_;
    my $description=<<END;
links:
END
    my @allfiles=keys %{$info{'LOCATION'}{$distribution}};
    foreach my $d (@$dirs) {
	# find files that are contained in this directory
	my @files;
	my @filesfull;
	foreach my $f (@allfiles) {
	    if ($f=~/^$d\/([^\/]+)$/) {
		push @files,$1;
		push @filesfull,$f;
	    }
	}
	# render starting HTML formatting elements
	if (@files) {
            foreach my $i (0..$#files) {
		my $category=$info{'LOCATION'}{$distribution}{$filesfull[$i]}{'CATEGORY'};
		my $linkto=$info{'LOCATION'}{$distribution}{$filesfull[$i]}{'LINKTO'};
		my $chown=$info{'OWNERSHIP'}{$category}{'CHOWN'};
		my $chmod=$info{'OWNERSHIP'}{$category}{'CHMOD'};
		my $devchown=$info{'DEVOWNERSHIP'}{$category}{'CHOWN'};
		my $devchmod=$info{'DEVOWNERSHIP'}{$category}{'CHMOD'};
		$description.=<<END if $category eq 'symbolic link';
\tln -s /$linkto \$(TARGET)/$filesfull[$i]
END
	    }
	}
    }
    $description.=<<END;

END
    return $description;
}

# ------ Installation commands for a Makefile used only by a rpm -ba invocation
sub make_directory_LCMakefile_segment {
    my ($dirs)=@_;
    my $description=<<END;
directories:
END
    foreach my $d (@$dirs) {
	my $category=$info{'DIRECTORY'}{$distribution}{$d}{'CATEGORY'};
	my $chown=$info{'OWNERSHIP'}{$category}{'CHOWN'};
	my $chmod=$info{'OWNERSHIP'}{$category}{'CHMOD'};
	my $devchown=$info{'DEVOWNERSHIP'}{$category}{'CHOWN'};
	my $devchmod=$info{'DEVOWNERSHIP'}{$category}{'CHMOD'};
	my $own=$devchown; $own=~s/\:/\,/;
	$description.=<<END;
\tinstall -m $devchmod -d \$(SOURCE)/$d \$(ROOT)/$d
END
    }
    $description.=<<END;

END
    return $description;
}

# ------ Installation commands for a Makefile used only by a rpm -ba invocation
sub make_files_LCMakefile_segment {
    my ($dirs)=@_;
    my $description=<<END;
files:
END
    my @allfiles=keys %{$info{'LOCATION'}{$distribution}};
    foreach my $d (@$dirs) {
	# set other values
	my $dirdescription=$info{'DIRECTORY'}{$distribution}{$d}{'DESCRIPTION'};
	$dirdescription="(" . $dirdescription . ")" if $dirdescription;
	# find files that are contained in this directory
	my @files;
	my @filesfull;
	foreach my $f (@allfiles) {
	    if ($f=~/^$d\/([^\/]+)$/) {
		push @files,$1;
		push @filesfull,$f;
	    }
	}
	# render starting HTML formatting elements
	if (@files) {
	    $description.=<<END;
\t# $d $dirdescription
END
        }
	if (@files) {
            foreach my $i (0..$#files) {
		my $category=$info{'LOCATION'}{$distribution}{$filesfull[$i]}{'CATEGORY'};
		my $chown=$info{'OWNERSHIP'}{$category}{'CHOWN'};
		my $chmod=$info{'OWNERSHIP'}{$category}{'CHMOD'};
		my $devchown=$info{'DEVOWNERSHIP'}{$category}{'CHOWN'};
		my $devchmod=$info{'DEVOWNERSHIP'}{$category}{'CHMOD'};
		my $rot=$filesfull[$i];
		$rot=~s/[^\/]+$/\./ if $rot=~/\*/;
		$description.=<<END if $category ne 'symbolic link';
\tinstall -m $devchmod \$(SOURCE)/$filesfull[$i] \$(ROOT)/$rot
END
	    }
	}
    }
    $description.=<<END;

END
    return $description;
}

# ------ Installation commands for a Makefile used only by a rpm -ba invocation
sub make_links_LCMakefile_segment {
    my ($dirs)=@_;
    my $description=<<END;
links:
END
    my @allfiles=keys %{$info{'LOCATION'}{$distribution}};
    foreach my $d (@$dirs) {
	# find files that are contained in this directory
	my @files;
	my @filesfull;
	foreach my $f (@allfiles) {
	    if ($f=~/^$d\/([^\/]+)$/) {
		push @files,$1;
		push @filesfull,$f;
	    }
	}
	# render starting HTML formatting elements
	if (@files) {
            foreach my $i (0..$#files) {
		my $category=$info{'LOCATION'}{$distribution}{$filesfull[$i]}{'CATEGORY'};
		my $linkto=$info{'LOCATION'}{$distribution}{$filesfull[$i]}{'LINKTO'};
		my $chown=$info{'OWNERSHIP'}{$category}{'CHOWN'};
		my $chmod=$info{'OWNERSHIP'}{$category}{'CHMOD'};
		my $devchown=$info{'DEVOWNERSHIP'}{$category}{'CHOWN'};
		my $devchmod=$info{'DEVOWNERSHIP'}{$category}{'CHMOD'};
		$description.=<<END if $category eq 'symbolic link';
\tln -s /$linkto \$(ROOT)/$filesfull[$i]
END
	    }
	}
    }
    $description.=<<END;

END
    return $description;
}

# --------------------------------- Installation commands to install directories
sub make_directory_install_segment {
    my ($dirs)=@_;
    my $description=<<END;
directories:
END
    foreach my $d (@$dirs) {
	my $category=$info{'DIRECTORY'}{$distribution}{$d}{'CATEGORY'};
	my $source=$info{'LOCATION'}{$distribution}{$filesfull[$i]}{'SOURCE'};
	my $chown=$info{'OWNERSHIP'}{$category}{'CHOWN'};
	my $chmod=$info{'OWNERSHIP'}{$category}{'CHMOD'};
	my $devchown=$info{'DEVOWNERSHIP'}{$category}{'CHOWN'};
	my $devchmod=$info{'DEVOWNERSHIP'}{$category}{'CHMOD'};
	my ($owner,$group)=split(/\:/,$devchown);
	my $own=$devchown; $own=~s/\:/\,/;
	$description.=<<END;
\tinstall -o $owner -g $group -m $devchmod -d \$(TARGET)/$d
END
    }
    $description.=<<END;

END
    return $description;
}

# ------------------------------------------------------ Commands to build files
sub make_files_build_segment {
    my ($dirs)=@_;
    my $description;
    my @allfiles=keys %{$info{'LOCATION'}{$distribution}};
    my $tab="\t";
    my $sources="# Dynamic Makefile generated by LON-CAPA build process\n\n";
    $sources.="SHELL=\"/bin/sh\"\n\n";
    $sources.="\nall: ";
    foreach my $d (@$dirs) {
	# set other values
	my $dirdescription=$info{'DIRECTORY'}{$distribution}{$d}{'DESCRIPTION'};
	$dirdescription="(" . $dirdescription . ")" if $dirdescription;
	# find files that are contained in this directory
	my @files;
	my @filesfull;
	foreach my $f (@allfiles) {
	    if ($f=~/^$d\/([^\/]+)$/) {
		push @files,$1;
		push @filesfull,$f;
	    }
	}
	if (@files) {
            foreach my $i (0..$#files) {
		# if has build information, output appropriate something
		my $build=$info{'LOCATION'}{$distribution}{$filesfull[$i]}{'BUILD'};
		my $source=$info{'LOCATION'}{$distribution}{$filesfull[$i]}{'SOURCE'};
		$build=~s/^\s+//; $build=~s/\s+$//;
		if ($build) {
		    my $dependencies=$info{'LOCATION'}{$distribution}{$filesfull[$i]}{'DEPENDENCIES'};
		    my $source2=$source;
#		    $source2=~s/^[^\/]+\///;
 		    $source2="../../" . $source2;
		    $sources.="$source2 ";
		    my $directory=$build;
#		    $directory=~s/^[^\/]+\///;
		    $directory=~s/([^\/]+)$//;
 		    $directory="../../" . $directory;
		    my $buildfile=$1;
		    my $sdir=$source;
#		    $sdir=~s/^[^\/]+\///;
		    $sdir=~s/([^\/]+)$//;
 		    $sdir="../../" . $sdir;
		    $dependencies=~s/\s+$//;
		    my $depstat="";
		    if ($dependencies=~s/\s+\[ALWAYS_RUN_BUILD_COMMAND\]//) {
			$depstat=" alwaysrun";
		    }
		    $dependencies=~s/\s+/ $sdir/gs;
		    my @deps=split(/\s+/,$dependencies);
		    shift @deps;
		    my $testing=<<END;
	\@if !(echo "");\\
	        then echo "**** LON-CAPA WARNING **** Strange shell. Check your path settings.";\\
END
		    foreach my $d (@deps) {
			$testing.=<<END;
	elif !(test -r $d);\\
		then echo "**** LON-CAPA WARNING **** missing the file: $d";\\
END
		    }
		    chop $testing;
		    $description.=<<END;
$source2: $depstat
$testing
        else \\
	    ${tab}cd $directory; sh ./$buildfile;\\
        fi

END
		}
		my $category=$info{'LOCATION'}{$distribution}{$filesfull[$i]}{'CATEGORY'};
		my $source=$info{'LOCATION'}{$distribution}{$filesfull[$i]}{'SOURCE'};
		my $chown=$info{'OWNERSHIP'}{$category}{'CHOWN'};
		my $chmod=$info{'OWNERSHIP'}{$category}{'CHMOD'};
		my $devchown=$info{'DEVOWNERSHIP'}{$category}{'CHOWN'};
		my $devchmod=$info{'DEVOWNERSHIP'}{$category}{'CHMOD'};
		my $rot=$filesfull[$i];
		$rot=~s/[^\/]+$/\./ if $rot=~/\*/;
#		$description.=<<END if $category ne 'symbolic link';
#\tinstall -o $owner -g $group -m $devchmod \$(SOURCE)/$source \$(TARGET)/$rot
#END
	    }
	}
    }
    $description.=<<END;
alwaysrun:

END
    $sources.="\n\n";
    return ($sources . $description);
}

# --------------------------------------- Installation commands to install files
sub make_files_install_segment {
    my ($dirs)=@_;
    my $description=<<END;
files:
END
    my @allfiles=keys %{$info{'LOCATION'}{$distribution}};
    foreach my $d (@$dirs) {
	# set other values
	my $dirdescription=$info{'DIRECTORY'}{$distribution}{$d}{'DESCRIPTION'};
	$dirdescription="(" . $dirdescription . ")" if $dirdescription;
	# find files that are contained in this directory
	my @files;
	my @filesfull;
	foreach my $f (@allfiles) {
	    if ($f=~/^$d\/([^\/]+)$/) {
		push @files,$1;
		push @filesfull,$f;
	    }
	}
	# render starting HTML formatting elements
	if (@files) {
	    $description.=<<END;
\t# $d $dirdescription
END
        }
	if (@files) {
            foreach my $i (0..$#files) {
		my $category=$info{'LOCATION'}{$distribution}{$filesfull[$i]}{'CATEGORY'};
		my $source=$info{'LOCATION'}{$distribution}{$filesfull[$i]}{'SOURCE'};
		my $chown=$info{'OWNERSHIP'}{$category}{'CHOWN'};
		my $chmod=$info{'OWNERSHIP'}{$category}{'CHMOD'};
		my $devchown=$info{'DEVOWNERSHIP'}{$category}{'CHOWN'};
		my $devchmod=$info{'DEVOWNERSHIP'}{$category}{'CHMOD'};
		my $rot=$filesfull[$i];
		$rot=~s/[^\/]+$/\./ if $rot=~/\*/;
		my ($owner,$group)=split(/\:/,$devchown);
		if ($category ne 'conf' && $category ne 'symbolic link') {
		    if ($source!~/\*/) {
			$description.=<<END;
\t\@test -e \$(SOURCE)/$source \&\& install -o $owner -g $group -m $devchmod \$(SOURCE)/$source \$(TARGET)/$rot || echo "**** LON-CAPA WARNING **** CVS source file does not exist: \$(SOURCE)/$source"
END
                    }
		    else {
			$description.=<<END;
\tinstall -o $owner -g $group -m $devchmod \$(SOURCE)/$source \$(TARGET)/$rot
END
		    }
                }
	    }
	}
    }
    $description.=<<END;

END
    return $description;
}

# ------ Installation commands to install configuration files (and make backups)
sub make_files_configinstall_segment {
    my ($dirs)=@_;
    my $description=<<END;
configfiles:
END
    my @allfiles=keys %{$info{'LOCATION'}{$distribution}};
    foreach my $d (@$dirs) {
	# set other values
	my $dirdescription=$info{'DIRECTORY'}{$distribution}{$d}{'DESCRIPTION'};
	$dirdescription="(" . $dirdescription . ")" if $dirdescription;
	# find files that are contained in this directory
	my @files;
	my @filesfull;
	foreach my $f (@allfiles) {
	    if ($f=~/^$d\/([^\/]+)$/) {
		push @files,$1;
		push @filesfull,$f;
	    }
	}
	# render starting HTML formatting elements
	if (@files) {
	    $description.=<<END;
\t# $d $dirdescription
END
        }
	if (@files) {
            foreach my $i (0..$#files) {
		my $category=$info{'LOCATION'}{$distribution}{$filesfull[$i]}{'CATEGORY'};
		my $source=$info{'LOCATION'}{$distribution}{$filesfull[$i]}{'SOURCE'};
		my $chown=$info{'OWNERSHIP'}{$category}{'CHOWN'};
		my $chmod=$info{'OWNERSHIP'}{$category}{'CHMOD'};
		my $devchown=$info{'DEVOWNERSHIP'}{$category}{'CHOWN'};
		my $devchmod=$info{'DEVOWNERSHIP'}{$category}{'CHMOD'};
		my $rot=$filesfull[$i];
		$rot=~s/[^\/]+$/\./ if $rot=~/\*/;
		my ($owner,$group)=split(/\:/,$devchown);
		if ($category eq 'conf') {
		    $description.=<<END;
\tcp -p \$(TARGET)/$rot \$(TARGET)/$rot`date +'.\%Y\%m\%d\%H\%M\%S'` 2>/dev/null; install -o $owner -g $group -m $devchmod \$(SOURCE)/$source \$(TARGET)/$rot
END
                }
	    }
	}
    }
    $description.=<<END;

END
    return $description;
}

# ------ Commands to enforce configuration file permissions
sub make_files_configpermissions_segment {
    my ($dirs)=@_;
    my $description=<<END;
configpermissions:
END
    my @allfiles=keys %{$info{'LOCATION'}{$distribution}};
    foreach my $d (@$dirs) {
	# set other values
	my $dirdescription=$info{'DIRECTORY'}{$distribution}{$d}{'DESCRIPTION'};
	$dirdescription="(" . $dirdescription . ")" if $dirdescription;
	# find files that are contained in this directory
	my @files;
	my @filesfull;
	foreach my $f (@allfiles) {
	    if ($f=~/^$d\/([^\/]+)$/) {
		push @files,$1;
		push @filesfull,$f;
	    }
	}
	# render starting HTML formatting elements
	if (@files) {
	    $description.=<<END;
\t# $d $dirdescription
END
        }
	if (@files) {
            foreach my $i (0..$#files) {
		my $category=$info{'LOCATION'}{$distribution}{$filesfull[$i]}{'CATEGORY'};
		my $source=$info{'LOCATION'}{$distribution}{$filesfull[$i]}{'SOURCE'};
		my $chown=$info{'OWNERSHIP'}{$category}{'CHOWN'};
		my $chmod=$info{'OWNERSHIP'}{$category}{'CHMOD'};
		my $devchown=$info{'DEVOWNERSHIP'}{$category}{'CHOWN'};
		my $devchmod=$info{'DEVOWNERSHIP'}{$category}{'CHMOD'};
		my $rot=$filesfull[$i];
		$rot=~s/[^\/]+$/\./ if $rot=~/\*/;
		my ($owner,$group)=split(/\:/,$devchown);
		if ($category eq 'conf') {
		    $description.=<<END;
\tchmod $devchmod \$(TARGET)/$rot
\tchown $devchown \$(TARGET)/$rot
END
                }
	    }
	}
    }
    $description.=<<END;

END
    return $description;
}

# ------------------------------ Installation commands to install symbolic links
sub make_links_install_segment {
    my ($dirs)=@_;
    my $description=<<END;
links:
END
    chop $description;
    my $description2;
    my @allfiles=keys %{$info{'LOCATION'}{$distribution}};
    foreach my $d (@$dirs) {
	# find files that are contained in this directory
	my @files;
	my @filesfull;
	foreach my $f (@allfiles) {
	    if ($f=~/^$d\/([^\/]+)$/) {
		push @files,$1;
		push @filesfull,$f;
	    }
	}
	# render starting HTML formatting elements
	if (@files) {
            foreach my $i (0..$#files) {
		my $category=$info{'LOCATION'}{$distribution}{$filesfull[$i]}{'CATEGORY'};
		my $linkto=$info{'LOCATION'}{$distribution}{$filesfull[$i]}{'LINKTO'};
		my $chown=$info{'OWNERSHIP'}{$category}{'CHOWN'};
		my $chmod=$info{'OWNERSHIP'}{$category}{'CHMOD'};
		my $devchown=$info{'DEVOWNERSHIP'}{$category}{'CHOWN'};
		my $devchmod=$info{'DEVOWNERSHIP'}{$category}{'CHMOD'};
		if ($category eq 'symbolic link') {
		    $description.=" \$(TARGET)/$filesfull[$i]";
		    $description2.=<<END;
\$(TARGET)/$filesfull[$i]:
\tln -s /$linkto \$(TARGET)/$filesfull[$i]

END
                }
	    }
	}
    }
    $description.=<<END;

END
    $description.=$description2;
    return $description;
}

# --------------------------------------------------------- Make RPM .spec block
sub make_rpm_spec_block {
    my $pwd=`pwd`; chop $pwd;
    my $buildroot="$pwd/LON-CAPA-BuildRoot";
    my $source=$info{'RPM'}{'Name'} . "-" . $info{'RPM'}{'Version'} . '.tar.gz';
    my $description=<<END;
Summary: $info{'RPM'}{'Summary'}
Name: $info{'RPM'}{'Name'}
Version: $info{'RPM'}{'Version'}
Release: $info{'RPM'}{'Release'}
Vendor: $info{'RPM'}{'Vendor'} 
BuildRoot: $buildroot
Copyright: $info{'RPM'}{'Copyright'}
Group: $info{'RPM'}{'Group'}
Source: $source
AutoReqProv: $info{'RPM'}{'AutoReqProv'}
\%description
$info{'RPM'}{'description'}

END
    return $description;
}

# --------------------------------------------------- Make RPM build .spec block
sub make_rpm_build_block {
    my $pwd=`pwd`; chop $pwd;
    my $buildroot="$pwd/LON-CAPA-BuildRoot";
    my $sourceroot="$pwd/LON-CAPA-SourceRoot";
    my $description=<<END;

\%prep
\%setup

\%build
rm -Rf "$buildroot"

\%install
make -f LCMakefile ROOT="\$RPM_BUILD_ROOT" SOURCE="$sourceroot" directories
make -f LCMakefile ROOT="\$RPM_BUILD_ROOT" SOURCE="$sourceroot" files
make -f LCMakefile ROOT="\$RPM_BUILD_ROOT" SOURCE="$sourceroot" links

\%pre
$info{'RPM'}{'pre'}

\%post
\%postun

\%files
# \%doc README COPYING ChangeLog LICENSE
END
    return $description;
}

# ------------------------------------- Make directory structure RPM .spec block
sub make_directory_structure_spec_block {
    my ($dirs)=@_;
    foreach my $d (@$dirs) {
	my $category=$info{'DIRECTORY'}{$distribution}{$d}{'CATEGORY'};
	my $chown=$info{'OWNERSHIP'}{$category}{'CHOWN'};
	my $chmod=$info{'OWNERSHIP'}{$category}{'CHMOD'};
	my $devchown=$info{'DEVOWNERSHIP'}{$category}{'CHOWN'};
	my $devchmod=$info{'DEVOWNERSHIP'}{$category}{'CHMOD'};
	my $own=$devchown; $own=~s/\:/\,/;
	$description.=<<END;
\%dir \%attr($devchmod,$own) /$d
END
    }
    return $description;
}

# ---------------------------- Make directory and file structure RPM .spec block
sub make_directory_and_file_structure_spec_block {
    my ($dirs)=@_;
    my @allfiles=keys %{$info{'LOCATION'}{$distribution}};
    foreach my $d (@$dirs) {
	# set other values
	my $dirdescription=$info{'DIRECTORY'}{$distribution}{$d}{'DESCRIPTION'};
	$dirdescription="(" . $dirdescription . ")" if $dirdescription;
	# find files that are contained in this directory
	my @files;
	my @filesfull;
	foreach my $f (@allfiles) {
	    if ($f=~/^$d\/([^\/]+)$/) {
		push @files,$1;
		push @filesfull,$f;
	    }
	}
	# render starting HTML formatting elements
	if (@files) {
	    $description.=<<END;
# $d $dirdescription
END
        }
	if (@files) {
            foreach my $i (0..$#files) {
		my $category=$info{'LOCATION'}{$distribution}{$filesfull[$i]}{'CATEGORY'};
		my $chown=$info{'OWNERSHIP'}{$category}{'CHOWN'};
		my $chmod=$info{'OWNERSHIP'}{$category}{'CHMOD'};
		my $devchown=$info{'DEVOWNERSHIP'}{$category}{'CHOWN'};
		my $devchmod=$info{'DEVOWNERSHIP'}{$category}{'CHMOD'};
		my $own=$devchown; $own=~s/\:/\,/;
		my $config="";
		$config="\%config " if $category eq 'conf';
		$devchmod='-' if $category eq 'symbolic link';
		$description.=<<END;
$config\%attr($devchmod,$own) /$filesfull[$i]
END
	    }
	}
    }
    return $description;
}

# ----------------------------------------------------------- End RPM .spec page
sub end_spec_page {
}

# ------------------------------------------------------- Begin description page
sub begin_description_page {
    my ($mode)=@_;
    my $description;
    unless ($mode eq 'status') {
    $description=<<END;
<HTML>
<HEAD>
<TITLE>LON-CAPA Software Description Page ($distribution, $date)</TITLE>
</HEAD>
<BODY>
<FONT SIZE=+2>LON-CAPA Software Description Page ($distribution, $date)</FONT>
<BR>Michigan State University
<BR>Learning Online with CAPA
<BR>Contact korte\@lon-capa.org
<UL>
<LI>About this file
<LI>Software Package Description
<LI>Directory Structure
<LI>File Type Ownership and Permissions
<LI>File and Directory Structure
</UL>
<FONT SIZE=+2>About this file</FONT>
<P>
This file is generated dynamically by <TT>parse.pl</TT> as
part of a development compilation process.  See 
http://install.lon-capa.org/compile/index.html for more
information.
</P>
END
}
    else {
	$description=<<END;
<HTML>
<HEAD>
<TITLE>LON-CAPA Software File System Status Page ($distribution, $date)</TITLE>
</HEAD>
<BODY>
<FONT SIZE=+2>LON-CAPA Software File System Status Page ($distribution, $date)</FONT>
<BR>Michigan State University
<BR>Learning Online with CAPA
<BR>Contact korte\@lon-capa.org
<UL>
<LI>About this file
<LI>Software Package Description
<LI>Directory Structure
<LI>File Type Ownership and Permissions
<LI>File and Directory Structure
</UL>
<FONT SIZE=+2>About this file</FONT>
<P>
This file is generated dynamically by <TT>parse.pl</TT> as
part of a status checking process.  See http://install.lon-capa.org/
for more information.
</P>
END
    }
    return $description;

}

# ------------------------------------------------- End description page
sub end_description_page {
    my $description=<<END;
<HR>
<FONT SIZE=-1>LON-CAPA Software Development Team</FONT>
</BODY>
</HTML>
END
    return $description;
}

# ------------------------------------------------- Make RPM description block
sub make_rpm_description_block {
    my ($mode)=@_;
    my $description;
    unless ($mode eq 'status') {
    $description=<<END;
<FONT SIZE=+2>Rolled in a RedHat 6.2 RPM, $date</FONT>
<P>
<TABLE BGCOLOR=#FFFFFF BORDER=0 CELLPADDING=10 CELLSPACING=0>
<TR><TD>
<PRE>
Name        : $info{'RPM'}{'Name'}
Version     : $info{'RPM'}{'Version'}
Vendor      : $info{'RPM'}{'Vendor'} 
Release     : $info{'RPM'}{'Release'}                             
Build Host  : $buildhost
Group       : $info{'RPM'}{'Group'}
License     : $info{'RPM'}{'Copyright'}
Summary     : $info{'RPM'}{'Summary'}
Description : 
$info{'RPM'}{'description'}
</PRE>
</TD></TR>
</TABLE>
</P>
END
}
    else {
	my $exist=`rpm -q LON-CAPA-base 2>/dev/null`;
	unless ($exist) {
	    $description=<<END;
<FONT SIZE=+2>No LON-CAPA RPM on the system, (installed ??????)</FONT>
<P>
<TABLE BGCOLOR=#FFFFFF BORDER=0 CELLPADDING=10 CELLSPACING=0>
<TR><TD>
<FONT SIZE=+3>Error! A LON-CAPA-base RPM
was never installed on this system!</FONT>
</TD></TR>
</TD></TR>
</TABLE>
</P>
END
	}
	else {
	    chop $exist;
	    my $rpmname=`rpm -q --queryformat '%{NAME}' LON-CAPA-base`;
	    my $rpmversion=`rpm -q --queryformat '%{VERSION}' LON-CAPA-base`;
	    my $rpmrelease=`rpm -q --queryformat '%{RELEASE}' LON-CAPA-base`;
	    my $idate=`rpm -q --queryformat '%{INSTALLTIME:date}' LON-CAPA-base`;
	    my $rpmvendor=`rpm -q --queryformat '%{VENDOR}' LON-CAPA-base`;
	    my $rpmbuildhost=`rpm -q --queryformat '%{BUILDHOST}' LON-CAPA-base`;
	    my $rpmgroup=`rpm -q --queryformat '%{GROUP}' LON-CAPA-base`;
	    my $rpmlicense=`rpm -q --queryformat '%{LICENSE}' LON-CAPA-base`;
	    my $rpmsummary=`rpm -q --queryformat '%{SUMMARY}' LON-CAPA-base`;
	    my $rpmdescription=`rpm -q --queryformat '%{DESCRIPTION}' LON-CAPA-base`;
	    $description=<<END;
<FONT SIZE=+2>Current RedHat RPM on the system, (installed $idate)</FONT>
<P>
<TABLE BGCOLOR=#FFFFFF BORDER=0 CELLPADDING=10 CELLSPACING=0>
<TR><TD>
<PRE>
Name        : $rpmname
Version     : $rpmversion
Vendor      : $rpmvendor
Release     : $rpmrelease
Build Host  : $rpmbuildhost
Group       : $rpmgroup
License     : $rpmlicense
Summary     : $rpmsummary
Description : 
$rpmdescription
</PRE>
</TD></TR>
</TABLE>
</P>
END
}
    }
    return $description;
}

# ----------------------------------------------- Determine directory structure
sub determine_directory_structure {
    my @directories=keys %{$info{'DIRECTORY'}{$distribution}};
    return (sort @directories);
}


# ---------------------------------- Make directory structure description block
sub make_directory_structure_description_block {
    my ($dirs,$mode)=@_;
    my $dirstatus; my $statusheader;
    my $description=<<END;
<FONT SIZE=+2>Directory Structure Description, $date</FONT>
<P>
The directory structure description below shows only those
directories which either contain LON-CAPA specific files
or normally do not exist on a RedHat Linux system (and
must be generated to allow proper placement of files
during LON-CAPA run-time operation).
</P>
<P>
<TABLE BORDER=1 CELLPADDING=3 CELLSPACING=0>
END
    my $maxcount=0;
    my @allfiles=keys %{$info{'LOCATION'}{$distribution}};
    my %diraccount; # hash to track which directories are accounted for
    foreach my $file (@allfiles) {
	$file=~/^(.*)\/([^\/]+)$/;
	$diraccount{$1}=1;
    }
    foreach my $d (@$dirs) {
        my (@matches)=($d=~/\//g);
	my $count=scalar(@matches);
	$maxcount=$count if $count>$maxcount;
	delete $diraccount{$d};
    }
    if ($mode eq 'status') {
	$statusheader="<TH ALIGN=LEFT BGCOLOR=#FFFFFF>Current Status</TH>";
    }
    $description.=<<END;
<TR>
$statusheader
<TH ALIGN=LEFT BGCOLOR=#FFFFFF>Category</TH>
<TH ALIGN=LEFT BGCOLOR=#FFFFFF>Permissions</TH>
<TH ALIGN=LEFT BGCOLOR=#FFFFFF><FONT COLOR=#FF0000>Development<BR>Permissions</FONT></TH>
END
    $description.="<TH ALIGN=LEFT BGCOLOR=#FFFFFF COLSPAN=".($maxcount+1).">Directory Path</TH>\n";
    if (keys %diraccount) {
	$description.= "<TR><TD ALIGN=LEFT BGCOLOR=#FFFFFF COLSPAN=".($maxcount+4)."><I><PRE>Directories that are unaccounted for: \n";
	foreach my $d (keys %diraccount) {
	    $description.="$d\n";
	}
	$description.="</PRE></I></TH></TR>\n";
    }
    foreach my $d (@$dirs) {
	my $dtable=$d;
	$dtable=~s/\//\<\/TD\>\<TD\>/g;
	my $category=$info{'DIRECTORY'}{$distribution}{$d}{'CATEGORY'};
	my $chown=$info{'OWNERSHIP'}{$category}{'CHOWN'};
	my $chmod=$info{'OWNERSHIP'}{$category}{'CHMOD'};
	my $devchown=$info{'DEVOWNERSHIP'}{$category}{'CHOWN'};
	my $devchmod=$info{'DEVOWNERSHIP'}{$category}{'CHMOD'};
	if ($mode eq 'status') {
	    my $ds=`find /$d -type d -prune -printf "\%m\t\%u\t\%g" 2>/dev/null`;
	    unless ($ds) {
		$dirstatus='<TD BGCOLOR=#FFFFFF><B><U>MISSING</U></B></TD>';
	    }
	    else {
		my @dss=split(/\t/,$ds);
		my $dssz=$dss[0];
		$dssz="0" . $dss[0] if length($dss[0])<4;
		$dss[0]=$dssz;
		$ds="$dss[0] $dss[1]:$dss[2]";
		if ($ds eq "$chmod $chown" && $ds eq "$devchmod $devchown") {
		    $dirstatus='<TD BGCOLOR=#FFFFFF>runtime+development</TD>';
		}
		elsif ($ds eq "$chmod $chown") {
		    $dirstatus='<TD BGCOLOR=#FFFFFF>runtime</TD>';
		}
		elsif ($ds eq "$devchmod $devchown") {
		    $dirstatus='<TD BGCOLOR=#FFFFFF>development</TD>';
		}
		else {
		    $dirstatus="<TD BGCOLOR=#FFFFFF><B><U>ERROR</U></B><BR>$ds</TD>";
		}
	    }
	}
	$description.=<<END;
<TR>
$dirstatus
<TD BGCOLOR=#FFFFFF>$category</TD>
<TD BGCOLOR=#FFFFFF><TT>$chmod $chown</TT></TD>
<TD BGCOLOR=#FFFFFF><FONT COLOR=#FF0000><TT>$devchmod $devchown</TT></FONT></TD>
<TD>
$dtable
</TD>
</TR>
END
    }
    $description.=<<END;
</TABLE>
</P>
END
    return $description;
}

# ------------------- Make file type ownership and permissions description block
sub make_file_type_ownership_and_permissions_description_block {
    my ($mode)=@_;
    my $description=<<END;
<FONT SIZE=+2>File Type Ownership and Permissions Descriptions, $date</FONT>
<P>
This table shows what permissions and ownership settings correspond
to each kind of file type.
</P>
<P>
<TABLE BORDER=1 CELLPADDING=5 WIDTH=60%>
<TR>
<TH ALIGN=LEFT BGCOLOR=#FFFFFF>Icon</TH>
<TH ALIGN=LEFT BGCOLOR=#FFFFFF>Type</TH>
<TH ALIGN=LEFT BGCOLOR=#FFFFFF>Permissions</TH>
<TH ALIGN=LEFT BGCOLOR=#FFFFFF>Development Permissions</TH>
</TR>
END
    foreach my $type (keys %{$info{'OWNERSHIP'}}) {
	if (defined($fcm{$type})) {
	    my $chmod=$info{'OWNERSHIP'}{$type}{'CHMOD'};
	    my $chown=$info{'OWNERSHIP'}{$type}{'CHOWN'};
	    my $devchmod=$info{'DEVOWNERSHIP'}{$type}{'CHMOD'};
	    my $devchown=$info{'DEVOWNERSHIP'}{$type}{'CHOWN'};
	    $description.=<<END;
<TR>
<TD><IMG SRC="$fcm{$type}.gif" ALT="$type"></TD>
<TD>$type</TD>
<TD><TT>$chmod $chown</TT></TD>
<TD><TT>$devchmod $devchown</TT></TD>
</TR>
END
        }
    }
    $description.=<<END;
</TABLE>
</P>
END
}

# ------------------------- Make directory and file structure description block
sub make_directory_and_file_structure_description_block {
    my ($dirs,$mode)=@_;
    my $statusheader; my $filestatus;
    my $description=<<END;
<FONT SIZE=+2>Directory and File Structure Description, $date</FONT>
<P>
The icons on the left column correspond to the file type
specified in the second column.  The last column "Notes" shows compilation,
dependency, and configuration information.  The CVS location
shows the location of the binary source file (if applicable) needed to
be copied to the target.  If the binary source file is not at
the specified location, then the text is shown in 
<FONT COLOR=#FF0000>red</FONT>.
</P>
<P>
<TABLE BORDER=1 CELLPADDING=5 WIDTH=500>
END
    my $counter=0;
    my @colorindex=("#80FF80","#80FFFF","#FFFF80");
    my @allfiles=keys %{$info{'LOCATION'}{$distribution}};
    foreach my $d (@$dirs) {
	# set color
	my $color=$colorindex[$counter%3];
	# set other values
	my $dirdescription=$info{'DIRECTORY'}{$distribution}{$d}{'DESCRIPTION'};
	$dirdescription="(" . $dirdescription . ")" if $dirdescription;
	# find subdirectories that are contained in this directory
	my @subdirs;
	foreach my $d2 (@$dirs) {
	    if ($d2=~/^$d\/([^\/]+)$/) {
		push @subdirs,$1;
	    }
	}
	# find files that are contained in this directory
	my @files;
	my @filesfull;
	foreach my $f (@allfiles) {
	    if ($f=~/^$d\/([^\/]+)$/) {
		push @files,$1;
		push @filesfull,$f;
	    }
	}
	# render starting HTML formatting elements
	if (@subdirs || @files) {
	    my $subdirstring="<BR>* Relevant subdirectories: " . join(", ",@subdirs) if @subdirs;
	    $description.=<<END;
<TR><TD BGCOLOR=#000000 COLSPAN=6><FONT COLOR=$color><IMG SRC="directory.gif" ALT="directory">DIRECTORY -- $d $dirdescription
$subdirstring</FONT></TD></TR>
END
        }
	else {
	    $description.=<<END;
<TR><TD BGCOLOR=#000000 COLSPAN=6><FONT COLOR=$color><IMG SRC="emptydirectory.gif" ALT="empty directory">EMPTY DIRECTORY - $d $dirdescription</FONT></TD></TR>
END
        }
	if (@files) {
	    if ($mode eq 'status') {
		$statusheader=<<END;
<TH BGCOLOR=$color ALIGN=LEFT>Current Status</TH>
END
	    }
	    $description.=<<END;
<TR>
$statusheader
<TH BGCOLOR=$color ALIGN=LEFT COLSPAN=2>Type</TH>
<TH BGCOLOR=$color ALIGN=LEFT>File Name</TH>
<TH BGCOLOR=$color ALIGN=LEFT>Function</TH>
<TH BGCOLOR=$color ALIGN=LEFT>CVS Location</TH>
<TH BGCOLOR=$color ALIGN=LEFT>Notes</TH>
</TR>
END
            foreach my $i (0..$#files) {
		my $category=$info{'LOCATION'}{$distribution}{$filesfull[$i]}{'CATEGORY'};
		my $fdescription=$info{'LOCATION'}{$distribution}{$filesfull[$i]}{'DESCRIPTION'};
		my $source=$info{'LOCATION'}{$distribution}{$filesfull[$i]}{'SOURCE'};
		my $source2=$info{'LOCATION'}{$distribution}{$filesfull[$i]}{'SOURCE'};
		my $note=$info{'LOCATION'}{$distribution}{$filesfull[$i]}{'NOTE'};
		$note.="<BR>" if $note;
		my $listing=$info{'LOCATION'}{$distribution}{$filesfull[$i]}{'FILES'};
		my @E=split(/\s+/,$listing);
		$source=~/(.*)\/[^\/]+$/;
		my $sd=$1;
		my $eflag=0;
		foreach my $e (@E) {
		    unless (-e "../../$sd/$e") {
			$e="<FONT COLOR=#FF0000>$e</FONT>";
			$eflag=1;
		    }
		}
		$listing=join("\n",@E);
		$listing="<B>listing</B><BR><FONT SIZE=-2>$listing</FONT>" if $listing;
		$listing.="<BR>" if $listing;
		my $build=$info{'LOCATION'}{$distribution}{$filesfull[$i]}{'BUILD'};
		$build="<B>build</B><BR>$build" if $build;
		$build.="<BR>" if $build;
		my $dependencies=$info{'LOCATION'}{$distribution}{$filesfull[$i]}{'DEPENDENCIES'};
		$dependencies="<B>dependencies</B><BR>$dependencies" if $dependencies;
		$dependencies.="<BR>" if $dependencies;
		unless (-e "../../$source") {
		    $source=~/([^\/]+)$/;
		    my $s=$1;
		    if ($source!~/\*/) {
			$source="<FONT COLOR=#FF0000>$source</FONT>";
		    }
		    elsif ($eflag) {
			$source="<FONT COLOR=#FF0000>$source</FONT>";
		    }
		}
		my $checksum;
		my $checksum_source;
		my $checksum_target;
		if ($mode eq 'status') {
		    $filestatus='';
		    my $fs;
		    my $listing2=$info{'LOCATION'}{$distribution}{$filesfull[$i]}{'FILES'};
		    my @E=split(/\s+/,$listing2); shift @E;
		    if (@E) {
			$fs=`find /$filesfull[$i] -prune -printf "\%m\t\%u\t\%g\n" 2>/dev/null | wc -l`; chop $fs;
			if ($fs!=(@E+0)) {
			    $ecount=(@E+0);
			    $estuff=join(",",@E);
			    $filestatus="<TD BGCOLOR=#FFFFFF><B><U>ERROR. SOME FILES ARE MISSING</U></B></TD>";
			}
			$fs=`find /$filesfull[$i] -prune -printf "\%m\t\%u\t\%g\n" 2>/dev/null | sort | uniq | wc -l`; chop $fs;
			if ($fs!=1) {
			    $filestatus='<TD BGCOLOR=#FFFFFF><B><U>ERROR. THERE ARE MULTIPLE OWNERSHIPS/PERMISSIONS WHEN ALL THESE FILES SHOULD HAVE THE SAME CONFIGURATION</U></B></TD>';
			}
			else {
			    $fs=`find /$filesfull[$i] -prune -printf "\%m\t\%u\t\%g\n" 2>/dev/null | sort | uniq`; chop $fs;
			}
		    }
		    else {
			$fs=`find /$filesfull[$i] -prune -printf "\%m\t\%u\t\%g" 2>/dev/null`;
			if (-f "/$filesfull[$i]" && !(-l "/$filesfull[$i]")) {
			    $checksum_source=`md5sum ../../$source2 | cut -d ' ' -f1`;
			    chop $checksum_source;
			    $checksum_target=`md5sum /$filesfull[$i] | cut -d ' ' -f1`;
			    chop $checksum_target;
#			    warn ("CS: $checksum_source, CT: $checksum_target\n");
			    unless ($checksum_source eq $checksum_target) {
				$checksum="<BR><B><U>CHECKSUM DIFFERENCE</U></B>";
			    }
			}
		    }
		    my $fsl=`find /$filesfull[$i] -type l -prune -printf "\%m\t\%u\t\%g" 2>/dev/null`;
		    unless ($fs || $filestatus) {
			$filestatus='<TD BGCOLOR=#FFFFFF><B><U>MISSING</U></B></TD>';
		    }
		    elsif (!$filestatus) {

			$chmod=$info{'OWNERSHIP'}{$category}{'CHMOD'};
			$chown=$info{'OWNERSHIP'}{$category}{'CHOWN'};
			$devchmod=$info{'DEVOWNERSHIP'}{$category}{'CHMOD'};
			$devchown=$info{'DEVOWNERSHIP'}{$category}{'CHOWN'};

			my @fss=split(/\t/,$fs);
			my $fssz=$fss[0];
			$fssz="0" . $fss[0] if length($fss[0])<4;
			$fss[0]=$fssz;
			$fs="$fss[0] $fss[1]:$fss[2]";
			$s=' ';
			if ($fsl) {
			    $fs="$fss[1]:$fss[2]";
			    $s='';
			}
			if ($fs eq "$chmod$s$chown" && $fs eq "$devchmod$s$devchown") {
			    $filestatus="<TD BGCOLOR=#FFFFFF>runtime+development$checksum</TD>";
			}
			elsif ($fs eq "$chmod$s$chown") {
			    $filestatus="<TD BGCOLOR=#FFFFFF>runtime$checksum</TD>";
			}
			elsif ($fs eq "$devchmod$s$devchown") {
			    $filestatus="<TD BGCOLOR=#FFFFFF>development$checksum</TD>";
			}
			else {
			    $filestatus="<TD BGCOLOR=#FFFFFF><B><U>ERROR</U></B><BR>$fs</TD>";
			}
		    }
		}	    
		$description.=<<END;
<TR>
$filestatus
<TD BGCOLOR=#A0A0A0><IMG SRC="$fcm{$category}.gif" ALT="$category"></TD>
<TD BGCOLOR=$color>$category</TD>
<TD BGCOLOR=$color>$files[$i]</TD>
<TD BGCOLOR=$color>$fdescription&nbsp;</TD>
<TD BGCOLOR=$color>$source</TD>
<TD BGCOLOR=$color>$note$listing$build$dependencies&nbsp;</TD>
</TR>
END
	    }
	}
	$counter++;
    }
    $description.=<<END;
</TABLE>
</P>
END
    return $description;
}
