--- loncom/build/Attic/parse.pl 2000/12/08 20:28:57 1.4 +++ loncom/build/Attic/parse.pl 2001/04/11 03:06:00 1.33 @@ -2,8 +2,18 @@ # Scott Harrison # November 2000 +# ... +# 04/10/2001 -# Read in loncapa tags and metagroup tags + +# 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; @@ -12,17 +22,30 @@ my ($file,$mode)=@ARGV; open IN,"<$file"; my @lines=; close IN; -my $info=join('',@lines); -my $info2=$info; # value to allow for meta data group retrieval +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 ($info=~/\/isg) { +while ($info1=~/\/isg) { my $keystring=$1; # In the parsing of LON-CAPA tags, remove boundary white-space, # and handle quotation commands. @@ -31,7 +54,6 @@ while ($info=~/\/isg) $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'}; @@ -52,19 +74,19 @@ while ($info=~/\/isg) $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'}}{'SOURCE'}= - $hash{'SOURCE'}; + $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)\>(.*?)\(.*?)\<\/(?: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'}}{$key}= + $info{$hash{'TYPE'}}{$hash{'DIST'}}{$hash{'TARGET'}}{uc($key)}= $value; } } @@ -74,8 +96,9 @@ while ($info=~/\/isg) } } -if ($mode eq "ALL" || $mode eq "HTML") { - my $a; +my $a; +my @directories; +if ($mode eq "HTML") { $a=&begin_description_page; print $a; $a=&make_rpm_description_block; @@ -83,15 +106,888 @@ if ($mode eq "ALL" || $mode eq "HTML") { @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<>setup_file_list.txt"; + print OUT "BinaryRoot/etc/hosts.deny\n"; + close OUT; + open OUT,">BinaryRoot/etc/hosts.deny"; + print 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<>setup_file_list.txt"; + print OUT "BinaryRoot/etc/pam.d/login\n"; + close OUT; + open OUT,">BinaryRoot/etc/pam.d/login"; + print OUT</dev/null; install -o $owner -g $group -m $devchmod \$(SOURCE)/$source \$(TARGET)/$rot +END + } + } + } + } + $description.=< LON-CAPA Software Description Page ($distribution, $date) @@ -105,6 +1001,7 @@ sub begin_description_page {
  • About this file
  • Software Package Description
  • Directory Structure +
  • File Type Ownership and Permissions
  • File and Directory Structure About this file @@ -115,14 +1012,42 @@ http://install.lon-capa.org/compile/inde information.

    END +} + else { + $description=< + +LON-CAPA Software File System Status Page ($distribution, $date) + + +LON-CAPA Software File System Status Page ($distribution, $date) +
    Michigan State University +
    Learning Online with CAPA +
    Contact korte\@lon-capa.org +
      +
    • About this file +
    • Software Package Description +
    • Directory Structure +
    • File Type Ownership and Permissions +
    • File and Directory Structure +
    +About this file +

    +This file is generated dynamically by parse.pl as +part of a status checking process. See http://install.lon-capa.org/ +for more information. +

    +END + } return $description; + } # ------------------------------------------------- End description page sub end_description_page { my $description=< -LON-CAPA Software Development Team +LON-CAPA Software Development Team END @@ -131,7 +1056,10 @@ END # ------------------------------------------------- Make RPM description block sub make_rpm_description_block { - my $description=<Rolled in a RedHat 6.2 RPM, $date

    @@ -146,13 +1074,64 @@ Group : $info{'RPM'}{'Group'} License : $info{'RPM'}{'Copyright'} Summary : $info{'RPM'}{'Summary'} Description : -
     $info{'RPM'}{'description'}
     

    END +} + else { + my $exist=`rpm -q LON-CAPA-base 2>/dev/null`; + unless ($exist) { + $description=<No LON-CAPA RPM on the system, (installed ??????) +

    + + + +
    +Error! A LON-CAPA-base RPM +was never installed on this system! +
    +

    +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=<Current RedHat RPM on the system, (installed $idate) +

    + + +
    +
    +Name        : $rpmname
    +Version     : $rpmversion
    +Vendor      : $rpmvendor
    +Release     : $rpmrelease
    +Build Host  : $rpmbuildhost
    +Group       : $rpmgroup
    +License     : $rpmlicense
    +Summary     : $rpmsummary
    +Description : 
    +$rpmdescription
    +
    +
    +

    +END +} + } return $description; } @@ -165,25 +1144,51 @@ sub determine_directory_structure { # ---------------------------------- Make directory structure description block sub make_directory_structure_description_block { - my ($dirs)=@_; + my ($dirs,$mode)=@_; + my $dirstatus; my $statusheader; my $description=<Directory Structure Description, $date

    +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). +

    +

    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=""; } $description.=< +$statusheader END $description.="\n"; + if (keys %diraccount) { + $description.= "\n"; + } foreach my $d (@$dirs) { my $dtable=$d; $dtable=~s/\//\<\/TD\>\/g; @@ -192,8 +1197,34 @@ END 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=''; + } + 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=''; + } + elsif ($ds eq "$chmod $chown") { + $dirstatus=''; + } + elsif ($ds eq "$devchmod $devchown") { + $dirstatus=''; + } + else { + $dirstatus=""; + } + } + } $description.=< +$dirstatus @@ -210,17 +1241,67 @@ END return $description; } +# ------------------- Make file type ownership and permissions description block +sub make_file_type_ownership_and_permissions_description_block { + my ($mode)=@_; + my $description=<File Type Ownership and Permissions Descriptions, $date +

    +This table shows what permissions and ownership settings correspond +to each kind of file type. +

    +

    +

    Current StatusCategory Permissions Development
    Permissions
    Directory Path
    Directories that are unaccounted for: \n";
    +	foreach my $d (keys %diraccount) {
    +	    $description.="$d\n";
    +	}
    +	$description.="
    MISSINGruntime+developmentruntimedevelopmentERROR
    $ds
    $category $chmod $chown $devchmod $devchown
    + + + + + + +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 + } + } + $description.=< +

    +END +} + # ------------------------- Make directory and file structure description block sub make_directory_and_file_structure_description_block { - my ($dirs)=@_; + my ($dirs,$mode)=@_; + my $statusheader; my $filestatus; my $description=<Directory and File Structure Description, $date

    -

    IconTypePermissionsDevelopment Permissions
    $type$type$chmod $chown$devchmod $devchown
    +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 +red. +

    +

    +

    END my $counter=0; my @colorindex=("#80FF80","#80FFFF","#FFFF80"); - my @allfiles=keys %{$info{'LOCATION'}{$distribution}{'TARGET'}}; + my @allfiles=keys %{$info{'LOCATION'}{$distribution}}; foreach my $d (@$dirs) { # set color my $color=$colorindex[$counter%3]; @@ -230,43 +1311,169 @@ END # find subdirectories that are contained in this directory my @subdirs; foreach my $d2 (@$dirs) { - if ($d2=~/$d\/([^\/]+)/) { + if ($d2=~/^$d\/([^\/]+)$/) { push @subdirs,$1; } } # find files that are contained in this directory my @files; + my @filesfull; foreach my $f (@allfiles) { - if ($file=~/$d\/(.+)/) { + if ($f=~/^$d\/([^\/]+)$/) { push @files,$1; + push @filesfull,$f; } } # render starting HTML formatting elements if (@subdirs || @files) { my $subdirstring="
    * Relevant subdirectories: " . join(", ",@subdirs) if @subdirs; $description.=< END } else { $description.=< + END } if (@files) { + if ($mode eq 'status') { + $statusheader=<Current Status +END + } $description.=< - - - - +$statusheader + + + + + END - } - $description.=</dev/null | wc -l`; chop $fs; + if ($fs!=(@E+0)) { + $ecount=(@E+0); + $estuff=join(",",@E); + $filestatus=""; + } + $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=''; + } + 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="
    CHECKSUM DIFFERENCE"; + } + } + } + my $fsl=`find /$filesfull[$i] -type l -prune -printf "\%m\t\%u\t\%g" 2>/dev/null`; + unless ($fs || $filestatus) { + $filestatus=''; + } + 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=""; + } + elsif ($fs eq "$chmod$s$chown") { + $filestatus=""; + } + elsif ($fs eq "$devchmod$s$devchown") { + $filestatus=""; + } + else { + $filestatus=""; + } + } + } + $description.=< +$filestatus + + + + + + END + } + } $counter++; } $description.=<
    directoryDIRECTORY -- $d $dirdescription -$subdirstring +
    directoryDIRECTORY -- $d $dirdescription +$subdirstring
    empty directoryEMPTY DIRECTORY - $d $dirdescription
    empty directoryEMPTY DIRECTORY - $d $dirdescription
    TypeFile NameFunctionNotesTypeFile NameFunctionCVS LocationNotes
    ERROR. SOME FILES ARE MISSINGERROR. THERE ARE MULTIPLE OWNERSHIPS/PERMISSIONS WHEN ALL THESE FILES SHOULD HAVE THE SAME CONFIGURATIONMISSINGruntime+development$checksumruntime$checksumdevelopment$checksumERROR
    $fs
    $category$category$files[$i]$fdescription $source$note$listing$build$dependencies