<?xml version="1.0"?>
<!DOCTYPE article PUBLIC "-//Norman Walsh//DTD DocBk XML V3.1.7//EN"
     "dtd/docbook-xml/3.1.7/docbookx.dtd" [
<!ENTITY tutorial_config SYSTEM "../samples/tutorial">
<!ENTITY tutorial_back_config SYSTEM "../samples/tutorial-back">
<!ENTITY tutorial_templates SYSTEM "../samples/tutorial.templates">
]>
<article>
  <artheader>
    <title>
      The Debconf Programmer's Tutorial
    </title>
    <author>
      <firstname>
	Joey
      </firstname>
      <surname>
	Hess
      </surname>
      <affiliation>
	<orgname>
	  The Debian Project
	</orgname>
	<address><email>joeyh@debian.org</email></address>
      </affiliation>   
    </author>
    <copyright>
      <year>
	1999
      </year>
      <year>
        2000
      </year>
      <holder>
	Joey Hess
      </holder>
    </copyright>
    <legalnotice>
      <para>
        This text is copyright by the author under the terms of the
        BSD license, without the advertising clause.
      </para>
    </legalnotice>
  </artheader>
  
  <sect1>
    <title>
      Introduction
    </title>
    <para>
      This is a guide to using debconf with your packages, aimed at a
      Debian developer.
    </para>
    <para>
      So, what is debconf? To save you reading the specification (which is
      in Debian policy if you're interested),
      debconf is a backend database, with a frontend that talks to it
      and presents an interface to the user. There can be many
      different types of frontends, from plain text to a web
      frontend. The frontend also talks to a special config script in
      the control section of a debian package, and it can talk to
      postinst scripts and other scripts as well, all using a special
      protocol. These scripts tell the frontend what values they need
      from the database, and the frontend asks the user questions to
      get those values if they aren't set.
    </para>
    <para>
      Debconf should be used whenever your package needs to output
      something to the user, or ask a question. I'll assume you already 
      have a package that does this and you want to convert it to use
      debconf.
    </para>
  </sect1>
  
  <sect1>
    <title>
      Getting started
    </title>
    <para>
      First, your package must depend on debconf (or pre-depend on it
      if it uses debconf in its preinst<footnote><para>Since policy frowns
      on pre-dependencies that haven't been approved by debian-devel, you
      could also make your package detect if debconf isn't installed, and use
      a sane fallback that doesn't involve debconf.</para></footnote>). This is
      necessary since debconf isn't essential.
    </para>
    <para>
      The first thing to do is look at your postinst, plus any program
      your postinst calls (like a "packageconfig" program), plus your
      preinst, and even your prerm and postrm. Take note of all output
      they can generate and all input they prompt the user for. All
      this output and input must be eliminated for your package to use
      debconf. (Output to stderr can be left as is.)
      <note>
      <para>
      If your preinst uses debconf, you must make your package Pre-Depend on
      <literal>debconf (&gt;= 0.2.17)</literal>.
      </para>
      </note>
    </para>
    <para>
      For example, a hypothetical package "foo" has the following postinst:
      <programlisting>
#!/bin/sh -e
echo -n "Do you like debian? [yn] "
read like
case "$like" in
n*|N*)
	echo "Poor misguided one. Why are you installing this package, then?"
	/etc/init.d/subliminal_messages start "I like debian."
;;
esac
      </programlisting>
    </para>
    <para>
      It's clear that it asks a question and sometimes outputs a
      message. In this tutorial, we will make it use use debconf to do both.
    </para>
  </sect1>

  <sect1>
    <title>
      The Templates file
    </title>
    <para>
      Start writing a debian/templates file. Each time you find a
      piece of output or a question, add it to the file as a new
      template. The format of this file is simple and quite similar to
      a Debian control file:
      <programlisting>
Template: <parameter>packagename</parameter>/<parameter>something</parameter>
Type: <parameter>[select,multiselect,string,boolean,note,text,password]</parameter>
Default: <parameter>[an optional default value]</parameter>
Description: Blah blah blah?
 Blah blah blah. Blah blah. Blah blah blah. Blah blah? Blah
 blah blah blah. Blah blah blah. Blah blah.
 .
 Blah blah blah. Blah blah. Blah blah blah. Blah blah. Blah blah blah.
 blah.

Template: ....
....
      </programlisting>
    </para>
    <para>
      <table frame="all">
        <title>Available data types</title>
        <tgroup cols="2">
	<thead>
	  <row>
	    <entry>Type</entry>
	    <entry>Description</entry>
	  </row>
	</thead>
	<tbody>
	  <row>
	    <entry>string</entry>
	    <entry>Holds any arbitrary string of data.</entry>
	  </row>
	  <row>
	    <entry>boolean</entry>
	    <entry>
	       Holds "<literal>true</literal>" or "<literal>false</literal>".
	    </entry>
	  </row>
	  <row>
	    <entry>select</entry>
	    <entry>
	      Holds one of a finite number of possible values. These
	      values must be specified in a field named
	      <literal>Choices:</literal>. Separate the possible values
	      with commas and spaces, like this:
	      <literal>
	        Choices: yes, no, maybe
	      </literal>
	    </entry>
	  </row>
	  <row>
	    <entry>multiselect</entry>
	    <entry>
	      Just like the select data type, except the user can choose any
	      number of items from the list. This means that the 
	      <literal>Default:</literal> field and the actual value of the
	      question may be a comma and space delimited list of values,
	      just like the <literal>Choices:</literal> field.
	      <note>
	        <para>
	          For compatability with old versions of Debconf, if you use
	          this data type, please make your package depend on
	          <literal>debconf (>= 0.2.26)</literal>
	        </para>
	      </note>
	    </entry>
	  </row>
	  <row>
	    <entry>note</entry>
	    <entry>
	      This template is a note that can be displayed to the user. As
	      opposed to text, it is something important, that the user really
	      should see. If debconf is not running interactively, it might be
	      saved to a log file or mailbox for them to see later.
	    </entry>
	  </row>
	  <row>
	    <entry>text</entry>
	    <entry>
	      This template is a scrap of text that can be displayed to
	      the user. It's intended to be used for mostly cosmetic
	      reasons, touching up around other questions that are asked
	      at the same time. Unlike a note, it isn't treated as
	      something the user should definitely see. Less complex frontends
	      may refuse to ever display this type of element.
	    </entry>
	  </row>
	  <row>
	    <entry>password</entry>
	    <entry>
	      Holds a password. Use with caution. Be aware that the password
	      the user enters will be written to debconf's database. You
	      should consider clearing that value out of the database as soon
	      as is possible.
	    </entry>
	  </row>
	</tbody>
      </tgroup>
      </table>
    </para>
    <para>
      Note that the Description field has two parts, a short
      description and a long description. Please note, that some
      frontends do not always display the long description, often only
      showing it if the user asks for additional help. So the short
      description should be entirely standalone.
    </para>
    <para>
      If you can't think up a long description, then first, think some
      more. Post to debian-devel. Ask for help. Take a writing class!
      That extended description is <emphasis>important</emphasis>.
      If after all that you still can't come up with anything, leave it
      blank. There is no point in duplicating the short description.
    </para>
    <para>
      Text in the long description will be word-wrapped, unless it is
      prefixed by additional whitespace (beyond the one required space).
      You can break it up into separate paragraphs by putting " ." on a
      line by itself between them.
    </para>
    <para>
      Following along in our example, we create a templates file with two
      templates in it:
      <programlisting>
<![RCDATA[&tutorial_templates;]]>
      </programlisting>
    </para>
    <sect2>
      <title>Localizing the templates file</title>
      <para>
        Later, you might want to add translations to your templates file.
	This is accomplished by adding more fields, with translated text in
	them. Any of the fields can be translated. For example, you might
	want to translate the description into Spanish. Just make a field
	named <literal>Description-es</literal>
	<footnote>
	  <para>
	    Actually, <literal>Description-es_ES</literal> (or es_MX, or
	    whatever) will be checked first.
	  </para>
	</footnote>
	that holds the translation. Of course, if a translated field is not
	available, it falls back to the normal field names.
      </para>
      <para>
        Note that you can (and should) even translate the
	<literal>Choices</literal> field of a select or multiselect question.
	If you do, you should list the same choices, in the same order as
	they appear in the main <literal>Choices</literal> field. It is
	<emphasis>very</emphasis> important the order is the same. You do not
	need to translate the <literal>Default</literal> field of a select
	or a multiselect question
	<footnote>
		<para>
			Unless the default value is locale dependent.
		</para>
	</footnote>, and the answer returned when you display
	the question will always be in English.
      </para>
      <para>
        As you won't certainly be able to translate your templates file
	into all the desired languages, you need some external help.
	Be kind with translators, they need to know when you update
	the templates file without having to manually check it all over
	the time, and the simplest way to help them is to keep
	translated templates in separate files, e.g.
	<literal>templates.it</literal> for Italian translation.  Thus
       when an Italian translator wants to translate your template file for
       the first time, he runs
	<programlisting>
	   debconf-getlang it templates > templates.it
	</programlisting>
	and change all translatable fields.  All you have to do then is
	to put this file along with your templates file in the
	<literal>debian</literal> subdirectory.  The
	debconf-mergetemplate program can merge several such templates
	files together to produce a combined file to put in your binary
	package.
	<footnote>
	<para>
	Debhelper will do this for you if you use the dh_installdebconf
	command.
	</para>
	</footnote>
      </para>
      <para>
        You may check that all strings have been translated by running
	<programlisting>
	   debconf-getlang --stats templates templates.it
	</programlisting>
      </para>
      <para>
        When you update English text, do not touch translated templates
	files.  Translators can check by running the command above that
	their translation is outdated, and merge changes by running
	<programlisting>
	   debconf-getlang it templates templates.it > new.it
	</programlisting>
	Fuzzy fields are tagged with <literal>-fuzzy</literal> in their
	name, and original field without value is inserted on a single
	line just before.  Translator updates such fields according to
	the English text, removes these marks and provides you with a
	newer version.  Again, all you have to do is to place this
	translated templates file in the <literal>debian</literal>
	subdirectory with the right name.
      </para>
    </sect2>
  </sect1>

  <sect1>
    <title>
      The Config Script
    </title>
    <para>
      Next, decide what order the questions should be asked and the
      messages to the user should be displayed, figure out what tests
      you'll make before asking the questions and displaying the
      messages, and start writing a debian/config file to ask and
      display them.
      <note>
      <para>
      These questions are asked by a separate config script,
      <emphasis>not</emphasis> by the postinst, so the package can be
      configured before it is installed, or reconfigured after it is
      installed. Do not make your postinst use debconf to ask
      questions.
      </para>
      </note>
      Depending on what language you choose to write
      debian/config in, you have some choices about how to communicate
      with the frontend:
      <itemizedlist>
	<listitem>
	  <para>
	    shell script
	  </para>
	  <para>  
	    You can source <literal>/usr/share/debconf/confmodule</literal>,
	    which will make a number of shell functions available to you. Each
 	    shell function corresponds to a command in the protocol
	    (lowercased, and with
            "<literal>db_</literal>" prefixed to its name). You pass parameters
	    to it and get a result back in the <literal>$RET</literal>
	    variable.
	    <note><para>
	      Some commands also return a number exitcode, to
              indicate failure and other unusual occurances, so you need to trap
	      that to prevent <literal>set -e</literal> shell scripts from dying.
	    </para></note>
	    For details, see <literal>confmodule.3</literal> and the
	    debconf protocol specification in Debian policy.
	  </para>
	</listitem>
	<listitem>
	  <para>
	    perl
	  </para>
	  <para>  
	    You can use the 
	    <literal>Debconf::Client::ConfModule</literal> perl module,
	    which makes a number of functions available to you. Each function
	    corresponds to a command in the protocol -- you pass parameters 
	    into it and it returns the result. For details, see the 
	    <literal>Debconf::Client::ConfModule (3pm)</literal> man
	    page, and the debconf protocol specification in Debian policy.
	  </para>
	</listitem>
	<listitem>
	  <para>
	    other
	  </para>
	  <para>
	    You'll have to communicate with the frontend directly via standard
	    input and standard output. This isn't hard; read the 
	    protocol specification for details (the specification is in
	    Debian policy).
	  </para>
	</listitem>
      </itemizedlist>
    </para>
    <para>
      A list and description of all the commands you can use to talk
      to the frontend is in the
      <link linkend="commands" endterm="commands"/> appendix. The most common 
      commands you will use in the config script 
      are "<literal>input</literal>", "<literal>go</literal>", and
      "<literal>get</literal>". Briefly, 
      "<literal>input <parameter>priority</parameter> 
      <parameter>question</parameter></literal>" 
      asks the frontend to make sure it has asked the user a question,
      specifying how important it is the user be asked. The 
      question names normally correspond to the names of the
      templates in the template files. "<literal>go</literal>" tells the
      frontend to display all accumulated input commands to the user. And
      "<literal>get <parameter>question</parameter></literal>" asks the
      frontend to return to you the answer to a question.
    </para>
    <para>
      Some other notes about config scripts: Just like other
      maintainer scripts, config scripts must be idempotent. The
      config script is passed 2 parameters.  The first is either
      "<literal>configure</literal>" or "<literal>reconfigure</literal>". The
      latter occurs only if a package is being reconfigured by
      dpkg-reconfig. The second parameter is the last version of the package
      that was configured.
      <footnote>
      <para>
      This is very similar to the arguments that are passed to the postinst
      script.
      </para>
      </footnote>.
    </para>
    <para>
      Continuing the example, we need a config script to display the
      first question, and if the user says they do not like debian, it
      should display the message about that.
      <programlisting id="config_example">
<![RCDATA[&tutorial_config;]]>
      </programlisting>
    </para>
    <note>
    <para>
      Note that the config script is run before the package is
      unpacked. It should only use commands that are in essential packages
      Also, it shouldn't actually edit files on the system, or affect it in
      any other way.
    </para>
    </note>
  </sect1>

  <sect1>
    <title>
      Modifying Existing Maintainer Scripts
    </title>
    <para>
      Once you have a templates file and a config script, it's time to
      move on to using the data your config script collects in other
      maintainer scripts of your package, like your postinst. Just
      like the config script, the postinst and other maintainer
      scripts can use the <literal>confmodule</literal> or
      <literal>Debconf::Client::ConfModule</literal> libraries, or
      they can speak directly to the frontend on standard output.
    </para>
    <para>
      Anything your maintainer scripts output to standard output is
      passed into the frontend as a command, so you need to remove all
      extraneous noise, like the starting and stopping of daemons,
      etc.
    </para>
    <para>
      The only command postinsts normally use to communicate with the
      frontend is "<literal>get</literal>" 
      <footnote><para>Though in reality they can use any commands, including
      "<literal>input</literal>", you are strongly encouraged not to do 
      so.</para></footnote>. Typically, the config script prompts the user
      for input, and the postinst then pulls that input out of the database
      via the get command.
    </para>
    <para>
      In the example, before debconf, the package's postinst did this:
      <programlisting>
#!/bin/sh -e
echo -n "Do you like debian? [yn] "
read like
case "$like" in
n*|N*)
	echo "Poor misguided one. Why are you installing this package, then?"
	/etc/init.d/subliminal_messages start "I like debian."
;;
esac
      </programlisting>
    </para>
    <para>
      Our config script already handles most of this. After debconf,
      the postinst becomes:
      <programlisting>
#!/bin/sh -e

# Source debconf library.
. /usr/share/debconf/confmodule

db_get foo/like_debian
if [ "$RET" = "false" ]; then
	/etc/init.d/subliminal_messages start "I like debian."
fi
      </programlisting>
    </para>
    <para>
      There is one other alteration you need to make to the postrm
      script. When your package is purged, it should get rid of all
      the questions and templates it was using in the
      database. Accomplishing this is simple; use the 
      "<literal>purge</literal>" command
      (make sure you don't fail if debconf has already been removed, though):
      <programlisting>
if [ "$1" = "purge" -a -e /usr/share/debconf/confmodule ]; then
	# Source debconf library.
	. /usr/share/debconf/confmodule
	# Remove my changes to the db.
	db_purge
fi
      </programlisting>
    </para>
    <note>
      <para>
        Debhelper will do this for you if you use the
        dh_installdebconf command.
      </para>
    </note>
    <note>
      <para>
        Even if your postinst doesn't do anything with debconf, you currently 
	need to make sure it loads one of the debconf libraries. This is
	because the debconf libraries do deep magic to make the config scripts
	work. This will be changed in the future.
      </para>
    </note>
  </sect1>

  <sect1>
    <title>
      Finishing Up
    </title>
    <para>
      Now you have a config script and a templates file. Install both
      into <literal>debian/tmp/DEBIAN/</literal>. Make sure to make the
      config script
      executable.
      <footnote>
        <para>
	  If you use debhelper, this will all be done automatically.
	</para>
      </footnote>
    </para>
    <para>
      Your package now uses debconf!
    </para>
  </sect1>

  <sect1>
    <title>
      Testing
    </title>
    <para>
      Before you go build your package, you probably want to test the config
      script you wrote. This is possible to do, without installing the
      package -- just run your config script. There is a problem though: the
      config script relies on your templates being loaded before it is run.
      When a package that uses debconf is installed, that is handled
      automatically. Luckily, in most cases it is also handled automatically
      when you run the config script by hand. Debconf uses two simple rules to
      try to figure out the templates file associated with the config script,
      and if it finds one, it loads it.
    </para>
    <para>
      First, if there is a file with a name that is <quote>.templates</quote>
      appended to the name of the config script that is being run, debconf
      assumes that is the templates file.
    </para>
    <para>
      If that fails, debconf looks to see if the config script that is being
      ran has a filename ending in <quote>config</quote>. If so, and if there
      exists a file with the same name, except the <quote>config</quote> is
      instead <quote>templates</quote>, debconf assumes that is the
      templates file.
      <note>
        <para>
          While this is a little ugly, it means you can name your config
          script debian/config, or debian/package.config, and name your
	  templates file likewise, and just run them, and things will work
	  fine, automatically.
        </para>
      </note>
    </para>
  </sect1>

  <sect1>
    <title>
      Troubleshooting
    </title>
    <para>
      A few things can commonly go wrong when you convert something
      over to debconf:
      <itemizedlist>
	<listitem>
	  <para>
	    Your postinst uses debconf and starts a daemon that
	    doesn't close all inherited file descriptors (all such
	    daemons are buggy, really). This makes debconf hang,
	    because the debconf frontend waits for the daemon to close
	    the fd's before continuing. Note that if you use
	    confmodule, the program probably needs to close fd's 0,
	    1, 2, and <emphasis>3</emphasis>.
	  </para>
	  <para>
	    To fix:
	    <itemizedlist>
	      <listitem>
		<para>
		  Redirect fd's to /dev/null before running the daemon
		</para>
	      </listitem>
	      <listitem>
		<para>
		  Or fix the daemon.
		</para>
	      </listitem>
	      <listitem>
		<para>
		  Or call the "<literal>stop</literal>" command at the end of
		  your postinst, to let the frontend know you're done.
		</para>
	      </listitem>
	    </itemizedlist>
	  </para>
	</listitem>
	<listitem>
	  <para>
	    Something weird is happening, and you don't understand what's
	    going on.
	  </para>
	  <para>
	    Try setting DEBCONF_DEBUG to 'developer' in the environment. This
	    makes debconf output debugging information, including the commands
	    your scripts send to it and its responses. See the User's
	    Manual for more information on the DEBCONF_DEBUG environment
	    variable.
	  </para>
	</listitem>
      </itemizedlist>
    </para>
  </sect1>

  <sect1>
    <title>
      Advanced Topics
    </title>
    <para>
      Now I'll move on to some more complicated areas of debconf.
    </para>
    <sect2>
      <title>
        Blocks
      </title>
      <para>
        This is really rather easy to do. Some debconf frontends have the
        ability to display more than one question on screen at the same time.
	However, the questions can't be dependent on each other.
	<footnote>
	<para>For example,
	if question b should only be asked if question a is true, you obviously
	can't display them at the same time.</para>
	</footnote>
	Just wrap the <literal>input</literal>
	commands inside
	<literal>beginblock</literal> and
	<literal>endblock</literal>
	commands.
      </para>
    </sect2>
    <sect2>
      <title>
        Letting the User Back Up
      </title>
      <para>
        It's very useful, if you are asking a long series of questions,
	if the user can jump backward in the list and change an answer.
	Debconf supports this, but it takes a fair amount of work on your
	part to make your package support it.
      </para>
      <para>
        The first step is to make your config script let debconf know it
	is capable of handling the user pressing a back button. You use the
	<literal>capb</literal> command to
	do this, passing <quote>backup</quote> as a parameter.
      </para>
      <para>
        Then after each <literal>go</literal>
	command, you must test to see if the user hit the back button, and
	if so jump back to the previous question. If the user hit the back
	button, the <literal>go</literal> command
	will return <literal>30</literal>.
      </para>
      <para>
        There are several ways to write the control structures of your program
	so it can jump back to previous questions when necessary. You can
	write goto-laden spaghetti code. Or you can create several functions
	and use recursion. But perhaps the cleanest and easiest way is to
	construct a state machine. So let's take the
	<link linkend="config_example">example</link> config script developed
	earlier in this tutorial, and make it support backing up. There is
	only one place in that config script where the user might hit a back
	button:
	<footnote>
	<para>
	Actually, there are two. The other time a back button might be useful
	is at the first question asked, when it might jump back from
	configuring this package to configuring the previous package. However,
	the details of how this would work are not worked out yet.	
	</para>
	</footnote>
	when the second question is displayed to them, to return to the first
	question. Here is a new version of the script that handles the back
	button:
	<programlisting>
<![RCDATA[&tutorial_back_config;]]>
	</programlisting> 
      </para>
    </sect2>
    <sect2>
      <title>
	Infinite Loop Prevention
      </title>
      <para>
	One gotcha with debconf comes up if you have a loop in your
	config script.  Suppose you're asking for input and validating
	it, and looping if it's not valid:
	<programlisting>
ok=''
do while [ ! "$ok" ];
	db_input low foo/bar || true
	db_go || true

	db_get foo/bar
	if [ "$RET" ]; then
		ok=1
	fi
done
	</programlisting>
      </para>
      <para>
	This looks ok at first glance. But consider what happens if
	the value of foo/bar is "" when this loop is entered, and the
	user has their priority set high, or is using a
	non-interactive frontend, and so they are not really asked for
	input. The value of foo/bar is not changed by the db_input,
	and so it fails the test and loops. And loops ...
      </para>
      <para>
	The fix for this is to make sure that before the loop is
	entered, the value of foo/bar is set to something that will
	pass the test in the loop. So for example if the default value
	of foo/bar is "<literal>1</literal>", then the
	"<literal>reset</literal>" command
	can just be called before entering the loop.
      </para>
      <para>
	Another fix is to check the return code of the 
	"<literal>input</literal>" command.
	If it is <literal>30</literal> then the user is not being shown the
	question you asked them, and you should break out of the loop.
      </para>
    </sect2>
    <sect2>
      <title>
	Choosing among related packages
      </title>
      <para>
	Sometimes a set of related packages can be installed, and you
	want to prompt the user which of the set should be used by
	default. Examples of such sets are window managers, or ispell
	dictionary files. While it would be possible for each package
	in the set to simply prompt <quote>Should this package be
	default?</quote>,
	this leads to a lot of repetitive questions if several of the
	packages are installed. It's possible with debconf to present
	a list of all the packages in the set and allow the user to
	choose between them. Here's how.
      </para>
      <para>
	Make all the packages in the set use a shared
	template. Something like this:
	<programlisting>
Template: shared/window-manager
Type: select
Choices: ${choices}
Description: Select the default window manager.
 Select the window manager that will be started by default when X
 starts.
	</programlisting>
      </para>
      <para>
	Each package should include a copy of the template. Then it
	should include some code like this in its config script:
	<programlisting>
db_metaget shared/window-manager owners
OWNERS=$RET
db_metaget shared/window-manager choices
CHOICES=$RET
	  
if [ "$OWNERS" != "$CHOICES" ]; then
	db_subst shared/window-manager choices $OWNERS
	db_fset shared/window-manager seen false
fi

db_input medium shared/window-manager || true
db_go || true
	</programlisting>
      </para>
      <para>
	A bit of an explanation is called for. By the time your config
	script runs, debconf has already read in all the templates for
	the packages that are being installed. Since the set of
	packages share a question, debconf records that fact in the
	owners field. By a strange coincidence, the format of the
	owners field is the same as that of the choices field (a comma
	and space delimited list of values).
      </para>
      <para>
	The "<literal>metaget</literal>"
	command can be used to get the list of owners and the list of
	choices. If they are different, then a new package has been
	installed. So use the 
	"<literal>subst</literal>"
	command to change the list of choices to be the same as
	the list of owners, and ask the question.
      </para>
      <para>
        When a package is removed, you probably want to see if that package
	is the currently selected choice, and if so, prompt the user to
	select a different package to replace it. 
      </para>
      <para>
        This can be accomplished by adding something like this to the
	prerm scripts of all related packages (replacing &lt;package&gt; with
	the package name):
	<programlisting>
if [ -e /usr/share/debconf/confmodule ]; then
	. /usr/share/debconf/confmodule
	# I no longer claim this question.
	db_unregister shared/window-manager
		
	# See if the shared question still exists.
	if db_get shared/window-manager; then
		db_metaget shared/window-manager owners
		db_subst shared/window-manager choices $RET
		db_metaget shared/window-manager value
		if [ "&lt;package&gt;" = "$RET" ] ; then
			db_fset shared/window-manage seen false
			db_input critical shared/window-manager || true
			db_go || true
		fi

		# Now do whatever the postinst script did tp upsate
		# the window manager symlink or whatever.
	fi
fi
	</programlisting>
      </para>
    </sect2>
    <sect2>
      <title>
        Standalone programs that use debconf
      </title>
      <para>
      	It's actually possible to use debconf in standalone programs,
	rather just from Debian package scripts. Whether or not doing
	this is a good idea, is a whole different matter.
	<note><para>
	  Remember, debconf is not intended to be a registry.
	</para></note>
	It might occasionally make sense to write a standalone program
	that uses debconf to prompt the user for questions. Standalone
	programs that use debconf work just like a debian config script:
	load up the debconf library for your language and proceed as usual.
      </para>
      <para>
        If you're doing this type of thing, you might find it useful to
	drop template files in /usr/share/debconf/$0.templates, where $0 is
	the name of the program that is running. Debconf will load such
	templates up when the program runs.
      </para>
    </sect2>
  </sect1>

  <appendix>
    <title id="commands">
      Commands
    </title>
    <para>
      This appendix has been removed now that the debconf specification is
      in Debian policy and is no longer built from the same tree as this
      document. Please see policy for a full list of the commands.
    </para>
  </appendix>

  <appendix>
    <title id="hierarchy">
      Question hierarchy
    </title>
    <para>
      Templates and questions in the debconf database are arranged in a
      hierarchical namespace. It can be arbitrarily deep, and is separated
      by '/' characters, like a Unix directory hierarchy. Here are the
      conventions we're using so far to divide up the namespace.
      <itemizedlist>
      	<listitem>
	  <para>
	    package/*
	  </para>
	  <para>
	    This is the property of a single package, and can be
	    subdivided however that package wants to.
	  </para>
	</listitem>
	<listitem>
	  <para>
	    shared/foo/*
	  </para>
	  <para>
	    This holds items that are shared between several packages.
	    "foo" is replaced by a name that relates to all of them. For
            example, news grabbers and readers all can use
	    <literal>shared/news/server</literal> to store the news server they use.
    	  </para>
          <para>
            Currently the following shared templates and questions exist:
            <itemizedlist>
              <listitem>
	        <para>
	          <literal>shared/news/server</literal>
	        </para>
	        <para>
	          Hostname of the news server.
	        </para>
	      </listitem>
            </itemizedlist>
          </para>
	</listitem>
      </itemizedlist>
    </para>
  </appendix>
</article>
