#!/bin/sh -fu
#
# Copyright (C) 2019  Paul Wolneykien <manowar@altlinux.org>
#
# This file is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.

MAXCOMMENTSIZE=2048
NSCA_DEFAULT_HOST="${NSCA_DEFAULT_HOST:-$(hostname -s)}"
NSCA_DEFAULT_SVC="${NSCA_DEFAULT_SVC:-}"
NSCA_DEFAULT_PERSISTENT=${NSCA_DEFAULT_PERSISTENT:-0}
NSCA_DEFAULT_AUTHOR="${NSCA_AUTHOR:-$USER}"
HISTTIMEFORMAT="${HISTTIMEFORMAT:-%Y-%m-%d %H:%M:%S }"

PROG="${0##*/}"
PROG_VERSION=1.0.0

_newline="
"

SHELL=/bin/bash

show_help()
{
	cat <<EOF
Usage: $PROG [options] [service_name] -- [shell arguments...]

$PROG is a tool to record a typescript of a terminal session
and then send it to a Nagios monitoring server in order to keep
a log of operations with a particular host or service.

Options:

  -H HOST, --host=HOST      connect to the NSCA server at address
                            HOST;

  -P POST, --port=PORT      connect to the NSCA server at port PORT;

  -t SEC, --timeout=SEC     set connection timeout to SEC seconds;

  -p, --persistent          send typescript data as persistent
                            comments;

  -a NAME, --author=NAME    use NAME for the author name
                            (default is \$USER);

  -s SHELL, --shell=SHELL   run SHELL instead of $SHELL;
                            WARNING! $PROG depends on
                            ~/.bash_history file --- if SHELL is not
                            bash-compatible then nothing or wrong
                            typescript data would be sent!

  -T FMT, --timeformat=FMT  use FMT for timestamps; the default
                            is current \$HISTTIMEFORMAT or
                            "%Y-%m-%d %H:%M:%S "

  -V,--version              print program version and exit;
  -h,--help                 show this text and exit.


Service name: With service name specified $PROG sends the typescript
with the ADD_SVC_COMMENT Nagios command. Otherwise, ADD_HOST_COMMENT
command is used.

Shell arguments: all subsequent argements are passed to the SHELL.

Environment:

  \$NSCA_DEFAULT_HOST    the name of the operation host (default is
                         hostname -s);

  \$NSCA_DEFAULT_SVC     the name of the service (can also be set
                         on the command line);

  \$NSCA_DEFAULT_PERSISTENT  persistent comment flag (can also be
                             set on the command line);

  \$NSCA_DEFAULT_AUTHOR  the name of the author (can also be set
                         on the command line);

  \$HISTTIMEFORMAT       timestamp format (can also be set on the
                         command line).


Report bugs to http://bugs.altlinux.ru/

EOF
}

print_version()
{
	cat <<EOF
$PROG version $PROG_VERSION
Written by Paul Wolneykien <manowar@altlinux.org>

Copyright (C) 2020 Paul Wolneykien <manowar@altlinux.org>
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE.
EOF
}

show_usage()
{
	cat <<EOF
Usage: $PROG [options] [service_name] -- [shell arguments...]

Run \`$PROG -h\` to see the help page.
EOF
}


OPTS=`getopt -n $PROG -o H:,P:,t:,p,a:,s:,T:,V,h \
             -l host:,port:,timeout:,persistent,author:,shell:,timeformat:,version,help -- "$@"` ||
	show_usage
eval set -- "$OPTS"

host=
port=
timeout=

while :; do
	case "$1" in
		-H|--host)
            shift
            host="$1"
            ;;
		-P|--port)
            shift
            port="$1"
            ;;
		-t|--timeout)
            shift
            timeout="$1"
            ;;
		-p|--persistent)
            NSCA_DEFAULT_PERSISTENT=1
            ;;
        -a|--author)
            shift
            NSCA_DEFAULT_AUTHOR="$1"
            ;;
        -s|--shell)
            shift
            SHELL="$1"
            ;;
        -T|--timeformat)
            shift
            HISTTIMEFORMAT="$1"
            ;;
		-V|--version)
            print_version
            exit 0
            ;;
		-h|--help)
            show_help
            exit 0
            ;;
        --)
            shift
            break
            ;;
		*)
            echo "Unrecognized option: $1" >&2
            exit 1
            ;;
	esac
	shift
done

if [ $# -gt 0 ]; then
    NSCA_DEFAULT_SVC="$1"
    shift
fi


### Functions

_send_history()
{
    local text="$1"

    [ -n "$text" ] || return

    if [ -n "$NSCA_DEFAULT_SVC" ]; then
        printf '%s\t%s\t%d\t%s\t%s' \
               "$NSCA_DEFAULT_HOST" \
               "$NSCA_DEFAULT_SVC" \
               $NSCA_DEFAULT_PERSISTENT \
               "$NSCA_DEFAULT_AUTHOR" \
               "$text" | \
            send_nsca ${host:+-H $host} ${port:+-p $port} ${timeout:+-to $timeout} -C
    else
        printf '%s\t%d\t%s\t%s' \
               "$NSCA_DEFAULT_HOST" \
               $NSCA_DEFAULT_PERSISTENT \
               "$NSCA_DEFAULT_AUTHOR" \
               "$text" | \
            send_nsca ${host:+-H $host} ${port:+-p $port} ${timeout:+-to $timeout} -C
    fi
}


### Interactive session and the typescript

if [ -n "$HISTTIMEFORMAT" ]; then
    NSCA_SESSION_START="$(date +"$HISTTIMEFORMAT")Session started for user $USER..."
else
    NSCA_SESSION_START=
fi

cat >"$HOME/.nsca_shell_rc" <<EOF
if [ -e "$HOME/.bashrc" ]; then
    . "$HOME/.bashrc"
fi

truncate -s 0 $HOME/.nsca_shell_typescript
chmod 0600 $HOME/.nsca_shell_typescript
trap "history -a $HOME/.nsca_shell_typescript" EXIT
export HISTTIMEFORMAT="$HISTTIMEFORMAT"
EOF

"$SHELL" --rcfile "$HOME/.nsca_shell_rc" "$@"

cat "$HOME/.nsca_shell_typescript" | (
    text=; timestamp=

    if [ -n "$NSCA_SESSION_START" ]; then
        text="$NSCA_SESSION_START"
    fi

    while read -r cmd; do
        if [ -n "$HISTTIMEFORMAT" ]; then
            if [ -z "$timestamp" ]; then
                timestamp="$(date -d "@${cmd#\#}" +"$HISTTIMEFORMAT")"
                continue #read next line
            else
                cmd="$timestamp$cmd"
                timestamp=
            fi
        fi

        if [ $((${#text} + ${#cmd})) -gt $MAXCOMMENTSIZE ]; then
            _send_history "$text"
            text=
        fi


        text="$text$_newline$cmd"
    done

    _send_history "$text"
)
