Index: Debconf/Config.pm
===================================================================
--- Debconf/Config.pm	(revision 1851)
+++ Debconf/Config.pm	(working copy)
@@ -181,6 +181,25 @@
 		);
 		$config->{config} = "_ENV_stack";
 	}
+
+	# If the templates database is readonly, stack a writable in-memory
+	# one on top so that at least we can act as a passthrough UI agent.
+	my $templates=Debconf::DbDriver->driver($config->{templates});
+	if (ref $templates and $templates->{readonly}) {
+		Debconf::Db->makedriver(
+			driver => "Pipe",
+			name => "_mem_templates_cache",
+			infd => "none",
+			outfd => "none",
+			format => "822",
+		);
+		Debconf::Db->makedriver(
+			driver => "Stack",
+			name => "_mem_templates_stack",
+			stack => "_mem_templates_cache, $config->{templates}",
+		);
+		$config->{templates} = "_mem_templates_stack";
+	}
 }
 
 =item getopt
Index: Debconf/DbDriver/Stack.pm
===================================================================
--- Debconf/DbDriver/Stack.pm	(revision 1851)
+++ Debconf/DbDriver/Stack.pm	(working copy)
@@ -18,7 +18,7 @@
 shadow items lower in the stack, so requests for items will be passed on
 to the first driver in the stack that contains the item.
 
-Writing to the stack is more complex, because we meed to worry about
+Writing to the stack is more complex, because we need to worry about
 readonly drivers. Instead of trying to write to a readonly driver and
 having it fail, this module will copy the item from the readonly driver
 to the writable driver closest to the top of the stack that accepts the
@@ -73,6 +73,15 @@
 	$this->error("stack is empty") if ! @{$this->{stack}};
 	#$this->error("topmost driver not writable")
 	#	if $this->{stack}->[0]->{readonly} && ! $this->{readonly};
+
+	if (! $this->{readonly}) {
+		# If all drivers are readonly, then the whole stack is.
+		my $readonly=1;
+		foreach my $driver (@{$this->{stack}}) {
+			$readonly=0 if ! $driver->{readonly};
+		}
+		$this->{readonly}=1 if $readonly;
+	}
 }
 
 =head2 iterator
Index: Debconf/DbDriver/Pipe.pm
===================================================================
--- Debconf/DbDriver/Pipe.pm	(revision 1851)
+++ Debconf/DbDriver/Pipe.pm	(working copy)
@@ -29,7 +29,9 @@
 
 =item outfd
 
-File descriptor number to write to. Defaults to writing to stdout.
+File descriptor number to write to. Defaults to writing to stdout. If
+it's set to "none", the db will be thrown away rather than saved. Setting
+both infd and outfd to none gets you a writable temporary db in memory.
 
 =item format
 
@@ -95,7 +97,7 @@
 =sub shutdown
 
 Save the entire cache out to the fd. Always writes the cache, even if it's
-not dirty, for consitency's sake.
+not dirty, for consistency's sake.
 
 =cut
 
@@ -106,20 +108,24 @@
 
 	my $fh;
 	if (defined $this->{outfd}) {
-		open ($fh, ">&=$this->{outfd}") or
-			$this->error("could not open file descriptor #$this->{outfd}: $!");
+		if ($this->{outfd} ne 'none') {
+			open ($fh, ">&=$this->{outfd}") or
+				$this->error("could not open file descriptor #$this->{outfd}: $!");
+		}
 	}
 	else {
 		open ($fh, '>-');
 	}
 	
-	$this->{format}->beginfile;
-	foreach my $item (sort keys %{$this->{cache}}) {
-		next unless defined $this->{cache}->{$item}; # skip deleted
-		$this->{format}->write($fh, $this->{cache}->{$item}, $item);
+	if (defined $fh) {
+		$this->{format}->beginfile;
+		foreach my $item (sort keys %{$this->{cache}}) {
+			next unless defined $this->{cache}->{$item}; # skip deleted
+			$this->{format}->write($fh, $this->{cache}->{$item}, $item);
+		}
+		$this->{format}->endfile;
+		close $fh;
 	}
-	$this->{format}->endfile;
-	close $fh;
 
 	return 1;
 }
