-(defun zone-write (zone &optional (stream *standard-output*))
- "Write a ZONE's records to STREAM."
- (labels ((fix-admin (a)
- (let ((at (position #\@ a))
- (s (concatenate 'string (string-downcase a) ".")))
- (when s
- (setf (char s at) #\.))
- s))
- (fix-host (h)
- (if (not h)
- "@"
- (let* ((h (string-downcase (stringify h)))
- (hl (length h))
- (r (string-downcase (zone-name zone)))
- (rl (length r)))
- (cond ((string= r h) "@")
- ((and (> hl rl)
- (char= (char h (- hl rl 1)) #\.)
- (string= h r :start1 (- hl rl)))
- (subseq h 0 (- hl rl 1)))
- (t (concatenate 'string h "."))))))
- (printrec (zr)
- (format stream "~A~20T~@[~8D~]~30TIN ~A~40T"
- (fix-host (zr-name zr))
- (and (/= (zr-ttl zr) (zone-default-ttl zone))
- (zr-ttl zr))
- (string-upcase (symbol-name (zr-type zr))))))
- (format stream "~
+(defgeneric zone-write (format zone stream)
+ (:documentation "Write ZONE's records to STREAM in the specified FORMAT."))
+
+(defvar *writing-zone* nil
+ "The zone currently being written.")
+
+(defvar *zone-output-stream* nil
+ "Stream to write zone data on.")
+
+(defmethod zone-write :around (format zone stream)
+ (let ((*writing-zone* zone)
+ (*zone-output-stream* stream))
+ (call-next-method)))
+
+(defun zone-save (zones &key (format :bind))
+ "Write the named ZONES to files. If no zones are given, write all the
+ zones."
+ (unless zones
+ (setf zones (hash-table-keys *zones*)))
+ (safely (safe)
+ (dolist (z zones)
+ (let ((zz (zone-find z)))
+ (unless zz
+ (error "Unknown zone `~A'." z))
+ (let ((stream (safely-open-output-stream safe
+ (zone-file-name z :zone))))
+ (zone-write format zz stream))))))
+
+;;;--------------------------------------------------------------------------
+;;; Bind format output.
+
+(defun bind-hostname (hostname)
+ (if (not hostname)
+ "@"
+ (let* ((h (string-downcase (stringify hostname)))
+ (hl (length h))
+ (r (string-downcase (zone-name *writing-zone*)))
+ (rl (length r)))
+ (cond ((string= r h) "@")
+ ((and (> hl rl)
+ (char= (char h (- hl rl 1)) #\.)
+ (string= h r :start1 (- hl rl)))
+ (subseq h 0 (- hl rl 1)))
+ (t (concatenate 'string h "."))))))
+
+(defmethod zone-write ((format (eql :bind)) zone stream)
+ (format stream "~