#! /bin/sh -
# -*- mode:sh -*-
# $Id: $
# Copyright (c) 2007 travis+code@subspacefield.org

# set base filename for prepending to errors
progname=$(basename "$0")
#
usage="\
$progname [editor]"

# TODO: allow specifying the time spec
# TODO: allow specifying the working conf filename
# TODO: allow specifying the new conf filename

# This is the canonical place for the pf config file.
pf=/etc/pf.conf

# This is always a backup of the last config deadman
# was able to verify.
working=/etc/pf_working.conf

# This is what where we'll save the edit
new=/etc/pf_new.conf

err () { echo "$@" >&2; exit 1; }

if test "$#" -gt 1
then
	EDITOR="$1"
	shift
fi

if test "$#" -ne 0
then
	err "$usage"
fi

# This is just used to flag that the at job ran.
tmpfn="$(mktemp)"
rm "$tmpfn"
export new working pf tmpfn

# If the last working and currently-installed configs are identical, start editing a new one
# Otherwise, the currently-installed config (/etc/pf.conf) needs to be tested, because someone
# might have edited it and not tried it yet.
if cmp "$working" "$pf"
then
    test -e "$new" || cp "$pf" "$new"
    $EDITOR $new || err "editor $?"
else
    echo "Warning: $pf is not the same as $working; probably last edit was not done with deadman." >&2
    echo "Thus, the first edit must be for any changes to pf.conf." >&2
    cp "$pf" "$new"
fi

# Syntax check the new config.
pfctl -nf "$new" || err "bad conf"

# Schedule an at job to reinstall working one
id="$((echo pfctl -f $working; echo touch $tmpfn) | at now + 2 minutes 2>&1 | (read whatshell; read job id rest; echo $id))"

# Try the new config
pfctl -f "$new"

echo "When you get back in, hit return".
read stuff
if test -e "$tmpfn"
then
	err "The at job ran, so this did not work"
else
	at -r "$id"
	echo "Installing new firewall rules..."
	cp "$new" "$working"
	cp "$new" "$pf"
fi

exit 0
