#!/bin/sh

# Copyright (C)2007 Sun Microsystems, Inc.
# Copyright (C)2009-2014, 2016, 2018-2020, 2022-2023 D. R. Commander
#
# This library is free software and may be redistributed and/or modified under
# the terms of the wxWindows Library License, Version 3.1 or (at your option)
# any later version.  The full license is in the LICENSE.txt file included
# with this distribution.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# wxWindows Library License for more details.

VGLUSERSONLY=1
DISABLEXTEST=1
FBDEVVGLUSERSONLY=1
RMMODNEEDED=0
NVIDIADRMNEEDED=0
UNATTENDED=0
SELINUX=0
WAYLAND=0
BACKEND=glx

GID=
GROUPADD=/usr/sbin/groupadd
if [ ! -x $GROUPADD ]; then GROUPADD=groupadd; fi
if [ "`uname -s`" = "FreeBSD" ]; then
	GROUPADD="pw groupadd"
fi
LSMOD=/sbin/lsmod
if [ ! -x $LSMOD ]; then LSMOD=lsmod; fi
MODPROBE=/sbin/modprobe
if [ ! -x $MODPROBE ]; then MODPROBE=modprobe; fi
SEMANAGE=
RESTORECON=

VGLGENKEY=vglgenkey

usage()
{
	echo
	echo "USAGE: $0 [flags]"
	echo
	echo "Flags (for unattended mode):"
	echo "+glx/-config    Configure server for use with VirtualGL (GLX + EGL back ends)"
	echo "-glx/-unconfig  Unconfigure server for use with VirtualGL (GLX + EGL back ends)"
	echo "+egl            Configure server for use with VirtualGL (EGL back end only)"
	echo "-egl            Unconfigure server for use with VirtualGL (EGL back end only)"
	echo "-s              Restrict 3D X server access to vglusers group [default]"
	echo "+s              Open 3D X server access to all users of this machine"
	echo "-f              Restrict framebuffer device access to vglusers group [default]"
	echo "+f              Open framebuffer device access to all users of this machine"
	echo "-t              Disable XTEST extension [default]"
	echo "+t              Enable XTEST extension"
	echo
	echo "Flags (for both interactive and unattended modes):"
	echo "-gid <g>  If vglusers group must be created, then set its group ID to <g>"
	echo
	exit $1
}

uid()
{
	id | cut -f2 -d = | cut -f1 -d \(;
}

maketemp()
{
	umask 077
	mktemp /tmp/$1.XXXXXX || exit 1
}

removeline()
{
	if [ -z "$1" -o -z "$2" ]; then
		echo 'USAGE: removeline <filename> <pattern>'
		return
	fi
	TMPFILE=`maketemp vglserver_config_1`
	sed "/$2/d" $1 >$TMPFILE && cp $TMPFILE $1
	if [ -f $TMPFILE ]; then rm $TMPFILE; fi
}

replaceline()
{
	if [ -z "$1" -o -z "$2" -o -z "$3" ]; then
		echo 'USAGE: replaceline <filename> <pattern to replace> <new text>'
		return
	fi
	TMPFILE=`maketemp vglserver_config_2`
	sed "s/^.*$2.*$/$3/g" $1 >$TMPFILE && cp $TMPFILE $1
	if [ -f $TMPFILE ]; then rm $TMPFILE; fi
}

uncommentline()
{
	if [ -z "$1" -o -z "$2" ]; then
		echo 'USAGE: uncommentline <filename> <regex of line to uncomment>'
		return
	fi
	TMPFILE=`maketemp vglserver_config_3`
	sed "/$2/s/^[ \t]*#*//g" $1 >$TMPFILE && cp $TMPFILE $1
	if [ -f $TMPFILE ]; then rm $TMPFILE; fi
}

commentline()
{
	uncommentline $1 $2
	if [ -z "$1" -o -z "$2" ]; then
		echo 'USAGE: commentline <filename> <regex of line to comment>'
		return
	fi
	TMPFILE=`maketemp vglserver_config_4`
	sed "/$2/s/^/#/g" $1 >$TMPFILE && cp $TMPFILE $1
	if [ -f $TMPFILE ]; then rm $TMPFILE; fi
}

addtobottom()
{
	if [ -z "$1" -o -z "$2" ]; then
		echo 'USAGE: addtobottom <filename> <line to add>'
		return
	fi
	TMPFILE=`maketemp vglserver_config_10`
	cat $1 >$TMPFILE && echo $2 >>$TMPFILE && cp $TMPFILE $1
	if [ -f $TMPFILE ]; then rm $TMPFILE; fi
}

addtotop()
{
	if [ -z "$1" -o -z "$2" ]; then
		echo 'USAGE: addtotop <filename> <line to add>'
		return
	fi
	TMPFILE=`maketemp vglserver_config_5`
	SCRFILE=`maketemp vglserver_config_6`
	AWK=nawk
	type $AWK >/dev/null 2>/dev/null || AWK=gawk
	cat > $SCRFILE <<EOF
BEGIN {DONE=0} {
	if(/^$|^[^#]/ && DONE==0) {
		printf("$2"); printf("\n");
		DONE=1;
	}
	print \$0
}
END {
	if(DONE==0) {
		printf("$2"); printf("\n");
	}
}
EOF
	$AWK -f $SCRFILE $1 >$TMPFILE && cp $TMPFILE $1
	if [ -f $SCRFILE ]; then rm $SCRFILE; fi
	if [ -f $TMPFILE ]; then rm $TMPFILE; fi
}

addtoconf()
{
	if [ -z "$1" -o -z "$2" -o -z "$3" -o -z "$4" ]; then
		echo 'USAGE: addtoconf <filename> <stanza name> <search string> <line to add>'
		return
	fi
	grep "\[$3\]" $1 >/dev/null 2>/dev/null
	if [ $? = 0 ]; then
		TMPFILE=`maketemp vglserver_config_7`
		AWK=nawk
		type $AWK >/dev/null 2>/dev/null || AWK=gawk
		$AWK -vstanza=$2 -vadd="$4" '{ if($0 ~ stanza) { print "["stanza"]"; print add } else print $0; }' $1 >$TMPFILE && cp $TMPFILE $1
		if [ -f $TMPFILE ]; then rm $TMPFILE; fi
	else
		addtobottom $1 "[$2]"
		addtobottom $1 "$4"
	fi
}

backup()
{
	if [ -z "$1" ]; then
		echo 'USAGE: backup <filename>'
		return
	fi
	if [ ! -f $1.orig.vgl ]; then
		cp $1 $1.orig.vgl
		echo ... $1 has been saved as $1.orig.vgl ...
	fi
}

delvglgenkey()
{
	echo ... Removing X server access from $1 script ...
	removeline $1 vglgenkey
	removeline $1 "xhost +*"
}

addvglgenkey()
{
	backup $1
	if [ "$VGLUSERSONLY" = "1" ]; then
		echo ... Adding vglgenkey to $1 script ...
	else
		echo ... Adding xhost \+LOCAL\: to $1 script ...
	fi
	removeline $1 vglgenkey
	removeline $1 "xhost +*"
	if [ "$VGLUSERSONLY" = "1" ]; then
		if [ "$2" = "bottom" ]; then
			addtobottom $1 $VGLGENKEY
		else
			addtotop $1 $VGLGENKEY
		fi
	else
		if [ "$2" = "bottom" ]; then
			addtobottom $1 "xhost +LOCAL:"
		else
			addtotop $1 "xhost +LOCAL:"
		fi
	fi
}

addvglgenkey_lightdm()
{
	backup $1
	if [ "$VGLUSERSONLY" = "1" ]; then
		echo ... Adding greeter-setup-script=vglgenkey to $1 ...
	else
		echo ... Adding greeter-setup-script=xhost \+LOCAL\: to $1 ...
	fi
	removeline $1 display-setup-script
	removeline $1 greeter-setup-script
	if [ "$VGLUSERSONLY" = "1" ]; then
		addtoconf $1 "Seat:seat*" "Seat:seat\*" greeter-setup-script=$VGLGENKEY
	else
		addtoconf $1 "Seat:seat*" "Seat:seat\*" "greeter-setup-script=xhost +LOCAL:"
	fi
}

disablextest()
{
	if [ -z "$1" ]; then
		echo 'USAGE: disablextest <filename>'
		return
	fi
	backup $1
	echo ... Disabling XTEST extension in $1 ...
	TMPFILE=`maketemp vglserver_config_7`
	sed -e "/\/X11\/X\>/s/[ #\t]*-tst//g" -e "/\/bin\/X\>/s/[ #\t]*-tst//g" -e "/\/bin\/Xorg\>/s/[ #\t]*-tst//g" -e "/\/bin\/Xsun\>/s/[ #\t]*-tst//g" -e "/\/bin\/Xserver\>/s/[ #\t]*-tst//g" $1 >$TMPFILE && cp $TMPFILE $1 && (
		sed -e "/\/X11\/X\>/s/$/\ -tst/g" -e "/\/bin\/X\>/s/$/\ -tst/g" -e "/\/bin\/Xorg\>/s/$/\ -tst/g" -e "/\/bin\/Xsun\>/s/$/\ -tst/g" -e "/\/bin\/Xserver\>/s/$/\ -tst/g" $1 >$TMPFILE && cp $TMPFILE $1
	)
	if [ -f $TMPFILE ]; then rm $TMPFILE; fi
}

disablextestkdm()
{
	if [ -z "$1" ]; then
		echo 'USAGE: disablextestkdm <filename>'
		return
	fi
	backup $1
	echo ... Disabling XTEST extension in $1 ...
	TMPFILE=`maketemp vglserver_config_12`
	uncommentline $1 ServerArgsLocal
	sed -e "/ServerArgsLocal\>/s/[ #\t]*-tst//g" $1 >$TMPFILE && cp $TMPFILE $1 && (
		sed -e "/ServerArgsLocal\>/s/$/\ -tst/g" $1 >$TMPFILE && cp $TMPFILE $1
	)
	if [ -f $TMPFILE ]; then rm $TMPFILE; fi
}

enablextest()
{
	if [ -z "$1" ]; then
		echo 'USAGE: enablextest <filename>'
		return
	fi
	echo ... Enabling XTEST extension in $1 ...
	TMPFILE=`maketemp vglserver_config_8`
	sed -e "/\/X11\/X\>/s/[ #\t]*-tst//g" -e "/\/bin\/X\>/s/[ #\t]*-tst//g" -e "/\/bin\/Xorg\>/s/[ #\t]*-tst//g" -e "/\/bin\/Xsun\>/s/[ #\t]*-tst//g" -e "/\/bin\/Xserver\>/s/[ #\t]*-tst//g" $1 >$TMPFILE && cp $TMPFILE $1
	if [ -f $TMPFILE ]; then rm $TMPFILE; fi
}

enablextestkdm()
{
	if [ -z "$1" ]; then
		echo 'USAGE: enablextestkdm <filename>'
		return
	fi
	echo ... Enabling XTEST extension in $1 ...
	TMPFILE=`maketemp vglserver_config_11`
	sed -e "/ServerArgsLocal\>/s/[ #\t]*-tst//g" $1 >$TMPFILE && cp $TMPFILE $1
	if [ -f $TMPFILE ]; then rm $TMPFILE; fi
}

disallowgdmtcp()
{
	echo ... Commenting out DisallowTCP line \(if it exists\) in $1 ...
	commentline $1 "DisallowTCP.*=.*"
}

disablewaylandgdm()
{
	backup $1
	echo ... Disabling Wayland in $1 ...
	grep -q "WaylandEnable.*=.*false" $1 && (
		uncommentline $1 "WaylandEnable.*=.*false"
	) || (
		grep -q "WaylandEnable" $1 && (
			replaceline $1 WaylandEnable "WaylandEnable=false"
		) || (
			removeline $1 WaylandEnable
			addtoconf $1 "daemon" "daemon" WaylandEnable=false
		)
	)
}

setdripermissions()
{
	if [ -z "$1" ]; then
		echo 'USAGE: setdripermissions <filename> [backup]'
		return
	fi
	if [ ! -f $1 ]; then return; fi
	if [ "$2" = "backup" ]; then
		backup $1
	fi
	if [ "$FBDEVVGLUSERSONLY" = "1" ]; then
		echo "... Modifying $1 to enable DRI"
		echo "    permissions for vglusers group ..."
	else
		echo "... Modifying $1 to enable DRI"
		echo "    permissions for all users ..."
	fi
	TMPFILE=`maketemp vglserver_config_9`
	# Delete Section "DRI" stanza
	sed '/Section.*"DRI"/,/EndSection/d' $1 >$TMPFILE && cp $TMPFILE $1
	# Ensure that exactly one line separates each stanza
	sed -n '1h;1!H;${;g;s/EndSection[\n \t]*Section\([^\n]*\)/EndSection\n\nSection\1/g;p;}' $1 >$TMPFILE && cp $TMPFILE $1
	if [ -f $TMPFILE ]; then rm $TMPFILE; fi
	if [ "$FBDEVVGLUSERSONLY" = "1" ]; then
		addtotop $1 "Section \\\"DRI\\\"\n\tMode 0660\n\tGroup \\\"vglusers\\\"\nEndSection"
	else
		addtotop $1 "Section \\\"DRI\\\"\n\tMode 0666\nEndSection"
	fi
}

unconfigdev()
{
	if [ "$UNAME_S" = "SunOS" ]; then
		echo ... Modifying /etc/logindevperm to enable automatic permissions for
		echo "    /dev/fbs/* ..."
		uncommentline /etc/logindevperm "\/dev\/console.*\/dev\/fbs"
	elif [ "$UNAME_S" = "Linux" ]; then
		if [ -f /etc/security/console.perms ]; then
			echo ... Modifying /etc/security/console.perms to enable automatic permissions
			echo "    for DRI devices ..."
			uncommentline /etc/security/console.perms "\<dri\>"
		fi
		if [ -f /etc/security/console.perms.d/50-default.perms ]; then
			echo ... Modifying /etc/security/console.perms.d/50-default.perms to enable automatic permissions
			echo "    for DRI devices ..."
			uncommentline /etc/security/console.perms.d/50-default.perms "\<dri\>"
		fi
		if [ -f /etc/logindevperm ]; then
			echo ... Modifying /etc/logindevperm to enable automatic permissions for
			echo "    /dev/nvidia* ..."
			uncommentline /etc/logindevperm "\/dev\/nvidia"
		fi
		if [ -f /etc/modprobe.d/virtualgl.conf -o -f /etc/modprobe.d/virtualgl ]; then
			echo ... Removing /etc/modprobe.d/virtualgl.conf to restore default permissions for
			echo "    /dev/nvidia* ..."
			rm -f /etc/modprobe.d/virtualgl
			rm -f /etc/modprobe.d/virtualgl.conf
			$LSMOD | grep -q nvidia >/dev/null 2>/dev/null
			if [ $? = 0 ]; then
				$LSMOD | grep -q nvidia_drm >/dev/null 2>/dev/null
				if [ $? = 0 ]; then
					NVIDIADRMNEEDED=1
				fi
				echo ... Attempting to remove nvidia module from memory so device permissions
				echo "    will be reloaded ..."
				$MODPROBE -r nvidia_uvm nvidia_drm nvidia_modeset nvidia || RMMODNEEDED=1
				# Reload the nvidia_drm module if necessary.  This prevents the DRI
				# devices from disappearing.
				if [ "$NVIDIADRMNEEDED" = "1" -a ! "$RMMODNEEDED" = "1" ]; then
					$MODPROBE nvidia_drm
				fi
			fi
		fi
		if [ -f /etc/udev/rules.d/99-virtualgl-dri.rules ]; then
			echo ... Removing /etc/udev/rules.d/99-virtualgl-dri.rules to restore default
			echo "    permissions for /dev/dri/card* and /dev/dri/renderD* at next boot ..."
			rm -f /etc/udev/rules.d/99-virtualgl-dri.rules
		fi
		if [ "$BACKEND" = "glx" -a -f /etc/X11/xorg.conf.d/99-virtualgl-dri ]; then
			echo ... Removing /etc/X11/xorg.conf.d/99-virtualgl-dri to restore default
			echo "    permissions for /dev/dri/card* ..."
			rm -f /etc/X11/xorg.conf.d/99-virtualgl-dri
		fi
		if [ "$BACKEND" = "glx" -a -f /etc/X11/xorg.conf.d/99-virtualgl-dri.conf ]; then
			echo ... Removing /etc/X11/xorg.conf.d/99-virtualgl-dri.conf to restore default
			echo "    permissions for /dev/dri/card* ..."
			rm -f /etc/X11/xorg.conf.d/99-virtualgl-dri.conf
		fi
	fi
}

configdev()
{
	if [ "$UNAME_S" = "SunOS" ]; then
		echo ... Modifying /etc/logindevperm to disable automatic permissions for
		echo "    /dev/fbs/* ..."
		commentline /etc/logindevperm "\/dev\/console.*\/dev\/fbs"
		chmod 755 /dev/fbs
		if [ "$FBDEVVGLUSERSONLY" = "1" ]; then
			echo ... Granting write permission to /dev/fbs/\* for vglusers group ...
			chmod 660 /dev/fbs/*
			chown root:vglusers /dev/fbs/*
		else
			echo ... Granting write permission to /dev/fbs/\* for all users ...
			chmod 666 /dev/fbs/*
			chown root:root /dev/fbs/*
		fi
	elif [ "$UNAME_S" = "Linux" ]; then
		if [ -f /etc/security/console.perms ]; then
			echo ... Modifying /etc/security/console.perms to disable automatic permissions
			echo "    for DRI devices ..."
			commentline /etc/security/console.perms "\<dri\>"
		fi
		if [ -f /etc/security/console.perms.d/50-default.perms ]; then
			echo ... Modifying /etc/security/console.perms.d/50-default.perms to disable automatic permissions
			echo "    for DRI devices ..."
			commentline /etc/security/console.perms.d/50-default.perms "\<dri\>"
		fi
		if [ -f /etc/logindevperm ]; then
			echo ... Modifying /etc/logindevperm to disable automatic permissions for
			echo "    /dev/nvidia* ..."
			commentline /etc/logindevperm "\/dev\/nvidia"
		fi
		if [ -d /etc/modprobe.d ]; then
			if [ -f /etc/modprobe.d/nvidia ]; then
				echo ... Modifying /etc/modprobe.d/nvidia to set requested permissions for
			else
				echo ... Creating /etc/modprobe.d/virtualgl.conf to set requested permissions for
			fi
			echo "    /dev/nvidia* ..."
			VGLUSERSGID=`grep vglusers /etc/group | cut -f3 -d:`
			if [ -f /etc/modprobe.d/nvidia ]; then
				if [ "$FBDEVVGLUSERSONLY" = "1" -a ! "$VGLUSERSGID" = "" ]; then
					replaceline /etc/modprobe.d/nvidia "options nvidia" "options nvidia NVreg_DeviceFileUID=0 NVreg_DeviceFileGID=$VGLUSERSGID NVreg_DeviceFileMode=0660"
				else
					replaceline /etc/modprobe.d/nvidia "options nvidia" "options nvidia NVreg_DeviceFileUID=0 NVreg_DeviceFileGID=0 NVreg_DeviceFileMode=0666"
				fi
			else
				if [ "$FBDEVVGLUSERSONLY" = "1" -a ! "$VGLUSERSGID" = "" ]; then
					echo "options nvidia NVreg_DeviceFileUID=0 NVreg_DeviceFileGID=$VGLUSERSGID NVreg_DeviceFileMode=0660" >/etc/modprobe.d/virtualgl.conf
				else
					echo "options nvidia NVreg_DeviceFileUID=0 NVreg_DeviceFileGID=0 NVreg_DeviceFileMode=0666" >/etc/modprobe.d/virtualgl.conf
				fi
				chmod 644 /etc/modprobe.d/virtualgl.conf
			fi
			$LSMOD | grep -q nvidia >/dev/null 2>/dev/null
			if [ $? = 0 ]; then
				$LSMOD | grep -q nvidia_drm >/dev/null 2>/dev/null
				if [ $? = 0 ]; then
					NVIDIADRMNEEDED=1
				fi
				echo ... Attempting to remove nvidia module from memory so device permissions
				echo "    will be reloaded ..."
				$MODPROBE -r nvidia_uvm nvidia_drm nvidia_modeset nvidia || RMMODNEEDED=1
				# Reload the nvidia_drm module if necessary.  This prevents the DRI
				# devices from disappearing.
				if [ "$NVIDIADRMNEEDED" = "1" -a ! "$RMMODNEEDED" = "1" ]; then
					$MODPROBE nvidia_drm
				fi
			fi
		fi
		if [ "$FBDEVVGLUSERSONLY" = "1" ]; then
			if [ -e /dev/nvidia0 -o -e /dev/nvidiactl ]; then
				echo ... Granting write permission to /dev/nvidia* for vglusers group ...
				chmod 660 /dev/nvidia*
				chown root:vglusers /dev/nvidia*
			fi
			if ls /dev/dri/card* >/dev/null 2>&1; then
				echo ... Granting write permission to /dev/dri/card* for vglusers group ...
				chmod 660 /dev/dri/card*
				chown root:vglusers /dev/dri/card*
			fi
			if ls /dev/dri/renderD* >/dev/null 2>&1; then
				echo ... Granting write permission to /dev/dri/renderD* for vglusers group ...
				chmod 660 /dev/dri/renderD*
				chown root:vglusers /dev/dri/renderD*
			fi
		else
			if [ -e /dev/nvidia0 -o -e /dev/nvidiactl ]; then
				echo ... Granting write permission to /dev/nvidia* for all users ...
				chmod 666 /dev/nvidia*
				chown root:root /dev/nvidia*
			fi
			if ls /dev/dri/card* >/dev/null 2>&1; then
				echo ... Granting write permission to /dev/dri/card* for all users ...
				chmod 666 /dev/dri/card*
				chown root:root /dev/dri/card*
			fi
			if ls /dev/dri/renderD* >/dev/null 2>&1; then
				echo ... Granting write permission to /dev/dri/renderD* for all users ...
				chmod 666 /dev/dri/renderD*
				chown root:root /dev/dri/renderD*
			fi
		fi
		if [ -d /etc/udev/rules.d ]; then
			if [ "$FBDEVVGLUSERSONLY" = "1" ]; then
				echo "KERNEL==\"card*|renderD*\", MODE=\"0660\", OWNER=\"root\", GROUP=\"vglusers\"" >/etc/udev/rules.d/99-virtualgl-dri.rules
			else
				echo "KERNEL==\"card*|renderD*\", MODE=\"0666\", OWNER=\"root\", GROUP=\"root\"" >/etc/udev/rules.d/99-virtualgl-dri.rules
			fi
		fi
		if [ "$BACKEND" = "glx" ]; then
			if [ -d /etc/X11/xorg.conf.d ]; then
				if [ -f /etc/X11/xorg.conf.d/99-virtualgl-dri ]; then
					rm /etc/X11/xorg.conf.d/99-virtualgl-dri
				fi
				touch /etc/X11/xorg.conf.d/99-virtualgl-dri.conf
				setdripermissions /etc/X11/xorg.conf.d/99-virtualgl-dri.conf
			fi
			setdripermissions /etc/X11/xorg.conf backup
			setdripermissions /etc/X11/XF86Config backup
		fi
	fi
}

ynprompt()
{
	if [ "$1" = "" ]; then
		echo 'USAGE: ynprompt <prompt>'
		return 0
	fi
	while [ 1 ]; do
		echo
		echo $1
		echo \[Y\/n\]
		read _CHOICE
		if [ "$_CHOICE" = "" ]; then return 1; fi
		case $_CHOICE in
			[yY]*) return 1 ;;
			[nN]*) return 0 ;;
		esac
	done
}

checkselinux()
{
	if [ ! "$UNAME_S" = "Linux" ]; then
		return 0
	fi
	if [ -f /selinux/enforce ]; then
		SELINUX=`cat /selinux/enforce`
	elif [ -f /sys/fs/selinux/enforce ]; then
		SELINUX=`cat /sys/fs/selinux/enforce`
	fi
	if [ $SELINUX != 1 ]; then
		return 0;
	fi
	if [ -x /usr/sbin/semanage ]; then
		SEMANAGE=/usr/sbin/semanage
	else
		SEMANAGE_TEMP=`which semanage 2>/dev/null`
		if [ $? = 0 ]; then
			SEMANAGE=$SEMANAGE_TEMP
		else
			echo
			echo "ERROR: SELinux is enabled, but the semanage program is not installed.  This"
			echo "program is usually contained in a package called \"policycoreutils\" or"
			echo "\"policycoreutils-python\" or \"policycoreutils-python-utils\".  On systems with"
			echo "YUM or DNF, try running \"yum install /usr/sbin/semanage\" or"
			echo "\"dnf install /usr/sbin/semanage\"."
			return 1
		fi
	fi
	if [ -x /sbin/restorecon ]; then
		RESTORECON=/sbin/restorecon
		return 0
	else
		RESTORECON_TEMP=`which restorecon 2>/dev/null`
		if [ $? = 0 ]; then
			RESTORECON=$RESTORECON_TEMP
			return 0
		else
			echo
			echo "ERROR: SELinux is enabled, but the restorecon program is not installed.  This"
			echo "program is usually contained in a package called \"policycoreutils\".  On systems"
			echo "with YUM or DNF, try running \"yum install /sbin/restorecon\" or"
			echo "\"dnf install /sbin/restorecon\"."
			return 1
		fi
	fi
}

checkwayland()
{
	which Xwayland >/dev/null 2>&1 || return 0
	if [ -f /etc/systemd/system/display-manager.service ]; then
		DM=`grep ExecStart=\/usr /etc/systemd/system/display-manager.service | sed 's/.*\///g'`
		if [ ! "$DM" = "gdm" -a ! "$DM" = "gdm3" ]; then
			return 0
		fi
	elif [ -f /etc/alternatives/default-displaymanager ]; then
		DM=`grep DISPLAYMANAGER=\/usr /etc/alternatives/default-displaymanager | sed 's/.*\///g'`
		if [ ! "$DM" = "gdm" ]; then
			return 0
		fi
	else
		return 0
	fi
	WAYLAND=1
	echo
	echo WARNING: Configuring this server for use with VirtualGL will disable the
	echo ability to log in locally with a Wayland session.
	if [ $UNATTENDED = 0 ]; then
		ynprompt "Continue?"
		if [ ! "$?" = "1" ]; then
			return 1
		fi
	else
		echo
	fi
	return 0
}

unconfigglx()
{
	if [ -d /etc/opt/VirtualGL ]; then
		checkselinux || return
		echo ... Removing /etc/opt/VirtualGL directory ...
		rm /etc/opt/VirtualGL/* 2>/dev/null
		rmdir /etc/opt/VirtualGL
		if [ $SELINUX = 1 ]; then
			echo ... Removing custom SELinux contexts ...
			# Try to combine operations (semanage is slow)
			$SEMANAGE -i - <<EOF >/dev/null
fcontext -d '/etc/opt/VirtualGL(/.*)?'
fcontext -d /usr/bin/xauth
EOF
			if [ $? = 1 ]; then
				# That didn't work.  Try the old-fashioned way
				$SEMANAGE fcontext -d '/etc/opt/VirtualGL(/.*)?'
				$SEMANAGE fcontext -d /usr/bin/xauth
			fi
			$RESTORECON -R -v /usr/bin/xauth
		fi
	fi

	if [ -f /etc/X11/xdm/Xsetup_0 -a ! -h /etc/X11/xdm/Xsetup_0 ]; then
		delvglgenkey /etc/X11/xdm/Xsetup_0
	else
		if [ -f /etc/X11/xdm/Xsetup -a ! -h /etc/X11/xdm/Xsetup ]; then
			delvglgenkey /etc/X11/xdm/Xsetup
		fi
	fi
	if [ -f /etc/X11/gdm/Init/:0 ]; then
		if [ ! -h /etc/X11/gdm/Init/:0 ]; then
			delvglgenkey /etc/X11/gdm/Init/:0
		fi
	else
		if [ -f /etc/X11/gdm/Init/Default -a ! -h /etc/X11/gdm/Init/Default ]; then
			delvglgenkey /etc/X11/gdm/Init/Default
		fi
	fi
	if [ -f /etc/X11/gdm/SunRayInit/Default ]; then
		delvglgenkey /etc/X11/gdm/SunRayInit/Default
	fi
	for file in /etc/gdm/Init/Default \
		/etc/gdm3/Init/Default \
		/usr/local/etc/gdm/Init/Default \
		/etc/opt/gnome/gdm/Init/Default \
		/etc/kde4/kdm/Xsetup \
		/usr/share/config/kdm/Xsetup \
		/usr/local/kde4/share/config/kdm/Xsetup \
		/etc/sddm/Xsetup \
		/usr/share/sddm/scripts/Xsetup \
		/etc/mdm/Init/Default; do
		if [ -f $file -a ! -h $file ]; then
			delvglgenkey $file
		fi
	done
	if [ -f /etc/lightdm/lightdm.conf ]; then
		echo "... Removing X server access from /etc/lightdm/lightdm.conf ..."
		removeline /etc/lightdm/lightdm.conf display-setup-script
		removeline /etc/lightdm/lightdm.conf greeter-setup-script
	fi
	for dir in /usr/share/gdm/greeter/autostart \
		/usr/local/share/gdm/greeter/autostart; do
		if [ -f $dir/virtualgl.desktop ]; then
			echo "... Removing $dir/virtualgl.desktop ..."
			rm $dir/virtualgl.desktop
		fi
	done

	for file in /etc/gdm/custom.conf \
		/etc/X11/gdm/custom.conf \
		/etc/gdm3/custom.conf \
		/etc/gdm3/daemon.conf; do
		if [ -f $file -a ! -h $file ]; then
			echo "... Re-enabling Wayland in $file ..."
			commentline $file "WaylandEnable.*=.*false"
		fi
	done

	if [ "$UNAME_S" = "SunOS" ]; then
		if [ -f /etc/dt/config/Xsetup ]; then
			delvglgenkey /etc/dt/config/Xsetup
		fi
		if [ -f /etc/dt/config/Xconfig ]; then
			echo ... Restoring default value of Dtlogin\*grabServer in ...
			echo "...     /etc/dt/config/Xconfig ..."
			commentline /etc/dt/config/Xconfig Dtlogin\\*grabServer
		fi
		if [ -f /etc/dt/config/Xconfig.SUNWut.prototype ]; then
			echo ... Restoring default value of Dtlogin\*grabServer in ...
			echo "...     /etc/dt/config/Xconfig.SUNWut.prototype ..."
			commentline /etc/dt/config/Xconfig.SUNWut.prototype Dtlogin\\*grabServer
		fi
	fi

	for file in /etc/X11/xdm/Xservers \
		/etc/X11/gdm/gdm.conf \
		/etc/gdm/custom.conf \
		/etc/gdm3/daemon.conf \
		/usr/local/etc/gdm/custom.conf \
		/etc/gdm/gdm.conf \
		/etc/X11/gdm/custom.conf \
		/etc/opt/gnome/gdm/gdm.conf \
		/etc/opt/kde3/share/config/kdm/Xservers \
		/etc/mdm/mdm.conf; do
		if [ -f $file -a ! -h $file ]; then
			enablextest $file
		fi
	done
	if [ -f /etc/gdm/gdm-cdd.conf ]; then
		enablextest /etc/gdm/gdm-cdd.conf
	fi
	for file in /etc/kde4/kdm/kdmrc \
		/etc/kde/kdm/kdmrc \
		/usr/share/config/kdm/kdmrc \
		/usr/local/kde4/share/config/kdm/kdmrc; do
		if [ -f $file -a ! -h $file ]; then
			enablextestkdm $file
		fi
	done
	if [ "$UNAME_S" = "SunOS" ]; then
		if [ -f /etc/dt/config/Xservers ]; then
			enablextest /etc/dt/config/Xservers
		fi
		if [ -x /usr/sbin/svccfg ]; then
			/usr/sbin/svccfg -s application/x11/x11-server delpropvalue options/server_args "*-tst*" 2>&1 >/dev/null
		fi
	fi

	for file in /etc/X11/gdm/gdm.conf \
		/etc/gdm/custom.conf \
		/etc/gdm3/daemon.conf \
		/usr/local/etc/gdm/custom.conf \
		/etc/gdm/gdm.conf \
		/etc/X11/gdm/custom.conf \
		/etc/opt/gnome/gdm/gdm.conf \
		/etc/mdm/mdm.conf; do
		if [ -f $file -a ! -h $file ]; then
			disallowgdmtcp $file
		fi
	done
	if [ -f /etc/gdm/gdm-cdd.conf ]; then
		disallowgdmtcp /etc/gdm/gdm-cdd.conf
	fi

	unconfigdev

	echo
	echo Done.  You must restart the display manager for the changes to take effect.
	if [ "$RMMODNEEDED" = "1" ]; then
		echo
		echo "IMPORTANT NOTE: Your system uses modprobe.d to set device permissions.  You"
		echo "must execute 'modprobe -r nvidia_uvm nvidia_drm nvidia_modeset nvidia' with the"
		echo "display manager stopped in order for the new device permission settings to"
		echo "become effective."
	fi
	echo
}

configegl()
{
	if [ $UNATTENDED = 0 ]; then
		ynprompt "Restrict framebuffer device access to vglusers group (recommended)?"
		if [ $? = 1 ]; then
			VGLUSERSONLY=1; FBDEVVGLUSERSONLY=1;
		else
			VGLUSERSONLY=0; FBDEVVGLUSERSONLY=0;
		fi
	fi

	if [ "$VGLUSERSONLY" = "1" ]; then
		echo ... Creating vglusers group ...
		if [ ! "$GID" = "" ]; then
			$GROUPADD -g $GID vglusers || echo "Could not add vglusers group (probably because it already exists.)"
		else
			$GROUPADD vglusers || echo "Could not add vglusers group (probably because it already exists.)"
		fi
	fi

	configdev
}

configglx()
{
	checkwayland || return

	if [ $UNATTENDED = 0 ]; then
		ynprompt "Restrict 3D X server access to vglusers group (recommended)?"
		if [ $? = 1 ]; then VGLUSERSONLY=1; else VGLUSERSONLY=0; fi

		ynprompt "Restrict framebuffer device access to vglusers group (recommended)?"
		if [ $? = 1 ]; then FBDEVVGLUSERSONLY=1; else FBDEVVGLUSERSONLY=0; fi

		ynprompt "Disable XTEST extension (recommended)?"
		if [ $? = 1 ]; then DISABLEXTEST=1; else DISABLEXTEST=0; fi
	fi

	if [ "$VGLUSERSONLY" = "1" ]; then
		checkselinux || return
		echo ... Creating vglusers group ...
		if [ ! "$GID" = "" ]; then
			$GROUPADD -g $GID vglusers || echo "Could not add vglusers group (probably because it already exists.)"
		else
			$GROUPADD vglusers || echo "Could not add vglusers group (probably because it already exists.)"
		fi

		if [ ! -d /etc/opt/VirtualGL ]; then
			echo ... Creating /etc/opt/VirtualGL/ ...
			mkdir -p /etc/opt/VirtualGL
		fi
		echo ... Granting read permission to /etc/opt/VirtualGL/ for vglusers group ...
		getent group gdm >/dev/null 2>&1 && (
			chown gdm:vglusers /etc/opt/VirtualGL
		) || (
			getent group Debian-gdm >/dev/null 2>&1 && (
				chown Debian-gdm:vglusers /etc/opt/VirtualGL
			) || (
				chown root:vglusers /etc/opt/VirtualGL
			)
		)
		chmod 750 /etc/opt/VirtualGL
		if [ $SELINUX = 1 ]; then
			echo ... Setting SELinux contexts to allow vglgenkey to run within GDM ...
			# Try to combine operations (semanage is slow)
			$SEMANAGE -i - <<EOF >/dev/null
fcontext -a -t xdm_rw_etc_t '/etc/opt/VirtualGL(/.*)?'
fcontext -a -t xdm_exec_t /usr/bin/xauth
EOF
			if [ $? = 1 ]; then
				# That didn't work.  Try the old-fashioned way
				$SEMANAGE fcontext -a -t xdm_rw_etc_t '/etc/opt/VirtualGL(/.*)?'
				$SEMANAGE fcontext -a -t xdm_exec_t /usr/bin/xauth
			fi
			$RESTORECON -R -v /etc/opt/VirtualGL /usr/bin/xauth
		fi
	fi

	configdev

	if [ -f /etc/X11/xdm/Xsetup_0 -a ! -h /etc/X11/xdm/Xsetup_0 ]; then
		addvglgenkey /etc/X11/xdm/Xsetup_0
	else
		if [ -f /etc/X11/xdm/Xsetup -a ! -h /etc/X11/xdm/Xsetup ]; then
			addvglgenkey /etc/X11/xdm/Xsetup
		fi
	fi
	if [ -f /etc/X11/gdm/Init/:0 ]; then
		if [ ! -h /etc/X11/gdm/Init/:0 ]; then
			addvglgenkey /etc/X11/gdm/Init/:0
		fi
	else
		if [ -f /etc/X11/gdm/Init/Default -a ! -h /etc/X11/gdm/Init/Default ]; then
			addvglgenkey /etc/X11/gdm/Init/Default
		fi
	fi
	if [ -f /etc/X11/gdm/SunRayInit/Default ]; then
		addvglgenkey /etc/X11/gdm/SunRayInit/Default
	fi
	for file in /etc/gdm/Init/Default \
		/etc/gdm3/Init/Default \
		/usr/local/etc/gdm/Init/Default \
		/etc/opt/gnome/gdm/Init/Default \
		/etc/kde4/kdm/Xsetup \
		/usr/share/config/kdm/Xsetup \
		/usr/local/kde4/share/config/kdm/Xsetup \
		/etc/sddm/Xsetup \
		/usr/share/sddm/scripts/Xsetup \
		/etc/mdm/Init/Default; do
		if [ -f $file -a ! -h $file ]; then
			addvglgenkey $file
		fi
	done
	if [ -f /etc/lightdm/lightdm.conf ]; then
		addvglgenkey_lightdm /etc/lightdm/lightdm.conf
	elif [ -d /etc/lightdm ]; then
		echo [SeatDefaults] >/etc/lightdm/lightdm.conf
		addvglgenkey_lightdm /etc/lightdm/lightdm.conf
	fi
	for dir in /usr/share/gdm/greeter/autostart \
		/usr/local/share/gdm/greeter/autostart; do
		if [ -d $dir ]; then
			echo ... Creating $dir/virtualgl.desktop ...
			if [ "$VGLUSERSONLY" = "1" ]; then
				cat >$dir/virtualgl.desktop <<EOF
[Desktop Entry]
Type=Application
Exec=$VGLGENKEY
EOF
			else
				cat >$dir/virtualgl.desktop <<EOF
[Desktop Entry]
Type=Application
Exec=xhost +LOCAL:
EOF
			fi
			chmod 644 $dir/virtualgl.desktop
		fi
	done

	for file in /etc/gdm/custom.conf \
		/etc/X11/gdm/custom.conf \
		/etc/gdm3/custom.conf \
		/etc/gdm3/daemon.conf; do
		if [ -f $file -a ! -h $file -a $WAYLAND = 1 ]; then
			disablewaylandgdm $file
		fi
	done

	if [ "$UNAME_S" = "SunOS" ]; then
		if [ ! -d /etc/dt/config ]; then
			echo ... Creating /etc/dt/config/ directory ...
			mkdir -p /etc/dt/config
			chmod 755 /etc/dt/config
		fi

		if [ ! -f /etc/dt/config/Xsetup ]; then
			if [ -f /usr/dt/config/Xsetup ]; then
				echo ... Copying /usr/dt/config/Xsetup to /etc/dt/config/Xsetup ...
				cp /usr/dt/config/Xsetup /etc/dt/config/Xsetup
			fi
		else
			backup /etc/dt/config/Xsetup
		fi
		if [ -f /etc/dt/config/Xsetup ]; then
			addvglgenkey /etc/dt/config/Xsetup bottom
		fi

		if [ ! -f /etc/dt/config/Xconfig ]; then
			if [ -f /usr/dt/config/Xconfig ]; then
				echo ... Copying /usr/dt/config/Xconfig to /etc/dt/config/Xconfig ...
				cp /usr/dt/config/Xconfig /etc/dt/config/Xconfig
			fi
		else
			backup /etc/dt/config/Xconfig
		fi
		if [ -f /etc/dt/config/Xconfig ]; then
			echo ... Setting Dtlogin\*grabServer to False in /etc/dt/config/Xconfig ...
			replaceline /etc/dt/config/Xconfig Dtlogin\\*grabServer "Dtlogin\*grabServer: False"
		fi
		if [ -f /etc/dt/config/Xconfig.SUNWut.prototype ]; then
			backup /etc/dt/config/Xconfig.SUNWut.prototype
			echo ... Setting Dtlogin\*grabServer to False in /etc/dt/config/Xconfig.SUNWut.prototype ...
			replaceline /etc/dt/config/Xconfig.SUNWut.prototype Dtlogin\\*grabServer "Dtlogin\*grabServer: False"
		fi

	fi

	for file in /etc/X11/xdm/Xservers \
		/etc/X11/gdm/gdm.conf \
		/etc/gdm/custom.conf \
		/etc/gdm3/daemon.conf \
		/usr/local/etc/gdm/custom.conf \
		/etc/gdm/gdm.conf \
		/etc/X11/gdm/custom.conf \
		/etc/opt/gnome/gdm/gdm.conf \
		/etc/opt/kde3/share/config/kdm/Xservers \
		/etc/mdm/mdm.conf; do
		if [ -f $file -a ! -h $file ]; then
			if [ "$DISABLEXTEST" = "1" ]; then
				disablextest $file
			else
				enablextest $file
			fi
		fi
	done
	if [ -f /etc/gdm/gdm-cdd.conf ]; then
		if [ "$DISABLEXTEST" = "1" ]; then
			disablextest /etc/gdm/gdm-cdd.conf
		else
			enablextest /etc/gdm/gdm-cdd.conf
		fi
	fi
	for file in /etc/kde4/kdm/kdmrc \
		/etc/kde/kdm/kdmrc \
		/usr/share/config/kdm/kdmrc \
		/usr/local/kde4/share/config/kdm/kdmrc; do
		if [ -f $file -a ! -h $file ]; then
			if [ "$DISABLEXTEST" = "1" ]; then
				disablextestkdm $file
			else
				enablextestkdm $file
			fi
		fi
	done
	if [ "$UNAME_S" = "SunOS" ]; then
		if [ "$DISABLEXTEST" = "1" ]; then
			if [ ! -f /etc/dt/config/Xservers ]; then
				if [ -f /usr/dt/config/Xservers ]; then
					echo ... Copying /usr/dt/config/Xservers to /etc/dt/config/Xservers ...
					cp /usr/dt/config/Xservers /etc/dt/config/Xservers
				fi
			fi
			if [ -f /etc/dt/config/Xservers ]; then
				disablextest /etc/dt/config/Xservers
			fi
			if [ -x /usr/sbin/svccfg ]; then
				/usr/sbin/svccfg -s application/x11/x11-server delpropvalue options/server_args "*-tst*" 2>&1 >/dev/null
				/usr/sbin/svccfg -s application/x11/x11-server addpropvalue options/server_args -tst 2>&1 >/dev/null
			fi
		else
			if [ -f /etc/dt/config/Xservers ]; then
				enablextest /etc/dt/config/Xservers
			fi
			if [ -x /usr/sbin/svccfg ]; then
				/usr/sbin/svccfg -s application/x11/x11-server delpropvalue options/server_args "*-tst*" 2>&1 >/dev/null
			fi
		fi
	fi

	if [ "$UNAME_S" = "Linux" ]; then
		if [ -f /etc/inittab ]; then
			echo ... Setting default run level to 5 \(enabling graphical login prompt\) ...
			replaceline /etc/inittab "id:[0-9]:initdefault:" "id:5:initdefault:"
		fi
	fi

	for file in /etc/X11/gdm/gdm.conf \
		/etc/gdm/custom.conf \
		/etc/gdm3/daemon.conf \
		/usr/local/etc/gdm/custom.conf \
		/etc/gdm/gdm.conf \
		/etc/X11/gdm/custom.conf \
		/etc/opt/gnome/gdm/gdm.conf \
		/etc/mdm/mdm.conf; do
		if [ -f $file -a ! -h $file ]; then
			disallowgdmtcp $file
		fi
	done
	if [ -f /etc/gdm/gdm-cdd.conf ]; then
		disallowgdmtcp /etc/gdm/gdm-cdd.conf
	fi

	echo
	echo Done.  You must restart the display manager for the changes to take effect.
	if [ "$RMMODNEEDED" = "1" ]; then
		echo
		echo "IMPORTANT NOTE: Your system uses modprobe.d to set device permissions.  You"
		echo "must execute 'modprobe -r nvidia_uvm nvidia_drm nvidia_modeset nvidia' with the"
		echo "display manager stopped in order for the new device permission settings to"
		echo "become effective."
	fi
	echo
}

MYPATH=$(dirname "$(realpath "$0")")
if [ -x $MYPATH/vglgenkey ]; then
	VGLGENKEY=$MYPATH/vglgenkey
else
	echo The vglgenkey script must be in the same directory as vglserver_config and must be executable.
	exit 1
fi

while [ $# -gt 0 ]; do
	case "$1" in
		-s) VGLUSERSONLY=1 ;;
		-f) FBDEVVGLUSERSONLY=1 ;;
		-t) DISABLEXTEST=1 ;;
		+s) VGLUSERSONLY=0 ;;
		+f) FBDEVVGLUSERSONLY=0 ;;
		+t) DISABLEXTEST=0 ;;
		-gid) GID=$2; shift ;;
		+glx) CONFIG_VGL="configglx"; UNATTENDED=1 ;;
		-glx) CONFIG_VGL="unconfigglx"; UNATTENDED=1 ;;
		-config) CONFIG_VGL="configglx"; UNATTENDED=1 ;;
		-unconfig) CONFIG_VGL="unconfigglx"; UNATTENDED=1 ;;
		+egl) BACKEND=egl; CONFIG_VGL="configegl"; UNATTENDED=1 ;;
		-egl) BACKEND=egl; CONFIG_VGL="unconfigdev"; UNATTENDED=1 ;;
		*) usage 0
	esac
	shift
done

if [ "$CONFIG_VGL" = "" -a $UNATTENDED = 1 ]; then
	usage 0
fi

UNAME_S=`uname -s`
UNAME_M=`uname -m`

if [ ! `uid` -eq 0 ]; then
	echo This script can only be executed by the root user.
	exit 1
fi

if [ $UNATTENDED = 0 ]; then
	while [ 1 ]
	do
		echo
		echo "1) Configure server for use with VirtualGL (GLX + EGL back ends)"
		echo "2) Unconfigure server for use with VirtualGL (GLX + EGL back ends)"
		echo "3) Configure server for use with VirtualGL (EGL back end only)"
		echo "4) Unconfigure server for use with VirtualGL (EGL back end only)"
		echo "X) Exit"
		echo
		echo Choose:
		read _CHOICE

		case $_CHOICE in
		1) configglx
			;;
		2) unconfigglx
			;;
		3) BACKEND=egl; configegl
			;;
		4) BACKEND=egl; unconfigdev
			;;
		X) break
			;;
		x) break
			;;
			esac
	done
else
	$CONFIG_VGL
fi
