#!/bin/sh
#
# Make a simple selinux type conditional ...
#
# Expect pcpupstream.te.in to contain lines like (mdadm_conf_t is
# the target type in the examples below)
# 
#	type mdadm_conf_t;
# allow pcp_pmcd_t ... mdadm_conf_t:...;
#
# and these become
# 
#	@PCP_MDADM_CONF_T@
# @PCP_MDADM_CONF_RULE@
#

dryrun=false
if [ $# -gt 1 -a "$1" = -n ]
then
    dryrun=true
    shift
fi

if [ $# -ne 1 ]
then
    echo "Usage: make-type-conditional [-n] selinux_type"
    exit 1
fi

tmp=/var/tmp/m-t-c-$$
trap "rm -f $tmp.*; exit 0" 0 1 2 3 15

type=$1

case "$type"
in
    *_t)
    	;;
    *)
	echo "$type: Fail: type does not end in _t, I can't help"
	exit 1
	;;
esac

if grep "type $type;" pcpupstream.te.in >/dev/null
then
    :
else
    echo "$type: Fail: type not in pcpupstream.te.in?"
    $dryrun || exit 1
fi

BASE=`echo $type | sed -e 's/_t$//' | tr '[a-z]' '[A-Z]'`

if grep "@PCP_${BASE}_T@" pcpupstream.te.in >/dev/null
then
    echo "$type: Fail: @PCP_${BASE}_T@ already used in pcpupstream.te.in"
    $dryrun || exit 1
fi

if grep "@PCP_${BASE}_RULE@" pcpupstream.te.in >/dev/null
then
    echo "$type: Fail: @PCP_${BASE}_RULE@ already used in pcpupstream.te.in"
    $dryrun || exit 1
fi

if grep "@PCP_SELINUX_${BASE}@" GNUlocaldefs >/dev/null
then
    echo "$type: Fail: @PCP_SELINUX_${BASE}@ already used in GNUlocaldefs"
    $dryrun || exit 1
fi

if grep "@PCP_${BASE}_T@" GNUmakefile >/dev/null
then
    echo "$type: Fail: @PCP_${BASE}_T@ already used in GNUmakefile"
    $dryrun || exit 1
fi

config=`echo "PCP_SELINUX_${BASE}" | tr '[A-Z]' '[a-z]'`

rule=`grep "^allow.* $type:" <pcpupstream.te.in`
if [ -z "$rule" ]
then
    echo "$type: Fail: no allow ... $type:... line pcpupstream.te.in?"
    $dryrun || exit 1
fi

# === pcpupstream.te.in ===
#
sed <pcpupstream.te.in >$tmp.out \
    -e "/type $type;/s//@PCP_${BASE}_T@/" \
    -e "/^allow.* $type:/s/.*/@PCP_${BASE}_RULE@/" \
# end

if $dryrun
then
    diff -C 1 pcpupstream.te.in $tmp.out
else
    mv $tmp.out pcpupstream.te.in
    echo "pcpupstream.te.in updated ..."
fi

# === GNUlocaldefs ===
# add ifeq block to define PCP_MDADM_CONF_T and PCP_MDADM_CONF_RULE
#
cat GNUlocaldefs >$tmp.out
cat <<End-of-File >>$tmp.out

ifeq "\$(PCP_SELINUX_${BASE})" "true"
PCP_${BASE}_T="type $type;"
PCP_${BASE}_RULE="$rule"
endif
End-of-File

if $dryrun
then
    diff -C 1 GNUlocaldefs $tmp.out
else
    mv $tmp.out GNUlocaldefs
    echo "GNUlocaldefs updated ..."
fi

# === GNUmakefile ===
# add sed to expand @PCP_MDADM_CONF_T@ and @PCP_MDADM_CONF_RULE@
#
awk <GNUmakefile >$tmp.out '
/@PCP_SELINUX_MACRO_RULE@/	{
		print "		-e '"'"'s+@PCP_MDADM_CONF_T@+'"'"'$(PCP_MDADM_CONF_T)'"'"'+'"'"' \\"
		print "		-e '"'"'s+@PCP_MDADM_CONF_RULE@+'"'"'$(PCP_MDADM_CONF_RULE)'"'"'+'"'"' \\"
				}
				{ print }'

if $dryrun
then
    diff -C 1 GNUmakefile $tmp.out
else
    mv $tmp.out GNUmakefile
    echo "GNUmakefile updated ..."
fi

# === ../include/builddefs.in
# add
# PCP_SELINUX_BASE = @pcp_selinux_mdadm_conf@
#
awk <../include/builddefs.in >$tmp.out '
BEGIN				{ selinux = 0 }
selinux == 0 && /selinux configuration bits/	{ selinux++ }
selinux == 1 && NF == 0		{ selinux++; print "'"PCP_SELINUX_${BASE} = @$config@"'" }
				{ print }'

if $dryrun
then
    diff -C 1 ../include/builddefs.in $tmp.out
else
    mv $tmp.out ../include/builddefs.in
    echo "../include/builddefs.in updated ..."
fi

# === ../../configure.ac
# add
# pcp_selinux_mdadm_conf=false
# ...
# grep '^[[   ]][[    ]]*mdadm_conf_t_t$' <conftest.out >/dev/null \
#   && pcp_selinux_mdadm_conf=true
# ...
# AC_SUBST(pcp_selinux_mdadm_conf)
#
# using pcp_selinux_kmod_exec as the anchor so insertions come at end
# of blocks with pcp_selinux_kmod_exec references
#
line="    grep '^[[ 	]][[ 	]]*$type\$' <conftest.out >/dev/null \\\\"
awk <../../configure.ac >$tmp.out '
BEGIN			{ state = 1 }
state == 2 && NF == 0	{ state = 3; print "'"$config=false"'" }
state == 4 && NF == 0	{ state = 5
			  print "'"$line"'"
			  print "'"	&& $config=true"'"
			}
			{ print }
state == 1 && /pcp_selinux_kmod_exec=false/	{ state = 2 }
state == 3 && /pcp_selinux_kmod_exec=true/	{ state = 4 }
state == 5 && /pcp_selinux_kmod_exec/		{ state = 6 }'

if $dryrun
then
    diff -C 2 ../../configure.ac $tmp.out
else
    mv $tmp.out ../../configure.ac
    echo "../../configure.ac updated ..."
fi
