#!/bin/sh -efu

. shell-quote

bind_root_dir=/var/lib/bind
bind_local_conf_file="$bind_root_dir/etc/local.conf"

### basic file processing

# usage: bind_local_conf_include path
# include additional file into bind local conf
bind_local_conf_include()
{
    local path="$1";shift
    local qpath;
    quote_sed_regexp_variable qpath "$path"

    grep -qs "include[[:space:]]\+\"$qpath\"[[:space:]]*;[[:space:]]*\$" "$bind_local_conf_file" ||
        printf 'include "%s";\n' "$path" >>"$bind_local_conf_file"
}

# usage: bind_local_conf_exclude path
# exclude additional file from bind local conf
bind_local_conf_exclude()
{
    local path
    quote_sed_regexp_variable path "$1";shift

    sed "/include[[:space:]]\+\"$path\"[[:space:]]*;[[:space:]]*\$/d" -i "$bind_local_conf_file"
}

### zone options

# usage: bind_domain_exists <domain-name>
# check are zone record exists in bind options
bind_domain_exists()
{
    local domain
    quote_sed_regexp_variable domain "$1"

    for f in `find "$bind_root_dir/etc" -type f -name '*.conf'`; do
	grep -qs "^[[:space:]]*zone[[:space:]]\+\"$domain\"[[:space:]]\+{[[:space:]]*\$" "$f" && return 0
    done
    return 1
}

# usage: bind_domain_list <file>
# list available domains in bind options
bind_domain_list()
{
    local file="$1";shift

    sed -n \
	-e 's/^[[:space:]]*zone[[:space:]]\+\"\([.a-zA-Z0-9_-]\+\)\"[[:space:]]\+{[[:space:]]*$/\1/p' \
	"$bind_root_dir/$file"
}

# usage: bind_domain_add <file> <domain-name> < OPTIONS
# add domain definition to file
# zone options readed from standard input
bind_domain_add()
{
    local file="$1";shift
    local domain="$1";shift

    bind_domain_exists "$domain" && return 0

    bind_local_conf_include "$file"

    local path="$bind_root_dir/$file"
    printf 'zone "%s" {\n' "$domain" >>"$path"
    cat>>"$path"
    printf '};\n'>>"$path"
}


# usage: bind_domain_del <file> <domain-name>
# remove domain definition from file
bind_domain_del()
{
    local file="$bind_root_dir/$1";shift

    local domain
    quote_sed_regexp_variable domain "$1"
    sed -e "/^[[:space:]]*zone[[:space:]]\+\"$domain\"[[:space:]]\+{[[:space:]]*\$/,/^[[:space:]]*};[[:space:]]*\$/d" \
	-i "$file"
}

# usage: bind_domain_get <file> <domain-name> <param>
# read domain parameter's value
bind_domain_get()
{
    local file="$bind_root_dir/$1";shift
    local domain param
    quote_sed_regexp_variable domain "$1";shift
    quote_sed_regexp_variable param "$1";shift

    sed -n \
	-e "/^[[:space:]]*zone[[:space:]]\+\"$domain\"[[:space:]]\+{[[:space:]]*\$/,/^[[:space:]]*};[[:space:]]*\$/ s/^[[:space:]]*$param[[:space:]]\+\(.*\)[[:space:]]*;\$/\1/p" \
	"$file"
}


# usage: bind_domain_set <file> <domain-name> <param> <value>
# write domain parameter's value
bind_domain_set()
{
    local file="$bind_root_dir/$1";shift
    local domain param
    quote_sed_regexp_variable domain "$1";shift
    quote_sed_regexp_variable param "$1";shift
    local value="$1";shift

    sed -e "/^[[:space:]]*zone[[:space:]]\+\"$domain\"[[:space:]]\+{[[:space:]]*\$/,/^[[:space:]]*};[[:space:]]*\$/ s/^\([[:space:]]*\)$param[[:space:]]\+.*/\1$param $value;/" \
	-i "$file"
}

### zone content

# usage: bind_domain_add <file> <domain-name> < CONTENT
# add zone definition to file
# zone content readed from standard input
# TODO: automatically write filename into appropriate domain definition
bind_zone_add()
{
    local path="$bind_root_dir/zone/$1";shift

    install -d -m770 -o root -g named -- "${path%/*}"
    [ -s "$path" ] || cat >"$path"
    chown named:named "$path"
}

bind_zone_del()
{
    local path="$bind_root_dir/zone/$1";shift

    rm -f -- "$path" "$path.jnl"
}

# usage: bind_serial_init
# return initial value of serial
bind_serial_first()
{
    date +%s
}

# usage: bind_serial_next
# return next value for current serial
bind_serial_next()
{
    date +%s
}
