Skip to content

Instantly share code, notes, and snippets.

@plavjanik
Created July 20, 2020 12:40
Show Gist options
  • Select an option

  • Save plavjanik/219ba63fe5881e718a2ef449e2c43e65 to your computer and use it in GitHub Desktop.

Select an option

Save plavjanik/219ba63fe5881e718a2ef449e2c43e65 to your computer and use it in GitHub Desktop.
setup2.pl
#! /usr/bin/env perl
use File::Basename;
use Cwd 'abs_path';
use lib dirname($0).'/oebin';
use CheckHeldOutput;
use Getopt::Long;
use Pod::Usage;
use File::Basename;
my ($uninstall, $help) = ();
GetOptions (
"uninstall" => \$uninstall,
"help|?" => \$help,
) or pod2usage(2);
pod2usage(1) if ($help);
my $user=uc($ENV{'LOGNAME'}?$ENV{'LOGNAME'}:uc(`id -un`));
chomp $user;
my $jclJobName=(length($user)>7?$user:"${user}A");
my $BYTES_PER_CYLINDER=696000;
my $rplRoot="___REPLACE_ROOT___";
my $usrHLQ=uc($ENV{'COMPILER_INSTALL_HLQ'}?$ENV{'COMPILER_INSTALL_HLQ'}:"${user}.NJSV12B");
my $leHLQ=uc($ENV{'LE_INSTALL_HLQ'}?$ENV{'LE_INSTALL_HLQ'}:"CEE");
my $rteHLQ=uc($ENV{'RTE_INSTALL_HLQ'}?$ENV{'RTE_INSTALL_HLQ'}:"CBC");
my $msgCLS=uc($ENV{'COMPILER_INSTALL_HELD_MSGCLASS'}?$ENV{'COMPILER_INSTALL_HELD_MSGCLASS'}:'S');
my $jclVol=($ENV{'COMPILER_INSTALL_VOLSER'}?" VOLUME($ENV{'COMPILER_INSTALL_VOLSER'})":());
my $accinfo=($ENV{'ACCOUNTING_INFO'}?$ENV{'ACCOUNTING_INFO'}:'157A,2326');
my $rplHLQ="___REPLACE_HLQ___";
my $rplLEHLQ="___REPLACE_LE_HLQ___";
my $rplRTEHLQ="___REPLACE_RTE_HLQ___";
my $sqfHLQ="USRHLQ";
my $instroot=abs_path(dirname($0));
my $ussRoot="$instroot/uss.images";
my $tgtRoot="$instroot/bin";
my @files=();
my @listOfDatasets=();
if (&isUninstall) {
die "<ERR> failed to uninstall because target path $tgtRoot does not exist, please make sure to run ".
"this script under the same directory where unpack.pl was previously run during installation"
if (!-d $tgtRoot);
} else {
# Prereq check
my $hasDependenciesInstalled=1;
if (! -d "/usr/include/le" ) {
print "WARNING: Dependency \"/usr/include/le\" not found\n";
$hasDependenciesInstalled=0;
}
if (! -f "/usr/lpp/cbclib/lib/libibmcmp.a" ) {
print "WARNING: Dependency \"/usr/lpp/cbclib/lib/libibmcmp.a\" not found\n";
$hasDependenciesInstalled=0;
}
if (!$hasDependenciesInstalled) {
print <<DEPS;
WARNING: Missing dependencies. Please ensure that the following PTFs are installed:
z/OS V2R2 with all the following PTFs installed:
- UI62788
- UI46658
- UI62416
- UI62415
z/OS V2R3 with all the following PTFs installed:
- UI61308
- UI61376
- UI61747
- UI61375
DEPS
$| = 1;
for (my $i=0; $i <= 2; $i++) {
print ".";
sleep 1;
}
$| = 0;
}
(system("mkdir -p $tgtRoot && cp -rmf $ussRoot/* $tgtRoot/") == 0)||die "copy failed";
}
open (FLIST,"find $tgtRoot -type f 2>/dev/null|")||die "failed to find files under $srcRoot";
while (<FLIST>) {
my $file=$_;
chomp $file;
if ($file =~ m/\/xmits\/$sqfHLQ.*.XMIT$/) {
push @listOfDatasets,$file;
} else {
push @files,$file;
}
}
close FLIST;
foreach my $ds (@listOfDatasets) {
if (&isUninstall) {
print "<DEB> deleting ".&mapDatasetName($ds)."\n";
&deleteDS(&mapDatasetName($ds)) || print "<DEB> cannot delete ".&mapDatasetName($ds)." -- has it already been deleted?\n";
} else {
print "<DEB> unloading $ds into ".&mapDatasetName($ds)."\n";
&receiveDSfromFile($ds, &mapDatasetName($ds)) || die "<ERR> cannot receive $ds to ". &mapDatasetName($ds);
}
}
sleep 120;
if (&isUninstall) {
opendir my $ussbindir, "$ussRoot/" or die "<ERR> cannot open uss.images dir $ussRoot:$!";
my @ussbinfiles = grep { /[^\.]/ } readdir ($ussbindir);
die "<ERR> $ussbindir is empty" if (scalar(@ussbinfiles)<1);
my $filesToDelete = join(' ',@ussbinfiles);
closedir $ussbindir;
(system("cd $tgtRoot/ && rm -rf $filesToDelete") == 0)||die "delete failed:$!";
print "<INFO> uninstallation complete!\n";
} else {
foreach my $f (@files) {
if (-T $f) {
print "<DEB> processing file $f\n";
&doReplaceDataset($f) || die "cannot parse $f to replace dataset";
&doReplaceRoot($f) || die "cannot parse $f to replace HFS root";
} else {
print "<DEB> skipping non-text file $f\n";
}
}
&runIVP() || die "fail to verify installation";
print "<INFO> installation complete!\n";
}
sub runIVP {
my $temphello="._temp.hello.cpp";
open (FHELLO,">$temphello")||die "failed to oepn $temphello";
print FHELLO "#include <iostream>\n";
print FHELLO "using namespace std;\n";
print FHELLO "int main () {\n";
print FHELLO " cout << \"Hello C++ World!\" << endl;\n";
print FHELLO " return 0;\n";
print FHELLO "}\n";
close FHELLO;
my $cmd="$tgtRoot/njsc++ $temphello -o hello -qphaseid && $tgtRoot/run ./hello && rm -f $temphello hello";
print "<INFO> running : $cmd!\n";
return(system("$cmd")==0);
}
sub doReplaceDataset {
my ($file) = @_;
my $ofile = "${file}._temp_out";
open (FIN,"<$file")||die "failed to open $file to read";
open (FOUT,">$ofile")||die "failed to open ofile to write";
while (<FIN>) {
my $line=$_;
$line=~s/$rplHLQ/$usrHLQ/ig;
$line=~s/$rplLEHLQ/$leHLQ/ig;
$line=~s/$rplRTEHLQ/$rteHLQ/ig;
print FOUT $line;
}
close FIN;
close FOUT;
(system("mv $ofile $file && chmod 755 $file")==0)||die " failed to rename $ofile to $file";
return 1;
}
sub doReplaceRoot {
my ($file) = @_;
my $ofile = "${file}._temp_out";
open (FIN,"<$file")||die "failed to open $file to read";
open (FOUT,">$ofile")||die "failed to open ofile to write";
while (<FIN>) {
my $line=$_;
if ($line=~m/$rplRoot/) {
$line=~s/$rplRoot/$tgtRoot/g;
#print "new line >>> $file >>> $line";
}
print FOUT $line;
}
close FIN;
close FOUT;
(system("mv $ofile $file && chmod 755 $file")==0)||die " failed to rename $ofile to $file";
return 1;
}
sub mapDatasetName {
my ($dataset) = @_;
if ($dataset =~ m/.*\/$sqfHLQ\.([^\/]*)\.XMIT$/g) {
$dataset = "$usrHLQ.$1";
}
return $dataset;
}
sub receiveDSfromFile {
my ($file, $dataset) = @_;
my $tempDS = getTempDSName();
if (! copyFileToSequentialDS($file, $tempDS)) {
warn "An error occurred while copying file $file to dataset $tempDS. -- $!";
return 0;
}
if (! receiveDSfromDS($tempDS, $dataset)) {
warn "An error occurred while receiving temporary dataset $tempDS to dataset $dataset.";
return 0;
}
if (! deleteDS($tempDS)) {
warn "An error occurred when deleting $tempDS.";
return 0;
}
return 1;
}
sub submit_jcl {
open (FJCL,">.tempjcl")||die "failed to open .tempjcl";
my (@list) = @_;
foreach my $line ( @list ) {
print FJCL "$line\n";
}
close FJCL;
my $cmd = "submit .tempjcl";
return (system ($cmd) == 0);
}
sub receiveDSfromDS {
my ($in_dataset, $target_dataset) = @_;
$in_dataset=uc($in_dataset);
$target_dataset=uc($target_dataset);
my @jcl;
my $hostname=uc(`hostname -s`);
chomp($hostname);
return 0 if (!$in_dataset || !$target_dataset || !$user || !$hostname);
my @receive_jcl = (
"//$jclJobName JOB ($accinfo),'RECEIVE',MSGLEVEL=(1,1),MSGCLASS=$msgCLS,",
"// CLASS=A,REGION=0M,USER=$user",
"//REC EXEC PGM=IKJEFT01,DYNAMNBR=3000",
"//SYSTSPRT DD SYSOUT=*",
"//SYSPRINT DD SYSOUT=*",
"//SYSTSIN DD DATA,DLM='!!'",
" RECEIVE +",
" INDATASET('$in_dataset')",
" DATASET('$target_dataset')".($jclVol?' +':''),
($jclVol?$jclVol:()),
);
push (@receive_jcl, "!!");
push (@receive_jcl, "//");
submit_jcl(@receive_jcl);
return 1;
}
sub copyFileToSequentialDS {
my ($file, $dataset) = @_;
return 0 if (!$dataset) && (!$file);
my $num_cyls = getNumCylinders($file);
#The space parameter doesn't seem to work properly and the documentation is incorrect.
#It seems that we always get 1 cylinder for the primary extent, so I have specified the
#required size twice, for primary and secondary allocation units.
my $copy_cmd = "cp -B -P \"recfm=fb, lrecl=80, blksize=3120, space=(cyl,($num_cyls,$num_cyls))\" $file \"//'$dataset'\"";
return (system ($copy_cmd) == 0);
}
sub getNumCylinders {
my ($file) = @_;
return 0 if (!$file);
my $size = -s $file;
#Determine the number of cylinders that we need for the DS (always round up by 1)
my $num_cyls = int($size / $BYTES_PER_CYLINDER) + 1;
}
sub deleteDS {
my ($dataset) = @_;
$dataset=uc($dataset);
my @delete_jcl = (
"//$jclJobName JOB ($accinfo),",
"// 'DELETE',",
"// MSGLEVEL=(1,1),",
"// MSGCLASS=$msgCLS,",
"// CLASS=A,",
"// USER=$user",
"//DELETE EXEC PGM=IEFBR14",
"//ACLBSR1 DD DISP=(MOD,DELETE,DELETE),",
"// DSN=$dataset,",
"// SPACE=(TRK,(1,1))",
"//",
);
}
sub getTempDSName {
my $time = time();
my @random_chars = ('A'..'Z');
#<LAST 7 DIGITS OF CURRENT TIME IN MS>.T<PID>
$random_string = "T" . substr($time, -7);
$random_string .= "." . $random_chars[int(rand(scalar(@random_chars)))];
$random_string .= int(rand(scalar(9999999)));
my $tempDS = "$usrHLQ.TMP.$random_string";
return $tempDS;
}
sub isUninstall {
return ($uninstall?1:0);
}
1;
=pod
=head1 NAME
B<unpack.pl> - install or uninstall the compiler from downloaded USS pax file
=head1 SYNOPSIS
B<unpack.pl> [B<-uninstall>] [--] [B<arg>]*
=head1 DESCRIPTION
description - this script will create or delete the compiler driver based on:
1. HFS parts for compiler placed under the uss.images HFS directory
2. MVS datasets for compiler packaged as sequential datasets placed under uss.images/xmits HFS directory
3. When no argument is passed to the script, it will install/restore the compiler; when -uninstall is passed to the script, it will uninstall the compiler.
4. The compiler will be installed/restored under the directory where this script is run, while the MVS portion of the compiler will be installed/restored under the user's High Level Qualifier where the script is run. Optionally, the MVS dataset High Level Qualifier can be overwritten by the environment variable COMPILER_INSTALL_HLQ if it is set.
=head1 OPTIONS
B<-uninstall>
=over 3
specifies whether the operation is an uninstallation, by default the script does the installation.
=back
=head1 EXAMPLES
example -
=over 3
To install the compiler under the current directory, run:
C<./unpack.pl>
=back
=head1 COPYRIGHT
Copyright 2017 IBM Corporation
=cut
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment