#!/bin/sh
#
#	$FreeBSD: head/ports-mgmt/pkg_jail/files/pkg_jail 446867 2017-07-29 06:02:24Z dinoex $
#
# Copyright (c) 2001-2017 by Dirk Meyer. All rights reserved.
#   Im Grund 4, 34317 Habichtswald, Germany
#   Email: dirk.meyer@dinoex.sub.org
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
# 3. Neither the name of the author nor the names of any co-contributors
#    may be used to endorse or promote products derived from this software
#    without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# -------------------------------------------------------------------------
#
. /etc/rc.subr
#
case "$0" in
/etc/rc*)
	# during boot (shutdown) $0 is /etc/rc (/etc/rc.shutdown),
	# so get the name of the script from $_file
	pkg_jail_script="$_file"
	;;
*)
	pkg_jail_script="$0"
	;;
esac
pkg_jail_prefix="${pkg_jail_script%/*}"
pkg_jail_config="${pkg_jail_prefix%/*}/etc/pkg_jail.conf"
echo "${pkg_jail_config}"
if test -s "${pkg_jail_config}"
then
	. "${pkg_jail_config}"
fi
#
name="pkg_jail"
rcvar="pkg_jail_enable"
init_cmd="pkg_jail_init"
start_cmd="pkg_jail_start"
shell_cmd="pkg_jail_shell"
list_cmd="pkg_jail_list"
stop_cmd="pkg_jail_stop"
status_cmd="pkg_jail_status"
extra_commands="status shell list init"
# defaults
: ${pkg_jail_enable="YES"}
: ${pkg_jail_hostname="build.local"}
: ${pkg_jail_short="${pkg_jail_hostname%%.*}"}
: ${pkg_jail_ip="127.0.0.1"}
: ${pkg_jail_dir="/usr/jail/mybuild"}
: ${pkg_jail_rule="127"}
#
pkg_jail_setup()
{
	if test ! -d "${pkg_jail_dir}"
	then
		mkdir -p "${pkg_jail_dir}"
	fi
	cd /usr/src
#	make buildworld
	make "DESTDIR=${pkg_jail_dir}" installworld
	make "DESTDIR=${D}" delete-old RM_I="-f -v"
	make "DESTDIR=${D}" delete-old-libs RM_I="-f -v"
	if test ! -f "${pkg_jail_dir}/etc/rc.conf"
	then
		if test ! -d "${pkg_jail_dir}/usr/ports"
		then
			mkdir "${pkg_jail_dir}/usr/ports"
		fi
		cd /usr/src/etc
		make "DESTDIR=${pkg_jail_dir}" distribution
		ln -sf dev/null "${pkg_jail_dir}/kernel"
		touch "${pkg_jail_dir}/etc/fstab"
		cp -pi /etc/localtime "${pkg_jail_dir}/etc/localtime"
		cp -pi /etc/resolv.conf "${pkg_jail_dir}/etc/resolv.conf"
		cp -pi /etc/make.conf "${pkg_jail_dir}/etc/make.conf"
		echo "hostname=\"${pkg_jail_hostname}\"" > "${pkg_jail_dir}/etc/rc.conf"
		cat >> "${pkg_jail_dir}/etc/rc.conf" << 'EOF'
portmap_enable="NO"
inetd_enable="NO"
blanktime="NO"
network_interfaces=""
releaseName="none"
sendmail_enable="NONE"
syslogd_flags="-ss"
entropy_file="NO"
background_fsck="NO"
EOF
	fi
}
pkg_jail_create_dev_rules()
{
	# Standard Jail ruleset
	/sbin/devfs rule -s ${pkg_jail_rule} delset
	/sbin/devfs rule -s ${pkg_jail_rule} add 100 hide
	/sbin/devfs rule -s ${pkg_jail_rule} add 200 path ptyp* unhide
	/sbin/devfs rule -s ${pkg_jail_rule} add 300 path ttyp* unhide
	/sbin/devfs rule -s ${pkg_jail_rule} add 400 path null unhide
	/sbin/devfs rule -s ${pkg_jail_rule} add 500 path zero unhide
	/sbin/devfs rule -s ${pkg_jail_rule} add 510 path crypto unhide
	/sbin/devfs rule -s ${pkg_jail_rule} add 600 path random unhide
	/sbin/devfs rule -s ${pkg_jail_rule} add 610 path urandom unhide
	/sbin/devfs rule -s ${pkg_jail_rule} add 700 path fd unhide
	/sbin/devfs rule -s ${pkg_jail_rule} add 800 path fd/* unhide
	/sbin/devfs rule -s ${pkg_jail_rule} add 810 path mdctl unhide
	/sbin/devfs rule -s ${pkg_jail_rule} add 900 path stdin unhide
	/sbin/devfs rule -s ${pkg_jail_rule} add 910 path stdout unhide
	/sbin/devfs rule -s ${pkg_jail_rule} add 920 path stderr unhide
	/sbin/devfs rule -s ${pkg_jail_rule} add 1000 path ptmx unhide
	/sbin/devfs rule -s ${pkg_jail_rule} add 1010 path pts unhide
	/sbin/devfs rule -s ${pkg_jail_rule} add 1020 path pts/* unhide
	/sbin/devfs rule -s ${pkg_jail_rule} add 1030 path pty unhide
	/sbin/devfs rule -s ${pkg_jail_rule} add 1040 path pty/* unhide
	/sbin/devfs rule -s ${pkg_jail_rule} add 1050 path tty* unhide
}
pkg_jail_create_dev_links()
{
	local devdir="${1}"
	local source="${2}"
	local target="${3}"
	(cd ${devdir} && ln -sf ${source} ${target})
}
pkg_jail_create_devfs()
{
	local jail_devdir="${pkg_jail_dir}/dev"
	local jail_devmount=`mount -t devfs | cut -d " " -f 3 | fgrep -x ${jail_devdir}`
	if test "${jail_devmount}" = ""
	then
		# create and mount devfs
		pkg_jail_create_dev_rules
		mount -t devfs dev ${jail_devdir}
		devfs -m ${jail_devdir} ruleset ${pkg_jail_rule}
		devfs -m ${jail_devdir} rule applyset
	fi
	if test ! -e "${jail_devdir}/console"
	then
		pkg_jail_create_dev_links ${jail_devdir} null console
	fi
	if test ! -e "${jail_devdir}/mem"
	then
		# for libkvm (ab)users
		pkg_jail_create_dev_links ${jail_devdir} null mem
		pkg_jail_create_dev_links ${jail_devdir} null kmem
	fi
	if test ! -e ${jail_devdir}/log
	then
		# Transitional symlink for old binaries
		pkg_jail_create_dev_links ${jail_devdir} ../var/run/log log
	fi
}
pkg_jail_create_jail_mount()
{
	if test ! -d "${pkg_jail_dir}/procfs/1"
	then
		if test ! -d "${pkg_jail_dir}/procfs"
		then
			mkdir "${pkg_jail_dir}/procfs"
		fi
		mount -t procfs -o ro procfs "${pkg_jail_dir}/procfs"
	fi
	if test ! -f "${pkg_jail_dir}/usr/src/Makefile"
	then
		mount -t nullfs -o ro /usr/src "${pkg_jail_dir}/usr/src"
	fi
	if test ! -f "${pkg_jail_dir}/usr/ports/Makefile"
	then
		mount -t nullfs -o rw /usr/ports "${pkg_jail_dir}/usr/ports"
	fi
}
pkg_jail_start()
{
	echo "Starting jail-${pkg_jail_hostname}-${pkg_jail_ip}"
	if test ! -d "${pkg_jail_dir}"
	then
		echo "${pkg_jail_dir}: Directory not found" >&2
		exit 1
	fi
	pkg_jail_create_devfs
	pkg_jail_create_jail_mount "${pkg_jail_dir}"
	sysctl security.jail.sysvipc_allowed=1
	/usr/sbin/jail -c name="${pkg_jail_short}" path="${pkg_jail_dir}" \
		host.hostname="${pkg_jail_hostname}" \
		allow.sysvipc allow.raw_sockets \
		ip4.addr="${pkg_jail_ip}"\
		command=/bin/sh /etc/rc
}
pkg_jail_status()
{
	/usr/sbin/jls | grep "${pkg_jail_hostname}"
}
pkg_jail_free()
{
	pkg_jail_status |
	while read jid dummy
	do
		if test "${jid}" -lt 1
		then
			continue
		fi
		echo "jail is already running" >&2
		pkg_jail_status >&2
		exit 69
	done
}
pkg_jail_umount()
{
	for dir in \
		"${pkg_jail_dir}/usr/ports" \
		"${pkg_jail_dir}/usr/src" \
		"${pkg_jail_dir}/procfs" \
		"${pkg_jail_dir}/dev" \

	do
		fstab=`fgrep "${dir}" /etc/fstab`
		if test -n "${fstab}"
		then
			continue
		fi
		mount=`mount | fgrep "${dir}"`
		if test -n "${mount}"
		then
			umount "${dir}"
		fi
	done
}
pkg_jail_init()
{
	if pkg_jail_free
	then
		pkg_jail_setup
		pkg_jail_create_devfs
		pkg_jail_create_jail_mount "${pkg_jail_dir}"
		/usr/sbin/jail -c name="${pkg_jail_short}" path="${pkg_jail_dir}" \
			host.hostname="${pkg_jail_hostname}" \
			allow.sysvipc allow.raw_sockets \
			ip4.addr="${pkg_jail_ip}"\
			command=/bin/sh -c "cd /usr/ports/ports-mgmt/pkg_jail && make install-ports"
		pkg_jail_umount
	fi
}
pkg_jail_shell()
{
	if pkg_jail_free
	then
		echo "Shell in jail-${pkg_jail_hostname}-${pkg_jail_ip}"
		pkg_jail_create_devfs
		pkg_jail_create_jail_mount "${pkg_jail_dir}"
		/usr/sbin/jail -c name="${pkg_jail_short}" path="${pkg_jail_dir}" \
			host.hostname="${pkg_jail_hostname}" \
			allow.sysvipc allow.raw_sockets \
			ip4.addr="${pkg_jail_ip}"\
			command=/bin/csh
		pkg_jail_umount
	fi
}
pkg_jail_list()
{
	/usr/sbin/jls | grep "${pkg_jail_hostname}" |
	while read jid dummy
	do
		if test "${jid}" -lt 1
		then
			continue
		fi
		ps -ax -o pid= -o jid= -o command= |
		while read pid pjid command
		do
			if test "${pjid}" != "${jid}"
			then
				continue
			fi
			echo "${pid}	${pjid}	${command}"
		done
	done
}
pkg_jail_stop()
{
	/usr/sbin/jls | grep "${pkg_jail_hostname}" |
	while read jid dummy
	do
		if test "${jid}" -lt 1
		then
			continue
		fi
		killall -j "${jid}"
	done
	pkg_jail_umount
}

load_rc_config $name
run_rc_command "$1"
# eof
