}
}
+proc run {what command args} {
+ ## Run a command, reporting the result. WHAT is shown in the output;
+ ## COMMAND are the command and arguments as a list; these are substituted
+ ## according to the string map ARGS. Return true if the command succeeded,
+ ## false if it failed.
+
+ global QUIS
+
+ ## Substitute tokens in the command.
+ set cmd {}
+ set subst [concat [list "%%" "%"] $args]
+ foreach item $command { lappend cmd [string map $subst $item] }
+
+ ## Run the command.
+ set rc [catch {
+ set out [eval exec -ignorestderr $cmd 2>@1]
+ } msg]
+
+ ## Sort out the report.
+ if {$rc} { set out $msg }
+ set out "| [string map [list "\n" "\n| "] $out]"
+
+ ## Announce the result.
+ if {$rc} {
+ puts stderr "$QUIS: $what failed..."
+ puts stderr $out
+ return false
+ } else {
+ puts "$QUIS: $what output..."
+ puts $out
+ return true
+ }
+}
+
###--------------------------------------------------------------------------
### Configuration spaces.
###
###--------------------------------------------------------------------------
### Processing the results.
-proc build-command {command args} {
- ## Return the COMMAND list, after applying the string map ARGS to each item
- ## in turn.
-
- set cmd {}
- foreach item $command {
- lappend cmd [string map $args $item]
- }
- return $cmd
-}
-
proc zone-file-name {view config} {
## Return the relative file name for the zone described by CONFIG, relative
## to the given VIEW. An absolute filename may be derived later, depending
global QUIS
array set zone $info
- set cmd [build-command $zone(signzone-command) \
- "%z" $zone(name) \
- "%f" $zone(file-name) \
- "%o" $zone(server-file-name) \
- "%q" $soafmt]
- set rc [catch {
- set out [eval exec -ignorestderr $cmd]
- } msg]
- if {$rc} { set out $msg }
- set out "| [string map [list "\n" "\n| "] $out]"
- set ident "zone `$zone(name)' in view `$zone(mapped-view)'"
- if {$rc} {
- puts stderr "$QUIS: signing zone $ident failed..."
- puts stderr $out
- return false
- } else {
- puts "$QUIS: signing zone $ident output..."
- puts $out
- return true
- }
+ return [run "zone `$zone(name)' in view `$zone(mapped-view)'" \
+ $zone(signzone-command) \
+ "%z" $zone(name) \
+ "%f" $zone(file-name) \
+ "%o" $zone(server-file-name) \
+ "%q" $soafmt]
}
proc write-zone-stanza {view chan config} {
close $chan
## Check the zone for sanity.
- set cmd [build-command $zone(checkzone-command) \
- "%z" $name \
- "%v" $view \
- "%f" $tmp]
- set rc [catch {
- set out [eval exec $cmd]
- } msg]
- if {$rc} { set out $msg }
- set out "| [string map [list "\n" "\n| "] $out]"
- if {$rc} {
- puts stderr "$QUIS: zone check failed..."
- puts stderr $out
+ if {![run "zone check" $zone(checkzone-command) \
+ "%z" $name \
+ "%v" $view \
+ "%f" $tmp]} {
eval $cleanup
exit 1
- } else {
- puts "$QUIS: zone check output..."
- puts $out
}
## If the zone wants signing, better to do that now.
file rename -force -- $tmp $zone(file-name)
set cleanup {}
foreach view $matchview {
- eval exec $cmd [build-command $zone(reload-command) \
- "%v" $view \
- "%z" $zone(name)]
+ if {![run "reload zone `$zone(name) in view `$view'" \
+ $zone(reload-command) \
+ "%v" $view \
+ "%z" $zone(name)]} {
+ exit 3
+ }
}
} {
eval $cleanup
confspc-eval toplevel [list source $CONFFILE]
## Grind through all of the zones.
- foreach iview $ZONECFG(all-views) {
+ array unset seen
+ foreach view $ZONECFG(all-views) {
foreach info $ZONES {
+
+ ## Fetch the zone information.
array unset zone
- set compinfo [compute-zone-properties $iview $info]
+ set compinfo [compute-zone-properties $view $info]
array set zone $compinfo
if {![string equal $zone(config-type) master]} { continue }
+
if {[string equal $zone(type) static] && $zone(sign)} {
- if {![sign-zone-file $compinfo $zone(file-name) $zone(soa-format)]} {
- set rc 2
+ ## Static zone: re-sign it if we haven't seen this user view before,
+ ## and then reload.
+
+ ## Sign the zone file if we haven't tried before.
+ set id [list $zone(name) $zone(mapped-view)]
+ if {![info exists seen($id)]} {
+ if {[sign-zone-file $compinfo \
+ $zone(file-name) $zone(soa-format)]} {
+ set seen($id) true
+ } else {
+ set rc 2
+ set seen($id) failed
+ }
+ }
+
+ ## If we succeeded, reload the zone in this server view.
+ if {[string equal $seen($id) true]} {
+ if {![run "reload zone `$zone(name) in server view `$view'" \
+ $zone(reload-command) \
+ "%z" $zone(name) \
+ "%v" $view]} {
+ set rc 2
+ }
}
} elseif {[string equal $zone(type) dynamic] &&
![string equal $zone(auto-dnssec) off]} {
- set cmd [build-command $zone(autosign-command) \
- "%z" $zone(name) \
- "%v" $iview]
- if {[catch { exec $cmd } msg]} {
- puts stderr "$QUIS: failed to reload `$zone(name)'"
- puts stderr "| [string map [list "\n" "\n| "] $msg]"
+ ## Dynamic zone: get BIND to re-sign it.
+
+ if {![run "re-sign zone `$zone(name) in server view `$view'" \
+ $zone(autosign-command) \
+ "%z" $zone(name) \
+ "%v" $view]} {
set rc 2
}
}