#!/bin/bash
# -------------------------------------------------------------------
# Copyright (C) 2008-2026 by Intevation GmbH
# Author(s):
# Sascha Wilde <wilde@intevation.de>
# Thomas Arendsen Hein <thomas@intevation.de>

# This program is free software under the GNU GPL (>=v2)
# Read the file COPYING coming with the software for details.
# -------------------------------------------------------------------

# Simple tool to report memory and filesystem usage exceeding limits
# See reporter.conf for configuration hints.

export LC_ALL=C

QUIET=0
WARNING="WARNING"
OLD_CONFFILE=/etc/default/reporter.conf
CONFFILE=/etc/adminton/reporter.conf

failed=0
run () {
    "$@" | awk -v quiet="$QUIET" -v sep="${print_separator:-0}" '
        quiet==0 && NR==1 && sep==1 {
            print ""
            print "--------------------------------------------------"
            print ""
        }
        quiet==0 {
            print
        }
        END {
            if (NR > 0) exit 99
        }
    '
    if [ $? -eq 99 ]; then
        print_separator=1
        failed=$((failed + 1))
    fi
}

get_warn_level () {
    # $1 = config key
    # $2 = default value if config key is missing
    key=`echo $1 | sed 's-\([./\]\)-\\\\\1-g'`
    warn_level=$(sed -n "s/^$key=\([0-9]\+\)/\1/p" <"$CONFFILE")
    [ -z "$warn_level" ] && warn_level="$2"
    printf "%s" "$warn_level"
}

check_memory () {
    old_default_warnlevel=`get_warn_level DEFAULT 0`
    memory_warnlevel=$(get_warn_level MEMORY $old_default_warnlevel)
    if [ "$memory_warnlevel" -eq 0 ]; then
        return
    fi

    memory_usage=$(free 2>/dev/null | awk '
        /^Mem:/ { total=$2; used=$3 }
        /^-\/\+ buffers\/cache:/ { used=$3 }
        END { print int(used / total * 100) }
    ')
    if [ "$WARNING" = "TEST" -o $memory_usage -gt $memory_warnlevel ]; then
        echo "$WARNING: memory usage over limit: $memory_usage% (limit: $memory_warnlevel%)"
        echo
        ps -e -o rss,vsz,uid,pid,comm= --sort -rss 2>/dev/null | head -n 5 | {
            column -t -R 1,2,3 2>/dev/null || column -t
        } | sed 's/[[:space:]]\+$//'
    fi
}

check_filesystem () {
    get_excluded_fs () {
        while read fs; do
            EXCLUDE_FSTYPE[${#EXCLUDE_FSTYPE[@]}]="--exclude-type=${fs}"
        done < <(awk -F= '$1 ~ "^EXCLUDE(_FSTYPE)?$" { print $2 }' "$CONFFILE")
    }

    EXCLUDE_FSTYPE=()

    df=/bin/df

    warningheader="$WARNING: some filesystem usage over limit.

   Size    Used   Avail Usage Limit  Mountpoint"

    old_default_warnlevel=`get_warn_level DEFAULT 0`
    filesystem_warnlevel=`get_warn_level FILESYSTEM $old_default_warnlevel`
    if [ "$filesystem_warnlevel" -eq 0 ]; then
        return
    fi

    get_excluded_fs

    $df --portability --human-readable "${EXCLUDE_FSTYPE[@]}" |
    while read filesystem size used avail useage mountpoint; do
        warnlevel=`get_warn_level $filesystem $filesystem_warnlevel`
        warnlevel=${warnlevel:-$filesystem_warnlevel}
        if [ "$warnlevel" -eq 0 ]; then
            continue
        fi
        [ $size = "Size" ] && continue  # skip header line
        if [ "$WARNING" = "TEST" -o ${useage%\%} -gt $warnlevel ]; then
            [ "$warningheader" ] && echo "$warningheader" && warningheader=""
            printf "%7s %7s %7s  %4s  %3s%%  %s\n" $size $used $avail $useage $warnlevel $mountpoint
        fi
    done
}


while getopts hqtc: flag; do
    case $flag in
        q)
            QUIET=1
            ;;
        t)
            WARNING="TEST"
            ;;
        c)
            CONFFILE="$OPTARG"
            OLD_CONFFILE=""
            ;;
        ?)
            printf "Usage: %s: [-q] [-t] [-c config-file]\n" $(basename $0)
    esac
done

if [ ! -f "$CONFFILE" -a -n "$OLD_CONFFILE" -a -f "$OLD_CONFFILE" ]; then
    CONFFILE="$OLD_CONFFILE"
fi

if [ ! -f "$CONFFILE" -o ! -r "$CONFFILE" ]; then
    echo >&2 "Can not read config file \"$CONFFILE\""
    exit 23
fi

run check_memory
run check_filesystem

exit $failed
