#!/bin/sh

# Copyright (c) 2017, Luca Pizzamiglio <pizzamig@FreeBSD.org>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice, this
#   list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright notice,
#   this list of conditions and the following disclaimer in the documentation
#   and/or other materials provided with the distribution.
#
# * Neither the name of the copyright holder nor the names of its
#   contributors may be used to endorse or promote products derived from
#   this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

# Force ifconfig into expected format
export IFCONFIG_FORMAT=addr:default

# Environment initialization and initial checks

# shellcheck disable=SC2034
_POT_VERSION=0.16.0
_POT_PATHNAME="$(realpath "$0")"
_POT_PREFIX="$(dirname "${_POT_PATHNAME}")"
_POT_INCLUDE="$( realpath "${_POT_PREFIX}/../share/pot")"
_POT_ETC="$( realpath "${_POT_PREFIX}/../etc/pot")"
if [ -d "${_POT_ETC}/flavours" ]; then
	_POT_FLAVOUR_DIR="$( realpath "${_POT_ETC}/flavours")"
else
	# shellcheck disable=SC2034
	_POT_FLAVOUR_DIR=
fi

if [ ! -d "${_POT_INCLUDE}" ]; then
	echo "Fatal error! Not able to find the subroutines directory as ${_POT_INCLUDE}!"
	exit 1
fi

# loading subroutines

if [ ! -r "${_POT_INCLUDE}/common.sh" ]; then
	echo "Fatal error! Not able to find common subroutines in ${_POT_INCLUDE}!"
	exit 1
fi
# shellcheck disable=SC1090
. "${_POT_INCLUDE}/common.sh"

if [ ! -r "${_POT_INCLUDE}/common-flv.sh" ]; then
	echo "Fatal error! Not able to find flavor subroutines in ${_POT_INCLUDE}!"
	exit 1
fi
# shellcheck disable=SC1090
. "${_POT_INCLUDE}/common-flv.sh"

if [ ! -r "${_POT_INCLUDE}/network.sh" ]; then
	echo "Fatal error! Not able to find network subroutines in ${_POT_INCLUDE}!"
	exit 1
fi
# shellcheck disable=SC1090
. "${_POT_INCLUDE}/network.sh"

# loading configuration
if [ -r "$_POT_ETC/pot.default.conf" ]; then
	# shellcheck disable=SC1090
	. "$_POT_ETC/pot.default.conf"
else
	_error "Fatal error! Not able to find default configuration file on $_POT_ETC"
	exit 1
fi

if [ -r "$_POT_ETC/pot.conf" ]; then
	# shellcheck disable=SC1090
	. "$_POT_ETC/pot.conf"
fi

usage() {
	cat <<-"EOF"
	Usage: pot command [options]

	Commands:
	    help    -- Show help
	    version -- Show version of the pot command
	    config  -- Show pot framework configuration
	    ls/list -- List of the installed pots
	    show    -- Show information on pots
	    info    -- Print minimal information on a pot
	    top     -- Run top(1) inside the pot
	    ps      -- Show running pots
	    init    -- Initialize the ZFS layout
	    de-init -- Remove pot from your system
	    vnet-start -- Start vnet configuration
	    create-base -- Create a new base image
	    create-fscomp -- Create a new fs component
	    create-private-bridge -- Create a new private bridge
	    create -- Create a new pot (jail)
	    clone -- Clone a pot, creating a new one
	    clone-fscomp -- Clone an fscomp
	    rename -- Rename a pot
	    destroy -- Destroy a pot
	    prune   -- Destroy non-running, prunable pots
	    copy-in -- Copy a file or a directory into a pot
	    copy-out -- Copy a file or a directory out of a pot
	    mount-in -- Mount directory, ZFS dataset, or fscomp into a pot
	    mount-out -- Unmount directory, ZFS dataset, or fscomp from a pot
	    add-dep -- Add a dependency
	    set-rss -- Set a resource constraint
	    get-rss -- Get the current resource usage
	    set-cmd -- Set the command to start the pot
	    set-env -- Set environment variables inside a pot
	    set-hosts -- Set /etc/hosts entries inside a pot
	    set-hook -- Set hook scripts for a pot
	    set-attribute/set-attr -- Set an attribute on a pot
	    get-attribute/set-attr -- Get an attribute from a pot
	    export-ports -- Allows exposing tcp and udp ports
	    start -- Start a pot (jail)
	    stop -- Stop a pot (jail)
	    term -- Open terminal inside of a pot
	    run -- Same as term, but start pot if it is not running
	    snap/snapshot -- Take a snapshot of a pot
	    rollback/revert -- Restore the latest snapshot
	    purge-snapshots -- Remove old/all snapshots
	    export -- Export a pot to a file
	    import -- Import a pot from a file or a URL
	    prepare -- Import and prepare a pot, used by orchestrators
	    update-config -- Update the configuration of a pot
	    last-run-stats -- Get statistics about a pot's last run
	    signal -- Send signal to pot
	    exec -- Execute a progam inside of a pot
	EOF
}

# shellcheck disable=SC2034
# variable initialization
_POT_VERBOSITY=1

# parsing command line subcommand
if [ $# -lt 1 ]; then
	usage
	exit 1
fi
CMD="$1"
shift

case "${CMD}" in
	ls)
		CMD=list
		;;
	rollback)
		CMD=revert
		;;
	snap)
		CMD=snapshot
		;;
	set-attr)
		CMD=set-attribute
		;;
	get-attr)
		CMD=get-attribute
		;;
esac

case "${CMD}" in
	help)
		if [ -n "$1" ]; then
			pot-cmd "${CMD}" "$1"
			exit 0
		else
			usage
			exit 0
		fi
		;;
	show|version|config|\
	list|info|ps|top|\
	init|de-init|vnet-start|\
	create-base|create-fscomp|create|\
	create-private-bridge|\
	copy-in|copy-out|mount-in|mount-out|prune|set-hook|\
	destroy|add-dep|set-rss|get-rss|set-cmd|set-env|set-hosts|\
	export|import|prepare|\
	export-ports|set-attribute|get-attribute|\
	start|stop|term|\
	rename|clone|clone-fscomp|promote|\
	snapshot|revert|purge-snapshots|update-config|\
	last-run-stats|signal|exec|set-status)
		pot-cmd "${CMD}" "$@"
		exit $?
		;;
	run)
		pot-cmd term -f "$@"
		exit $?
		;;
	*)
		usage
		exit 1
		;;
esac
