#!/bin/bash
# Etersoft, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2015, 2017, 2019, 2020, 2021, 2022, 2023, 2024
# 2010-2015, 2017 (c) Vitaly Lipatov <lav@etersoft.ru>
# 2012 (c) Denis Baranov <baraka@etersoft.ru>
# Без параметров - список погребов
# с названием погреба - список полок
# с названием полки - список бутылок
# с полкой/бутылкой - вход, если есть.

# Переводит пользователя под пользователя wine
# Устанавливает авторизацию для доступа к Иксам
# Настраивает wine на соотв. рабочий каталог
# Использует sudo su - wine и xhost
# TODO: добавить поддержку chroot, внутренних скриптов настройки (монтирования), иксов
# TODO: добавить поиск
# TODO: добавить перемещение
# TODO: добавить upload

PROGRAM_DESCRIPTION="Etersoft's racks and bottles handler. (c) 2006-2015, 2017, 2019, 2020, 2021, 2022, 2023, 2024"
PROGRAM_VERSION="swine version 1.9.10"

print_message()
{
	local DESC="$1"
	shift
	echo "$DESC in $(basename $0): $@"
}

# Print error message and stop the program
fatal()
{
	print_message Error "$@" >&2
	exit 1
}

if [ "$UID" = "0" ]; then
	fatal "It is forbidden to run swine as root"
fi

if [ "$LANG" = "C" ] ; then
	fatal "Don't run me in C locale (check $ locale output)"
fi

### copied from etersoft-build-utils common

# FIXME on Android: FIX ME! implement ttyname_r() bionic/libc/bionic/stubs.c:366
inputisatty()
{
	# check stdin
	tty -s 2>/dev/null
}

isatty()
{
	# check stdout
	test -t 1
}

isatty2()
{
	# check stderr
	test -t 2
}

check_tty()
{
	isatty2 || return

	# Set a sane TERM required for tput
	[ -n "$TERM" ] || TERM=dumb
	export TERM

	# egrep from busybox may not --color
	# egrep from MacOS print help to stderr
	if egrep --help 2>&1 | grep -q -- "--color" ; then
		export EGREPCOLOR="--color"
	fi

	which tput >/dev/null 2>/dev/null || return
	# FreeBSD does not support tput -S
	echo | tput -S >/dev/null 2>/dev/null || return
	[ -z "$USETTY" ] || return
	export USETTY=1
}

check_tty

: ${BLACK:=0} ${RED:=1} ${GREEN:=2} ${YELLOW:=3} ${BLUE:=4} ${MAGENTA:=5} ${CYAN:=6} ${WHITE:=7}

set_boldcolor()
{
	[ "$USETTY" = "1" ] || return
	{
		echo bold
		echo setaf $1
	} |tput -S
}

restore_color()
{
	[ "$USETTY" = "1" ] || return
	{
		echo op; # set Original color Pair.
		echo sgr0; # turn off all special graphics mode (bold in our case).
	} |tput -S
}

echover()
{
    [ -z "$verbose" ] && return
    echo "$*" >&2
}

# echo string without EOL
echon()
{
	# default /bin/sh on MacOS does not recognize -n
	/bin/echo -n "$@"
}

# Print command line and run command line
showcmd()
{
	if [ -z "$quiet" ] ; then
		set_boldcolor $GREEN
		local PROMTSIG="\$"
		[ "$EFFUID" = 0 ] && PROMTSIG="#"
		echo " $PROMTSIG $@"
		restore_color
	fi >&2
}

# Print command line and run command line
docmd()
{
	showcmd "$@$EXTRA_SHOWDOCMD"
#CHECKME
	"$@"
}



check_ssh_key()
{
	echo "Check access to SSH private key..."
	ssh-add -l >/dev/null && return
	ssh-add $SSH_KEYFILE && return
	fatal "Please, check your ssh-agent settings."
}

##### end of the copy

check_swine_alias()
{
    local SWINEALIAS=/etc/etersoft/swine.alias
    [ -r "$SWINEALIAS" ] || fatal "No $SWINEALIAS file"
    local RES=$(grep "^$1 " $SWINEALIAS)
    [ -n "$RES" ] || return
    echo "$RES" | sed -e "s|.* ||g"
}

list_swine_alias()
{
    local SWINEALIAS=/etc/etersoft/swine.alias
    [ -r "$SWINEALIAS" ] || fatal "No $SWINEALIAS file"
    cat $SWINEALIAS | grep -v "^#" | sed -e "s| .*||"
}

list_swine_alias_pretty()
{
    local SWINEALIAS=/etc/etersoft/swine.alias
    [ -r "$SWINEALIAS" ] || fatal "No $SWINEALIAS file"
    curhost=''
    cat $SWINEALIAS | grep -v "^#" | sort -k2 | while read f1 host ; do
        if [ "$curhost" != "$host" ] ; then
            set_boldcolor $CYAN
                echo "    $host"
            restore_color
            curhost="$host"
        fi
        [ "$host" != "$f1" ] && printf "        %-30s\n" "$f1"
    done
}

try_hostalias()
{
	# allow only one entry
	[ -n "$REALCELLARNAME" ] && return 1

	# redefine default bottle from the first script arg
	REALCELLARNAME=$(check_swine_alias "$1")
	if [ -n "$REALCELLARNAME" ] ; then
		CELLARNAME=$REALCELLARNAME
		return 0
	fi
	return 1
}

# you can override that defaults in /etc/etersoft/swine.conf or in ~/.config/swine.conf
# default bottle
CELLARNAME=winestaging64
# local company domain
DOMAINNAME=office.etersoft.ru
# remote ssh alias
#SERVERNAME="seni.etersoft.ru -p32"
SERVERNAME="office"
# opt args for ssh (see eterbug #10725)
SSH_OPTS=''
#"-o Compression=no -o ControlMaster=auto -o ControlPath=$TMPDIR/ssh_mux_%h_%p_%r -o ControlPersist=4h "
# default shell to run
COMMANDTORUN=bash
# server side temp dir for tarballs for download
ARDIR=/var/ftp/tmp/wine
# root bottle dir
BOTDIR=/net/wine
# wine user
WINEUSER=wine
# used transfer format
TARFORMAT=tar
#epm assure 7z p7zip || exit
#epm assure xz || exit
TARFORMAT_ASSURE="tar tar"
PEOPLE=people

[ -r /etc/etersoft/swine.conf ] && . /etc/etersoft/swine.conf
[ -r ~/.config/swine.conf ] && . ~/.config/swine.conf

[ -n "$TMPDIR" ] || TMPDIR=/tmp
[ -w "$TMPDIR" ] || fatal "Can't write to tmpdir '$TMPDIR'"

if [ -z "$1" ] ; then
	echo "List of available cellars (with aliases):"
	list_swine_alias_pretty
	exit 0
fi

if [ "$1" = "--version" ] ; then
		echo "$PROGRAM_VERSION"
		exit
fi

if [ "$1" = "-h" ] || [ "$1" = "--help" ] ; then
		echo "$PROGRAM_DESCRIPTION"
		echo "$PROGRAM_VERSION"
		echo "Check http://winehq.org.ru/swine for description in Russian"
		echo "Usage:"
		echo "swine [cellar] [options] [rackname][/][bottle name] [shell command]"
		echo "      cellar - alias name or hostname to connect (run without args to get the list)"
		echo "      rackname (R) - name of the rack to use"
		echo "      bootle name (B) - name of the bottle in the rack to use"
		echo
		echo "Options:"
		echo "      --remove R/B                remove the bottle (rack)"
		#echo "      --search [-s] name         search for the bottle name"
		echo "      --clone [-o] R/B [-p] R/B   clone the source bottle to the new bottle (-p is allowed also)"
		echo "      --download [-d] [-p] R/B         download tarball with bottle"
		echo "      --Download [-D] [-p] R/B         download tarball with bottle and unpack it"
		echo "      --upload [-u] <dir or archive> R/B  upload tarball (or dir) with a bottle and unpack it to R/B bottle"
		#echo "      --move  <rack/bottle> <rack/bottle>   move  the bottle to other rack"
		echo "      --private [-p] B            use private bottle B (see $PEOPLE/USER/bottle"
		echo "      --local [-l]                use local host instead remote host"
		#echo "      --host [-h]                use another host for bottle"
		echo "      --recursive [-r]            recursive bottle list (--Recursive|-R for list $PEOPLE bottles too)"
		echo "      --force                     force login to used bottle"
		echo "      --ssh [-s]                  use ssh tunnel instead direct DISPLAY (default for remote connections)"
		echo "      --rx [-t]                   connect with rxclient with use NX protocol"
		echo "      --create [-c] [description] create the bottle (use WINEARCH=win32 swine to create 32 bit bottle)"
		echo "      --quiet [-q]                make silent output"
		echo
		echo "Examples:"
		echo " $ swine [rackname] -- lists available racks & bottles"
		echo " $ swine vanilla -d bugs/1234 -- download tarball for bugs/1234 wine prefix from vanilla container"
		echo " $ swine vanilla --nx bugs/1234 -- download tarball for bugs/1234 wine prefix from vanilla container"
		exit 0
fi

PASSTO=''

# TODO: divide on swine and swine-internal
if [ "$1" = "--internal" ] ; then
	shift
	INTERNAL=1
else

while [ -n "$1" ] ; do
	if try_hostalias "$1" ; then
		shift
		continue
	fi
	case "$1" in
		-l|--local)
			LOCALRUN=1
			;;
		-t|--rx|--nx)
			NXMODE=1
			;;
		-s|--ssh)
			SSHTUNNEL=1
			;;
		-d|--download)
			DOWNLOAD=1
			;;
		-D|--Download)
			DOWNLOAD=1
			UNPACK_TARBALL=1
			;;
		-u|--upload)
			UPLOAD=1
			;;
		-p|--private|--remove|-o|--clone|-r|--recursive|-R|--Recursive|--force|-c|--create|-q|--quiet)
			PASSTO="$PASSTO $1"
			;;
		-*|--*)
			# do not handle any other params here
			fatal "Unknown option '$1'. Use -h or --help for get help."
			;;
		*)
			PASSTO="$PASSTO $1"
			;;
	esac
	shift
done
set -- $PASSTO
fi


if [ -z "$INTERNAL" ] ; then

	REMOTECMD=
	# out of the office
	if [ -z "$LOCALRUN" ] && ! hostname -d | grep -q "$DOMAINNAME\$" ; then
		echo "Running out of the Etersoft office (your domain is $(hostname -d)) is detected"
		REMOTECMD="ssh -t -Y -C -A $SSH_OPTS $SERVERNAME"
		if [ -z "$NXMODE$SSHTUNNEL" ] ; then
			echo "Force using ssh tunnel to $SERVERNAME"
			SSHTUNNEL=1
		fi
		# TODO: use pipe and <<< like in gluster script
		remote_run()
		{
			$REMOTECMD ssh $SSH_OPTS $WINEUSER@$CELLARNAME "\"$@\""
		}
	else
		# TODO: use pipe and <<< like in gluster script
		remote_run()
		{
			ssh $SSH_OPTS $WINEUSER@$CELLARNAME "$@"
		}
	fi

	# Check for repeatable entry
	if [ -n "$ORIG_USER" ] && [ "$USER" = "$WINEUSER" ] && [ `hostname -s` = "$CELLARNAME" ] ; then
		fatal "You are already in wine '$CELLARNAME' :)"
	fi

	# Заходим локально
	# TODO: obsoleted
	if false && [ -n "$LOCALRUN" ] ; then
		export CELLARNAME=`hostname -s`
		# TODO: replace with xauth
		# read man xhost
		IP=+$HOSTNAME
		test -z "$IP" && IP=+localhost
		# if DISPLAY is local, allow for local
		echo "$DISPLAY" | grep -q "^:" && IP=local:
		xhost $IP

		echo "Local bottling to $CELLARNAME (allow X access for $IP)"
		# Put some env vars through userchange, f.i. NXSESSIONID
		sudo /bin/su - $WINEUSER -c "CELLARNAME=$CELLARNAME NXSESSIONID=$NXSESSIONID swine --internal $USER --display $DISPLAY $*"
		exit

	elif [ -n "$UPLOAD" ] ; then

		[ -z "$1" ] && fatal "Missing local name for upload"
		LOCAL_BOTTLE="$1"
		shift

		[ -z "$1" ] && fatal "Missing remote bottle name for upload"
		UPLOAD_BOTTLE="$@"
		shift

		check_ssh_key || exit

		epm assure $TARFORMAT_ASSURE || fatal

		if [ -d "$LOCAL_BOTTLE" ] ; then
			LOCAL_TAR="$LOCAL_BOTTLE.tar"
			if [ -s "$LOCAL_TAR" ] ; then
				echo "Skipping create already existing tarball $LOCAL_TAR"
			else
				docmd epm tool erc a $LOCAL_TAR $LOCAL_BOTTLE || fatal "Can't pack"
			fi
		else
			LOCAL_TAR="$LOCAL_BOTTLE"
		fi

		PATHCELLARTMP=$ARDIR/$LOCAL_TAR

		epm assure rsync || fatal
		echo "Uploading tarball to remote place ..."
		RSYNC_OPT='-z --compress-level=1'
		# use optimal compression for remote transfer (via Internet)
		[ -n "$REMOTECMD" ] && RSYNC_OPT='-z'
		docmd rsync -av $RSYNC_OPT --inplace --fuzzy --partial --progress -e "$REMOTECMD ssh $SSH_OPTS" $LOCAL_TAR $WINEUSER@$CELLARNAME:$PATHCELLARTMP || exit

		$REMOTECMD ssh -t $SSHOPTIONS $SSH_OPTS $WINEUSER@$CELLARNAME swine --internal $USER $UPLOAD_BOTTLE --unpack $PATHCELLARTMP || exit

		[ "$LOCAL_TAR" = "$LOCAL_BOTTLE" ] || rm -v "$LOCAL_TAR"
		echo "Done, run $ swine $CELLARNAME $UPLOAD_BOTTLE to use it."
		exit 0

	elif [ -n "$DOWNLOAD" ] ; then

		TARGETRACK=''
		while [ -n "$1" ] ; do
			case "$1" in
				-p)
					TARGETRACK=$PEOPLE/$USER
					;;
				-*)
					fatal "Unknown option '$1'"
					;;
				*)
					DOWNLOAD_BOTTLE="$1"
					;;
			esac
			shift
		done

		[ -n "$DOWNLOAD_BOTTLE" ] || fatal "Missing bottle name for download"

		check_ssh_key || exit

		DOWNLOADDIR=$(pwd)

		DIR_BOTTLE=`dirname $DOWNLOAD_BOTTLE`
		if [ -n "$TARGETRACK" ] ; then
			[ "$DIR_BOTTLE" = "." ] && DIR_BOTTLE=$TARGETRACK || DIR_BOTTLE=$TARGETRACK/$DIR_BOTTLE
		else
			[ "$DIR_BOTTLE" = "." ] && fatal "Incorrect bottle name $DOWNLOAD_BOTTLE"
		fi

		PREFIXNAME="$CELLARNAME"
		[ -n "$PREFIXNAME" ] || PREFIXNAME="wine"
		echo "$PREFIXNAME" | grep -q ^wine || PREFIXNAME="wine-$PREFIXNAME"
		TARNAME=$PREFIXNAME-$(echo $DOWNLOAD_BOTTLE | sed -e 's|/|-|g')

		BOTTLENAME=".wine-$(basename $DOWNLOAD_BOTTLE)"

		PATHCELLARTMP=$ARDIR/$TARNAME.$TARFORMAT
		PATH_BOTTLE="$BOTDIR/bottles/$DIR_BOTTLE"

		if remote_run test -s $PATHCELLARTMP ; then
			echo "Tarball $SERVERNAME:$CELLARNAME:$PATHCELLARTMP already exists, do not recreate. Skipping."
		else
			echo "Archiving remote bottle $PATH_BOTTLE/$BOTTLENAME to $CELLARNAME:$PATHCELLARTMP tarball"
			# remove if failed
			# TODO: skip drive_c/users/*
			if ! remote_run "cd $PATH_BOTTLE && epm tool erc --quiet create $PATHCELLARTMP $BOTTLENAME" ; then
				remote_run rm -vf $PATHCELLARTMP
				exit 1
			fi
		fi

		epm assure rsync || fatal
		RSYNC_OPT='-z --compress-level=1'
		# use optimal compression for remote transfer (via Internet)
		[ -n "$REMOTECMD" ] && RSYNC_OPT='-z'
		echo "Downloading tarball to local place $DOWNLOADDIR/$TARNAME.$TARFORMAT ..."
		docmd rsync -av $RSYNC_OPT --inplace --partial --fuzzy --progress -e "$REMOTECMD ssh $SSH_OPTS" $WINEUSER@$CELLARNAME:$PATHCELLARTMP $TARNAME.$TARFORMAT || exit

		epm assure $TARFORMAT_ASSURE || exit
		if ! docmd epm tool erc test $TARNAME.$TARFORMAT ; then
			echo "Tarball is broken, remove it from all!"
			echo "Removing local tarball ..."
			rm -v $TARNAME.$TARFORMAT
			echo "Removing remote tarball $SERVERNAME:$CELLARNAME:$PATHCELLARTMP ..."
			remote_run rm -v $PATHCELLARTMP
			exit 1
		fi

		if [ -n "$UNPACK_TARBALL" ] && [ -d "$BOTTLENAME" ] ; then
			echo "Downloaded bottle $BOTTLE is already exists locally in $(pwd)."
			echo "Remove something and rerun the command."
			exit 1
		fi

		echo "Removing remote tarball $SERVERNAME:$CELLARNAME:$PATHCELLARTMP ..."
		remote_run rm -v $PATHCELLARTMP

		if [ -n "$UNPACK_TARBALL" ] ; then
			echo "Unpacking bottle .$TARNAME to the current dir $(pwd)"
			epm tool erc --quiet extract $TARNAME.$TARFORMAT || exit

			echo "Removing local tarball..."
			rm -v $DOWNLOADDIR/$TARNAME.$TARFORMAT
		else
			echo "Completed. You can unpack the tarball with command 'epm tool erc $DOWNLOADDIR/$TARNAME.$TARFORMAT'"
		fi
		exit 0

	elif [ "$USER" != "$WINEUSER" ] || [ `hostname -s` != "$CELLARNAME" ] ; then

		# Конектимся через nx
		if [ -n "$NXMODE" ] ; then
		    echo "Run in NX mode"
		    [ -n "$NXCLIENT" ] || NXCLIENT="rxclient"
		    [ -n "$NXCLIENT_CONFIG" ] || NXCLIENT_CONFIG="$HOME/.nx/config/swine.nxs"
		    if [ ! -e "$NXCLIENT_CONFIG" ]; then
			echo "Copying default nxclient configuration..."
			mkdir -p `dirname "$NXCLIENT_CONFIG"`
			cp /etc/etersoft/swine.nxs $NXCLIENT_CONFIG
		    fi
		    [ -n "$NXCOMMAND" ] || NXCOMMAND="xterm -e swine -l $@"
		    sed -i -e "s|<option key=\"Server host\" value=\".*\"|<option key=\"Server host\" value=\"$CELLARNAME\"|g" $NXCLIENT_CONFIG
		    sed -i -e "s|<option key=\"Command line\" value=\".*\"|<option key=\"Command line\" value=\"$NXCOMMAND\"|g" $NXCLIENT_CONFIG
		    $NXCLIENT --session "$NXCLIENT_CONFIG"
		    exit 0
		fi

		check_ssh_key || exit

		# FIXME: xhost contains some security issues
		#export ORIG_USER=$USER
		if [ -n "$SSHTUNNEL" ] ; then
			OURDISPLAY=NONE
			SSHOPTIONS="-Y"
		else
			xhost +$CELLARNAME
			OURDISPLAY="$DISPLAY"
			HOSTFROM=${OURDISPLAY/:*/}
			# FIXME: in hope we will can ping from cellar back to our host
			CURRENTHOST="$(hostname)"
			[ -z "$HOSTFROM" ] && OURDISPLAY="$CURRENTHOST$OURDISPLAY"
			SSHOPTIONS=""
		fi

		arg_winearch=''
		[ -n "$WINEARCH" ] && arg_winearch="--winearch $WINEARCH"
		[ -n "$QUIET" ] || echo "\$> $REMOTECMD ssh -t $SSHOPTIONS $SSH_OPTS $WINEUSER@$CELLARNAME swine --internal $USER --display $OURDISPLAY $arg_winearch $@"
		$REMOTECMD ssh -t $SSHOPTIONS $SSH_OPTS $WINEUSER@$CELLARNAME swine --internal $USER --display $OURDISPLAY $arg_winearch "$@"
		exit
	fi

	fatal "Logical error. Direct run in cellar is unsupported."
fi

##########################################################################################
# Internal entry on cellar host
##########################################################################################

export CELLARNAME=`hostname -s`

# like BOTDIR, but locally
BOTPATH=~/bottles

export ORIG_USER=$1
shift

if [ "$1" = "--display" ] ; then
	shift
	[ "$1" = "NONE" ] || export DISPLAY="$1"
	shift
fi

if [ "$1" = "--winearch" ] ; then
	shift
	[ "$1" = "NONE" ] || export WINEARCH="$1"
	shift
fi

get_runfile()
{
	echo $HOME/tmp/run-${RACK//\//_}-$BOTTLE
}

get_holder()
{
	#local BOTTLE=$1
	head -n 1 $TPBOTTLE | cut -d " " -f 2
	# TODO: print out name of the person
}

print_comment()
{
	local COMFILE="$1/comment"
	if [ -r "$COMFILE" ] ; then
		head -n1 < "$COMFILE" | cat
	fi
}

# Save comment to
set_comment()
{
	local COMFILE="$1/comment"
	shift
	local COMMENT="$@"
	if [ -n "$COMMENT" ] ; then
		touch "$COMFILE"
		if [ -w "$COMFILE" ] ; then
			echo "Just update comment: '$COMMENT'"
		else
			echo "Error: can't write comment"
			return 1
		fi
		echo "$COMMENT" | cat > "$COMFILE" || return 1
	else
		return 1
	fi
	return 0
}

print_creator()
{
	local COMFILE="$1/creator"
	if [ -r "$COMFILE" ] ; then
		echo -n ", created by "
		head -n1 < "$COMFILE" | cat
	fi
}

set_creator()
{
	local COMFILE="$1/creator"
	shift
	echo "$ORIG_USER" > "$COMFILE" || return 1
	return 0
}

# Print list racks and bottles, call print_list RACK [step N]
print_list()
{
	local LB RACK=$1 RACKCOM BOTCOM STEP=0
	shift
	if [ "$1" = "step" ] ; then
		shift
		STEP=$1
		shift
	else
		if [ -z "$QUIET" ] ; then
			if [ -z "$RACK" ] ; then
				echo "List of available racks on $CELLARNAME:"
			else
				RACKCOM=$(print_comment "$BOTPATH/$RACK")
				[ -n "$RACKCOM" ] && RACKCOM=" ($RACKCOM)"
				echo "List of available bottles in the '$RACK'$RACKCOM rack:"
			fi
		fi
	fi

	# List available racks (exclude symlinks)
	LD=`(cd $BOTPATH ; find $RACK -maxdepth 1 -type d 2>/dev/null | grep -v "^$RACK\$" | grep -v "^\.\$" | grep -v "\.wine" | sort | sed -e "s|^\./||g")`
	for INRA in $LD ; do
		[ -z "$RACK" ] && [ -L "$BOTPATH/$INRA" ] && continue
		if [ -n "$QUIET" ] ; then
			echo "$INRA"
		else
			RACKCOM=$(print_comment "$BOTPATH/$INRA")
			printf "%-${STEP}s" ""
			set_boldcolor $CYAN
			printf "  %-30s %s\n" "[R] $(basename $INRA)" "$RACKCOM"
			restore_color
		fi
		if [ -z "$RECURSIVEFULL" ] && [ "$INRA" = "$PEOPLE" ] ; then
			printf "%-4s" ""
			echo "  (use '-R' for list $PEOPLE too, or '-r $PEOPLE' for list $PEOPLE separately)"
			continue
		fi
		if [ -n "$RECURSIVE" ] ; then
			print_list "$INRA" step $(($STEP + 4))
			[ "$STEP" = "0" ] && [ -z "$QUIET" ] && echo
		fi
	done

	# List available bottles
	LB=`(cd $BOTPATH ; find $RACK -maxdepth 1 -type d -name ".wine-*" 2>/dev/null | grep -v "^$RACK\$" | sort)`
	for FD in $LB ; do
		BOTTLE=$(echo $FD | sed 's|.*\.wine-||g')

		if [ -n "$QUIET" ] ; then
			echo "$RACK/$BOTTLE"
		else
			TPBOTTLE=$(get_runfile)
			PROGNAME="$BOTTLE"
			[ -e "$TPBOTTLE" ] && PROGNAME+="  (USED by $(get_holder))"
			BOTCOM=$(print_comment "$BOTPATH/$RACK/.wine-$BOTTLE")
			BOTCRE=$(print_creator "$BOTPATH/$RACK/.wine-$BOTTLE")
			printf "%-${STEP}s" ""
			printf "  %-$((30 - $STEP))s %s\n" "$PROGNAME" "$BOTCOM$BOTCRE"
		fi
	done

	# Print if the rack is empty
	if [ -z "$LB$LD" ] && [ -n "$RACK" ] && [ -z "$QUIET" ] ; then
		printf "%-${STEP}s" ""
		echo "  empty"
		return 1
	fi

}

# Check for rack part (check real dir exists too)
get_rack()
{
	local DN=$(dirname -- "$1")
	if [ -d "$BOTPATH/$1" ] || echo "$1" | grep '.*/$' >/dev/null; then
		echo "$1" | sed 's|/$||g'
		return
	fi
	if [ "$DN" = "." ] ; then
		echo "$1" | sed 's|/.*||g'
	else
		echo "$DN"
	fi
}

# Check for bottle part (check real dir exists too)
get_bottle()
{
	local BN=$(basename -- "$1")
	if [ -d "$BOTPATH/$1" ] || echo "$1" | grep '.*/$' >/dev/null; then
		echo ""
		return
	fi
	if [ "$BN" = "$1" ] || [ "$BN/" = "$1" ] ; then
		echo ""
	else
		echo "$BN"
	fi
}

FORCE=
REMOVE=
CREATE=
PRIVATE=
RECURSIVE=
RECURSIVEFULL=
QUIET=
CLONE=
UNPACK=
COMNAME=
COMNAME2=

# skip unknown options
while [ -n "$1" ] ; do
	case "$1" in
		--force)
			FORCE=yes
			;;
		--remove)
			REMOVE=yes
			;;
		-c|--create)
			CREATE=yes
			;;
		-p|--private)
			PRIVATE=yes
			;;
		-r|--recursive)
			RECURSIVE=yes
			;;
		-R|--Recursive)
			RECURSIVE=yes
			RECURSIVEFULL=yes
			;;
		-q|--quiet)
			QUIET=yes
			;;
		-o|--clone)
			CLONE=yes
			;;
		--unpack)
			UNPACK=yes
			shift
			UNPACK_TARBALL="$1"
			;;
		-*)
			echo "Note: Skip unknown option '$1'"
			;;
		*)
			# [ -n "$COMNAME2" ] && echo "Noke: Skip unknown arg '$1'"
			[ -z "$COMNAME" ] && COMNAME="$1" || COMNAME2="$COMNAME2 $1"
			;;
	esac
	shift
done

# run without args: lists available racks
if [ -z "$COMNAME" ] ; then
	if [ -n "$PRIVATE" ] ; then
		RACK="$PEOPLE/$ORIG_USER"
	else
		RACK=""
	fi
	print_list "$RACK"
	exit 0
fi

[ -z "$QUIET" ] || echo "$PROGRAM_DESCRIPTION"

RACK=$(get_rack "$COMNAME")
BOTTLE=$(get_bottle "$COMNAME")

if [ -n "$PRIVATE" ] && [ -z "$CLONE" ] ; then
	RACK="$PEOPLE/$ORIG_USER"
	BOTTLE="$COMNAME"
fi

##################################################################3
# Run with rack name only
if [ -z "$BOTTLE" ] && [ -n "$RACK" ] ; then

	# Create rack if needed
	if [ -n "$CREATE" ] ; then
		if [ -e "$BOTPATH/$RACK" ] ; then
			echo "$BOTPATH/$RACK already exists."
			set_comment "$BOTPATH/$RACK" "$COMNAME2"
			exit $?
		fi
		echo Create "$BOTPATH/$RACK"
		mkdir -p "$BOTPATH/$RACK" || exit 1
		set_comment "$BOTPATH/$RACK" "$COMNAME2"
		exit 0
	fi

	# List bottles
	if [ -d "$BOTPATH/$RACK" ] ; then
		print_list "$RACK"
		if [ "$?" = "1" ] && [ -n "$REMOVE" ]; then
			rmdir "$BOTPATH/$RACK" || exit 1
			echo "Rack '$RACK' is succesfully removed"
			exit 0
		fi
	else
		echo "'$RACK' rack does not exist. You can create it with command 'swine $RACK -c [Rack description]'"
	fi
	exit 0
fi

# If DISPLAY is broken
if ! xset -b ; then
	echo "Warning: you have no access to your X server from $CELLARNAME. Check with ps -ax | grep X for nolisten tcp. Check local DISPLAY variable."
	echo "Also you can use swine without direct DISPLAY with --ssh option (for local connections)."
fi


################################################################
# Run with full path to bottle
BOTTLEDIR="$BOTPATH/$RACK"
BOTTLENAME=".wine-$BOTTLE"
export WINEPREFIX="$BOTTLEDIR/$BOTTLENAME"

TPBOTTLE=$(get_runfile)
COMNAME="$RACK/$BOTTLE"
set -- $COMNAME2

if [ -n "$UNPACK" ] ; then
	[ -s "$UNPACK_TARBALL" ] || fatal "Can't find $UNPACK_TARBALL."
	mkdir -p $BOTTLEDIR && cd $BOTTLEDIR || fatal "Can't create $BOTTLEDIR"
	[ -d "$BOTTLENAME" ] && fatal "Bottle name '$BOTTLENAME' is already used"
	mkdir $BOTTLENAME.tmp && cd $BOTTLENAME.tmp || fatal "Can't create $BOTTLENAME.tmp dir"
	epm tool erc $UNPACK_TARBALL && mv -v $(find -mindepth 1 -maxdepth 1 -type d) ../$BOTTLENAME || fatal "Can't unpack"
	cd - && rmdir $BOTTLENAME.tmp || fatal
	rm -v $UNPACK_TARBALL
	echo "$ORIG_USER" > $WINEPREFIX/creator
	echo "uploaded from $(basename $UNPACK_TARBALL)" > $WINEPREFIX/comment
	exit 1
fi

if [ -n "$CLONE" ] ; then
	if [ ! -d "$WINEPREFIX" ] ; then
		echo "Source bottle $RACK/$BOTTLE does not exist ($WINEPREFIX path)"
	else
		if [ -n "$PRIVATE" ] ; then
			TARGETRACK=$PEOPLE/$ORIG_USER
			mkdir -p $TARGETRACK
			TARGETBOTTLE="$1"
			[ -n "$TARGETBOTTLE" ] || TARGETBOTTLE="$BOTTLE"
		else
			TARGETRACK=$(get_rack "$1")
			TARGETBOTTLE=$(get_bottle "$1")
			[ -n "$TARGETBOTTLE" ] || fatal "Can't be used with empty bottle name"
		fi
		[ -d "$BOTPATH/$TARGETRACK" ] || fatal "'$TARGETRACK' rack does not exist. You can create it with command 'swine $TARGETRACK -c [Rack description]'"
		TARGETBOTTLENAME="$TARGETRACK/.wine-$TARGETBOTTLE"
		[ -d  "$BOTPATH/$TARGETBOTTLENAME" ] && fatal "$TARGETBOTTLENAME is already exists."
		echo "Copying `basename $WINEPREFIX` to $TARGETBOTTLENAME ..."
		mkdir -p "$BOTPATH/$TARGETRACK"
		# Allow CoW with --reflink=auto (we use BTRFS)
		cp -a --reflink=auto "$WINEPREFIX" "$BOTPATH/$TARGETBOTTLENAME" || fatal
		set_comment "$BOTPATH/$TARGETBOTTLENAME" "cloned from $COMNAME by $ORIG_USER"
		set_creator "$BOTPATH/$TARGETBOTTLENAME" "$ORIG_USER"
		echo "Done."
	fi
	exit 0
fi

if [ -n "$FORCE" ] ; then
	rm -f "$TPBOTTLE"
fi

if [ -f "$TPBOTTLE" ] ; then
	BOTTLEUSER=$(cat "$TPBOTTLE")
	if [ "$BOTTLEUSER" = "$ORIG_USER" ] ; then
		echo "Attention: you already entered somewhere"
	else
		fatal "$COMNAME bottle is already used by $(get_holder). You can override it with --force key"
	fi
fi

if [ -n "$REMOVE" ] ; then
	[ -d "$WINEPREFIX" ] || fatal "Bottle $RACK/$BOTTLENAME does not exist"
	chmod u+rwX "$WINEPREFIX" -R
	rm -r "$WINEPREFIX" || exit 1
	echo "Bottle $RACK/$BOTTLE succesfully removed"
	exit 0
fi

# Set we use this bottle
echo "$ORIG_USER" > "$TPBOTTLE" || exit 1

if [ -d "$WINEPREFIX" ] ; then
	if [ -n "$CREATE" ] ; then
		# just change a comment when run create twice
		set_comment "$WINEPREFIX" "$@"
		rm -f "$TPBOTTLE"
		exit 0
	fi
else
	if [ -n "$CREATE" ] ; then
		# initial wine creating
		mkdir -p "$WINEPREFIX"
		WINECOMMAND=wine
		! which $WINECOMMAND 2>/dev/null && which wine64 >/dev/null 2>/dev/null && WINECOMMAND=wine64
		# wine vanilla needs precreated prefix and some command to run
		$WINECOMMAND cmd.exe /C ver
		# disable autoupdate prefix
		echo "disable" > "$WINEPREFIX/.update-timestamp"
		set_comment "$WINEPREFIX" "$@"
		set_creator "$WINEPREFIX" "$@"
		set -- ''
		exit 0
	else
		echo "Error: '$COMNAME' bottle does NOT exist, run with '-c <comment>' to force create it"
		rm -f "$TPBOTTLE"
		exit 1
	fi
fi

echo "Your are on `hostname` host in '$COMNAME' Wine bottle$(print_creator $WINEPREFIX)..."
cd "$WINEPREFIX" || exit
WINEPKGVERSION=$(epmqf --quiet wine | epm --quiet print version-release for package)
WINEPKGNAME=$(epmqf --quiet --short wine | sed -e 's|-common||')
export HISTFILE=$WINEPREFIX/.bash_history
export PS1="[$WINEPKGNAME-$WINEPKGVERSION@\h:$COMNAME \W]\$ "
[ -n "$1" ] && "$@" || $COMMANDTORUN
rm -f "$TPBOTTLE"
