#!/bin/bash

################################################################################
# Copyright (C) 2010-2026 NICE s.r.l.
# Copyright (C) 2004-2009 IBM Corporation
# All Rights Reserved
#
# This software is the confidential and proprietary information
# of NICE s.r.l. ("Confidential Information").
# You shall not disclose such Confidential Information
# and shall use it only in accordance with the terms of
# the license agreement you entered into with NICE.
################################################################################

RETVAL=0

prog="dcvgladmin"

dcv_version=2026.0.1122

glvnd_enabled=1

current_uid=`id -u`

SELinuxMode=`getenforce 2> /dev/null`
if [ -z "${SELinuxMode}" ]; then
    SELinuxMode="Disabled"
fi

basedir="/var/lib/dcv-gl"

_copyright_message() {
    which dcv >/dev/null 2> /dev/null
    if [ $? -eq 0 ]; then
        dcv version
    fi
}

_info() {
    if [ -n "$verbose" ]; then
        echo "INFO: $1"
    fi
}

_printf_verbose () {
    if [ -n "$verbose" ]; then
        printf "$1"
    fi
}

_warning() {
    echo "WARNING: $1"
}

_error() {
    echo "ERROR: $1"

    if [ $# -gt 1 ]; then
        echo "       $2"
    fi
}

backup_suffix=".dcv-backup"

arch=$(uname -m)

if [ -f /usr/lib/nvidia/libGL.so.1 ]; then
    nvidia32dir="/usr/lib/nvidia/"
elif [ -f /usr/lib/i386-linux-gnu/libGL.so.1 ]; then
    nvidia32dir="/usr/lib/i386-linux-gnu/"
else
    nvidia32dir="/usr/lib/"
fi

dcv_lib="${nvidia32dir}libGL.so.99999.99999.99999"
usr_lib="${nvidia32dir}libGL.so.1"
sys_lib="$basedir/lib/libGL_SYS.so.1.0.0"
dcv_glvnd_lib="${nvidia32dir}libGLX_dcv.so.0"

if [ -f /usr/lib/i386-linux-gnu/dcv-gl/libGL_WRAPPER.so.1.0.0 ]; then
    wrapper_lib="/usr/lib/i386-linux-gnu/dcv-gl/libGL_WRAPPER.so.1.0.0"
else
    wrapper_lib="/usr/lib/dcv-gl/libGL_WRAPPER.so.1.0.0"
fi

dcv_gl_32_installed="0"
if [ ! -f "$wrapper_lib" ]; then
    dcv_gl_32_installed="1"
fi

if [ -f /usr/lib/i386-linux-gnu/dcv-gl/libGLX_dcv.so.0 ]; then
    vendor_lib="/usr/lib/i386-linux-gnu/dcv-gl/libGLX_dcv.so.0"
else
    vendor_lib="/usr/lib/dcv-gl/libGLX_dcv.so.0"
fi

dcv_glvnd_32_installed="0"
if [ ! -f "$vendor_lib" ]; then
    dcv_glvnd_32_installed="1"
fi

if [ -f /usr/lib64/nvidia/libGL.so.1 ]; then
    nvidia64dir="/usr/lib64/nvidia/"
elif [ -f /usr/lib/x86_64-linux-gnu/libGL.so.1 ]; then
    nvidia64dir="/usr/lib/x86_64-linux-gnu/"
elif [ -f /usr/X11R6/lib64/libGL.so.1 ]; then
    nvidia64dir="/usr/X11R6/lib64/"
elif [ -f /usr/lib/nvidia*/libGL.so.1 ]; then
    nvidia64dir=$(find /usr/lib/nvidia* -name  "libGL.so.1" | awk  -F 'libGL.so.1' 'NR==1{print $1}')
else
    nvidia64dir="/usr/lib64/"
fi

dcv_lib64="${nvidia64dir}libGL.so.99999.99999.99999"
usr_lib64="${nvidia64dir}libGL.so.1"
sys_lib64="$basedir/lib64/libGL_SYS.so.1.0.0"
dcv_glvnd_lib64="${nvidia64dir}libGLX_dcv.so.0"

if [ -f /usr/lib/x86_64-linux-gnu/dcv-gl/libGL_WRAPPER.so.1.0.0 ]; then
    wrapper_lib64="/usr/lib/x86_64-linux-gnu/dcv-gl/libGL_WRAPPER.so.1.0.0"
else
    wrapper_lib64="/usr/lib64/dcv-gl/libGL_WRAPPER.so.1.0.0"
fi

if [ -f /usr/lib/x86_64-linux-gnu/dcv-gl/libGLX_dcv.so.0 ]; then
    vendor_lib64="/usr/lib/x86_64-linux-gnu/dcv-gl/libGLX_dcv.so.0"
else
    vendor_lib64="/usr/lib64/dcv-gl/libGLX_dcv.so.0"
fi

get_glvnd_system_lib_realpath() {

    local bit=$1
    ret=""

    for glvnd_path in $(/sbin/ldconfig -p 2>/dev/null | grep libGLX.so.0 | sed -r 's/^.*=>\s//g'); do
        local res="$(od -An -t x1 -j 4 -N 1 "$glvnd_path" | xargs)"
        if [ "$res" == "01" -a "$bit" == "32" ] || [ "$res" == "02" -a "$bit" == "64" ]; then
            ret=$(readlink -f "$glvnd_path")
        fi
    done

    echo $ret
}

glvnd_do_enable() {

    local bit=$1
    local ret=1

    mkdir -p "$basedir" 2> /dev/null

    if [ "$bit" = "32" ] || [ "$dcv_glvnd_32_installed" = "0" -a "$bit" != "64" ]; then
        _check 32 glvnd
        if [ $? -eq 0 ]; then
            echo "DCV GL (GLVND) 32 is ALREADY enabled."
            ret=0
        else
            if [ ! -f "$vendor_lib" ]; then
                _error "Cannot find the DCV GL (GLVND) libGLX_dcv.so.0 32bit library."
                echo "DCV GL (GLVND) cannot be enabled for 32 bit applications."
                return 1
            fi
            cp -af "$vendor_lib" "$dcv_glvnd_lib"
            if [ $? -ne 0 ]; then
                _error "Failed to copy the DCV GL (GLVND) libGLX_dcv.so.0 32bit library."
                echo "DCV GL (GLVND) cannot be enabled for 32 bit applications."
                return 1
            fi

            local glvnd_system_lib_realpath=$(get_glvnd_system_lib_realpath 32)
            if [ -n "$glvnd_system_lib_realpath" ]; then
                echo "$glvnd_system_lib_realpath:32" >> "$basedir/backup"
                if [ $? -eq 0 ]; then
                    echo "DCV GL (GLVND) has been enabled for 32 bit applications."
                    ret=0
                else
                    _error "Failed to copy GLVND 32 bit library realpath to $basedir/backup"
                fi
            else
                _error "Failed to get the GLVND 32 bit library realpath."
            fi
        fi
    fi

    if [ "$bit" != "32" ]; then
        _check 64 glvnd
        if [ $? -eq 0 ]; then
           echo "DCV GL (GLVND) 64 is ALREADY enabled."
           ret=0
        else
            if [ ! -f "$vendor_lib64" ]; then
                _error "Cannot find the DCV GL (GLVND) libGLX_dcv.so.0 64 bit library."
                echo "DCV GL (GLVND) cannot be enabled for 64 bit applications."
                return 1
            fi
            cp -af "$vendor_lib64" "$dcv_glvnd_lib64"
            if [ $? -ne 0 ]; then
                _error "Failed to copy the DCV GL (GLVND) libGLX_dcv.so.0 64 bit library."
                echo "DCV GL (GLVND) cannot be enabled for 64 bit applications."
                return 1
            fi

            local glvnd_system_lib64_realpath=$(get_glvnd_system_lib_realpath 64)
            if [ ! -z $glvnd_system_lib64_realpath ]; then
                echo "$glvnd_system_lib64_realpath:64" >> "$basedir/backup"
                if [ $? -eq 0 ]; then
                    echo "DCV GL (GLVND) has been enabled for 64 bit applications."
                    ret=0
                else
                    _error "Failed to copy GLVND 64 bit library realpath to $basedir/backup"
                fi
            else
                _error "Failed to get the GLVND 64 bit library realpath."
            fi
        fi
    fi

    # Ensure we have the right permissions on the base dir
    if [ -d "${basedir}" ]; then
        chmod 755 -R "${basedir}"
    fi

    return $ret
}

glvnd_do_disable() {

    local ret=1
    local bit=$1

    _info "Disabling DCV GL for 32 bit applications..."
    if [ "$bit" = "32" ] || [ "$dcv_glvnd_32_installed" = "0" -a "$bit" != "64" ]; then
        _check 32 glvnd
        if [ $? -eq 0 ]; then
            rm -f "$dcv_glvnd_lib" 2>/dev/null
            if [ $? -ne 0 ]; then
                _error "Failed to remove the DCV GL GLVND libGLX_dcv.so.0 32 bit library."
                echo "DCV GL (GLVND) cannot be disabled for 32 bit applications."
                return 1
            fi
            sed -i '/:32/d' "$basedir/backup"
            if [ $? -ne 0 ]; then
                _error "Failed to remove the GLVND 32 bit library realpath from $basedir/backup"
                return 1
            else
                echo "DCV GL (GLVND) has been disabled for 32 bit applications."
                ret=0
            fi
        else
            echo "DCV GL (GLVND) is NOT enabled for 32 bit applications."
            ret=0
        fi
    fi

    if [ "$bit" != "32" ]; then
        _check 64 glvnd
        if [ $? -eq 0 ]; then
            rm -f "$dcv_glvnd_lib64" 2>/dev/null
            if [ $? -ne 0 ]; then
                _error "Failed to remove the DCV GL GLVND libGLX_dcv.so.0 64 bit library."
                echo "DCV GL (GLVND) cannot be disabled for 64 bit applications."
                ret=1
            fi
            sed -i '/:64/d' "$basedir/backup"
            if [ $? -ne 0 ]; then
                _error "Failed to remove the GLVND 64 bit library realpath from $basedir/backup"
            else
                echo "DCV GL (GLVND) has been disabled for 64 bit applications."
                ret=0
            fi
        else
            echo "DCV GL (GLVND) is NOT enabled for 32 bit applications."
            ret=0
        fi
    fi

    _check 32 glvnd
    local disabled_32=$?
    _check 64 glvnd
    local disabled_64=$?

    if [ $disabled_32 -eq 1 ] && [ $disabled_64 -eq 1 ] && [ $ret -eq 0 ]; then
        _info "Removing backup files and X access for all architectures..."
        rm -f "$basedir"/* 2>/dev/null
    fi

    return $ret
}

_check() {
    if [ ! -d "$basedir" ]; then
        return 1
    fi

    local arch=$1

    local check_lib=$dcv_lib
    local check_lib64=$dcv_lib64
    if [ "$2" = "glvnd" ]; then
        check_lib=$dcv_glvnd_lib
        check_lib64=$dcv_glvnd_lib64
    fi

    if [ "$arch" = "32" ]; then
        if [ -f "$check_lib" ]
        then
            return 0
        fi
    elif [ "$1" = "64" ]; then
        if [ -f "$check_lib64" ]; then
            return 0
        fi
    fi

    return 1
}

_find_gl_lib() {
    gl_lib=""
    if [ "$1" = "32" ]; then
        gl_lib="`readlink -f \"$usr_lib\"`"
    fi

    if [ "$1" = "64" ]; then
        gl_lib="`readlink -f \"$usr_lib64\"`"
    fi

    if [ -f "$gl_lib" ]; then
      return 0
    else
      gl_lib=""
      return 1
    fi
}

check_glvnd_support() {
    local ret=0
    rpm -qa 2>/dev/null | grep libglvnd >/dev/null
    r1=$?
    dpkg -l 2>/dev/null | grep libglvnd0 >/dev/null
    r2=$?
    if [ "$r1" = "0" ] || [ "$r2" = "0" ]; then
        return 0
    fi
    return 1
}

# do_enable(arch_bits glvnd)
do_enable() {
    local ret=1

    if [ ${current_uid} -ne 0 ]; then
        _error "Only root can enable DCV GL."
        return ${ret}
    fi

    if [ "$2" = "1" ]; then
        _info "Autodetecting GLVND support.."
        check_glvnd_support
        if [ "$?" = "1" ]; then
            _info "GLVND is not supported."
        else
            _check 32 || _check 64
            if [ $? -eq 0 ]; then
                _warning "Disabling legacy DCV GL wrapper. It is not compatible with GLVND."
                do_disable
            fi
            _info "GLVND is supported!"
            glvnd_do_enable "$1"
            return $?
        fi
    else
        _check 32 glvnd || _check 64 glvnd
        if [ $? -eq 0 ]; then
            _warning "Disabling GLVND. It is not compatible with legacy DCV GL wrapper."
            glvnd_do_disable
        fi
    fi
    if [ "$1" = "32" ] || [ "${dcv_gl_32_installed}" = "0" -a "$1" != "64" ]; then
        _info "Enabling DCV GL for 32 bit applications..."
        _check 32
        if [ $? -eq 0 ]; then
            echo "DCV GL is ALREADY enabled for 32 bit applications."
            ret=0
        else
            if [ ! -f "$wrapper_lib" ]; then
                _error "Cannot find the DCV GL wrapper for the system 32 bit OpenGL library." "Please ensure the 32 bits package is installed."
                echo "DCV GL cannot be enabled for 32 bit applications."
            else
                mkdir -p "$basedir/lib" 2> /dev/null
                if [ $? -ne 0 ]; then
                    _error "cannot create the '$basedir/lib' directory."
                    return ${ret}
                fi

                rm -f "$sys_lib" 2> /dev/null
                _find_gl_lib 32
                if [ $? -eq 0 ]; then
                    _info "Using '$gl_lib' as system 32 bit OpenGL library."
                    ln -s "$gl_lib" "$sys_lib" 2> /dev/null
                else
                    _warning "cannot find system 32 bit OpenGL library."
                    skip_enable_32=1
                fi

                if [ ! -f "$sys_lib" ]; then
                    _warning "cannot create the '$sys_lib' symlink to system 32 bit OpenGL library."
                    skip_enable_32=1
                fi

                if [ -z "$skip_enable_32" ]; then
                    cp -a -f "$wrapper_lib" "$dcv_lib" 2> /dev/null
                    if [ $? -ne 0 ]; then
                        _error "cannot install the DCV GL 32 bit wrapper library."
                        return ${ret}
                    fi

                    _info "The DCV GL 32 bit wrapper library has been copied to '`dirname \"$dcv_lib\"`'."
                    chcon -R -t textrel_shlib_t "$dcv_lib" 2> /dev/null
                    if [ $? -eq 0 ]; then
                        _info "The SELinux security context of the DCV GL 32 bit wrapper library has been set to 'textrel_shlib_t'."
                    else
                        if [ "${SELinuxMode}" != "Disabled" ]; then
                            _warning "Cannot set the SELinux security context of the DCV GL 32 bit wrapper library."
                        fi
                    fi

                    chcon -R -t textrel_shlib_t "$sys_lib" 2> /dev/null
                    if [ $? -eq 0 ]; then
                        _info "The SELinux security context of the DCV GL 32 bit system library has been set to 'textrel_shlib_t'."
                    else
                        if [ "${SELinuxMode}" != "Disabled" ]; then
                            _warning "Cannot set the SELinux security context of the DCV GL 32 bit system library."
                        fi
                    fi

                    /sbin/ldconfig 2> /dev/null
                    _info "The dynamic linker run-time bindings have been reconfigured."
                    echo "DCV GL has been enabled for 32 bit applications."
                else
                    _warning "DCV GL has not been enabled for 32 bit applications."
                fi
                ret=0
            fi
        fi
    fi

    if [ "$1" != "32" ]; then
        _info "Setting up DCV GL for 64 bit applications..."
        _check 64
        if [ $? -eq 0 ]; then
            echo "DCV GL is ALREADY enabled for 64 bit applications."
            ret=0
        else
            if [ ! -f "$wrapper_lib64" ]; then
                _error "cannot find the DCV GL wrapper for the system 64 bit OpenGL library."
                echo "DCV GL cannot be enabled for 64 bit applications."
            else
                mkdir -p "$basedir/lib64" 2> /dev/null
                if [ $? -ne 0 ]; then
                    _error "cannot create the '$basedir/lib64' directory."
                    return ${ret}
                fi

                rm -f "$sys_lib64"
                _find_gl_lib 64
                if [ $? -eq 0 ]; then
                    _info "Use '$gl_lib' as system 64 bit OpenGL library."
                    ln -s "$gl_lib" "$sys_lib64" 2> /dev/null
                else
                    _warning "cannot find system 64 bit OpenGL library."
                    skip_enable_64=1
                fi

                if [ ! -f "$sys_lib64" ]; then
                    _warning "cannot create the '$sys_lib64' symlink to system 64 bit OpenGL library."
                    skip_enable_64=1
                fi

                if [ -z "$skip_enable_64" ]; then
                    cp -a -f "$wrapper_lib64" "$dcv_lib64" 2> /dev/null
                    if [ $? -ne 0 ]; then
                        _error "cannot install the DCV GL 64 bit wrapper library."
                        return ${ret}
                    fi

                    _info "The DCV GL 64 bit wrapper library has been copied to '`dirname \"$dcv_lib64\"`'."
                    chcon -R -t textrel_shlib_t "$dcv_lib64" 2> /dev/null
                    if [ $? -eq 0 ]; then
                        _info "The SELinux security context of the DCV GL 64 bit wrapper library has been set to 'textrel_shlib_t'."
                    else
                        if [ "${SELinuxMode}" != "Disabled" ]; then
                            _warning "Cannot set the SELinux security context of the DCV GL 64 bit wrapper library."
                        fi
                    fi

                    chcon -R -t textrel_shlib_t "$sys_lib64" 2> /dev/null
                    if [ $? -eq 0 ]; then
                        _info "The SELinux security context of the DCV GL 64 bit system library has been set to 'textrel_shlib_t'."
                    else
                        if [ "${SELinuxMode}" != "Disabled" ]; then
                            _warning "Cannot set the SELinux security context of the DCV GL 64 bit system library."
                        fi
                    fi

                    /sbin/ldconfig 2> /dev/null
                    _info "The dynamic linker run-time bindings have been reconfigured."
                    echo "DCV GL has been enabled for 64 bit applications."
                else
                    _warning "DCV GL has not been enabled for 64 bit applications."
                fi
                ret=0
            fi
        fi
    fi

    # Ensure we have the right permissions on the base dir
    if [ -d "${basedir}" ]; then
        chmod 755 -R "${basedir}"
    fi

    return ${ret}
}

do_disable() {
    local ret=1

    if [ ${current_uid} -ne 0 ]; then
        _error "Only root can disable DCV GL."
        return ${ret}
    fi

    _check 32 glvnd || _check 64 glvnd
    if [ $? -eq 0 ]; then
        glvnd_do_disable $1
        return $?
    fi

    # Legacy

    if [ "$1" = "32" ] || [ "${dcv_gl_32_installed}" = "0" -a "$1" != "64" ]; then
        _info "Disabling DCV GL for 32 bit applications..."
        _check 32
        if [ $? -eq 0 ]; then
            rm -f "$dcv_lib" 2> /dev/null
            if [ -f "$dcv_lib" ]; then
                _error "Cannot remove the DCV GL 32 bit wrapper library."
                echo "DCV GL cannot be disabled for 32 bit applications."
            else
                _info "The DCV GL 32 bit wrapper library has been removed."
                rm -f "$sys_lib" 2> /dev/null
                if [ -f "$sys_lib" ]; then
                    _warning "Cannot remove the link to the system 32 bit OpenGL library."
                else
                    _info "The link to the system 32 bit OpenGL library has been removed."
                fi

                /sbin/ldconfig 2> /dev/null
                _info "The dynamic linker run-time bindings have been reconfigured."
                echo "DCV GL has been disabled for 32 bit applications."
                ret=0
            fi
        else
            echo "DCV GL is NOT enabled for 32 bit applications."
            ret=0
        fi
    fi

    if [ "$1" != "32" ]; then
        _info "Removing DCV GL for 64 bit applications..."
        _check 64
        if [ $? -eq 0 ]; then
            rm -f "$dcv_lib64" 2> /dev/null
            if [ -f "$dcv_lib64" ]; then
                _error "Cannot remove the DCV GL 64 bit wrapper library."
                echo "DCV GL cannot be disabled for 64 bit applications."
            else
                _info "The DCV GL 64 bit wrapper library has been removed."
                rm -f "$sys_lib64" 2> /dev/null
                if [ -f "$sys_lib64" ]; then
                    _warning "Cannot remove the link to the system 64 bit OpenGL library."
                else
                    _info "The link to the system 64 bit OpenGL library has been removed."
                fi

                /sbin/ldconfig 2> /dev/null
                _info "The dynamic linker run-time bindings have been reconfigured."
                echo "DCV GL has been disabled for 64 bit applications."
                ret=0
            fi
        else
            echo "DCV GL is NOT enabled for 64 bit applications."
            ret=0
        fi
    fi

    _check 32
    local disabled_32=$?
    _check 64
    local disabled_64=$?

    return ${ret}
}

do_status() {
    _copyright_message
    local final_ret=0
    local glvnd_ret=0
    local glvnd_ret_32=0
    local legacy_ret=0
    local legacy_ret_32=0

    if [ "${dcv_glvnd_32_installed}" = "0" ]; then
        _check 32 glvnd
        glvnd_ret_32=$?
    else
        glvnd_ret_32=1
    fi
    if [ "${dcv_gl_32_installed}" = "0" ]; then
        _check 32
        legacy_ret_32=$?
    else
        legacy_ret_32=1
    fi

    if [ "$1" != "32" ]; then
        _check 64
        legacy_ret=$?
        _check 64 glvnd
        glvnd_ret=$?
    fi

    if [ "$1" = "32" ] || [ "$1" != "64" -a "${dcv_gl_32_installed}" = "0" ]; then
        if [ "$glvnd_ret_32" = "0" ]; then
            echo "DCV GL (GLVND) is enabled for 32 bit applications."
        elif [ "$legacy_ret_32" = "0" ]; then
            echo "DCV GL is enabled for 32 bit applications."
        elif [ "$glvnd_ret" = "0" ]; then
            echo "DCV GL (GLVND) is NOT enabled for 32 bit applications."
            final_ret=1
        else
            echo "DCV GL is NOT enabled for 32 bit applications."
            final_ret=1
        fi
    fi
    if [ "$1" != "32" ]; then
        if [ "$glvnd_ret" = "0" ]; then
            echo "DCV GL (GLVND) is enabled for 64 bit applications."
        elif [ "$legacy_ret" = "0" ]; then
            echo "DCV GL is enabled for 64 bit applications."
        elif [ "$glvnd_ret_32" = "0" ]; then
            echo "DCV GL (GLVND) is NOT enabled for 64 bit applications."
            final_ret=1
        else
            echo "DCV GL is NOT enabled for 64 bit applications."
            final_ret=1
        fi
    fi

    return $final_ret
}

if [ "$1" = "-v" -o "$1" = "--verbose" ]; then
    verbose=1
    shift
fi

action="$1"
shift

arch_bits=""
if [ "$1" = "32" -o "$1" = "64" ]; then
    arch_bits="$1"
    shift
fi

if [ "$1" = "--noglvnd" ]; then
    if [ "$glvnd_enabled" = "0" ]; then
        _warning "$1 is ignored: GLVND is not available on this system"
    fi
    glvnd_enabled=0
    shift
fi

_info "DCV GL is installed in the directory."

case "$action" in
enable)
    do_enable "$arch_bits" $glvnd_enabled
    RETVAL=$?
    ;;

disable)
    do_disable "$arch_bits"
    RETVAL=$?
    ;;

status)
    do_status "$arch_bits"
    RETVAL=$?
    ;;

*)
    echo "Usage: $prog [-v] <enable|disable|status> [32|64] [--noglvnd]"
    RETVAL=2
    ;;
esac

exit $RETVAL

# ex:set ts=4 et:
