#!/bin/bash
# Copyright (C) 2019 Checkmk GmbH - License: GNU General Public License v2
# This file is part of Checkmk (https://checkmk.com). It is subject to the terms and
# conditions defined in the file COPYING, which is part of this source code package.

# Reason for this no-op: shellcheck disable=... before the first command disables the error for the
# entire script.
:

# Disable unused variable error (needed to keep track of version)
# shellcheck disable=SC2034
CMK_VERSION="2.4.0"

# Informix
# Make ENV-VARs avail for subshells
set -a

#   .--helper--------------------------------------------------------------.
#   |                    _          _                                      |
#   |                   | |__   ___| |_ __   ___ _ __                      |
#   |                   | '_ \ / _ \ | '_ \ / _ \ '__|                     |
#   |                   | | | |  __/ | |_) |  __/ |                        |
#   |                   |_| |_|\___|_| .__/ \___|_|                        |
#   |                                |_|                                   |
#   '----------------------------------------------------------------------'

# BEGIN COMMON PLUGIN CODE

# check that no users other than root can change the file
only_root_can_modify() {
    permissions=$1
    owner=$2
    group=$3

    group_write_perm=$(echo "$permissions" | cut -c 6)
    other_write_perm=$(echo "$permissions" | cut -c 9)

    if [ "$owner" != "root" ] || [ "$other_write_perm" != "-" ]; then
        return 1
    fi

    [ "$group" = "root" ] || [ "$group_write_perm" = "-" ]
}

get_binary_owner() {
    BINARY_PATH=$1
    stat -c '%U' "${BINARY_PATH}"
}

get_binary_execution_mode() {
    BINARY_PATH=$1
    BINARY_USER=$2

    # if the executable belongs to someone besides root, do not execute it as root
    if needs_user_switch_before_executing "$BINARY_PATH"; then
        echo "su ${BINARY_USER} -c"
        return
    fi
    echo "bash -c"
}

needs_user_switch_before_executing() {
    BINARY_PATH=$1

    [ "$(whoami)" = "root" ] && ! only_root_can_modify "$(stat -c '%A' "$BINARY_PATH")" "$(stat -c '%U' "$BINARY_PATH")" "$(stat -c '%G' "$BINARY_PATH")"
}

# END COMMON PLUGIN CODE

set_env() {
    # set environment variables given in the form VARNAME1=value1;VARNAME2=value2;...
    while IFS=';' read -ra parts; do
        for part in "${parts[@]}"; do
            var_name="${part%%=*}"
            var_value="${part#*=}"
            export "$var_name"="$var_value"
        done
    done <<<"$1"
}


#.
#   .--sqls----------------------------------------------------------------.
#   |                                     _                                |
#   |                           ___  __ _| |___                            |
#   |                          / __|/ _` | / __|                           |
#   |                          \__ \ (_| | \__ \                           |
#   |                          |___/\__, |_|___/                           |
#   |                                  |_|                                 |
#   '----------------------------------------------------------------------'

informix_transactions() {
    echo "<<<informix_transactions>>>"
    echo "[[[$INFORMIXSERVER/$SERVERNUM]]]"
    $EXECUTION_MODE "\"$INFORMIXDIR\"/bin/onstat -l" | grep C | tail -n 1
    $EXECUTION_MODE "\"$INFORMIXDIR\"/bin/onstat -x" | egrep -v 'IBM|maximum|Transactions|est.|userthread|logpos' | sed 's/:[^:]*$//'
}


#.
#   .--config--------------------------------------------------------------.
#   |                                      __ _                            |
#   |                      ___ ___  _ __  / _(_) __ _                      |
#   |                     / __/ _ \| '_ \| |_| |/ _` |                     |
#   |                    | (_| (_) | | | |  _| | (_| |                     |
#   |                     \___\___/|_| |_|_| |_|\__, |                     |
#   |                                           |___/                      |
#   '----------------------------------------------------------------------'

# Config opts:
# - oninit-path; Default is empty, which means autodetection:
#       ONINIT_PATH=<path to oninit-binary>
# - Excluding sections ("status sessions locks tabextents dbspaces logusage"):
#       EXCLUDES="SECTION SECTION ..."
#       EXCLUDES=ALL

# shellcheck source=agents/cfg_examples/informix.cfg
. "$MK_CONFDIR/informix.cfg" 2>/dev/null

if [ -z "$ONINIT_PATH" ] || [ ! -x "$ONINIT_PATH" ]; then
    ONINIT=$(UNIX95=true ps ax | grep oninit | grep -v grep | head -1 | awk '{print $1 " " $5}')
    if [ -z "$ONINIT" ]; then
        exit 0
    fi

    ONINIT_PATH=${ONINIT#* }
    ONINIT_PID=${ONINIT% *}
    case "$ONINIT_PATH" in
        /*) ;;

        *) # BUG not platform independent!
            ONINIT_PATH=$(readlink "/proc/$ONINIT_PID/exe")
            ;;
    esac

    # If not set in config or not found we end up here
    if [ -z "$ONINIT_PATH" ] || [ ! -f "$ONINIT_PATH" ]; then
        exit 1
    fi
fi

#.
#   .--main----------------------------------------------------------------.
#   |                                       _                              |
#   |                       _ __ ___   __ _(_)_ __                         |
#   |                      | '_ ` _ \ / _` | | '_ \                        |
#   |                      | | | | | | (_| | | | | |                       |
#   |                      |_| |_| |_|\__,_|_|_| |_|                       |
#   |                                                                      |
#   '----------------------------------------------------------------------'

INFORMIXDIR=${ONINIT_PATH%/bin*}

if [ ! -f "$INFORMIXDIR/bin/onstat" ]; then
    exit 1
fi

EXECUTION_MODE="$(get_binary_execution_mode "$INFORMIXDIR/bin/onstat" "$(get_binary_owner "$INFORMIXDIR/bin/onstat")")"

for IDSENV in $(
    $EXECUTION_MODE "$INFORMIXDIR/bin/onstat -g dis" |
        grep -E '^Server[         ]*:|^Server Number[     ]*:|^INFORMIX|^SQLHOSTS|^ONCONFIG' |
        sed -e 's/Server Number/SERVERNUM/' \
            -e 's/Server/INFORMIXSERVER/' \
            -e 's/SQLHOSTS/INFORMIXSQLHOSTS/' \
            -e 's/[     ]*:[    ]*/=/' |
        tr '\n' ';' |
        sed -e 's/;$/\n/' -e 's/;\(INFORMIXSERVER=[^;]*;\)/\n\1/g'

); do
    (
        set_env "$IDSENV"

        # try to set them via 'onstat -g env' otherwise
        # DB HAS TO BE RUNNING
        if [ -z "$INFORMIXSQLHOSTS" ] || [ -z "$ONCONFIG" ]; then
            $EXECUTION_MODE "$INFORMIXDIR/bin/onstat -g env" | grep -E -e '^INFORMIXSQLHOSTS' \
                -e '^ONCONFIG' |
                sed -e 's/[         ][      ]*/=/'
        fi

        informix_transactions
    )
done
