#!/bin/sh
# Copyright (C) 2004, 2005, 2006, 2007, 2008 Etersoft, Vitaly Lipatov <lav@etersoft.ru>
# Redistribution of this file is permitted under the terms of the
# GNU Public License (GPL)

WINECONFDIR=/etc/wine
SYSCONFDIR=/etc/sysconfig
WINEDATADIR=/usr/share/wine
STATEDIR=/var/lib/wine
exec_prefix=@exec_prefix@
BINDIR=/usr/bin

WINEADMGRP=wineadmin

# Use ~/.wine by default
[ -z "$WINEPREFIX" ] && export WINEPREFIX=${HOME}/.wine

PROGRESS=$WINEPREFIX/winesplash.progress

# Use /etc/wine/config for set UMASK or ATTACH_MODE
test -f $WINECONFDIR/config && . $WINECONFDIR/config

# Work in the group, allow world to read our dir for shared mode
[ -z "$UMASK" ] && export UMASK=0002

# FIXME: we do not need override it in right way
[ -z "$WINELOADER" ] && export WINELOADER=$BINDIR/wine-glibc
[ -z "$WINESERVER" ] && export WINESERVER=$BINDIR/wineserver
# missed on FreeBSD
[ -z "$UID" ] && export UID=`id -u`

test -n "$UMASK" && umask $UMASK

WINEDIAG=$BINDIR/winediag

# install is missed on Solaris
INSTALL=`which ginstall 2>/dev/null`
test -z "$INSTALL" && INSTALL=`which install 2>/dev/null`

stop_splash()
{
	rm -f "$PROGRESS"
}

signal_handler() {
	local rc=$?
	trap - HUP PIPE INT TERM QUIT EXIT
	stop_splash
	exit $rc
}

fatal()
{
	echo "$@" >&2
#	stop_splash
	exit 1
}

# trap signals to be able to correct exit from script
trap signal_handler HUP PIPE INT TERM QUIT EXIT

# run program with wine
run_wine()
{
	# run wineserver for more delay
	# $WINESERVER -p 7
	if tty -s ; then
		exec $WINELOADER "$@"
	else
		echo "$0: Running without console, disable input" >&2
		if false && [ -z "$WINELOGFILO" ] ; then
			exec $WINELOADER "$@" </dev/null >$WINEPREFIX/wine.log 2>$WINEPREFIX/wine.log
		else
			exec $WINELOADER "$@" </dev/null
		fi
	fi
}

init_splash()
{
	i_progress=0
	echo $i_progress >$PROGRESS
	# run wine splash
	$BINDIR/winesplash $PROGRESS $WINEDATADIR/winesplash.xpm 2>/dev/null >/dev/null &
}

step_progress()
{
	i_progress=$(($i_progress+8))
	if [ $i_progress -ge 100 ] ; then
		i_progress=99
	fi
	echo $i_progress >$PROGRESS
}

map_drive()
{
	test -d "${DEV}" || { echo "Dosdevices dir '${DEV}' does not exists" >&2; return 1; }
	test -e "$1" || { echo "Target '$1' does not exists. Skip '$2' device creating." >&2; return 1; }
	#test -e ${DEV}/$2 && { echo "    SKIP: Device '$2' already mapped as '$(readlink ${DEV}/$2)'"; return 0; }
	test -e ${DEV}/$2 && return 0;
	ln -sf "$1" ${DEV}/$2 && echo "Device '$2' created as link for '$1' target." || echo "Skipped $2"
	return 0
}

remove_printers()
{
	echo "Removing registry entries about printer drivers..."
	$WINELOADER regedit /D "HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Control\\Print\\Environments\\Windows 4.0\\Drivers"
	$WINELOADER regedit /D "HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Control\\Print\\Environments\\Windows NT x86\\Drivers"
	$WINELOADER regedit /D "HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Control\\Print\\Printers"
}

print_help()
{
	$WINELOADER
	echo "       wine --update                 Update WINE tree (registry and so on)"
	echo "       wine --attach [dir]           Attach user wine to shared dir"
	echo "       wine --admin [dir]            Create admin setup in shared dir (only for $WINEADMGRP group)"
	echo "       wine --removeprinters         Remove printer related registry entries"
}

# update or first run
update_wine()
{
	####### WINE dir preparing ########
	export DEVDIR=${WINEPREFIX}/dosdevices
	mkdir -p ${WINEPREFIX} ${DEVDIR}/unc
	export SYSDRIVE="c:"
	PROFILES=windows/profiles
	WINTEMP=windows/temp
	INFDIR=windows/inf
	SYSREG=$INFDIR/system.reg
	USERDEFREG=$INFDIR/userdef.reg
	export CROOT=${DEVDIR}/$SYSDRIVE

	echo "Using WINEPREFIX=$WINEPREFIX"
	date >>$WINEPREFIX/install.log
	init_splash

	# Kill all wine processes for any conflicts
	$WINESERVER -k 2>/dev/null

	if [ "$ATTACH_MODE" = "yes" ] || [ "$ATTACH_MODE" = "1" ] ; then
		WINEMODE="--attach"
	fi

	# get initialize mode from parameter
	if [ "$1" = "--admin" ] || [ "$1" = "--attach" ] ; then
		WINEMODE=$1
		shift
		WINEADMIN=$1
	fi

	if [ -n "$WINEMODE" ] ; then
		[ -z "$WINEADMIN" ] && WINEADMIN=default || shift
	fi

	# Tune admin setup
	if [ "$WINEMODE" = "--admin" ]; then
		[ `basename $WINEADMIN` = "$WINEADMIN" ] && WINEADMIN=$STATEDIR/$WINEADMIN
		[ -z "$WINEADMIN" ] && fatal "Use --admin with path to shared C:"

		# create shared dir and set permissions
		mkdir -p $WINEADMIN/$PROFILES $WINEADMIN/$WINTEMP $WINEADMIN/$INFDIR
		chgrp $WINEADMGRP $WINEADMIN 2>/dev/null && chmod 2775 $WINEADMIN || fatal "Shared dir $WINEADMIN cannot be accessed. Check you are in $WINEADMGRP group."
		chmod a+rwxt "$WINEADMIN/$PROFILES/" 2>/dev/null
		# Set tmp permission
		chgrp $WINEADMGRP "$WINEADMIN/$WINTEMP" 2>/dev/null && chmod a+rwxt "$WINEADMIN/$WINTEMP" 2>/dev/null

		# create empty registry files
		echo "WINE REGISTRY Version 2" > "$WINEADMIN/$SYSREG" && chgrp $WINEADMGRP "$WINEADMIN/$SYSREG" 2>/dev/null
		echo "WINE REGISTRY Version 2" > "$WINEADMIN/$USERDEFREG" && chgrp $WINEADMGRP "$WINEADMIN/$USERDEFREG" 2>/dev/null
	fi

	# Attach user to the directory
	if [ "$WINEMODE" = "--attach" ]; then
		[ -d $STATEDIR/$WINEADMIN ] && WINEADMIN=$STATEDIR/$WINEADMIN
		[ ! -d /$WINEADMIN ] && fatal "Prepared dir $WINEADMIN is not found"
		[ ! -f $WINEADMIN/$SYSREG ] && fatal "Dir $WINEADMIN is not prepared dir"
	fi

	export WINEMODE
	export WINEADMIN

	# Attach shared dir
	if [ -n "$WINEADMIN" ] ; then
		echo "Using shared WINE tree in $WINEADMIN"
		export DEV=${DEVDIR}
		# Make C: link to shared dir
		map_drive $WINEADMIN $SYSDRIVE
		# attach to shared registry
		ln -sf dosdevices/$SYSDRIVE/$SYSREG "$WINEPREFIX/system.reg"
		ln -sf dosdevices/$SYSDRIVE/$USERDEFREG "$WINEPREFIX/userdef.reg"
	fi

	WINDIR=$CROOT/windows

	if [ ! "$WINEMODE" = "--attach" ] ; then
		# Workaround for dir renaming:
		if test -d "$WINDIR/fonts" && ! test -d "$WINDIR/Fonts" ; then
			mv -f $WINDIR/fonts $WINDIR/Fonts
		fi

		#MS.NET is needed for some damaged program (see eterbug #1530)
		# TODO: use wineprefixcreate
		# Follows for each cycle is copied from wineprefixcreate
		echo "Creating default file tree..."
		for i in \
		    "$WINDIR/command" \
		    "$WINDIR/Fonts" \
		    "$WINDIR/inf" \
		    "$WINDIR/system32" \
		    "$WINDIR/system32/color" \
		    "$WINDIR/system32/drivers" \
		    "$WINDIR/system32/spool" \
		    "$WINDIR/system32/spool/PRINTERS" \
		    "$WINDIR/system32/spool/drivers" \
		    "$WINDIR/system32/spool/drivers/color" \
		    "$WINDIR/Microsoft.NET/Framework/v1.1.4322" \
		    "$WINDIR/temp"
		do
		    mkdir -p "$i"
		done

		# Make link for compatibility
		[ -e "$CROOT/windows/system" ] || ln -s system32 $CROOT/windows/system
	fi

	# Fix profile permission
	mkdir -p ${CROOT}/$PROFILES/$USER && chmod o-rwx ${CROOT}/$PROFILES/$USER

	[ -w $CROOT/$WINTEMP/ ] || fatal "Broken environment. We need writable $CROOT/$WINTEMP/"

	step_progress

	# Copy .reg files to CROOT (if writable)
	if [ -w "$CROOT/$INFDIR/" ] ; then
		# Apply additional reg files from /etc
		ls -1 ${WINECONFDIR}/*.reg | sort | xargs cat > "${CROOT}/$INFDIR/vendor.reg"
	fi

	# Copying from datadir if we have some prepared tree there
	if [ ! "$WINEMODE" = "--attach" ] && cd ${WINEDATADIR}/skel 2>/dev/null ; then
		echo "Copying prepared tree from '${WINEDATADIR}/skel' ..."
		XARGS="xargs -IQQQ"
		echo | $XARGS 2>/dev/null || XARGS="xargs -iQQQ"
		find ./ -type d | $XARGS install -m 2775 -d "${CROOT}/QQQ" 2>/dev/null
		find ./ -type f | $XARGS ln -sf "${WINEDATADIR}/skel/QQQ" "${CROOT}/QQQ" 2>/dev/null
		#chmod a+x ${CROOT}/windows/command/* 2>/dev/null
		#chmod a+x ${CROOT}/windows/system32/*.exe 2>/dev/null
		#find ./ -type f | $XARGS ln "QQQ" "${CROOT}/QQQ" 2>/dev/null
		cd - >/dev/null
	fi

	# jump to C: before run internal wine programs
	cd "$CROOT/$WINTEMP"
	step_progress

	# Run in win98 mode for commercial version
	if [ -e $WINEDIAG ] ; then
		export WINDOWS_VERSION="win98"
		export WINEDLLOVERRIDES="rpcrt4,ole32,oleaut32,olepro=b"
	fi

	$WINELOADER --version || fatal "$WINELOADER is broken on this system. Check for use appropriate 32-bit OS"

	# Create initial registry
	if [ ! -r ${WINEPREFIX}/user.reg ] ; then
		echo "Initialize registry and environments..."
		"${WINELOADER}" wineboot.exe --init
	else
		echo "Update registry and environments..."
	fi
	# Force update (--init do not perform registry update)
	"${WINELOADER}" wineboot.exe --update

	${WINELOADER} regedit.exe "$CROOT/$INFDIR/vendor.reg"
	step_progress

	# check for locking if network version
	WINELOCKTEST=$BINDIR/winelocktest
	if [ ! "$UID" = "0" ] && [ -e $WINELOCKTEST ] && ! "$WINELOCKTEST" >/dev/null ; then
		echo "Check for correct file locking..."
		$WINELOCKTEST
		echo "Error: Lock test is not passed for `pwd`. Wait troubles..."
	fi

	# immediately stop wineserver (it saves the registry)
	# $WINESERVER -k
	# Run /etc/wine scripts
	echo "Building local environment..."
	export DEV=${DEVDIR}
	for i in `ls -1 ${WINECONFDIR}/*.sh | sort` ; do
		[ -r $i ] && . $i ${DEVDIR}
		step_progress
	done

	# TODO: for better years
	# Tune WINE apps autostart during X login
	# mkdir -p ~/.xsession.d
	# test -f ~/.xsession.d/wineboot || ln -sf $BINDIR/wineboot ~/.xsession.d

	# for usability
	if [ ! -d ${HOME}/wine_c ] && [ ! -f ${HOME}/wine_c ] ; then
		rm -f ${HOME}/wine_c
		ln -s ${CROOT} ${HOME}/wine_c || :
	fi

	# Test for libwine-etersoft installed
	[ -e $WINEDIAG ] && ( echo "Please do not change this file." ; $WINELOADER --version ) >${WINEPREFIX}/.etersoft-release

	# $WINELOADER wineboot

	cd - >/dev/null
	stop_splash
	unset WINEDLLOVERRIDES
}

if [ "$1" = "--help" ] ; then
	print_help
	exit 0
fi

# Detect LinuxXP or Mandriva (Corporate distros)
if grep "Linux XP" /etc/fedora-release >/dev/null 2>/dev/null || [ -e /etc/mandriva-release ] || [ -e /usr/bin/viewboots ] ; then
	export ONECLICKDESKTOP=1
fi

if [ "$UID" = "0" ] && [ -z "$ONECLICKDESKTOP" ] ; then
	fatal "It is not recommended to run WINE as root"
fi

if [ "$1" = "--update" ]; then
	echo -n "Updating... "
	update_wine $@
	exit 0
fi

if [ -r ${WINEPREFIX}/user.reg ] ; then
    if [ "$1" = "--admin" ] || [ "$1" = "--attach" ] ; then
        fatal "WINE $WINEPREFIX directory is already exists. Move it before attach to shared C drive."
    fi
else
	echo -n "First running... "
	update_wine $@

	echo "`${WINELOADER} --version` has been configured for the first time."
	if [ -z "$1" ] ; then
		echo "Use ${HOME}/wine_c as WINE C:\\ disk."
		echo "Copy your program into and install it."
		echo
		exit 0
	fi
fi

# If all environment is already created
if [ -f ${WINEPREFIX}/config ] ; then
	echo "ERROR: You have UNUSED old config file in $WINEPREFIX." >&2
	echo "It is recommended to rename (remove) old $WINEPREFIX and set new WINE environment." >&2
	fatal ""
fi

# Disable due lazy write to registry files
#SYSREGSIZE=`cat ${WINEPREFIX}/system.reg | wc -c`
#if [ "$SYSREGSIZE" -le 100000 ] ; then
#	echo "ERROR: You have broken system.reg (it has $SYSREGSIZE bytes, fewer than 100000 bytes)" >&2
#	echo "Check your WINE installation or ask your support company" >&2
#	fatal ""
#fi

if [ -e "$WINEDIAG" ] ; then
	# Only if libwine-etersoft present
	$WINEDIAG >/dev/null 2>&1 || echo "Warning: there are some errors in winediag output. Run winediag command and check it." >&2
	if [ ! -f ${WINEPREFIX}/.etersoft-release ] ; then
		echo "ERROR: Your WINE dir ($WINEPREFIX) is obsoleted. It can cause some problems." >&2
		echo "It is recommended to rename (remove) old $WINEPREFIX and set new WINE environment." >&2
		echo "Also you can update you WINE tree with wine --update command." >&2
		fatal
	else
		# check for version consistency
		CURLINE=`head -n2 < ${WINEPREFIX}/.etersoft-release | tail -n1`
		NEWLINE=`$WINELOADER --version | head -n1`
		if false && [ "$CURLINE" != "$NEWLINE" ] && [ ! -r ${WINEPREFIX}/.noautoupdate ] ; then
			echo "Run autoupdate due version changed to $NEWLINE"
			update_wine
			remove_printers
		fi
	fi
fi

# If wine without params was called
if [ -z "$1" ] ;  then
	print_help
	exit 0
fi

if [ "$1" = "--removeprinters" ] ; then
	remove_printers
	exit 0
fi

if [ "$1" = "--admin" ] || [ "$1" = "--attach" ] ; then
        exit 0
fi

run_wine "$@"

