#!/bin/sh
# Copyright (C) 2004, 2005, 2006, 2007 Etersoft, Vitaly Lipatov <lav@etersoft.ru>
# $Id: winelauncher,v 1.89.2.17 2007/12/24 20:03:04 lav Exp $
# Redistribution of this file is permitted under the terms of the
# GNU Public License (GPL)

# Now: Allow world to read our dir...
UMASK=0002
umask $UMASK

BINDIR=`dirname $0`

# 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`

ETCDIR=$BINDIR/../etc/wine
[ -d $ETCDIR ] || ETCDIR=/etc/wine
DATADIR=$BINDIR/../share/wine
STATEDIR=/var/lib/wine

WINEDIAG=$BINDIR/winediag

# 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"
		exec $WINELOADER "$@" </dev/null
		# TODO use log, but check winelog too
		# >$WINEPREFIX/output.log 2>&1
	fi
}

map_drive()
{
	test -d "${DEV}" || { echo "Dosdevices dir '${DEV}' does not exists"; return 1; }
	test -e "$1" || { echo "!!! Warning: Target '$1' does not exists. Skip '$2' device creating." ; 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 -s "$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"
}

# 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
	export CROOT=${DEVDIR}/$SYSDRIVE

	echo "Using WINEPREFIX=$WINEPREFIX"
	[ -e $WINEDIAG ] || echo "Note: you use non-commercial, free build of WINE@Etersoft"

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

	# Tune admin setup
	if [ "$1" = "--admin" ]; then
		WINEMODE=$1
		shift
		WINEADMIN=$1 ; [ -z "$WINEADMIN" ] && WINEADMIN=default || shift
		[ `basename $WINEADMIN` = "$WINEADMIN" ] && WINEADMIN=$STATEDIR/$WINEADMIN
		[ -z "$WINEADMIN" ] && { echo "Use --admin with path to shared C:" ; exit 1; }
		mkdir -p $WINEADMIN 
		chgrp wineadmin $WINEADMIN 2>/dev/null && chmod 2775 $WINEADMIN || { echo "Shared dir $WINEADMIN cannot be accessed. Check you are in wineadmin group."; exit 1; }
		#UMASK=0002
	fi

	# Attach user to the directory
	if [ "$1" = "--attach" ]; then
		WINEMODE=$1
		shift
		WINEADMIN=$1 ; [ -z "$WINEADMIN" ] && WINEADMIN=default || shift
		[ -d $STATEDIR/$WINEADMIN ] && WINEADMIN=$STATEDIR/$WINEADMIN
		[ ! -d /$WINEADMIN ] && { echo "Prepared dir $WINEADMIN is not found"; exit 1; }
		[ ! -f $WINEADMIN/windows/inf/system.reg ] && { echo "Dir $WINEADMIN is not prepared dir"; exit 1; }

		ln -s dosdevices/$SYSDRIVE/windows/inf/system.reg ${WINEPREFIX}/system.reg
		ln -s dosdevices/$SYSDRIVE/windows/inf/userdef.reg ${WINEPREFIX}/userdef.reg
	fi

	export WINEMODE
	export WINEADMIN

	# Attach shared dir
	if [ -n "$WINEADMIN" ] ; then
		echo "Using shared WINE tree in $WINEADMIN"
		# load map_drive function
		#. $ETCDIR/map_devices.sh ""
		export DEV=${DEVDIR}
		map_drive $WINEADMIN $SYSDRIVE
	fi


	# TODO: use wineprefixcreate
	# Follows for each cycle is copied from wineprefixcreate
	echo "Creating default file tree..."
	for i in \
	    "$CROOT/windows" \
	    "$CROOT/windows/command" \
	    "$CROOT/windows/fonts" \
	    "$CROOT/windows/inf" \
	    "$CROOT/windows/system32" \
	    "$CROOT/windows/system32/color" \
	    "$CROOT/windows/system32/drivers" \
	    "$CROOT/windows/system32/spool" \
	    "$CROOT/windows/system32/spool/drivers" \
	    "$CROOT/windows/temp"
	do
	    mkdir -p "$i"
	done

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

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

	if [ ! -w $CROOT/$WINTEMP/ ] ; then
		echo "Broken environment. We need writable $CROOT/$WINTEMP/"
		exit 1
	fi

	# Copy .reg anf .inf files to CROOT (if writable)
	if [ -w "$CROOT/windows/inf/" ] ; then
		install -m664 "$DATADIR/wine.inf" "$CROOT/windows/inf/wine.inf"
		# Apply additional reg files from /etc
		ls -1 ${ETCDIR}/*.reg | sort | xargs cat > "${CROOT}/windows/inf/vendor.reg"
	fi

	# Copying from datadir if we have some prepared tree there
	if [ ! "$WINEMODE" = "--attach" ] && cd ${DATADIR}/skel 2>/dev/null ; then
		echo "Copying prepared tree from '${DATADIR}/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
		# FIXME: use hard links if possible, preserve attributions (like cp -p)
		find ./ -type f | $XARGS install -m 664 "QQQ" "${CROOT}/QQQ" 2>/dev/null
		chmod a+x ${CROOT}/windows/command/* 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"

	# Run in win98 mode for commercial version
	[ -e $WINEDIAG ] && export WINDOWS_VERSION="win98"

	$WINELOADER --version || { echo "$WINELOADER is broken on this system. Check for use appropriate 32-bit OS" ; exit 1; }

	echo "Initialize registry and environments..."
	"${WINELOADER}" rundll32.exe setupapi.dll,InstallHinfSection DefaultInstall 128 wine.inf
	"${WINELOADER}" regedit.exe "$CROOT/windows/inf/vendor.reg"

	# 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

	$WINESERVER -w

	# OLD: check for wineadmin : groups >/dev/null 2>&1 | grep wineadmin
	if [ -n "$WINEADMIN" ] ; then
		# attach to registry if not yet
		SYSREG=windows/inf/system.reg
		USERDEFREG=windows/inf/userdef.reg
		if [ ! -f ${CROOT}/$SYSREG ] && [ ! -L ${WINEPREFIX}/system.reg ] ; then
			mv ${WINEPREFIX}/system.reg "$CROOT/$SYSREG" && chgrp wineadmin "$CROOT/$SYSREG" 2>/dev/null
			ln -s dosdevices/c:/$SYSREG "$WINEPREFIX/system.reg"
			mv ${WINEPREFIX}/userdef.reg "$CROOT/$USERDEFREG" && chgrp wineadmin "$CROOT/$USERDEFREG" 2>/dev/null
			ln -s dosdevices/c:/$USERDEFREG "$WINEPREFIX/userdef.reg"
		fi
		chmod a+rwxt "$WINEADMIN/$PROFILES/" 2>/dev/null
		# Fix tmp permission
		chgrp wineadmin "$CROOT/$WINTEMP" 2>/dev/null && chmod a+rwxt "$CROOT/$WINTEMP" 2>/dev/null
	fi


	# Run /etc/wine scripts
	echo "Building local environment..."
	export DEV=${DEVDIR}
	for i in `ls -1 ${ETCDIR}/*.sh | sort` ; do
		[ -r $i ] && . $i ${DEVDIR}
	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

}

# 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
	echo "It is not recommended to run WINE as root"
	exit 1
fi

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


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

if [ ! -r ${WINEPREFIX}/user.reg ] ; then
	echo -n "First running... "
	update_wine $@

	echo "WINE@Etersoft has been configured for the first time."
	echo "Use ${HOME}/wine_c as WINE C:\\ disk."
	echo "Copy your program into and install it."
	echo
	[ -z "$1" ] && exit 0
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
	echo
	exit 1
fi

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
	exit 1
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
		echo
		exit 1
	else
		# check for version consistency
		CURLINE=`head -n2 < ${WINEPREFIX}/.etersoft-release | tail -n1`
		NEWLINE=`$WINELOADER --version | head -n1`
		if [ "$CURLINE" != "$NEWLINE" ] ; then
			echo "Run autoupdate due version changed to $NEWLINE"
			update_wine
			remove_printers
		fi
	fi
fi

if [ -z "$1" ] || [ "$1" = "--help" ] ; then
	$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 wineadmin group)"
	echo "       wine --removeprinters         Remove printer related registry entries"
	exit 0
fi

[ "$1" = "--admin" ] || [ "$1" = "--attach" ] && { echo "WINE $WINEPREFIX directory is already exists. Move it before attach to shared mode." ; exit 1; }

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

run_wine "$@"

