#!/bin/ksh -p
#
# ident "@(#)utlib64ctl.ksh	1.11	10/04/14 SMI"
#
# Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
# Use is subject to license terms.
#
#uncomment following line for debug output
#DEBUG=/var/log/SUNWut/utctl.`date '+%Y_%m_%d_%H:%M:%S'`.log; exec > $DEBUG 2>&1; set -x

set -u

########################################################################
#
# Installs the 64bit libraries onto the system.
# Creates architecture specific subdirectories
# with symbolic links to appropriate library
# (32-bit or 64-bit).
#
#
# NOTE: The libraries will be symbolically link to the target library.
#	This script will run on both 32-bit and 64-bit Linux installations.
#
########################################################################



########################################################################
#
# Operation entry points, one for each keyword.  This is where the
# specific work for this feature happens.
#
########################################################################


#
# disable()
#
disable() {
test -n "${DEBUG:-}" && set -x

	typeset REMOVED=false
	typeset PLATFORM_RM=false

	for F in $LIBRARY_LIST
	do
		if [ -L $DST_DIR_PRELD/$arch32/$F ] ; then
			rm -f $DST_DIR_PRELD/$arch32/$F
			PLATFORM_RM=true
		fi
	done
	rmdir $DST_DIR_PRELD/$arch32 $DST_DIR_PRELD >/dev/null 2>&1
	if $VERB && $PLATFORM_RM; then
		print "platform specific library links disabled"
	fi

	if [ ! -d ${TARGET_DIR} ]; then
		# target directory not found, nothing to disable
		return 0
	fi

	for F in $LIBRARY_LIST
	do
		if [ -L $DST_DIR_PRELD/$arch64/$F ] ; then
			rm -f $DST_DIR_PRELD/$arch64/$F
		fi
		if [ -L ${TARGET_DIR}/$F ] ; then
			rm -rf ${TARGET_DIR}/$F
			REMOVED=true
		fi
	done
	rmdir $DST_DIR_PRELD/$arch64 $DST_DIR_PRELD >/dev/null 2>&1
	if $VERB && $REMOVED; then
		print "64bit libraries disabled"
	fi
	return 0
}

#
# enable()
# NOTE: always overwriting any existing link.
#
enable() {
test -n "${DEBUG:-}" && set -x
	if [ -n "$arch32" ]
	then
	    test ! -d $DST_DIR_PRELD/$arch32 && mkdir -p $DST_DIR_PRELD/$arch32

	    for F in $LIBRARY_LIST
	    do
		if [ "$F" = "libc_ut.so" ]; then
                    ln -s -f ${SRC32_DIR}/$F $DST_DIR_PRELD/$arch32/$F
                else
                    ln -s -f ${SUNWUT}/lib/$F $DST_DIR_PRELD/$arch32/$F
                fi
	    done
	    if [ -d "$KIO_SRC32_DIR" ]  ; then
		for K in $KIOSK_LIBRARY_LIST
		do
		    ln -s -f ${KIO_SRC32_DIR}/$K $DST_DIR_PRELD/$arch32/$K
		done
	    fi
	    if $VERB; then
		    print "platform specific library links enabled"
	    fi
	fi

	if [ ! -d ${TARGET_DIR} ]; then
		# target directory not found, nothing to enable
		return 0
	fi

	test -n "$arch64" && test ! -d $DST_DIR_PRELD/$arch64 && mkdir -p $DST_DIR_PRELD/$arch64

	for F in $LIBRARY_LIST
	do
		ln -s -f ${SRC_DIR}/$F ${TARGET_DIR}/$F
		test -n "$arch64" && ln -s -f ${SRC_DIR}/$F $DST_DIR_PRELD/$arch64/$F
	done
	if [ -n "$arch64" -a -d "$KIO_SRC_DIR" ]  ; then
	    for K in $KIOSK_LIBRARY_LIST
	    do
		ln -s -f ${KIO_SRC_DIR}/$K $DST_DIR_PRELD/$arch64/$K
	    done
	fi
	if $VERB; then
		print "64bit libraries enabled"
	fi
	return 0
}

# This is a separate function to allow updating it (to use utprodinfo)
# or moving it to the utlctl framework when needed by further features.
kiosk_location() {
	# Kiosk is not really relocatable - save a utprodinfo call
	echo /opt/SUNWkio
}

#########################################
# LOCAL VARIABLES
# They must defined here to resolve the some of parameter resolution
# problem
#########################################
local_variables() {
test -n "${DEBUG:-}" && set -x
	# As opposed to SUNWUT this is not defined by the framework
	SUNWKIO=`kiosk_location`
	
	TARGET_DIR=/usr/lib64
	SRC_DIR=${SUNWUT}/lib64
	KIO_SRC_DIR=${SUNWKIO}/lib64
	LIBRARY_LIST="libc_ut.so"
	KIOSK_LIBRARY_LIST="pam_kiosk.so.1"
	LIBRARY_LIST="$LIBRARY_LIST pam_sunray_amgh.so.1"
	LIBRARY_LIST="$LIBRARY_LIST pam_sunray_hotdesk.so.1"
	LIBRARY_LIST="$LIBRARY_LIST sunray_get_user.so.1"
	SRC32_DIR=/usr/lib
	KIO_SRC32_DIR=${SUNWKIO}/lib
	DST_DIR_PRELD=${SUNWUTETC}/lib
	# below sets arch32 and arch64 if 64-bit platform
	determine_platform libc_ut.so ${SRC32_DIR}/libc_ut.so ${SRC_DIR}/libc_ut.so
}


#########################################
#
# Configurable parameter
#
#########################################
# NONE

#########################################
#
# variables used in the shared script utctl-shlib
#
#########################################
DESCR="sets up the 64bit libraries for Sun Ray programs"


########################################################################
#
# Execution starts here
#

#
# process Linux ldd output to extract substituted value for $PLATFORM
#
# finds first path component that is different and contains PLATFORM
#
# Example of ldd output on Linux showing $PLATFORM expansion on both
# 64-bit and 32-bit binaries:
#
# ldd /bin/cat
#    /etc/opt/SUNWut/lib/$PLATFORM/libc_ut.so => /etc/opt/SUNWut/lib/x86_64/libc_ut.so (0x0000002a95557000)
#    libc.so.6 => /lib64/tls/libc.so.6 (0x00000034c7700000)
#    libdl.so.2 => /lib64/libdl.so.2 (0x00000034c7500000)
#    /lib64/ld-linux-x86-64.so.2 (0x00000034c7300000)
#
# ldd /opt/SUNWut/bin/utaction
#    /etc/opt/SUNWut/lib/$PLATFORM/libc_ut.so => /etc/opt/SUNWut/lib/i686/libc_ut.so (0xf7ffb000)
#    linux-gate.so.1 =>  (0xffffe000)
#    libutsession.so.1 => /opt/SUNWut/bin/../lib/libutsession.so.1 (0xf7ff5000)
#    libutoscompat.so.1 => /opt/SUNWut/bin/../lib/libutoscompat.so.1 (0xf7ff2000)
#    libnsl.so.1 => /lib/libnsl.so.1 (0xf7faf000)
#    libX11.so.6 => /usr/X11R6/lib/libX11.so.6 (0x00a2a000)
#    libc.so.6 => /lib/tls/libc.so.6 (0x00536000)
#    libdl.so.2 => /lib/libdl.so.2 (0x00662000)
#    libm.so.6 => /lib/tls/libm.so.6 (0x00668000)
#    /lib/ld-linux.so.2 (0x0051d000)
#
ldd_platform_string() {
awk '#
/ERROR: ld\.so/	{next};
/PLATFORM/	{np1=split($1,path1,"/");
		 np2=split($3,path2,"/");
		 if (np1 == np2) {
		     for (i=1; i<=np1; i++) {
			 if (path1[i] == path2[i])
			     continue;
			 if (path1[i] ~ /PLATFORM/) {
			     print path2[i];
			     break;
			 }
		     }
		 }
		}
' "$@"
}

#
# generate a list of possible 64-bit/32-bit platform
# strings that the run-time loader will use for 32-bit
# values of $PLATFORM and 64-bit values of $PLATFORM.
# uname -m output will be the likely 64-bit architecture name
#
# Porting note:  The list of platform strings is in the
# Linux glibc-2.3.6 source code.
# see file sysdeps/<arch>/dl-procinfo.c PROCINFO_DECL
# which is included by sysdeps/generic/ldsodefs.h
# also file sysdeps/<arch>/dl-machine.h ELF_MACHINE_NAME
#
get_platform_candidates() {
    echo  "`uname -m`" "`uname -p`" "`uname -i`" \
	  "x86_64" "i386"  "i486"  "i586"  "i686"
}

#
# test a list of possible 64-bit/32-bit platform strings
# to determine which ones the run-time loader actually uses.
#
# ARGUMENTS:
#    $1	basename of pre-loadable library to test with
#    $2	full pathname of 32-bit pre-loadable library to test with
#    $3	full pathname of 64-bit pre-loadable library to test with
#
# OUTPUT:
#    sets shell variable arch32
#    sets shell variable arch64 (only if 64-bit platform)
#
determine_platform() {
test -n "${DEBUG:-}" && set -x
    typeset tdir adir nbits platform_strings
    if [ "$OS" = "Linux" -a -d ${SUNWUT} ]
    then
	nbits=`file /bin/cat | sed 's/^.*\([0-9][0-9]\)-bit.*$/\1/'`
	tdir=/tmp/lddtest$$
	mkdir -p $tdir
	platform_strings=`get_platform_candidates`
	for arch in $platform_strings
	do
	    adir=$tdir/lib/$arch
	    if [ ! -d $adir ]
	    then
		mkdir -p $adir
		case $arch in
		    *64*)	if [ "$nbits" = 64 ]
		    		then
				    test -f $3 && ln -s $3 $adir
				else
				    test -f $2 && ln -s $2 $adir
				fi
			    ;;
		       *)	test -f $2 && ln -s $2 $adir
			    ;;
		esac
	    fi
	done
	DEBUGOUT=${DEBUG:+&2}
	DEBUGOUT=${DEBUGOUT:-/dev/null}
	export LD_PRELOAD=$tdir/lib/\$PLATFORM/$1
	arch32=`ldd ${SUNWUT}/bin/utaction 2>&1 | ldd_platform_string - 2>$DEBUGOUT`
	eval arch$nbits=`ldd /bin/cat 2>&1 | ldd_platform_string - 2>$DEBUGOUT`
	unset LD_PRELOAD
	rm -rf $tdir
    fi
}

PROGPATH=`dirname $0`
. $PROGPATH/utctl-shlib
