#!/bin/bash -p
# ^ -p protects us from shellshock

realdir ()
{
    # print the canonical path of a directory, resolving symlinks in
    # the way. On files, it will just echo back the argument.
    if [ -d "$1" ]; then
        ( cd "$1" && pwd -P )
    else
        echo "$1"
        return 1
    fi
}

check_cert()
{
    CERT=$1
    echo "***** Certificate: $CERT"
    if [ -r $CERT ]; then
        openssl x509 -in $CERT -text -noout
    else
        echo "Can't read $CERT"
    fi
    echo ""
}

tail_log()
{
    LOG=$1
    LINES=$2
    if [ -r $LOG ]; then
        echo "***** $LOG (last $LINES lines)"
        tail --lines=$LINES $LOG
    else
        echo "***** $LOG (doesn't exist)"
    fi
    echo ""
}

dump_file()
{
    FILE=$1
    if [ -r $FILE ]; then
        echo "***** $FILE"
        cat $FILE
    else
        echo "***** $FILE (doesn't exist)"
    fi
    echo ""
}

dump_files_that_exist()
{
    local FILENAME
    for FILENAME in "$@"; do
        if [[ -f $FILENAME ]]; then
            dump_file "$FILENAME"
        fi
    done
}

dump_files_in_dir()
{
    DIR=$1
    echo "***** Files in $DIR"
    if [ -L $DIR ]; then
        REAL_DIR=$(realdir "$DIR")
        echo "(symbolic link to $REAL_DIR)"
    else
        REAL_DIR=$DIR
    fi

    if [ -d $REAL_DIR ]; then
        find $REAL_DIR \
            ! -name 'osg-profile.txt*' \
            -type f -print0 | sort -z | xargs -0 bash -c '
                for X in "$@"; do
                    echo "File: $X"; cat "$X"; echo
                done' -
    else
        echo "$REAL_DIR can't be read as a directory"
    fi
    echo ""
}

list_directory()
{
    DIR=$1
    echo "***** Contents of $DIR"
    if [ -L $DIR ]; then
        REAL_DIR=$(realdir "$DIR")
        echo "(symbolic link to $REAL_DIR)"
    else
        REAL_DIR=$DIR
    fi

    if [ -d $REAL_DIR ]; then
        ls -laF $REAL_DIR
    else
        echo $REAL_DIR
    fi
    echo ""
}

run_cmd()
{
    CMD=$1
    shift
    OPTIONS=$@

    echo "***** Running: $CMD $OPTIONS"
    which $CMD > /dev/null 2>&1
    if [ $? -eq 0 ]; then
        $CMD $OPTIONS
    else
        echo $?
        echo "Cannot find $CMD."
    fi
    echo ""
}

message() {
    echo "$@" >&3
}

dir=`pwd`

if [ ! -w $dir ]; then
    echo "I'm sorry, I don't have permission to create osg-profile.txt"
    echo "in the current directory. Please change into a directory where"
    echo "you have permission, or switch to a user that does have permission"
    exit 1
fi

tmpd=$(mktemp -d)
trap 'rm -rf "$tmpd"' EXIT

tmplog=$tmpd/osg-profile.txt

# Redirect remaining output to $tmplog; send any status messages (via the
# message function) to console (stdout)
exec 3>&2 > "$tmplog" 2>&1

# Determine whether we are profiling a tarball install or an rpm install
# based on whether or not $OSG_LOCATION is defined.

# XXX This will falsely identify an OSG 1.2 install as a tarball install
tarball_install=false
rpm_install=true
if [[ -n $OSG_LOCATION ]]; then
    tarball_install=true
    rpm_install=false
fi

message "OSG System Profiler"
if $tarball_install; then
    message "Analyzing tarball install with OSG_LOCATION=$OSG_LOCATION..."
    echo "OSG System Profile (tarball OSG_LOCATION=$OSG_LOCATION)"
elif $rpm_install; then
    message "Analyzing RPM install..."
    echo "OSG System Profile (RPM)"
fi

echo Created at `date`
echo ""

run_cmd hostname -f
run_cmd uname -a

dump_file "/etc/redhat-release"
dump_file "/etc/nsswitch.conf"
dump_file "/etc/hosts"

run_cmd df --human-readable --print-type
run_cmd free

dump_file "/proc/cpuinfo"

run_cmd netstat -i

if [ root = `whoami` ]; then
    run_cmd /sbin/iptables -vL
else
    echo "***** No iptables info (user was not root)"
fi

dump_file "/etc/selinux/config"
dump_file "/selinux/enforce"


if which selinuxenabled &>/dev/null && selinuxenabled; then
    echo "***** SELinux audit log"
    # Change the section marker of the sealert output to avoid clashing with
    # our section markers.
    sealert -a /var/log/audit/audit.log | sed -e 's/^[*][*][*][*][*]/******/'
fi


if $rpm_install; then
    rpm -qa | grep "^osg" | sort | xargs --no-run-if-empty -n 1 rpm -q
    echo ""

    tail_log /var/log/osg/osg-configure.log 200
    dump_files_in_dir "/etc/osg/config.d"
fi

echo "***** Xrootd information:"
for file in /etc/xrootd/xrootd-*.cfg
do
    dump_file $file
done
dump_files_in_dir "/etc/xrootd/config.d"

echo "***** Showing processes owned by the user xrootd"
ps -u xrootd u
echo ""

echo "***** Python information:"
python -c "import sys; print 'Version: ' + sys.version"
python -c "import sys; print 'Executable: ' + sys.executable"
python -c "import sys; print 'Prefix: ' + sys.prefix"
python -c 'import platform; print "Architecture: ",; print platform.architecture()'
python -c "import sys; print 'Search paths: ',; print  sys.path"
echo ""

run_cmd openssl version

if $tarball_install; then
    dump_file $OSG_LOCATION/setup.sh
    dump_file $OSG_LOCATION/setup.csh
fi

echo "***** Running: /usr/bin/env | sort"
/usr/bin/env | sort
echo ""

list_directory "${OSG_LOCATION-}/etc/grid-security"
if $rpm_install; then
    check_cert "/etc/grid-security/hostcert.pem"
    check_cert "/etc/grid-security/rsv/rsvcert.pem"
    check_cert "/etc/grid-security/voms/vomscert.pem"

    run_cmd rpm -q --whatprovides grid-certificates
fi

list_directory "${OSG_LOCATION-}/etc/grid-security/certificates"

echo "***** Enabled gratia probe cronjobs"
if [[ -x /etc/cron.d ]]; then
    perl -n - /etc/cron.d/* <<"__END__"
BEGIN {
    our $pattern = qr{(?xm) ^ \s* [^#] .* gratia/ (?:probe/)? ([^/]+) /};
    our $found = 0;
    our $output = sprintf("%-20s %s\n", 'Probe', 'In File');
}

if ( $_ =~ $pattern ) {
    $found = 1;
    my $probename = $1;
    my $shortfilename = $ARGV;
    $shortfilename =~ s{^/etc/cron.d/}{};
    $output .= sprintf("%-20s %s\n", $probename, $shortfilename);
}

END {
    if ($found) {
        print $output;
    } else {
        print "None\n"
    }
}
__END__
else
    echo "Could not look in /etc/cron.d"
fi


if $rpm_install; then
    PATH=$PATH:/usr/libexec/osg-system-profiler
    if type -f gratia-pbs-lsf-config-check &>/dev/null && rpm -q gratia-probe-pbs-lsf &>/dev/null; then
        echo "***** Gratia PBS/LSF config check"
        gratia-pbs-lsf-config-check
    fi

    dump_file "/etc/grid-security/gsi-authz.conf"
    dump_file "/etc/lcmaps.db"

    dump_file "/etc/yum.conf"

    dump_files_in_dir "/etc/yum.repos.d/"

    dump_files_in_dir "/etc/globus/"

    tail_log /var/log/gridftp.log 200
    tail_log /var/log/gridftp-auth.log 200

    # List all RPMs and verify them. Put the listing and the verification in
    # separate sections.  Verification only lists modified RPMs.
    message "Verifying RPMs. This may take a while."

    all_rpms_log=$(mktemp $dir/allrpmslog.XXXXXX)
    rpm_verify_log=$(mktemp $dir/rpmverifylog.XXXXXX)

    rpm -qa | grep -v kernel-devel |  sort -u | while read rpm_to_verify; do
        message -n .
        echo $rpm_to_verify >> $all_rpms_log

        # This awk trick prints out the header iff rpm --verify actually produces output
        rpm --verify $rpm_to_verify 2> /dev/null | awk '
            NR==1 { print "***** rpm --verify '$rpm_to_verify'" }
            { print }' >> $rpm_verify_log
    done
    message ""
    echo "***** All RPMs"
    cat $all_rpms_log
    echo ""
    cat $rpm_verify_log

    rm -f $all_rpms_log $rpm_verify_log
fi

if $tarball_install; then
    dump_file "$OSG_LOCATION"/etc/fetch-crl*.conf
fi

log=$dir/"osg-profile.txt"
if [ -e $log ]; then
    message "Backing up old $log to $log.bak"
    mv -f "$log" "$log.bak"
fi
mv -f "$tmplog" "$log"

message ""
message "Your system profile is located in:"
message "  $log"
message ""
message "If you are having problems with your installation, please create a"
message "ticket by sending email to help@opensciencegrid.org."
message ""
message "You should attach $log to the ticket."
message ""
message "You may also follow one of the other methods for getting help"
message "listed at:"
message "  https://opensciencegrid.github.io/docs/common/help/"
message ""

echo Finished at `date`

exit 0
