Scott Barker wrote: > My reading of it was that you use the debconf functions from within the > post-install script. I'm talking about a completely new functionality for the > packaging system, where a config script is defined, and is not the > post-install script. I will check again, in case I missed something.
The introduction I posted is short on many details. They are all explained in the debconf tutorial, which I will append to this message. Be assurred, a config script is defined just like you hoped. Introduction ------------ This is a guide to using debconf with your packages, aimed at a Debian developer. So, what is debconf? To save you reading the spec (http://www.debian.org/~wakkerma/config6/), 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 arn't set. Debconf should be used whenever your package needs to output something to the user, or ask a question of the user. I'll assume you already have a package that does this and you want to convert it to use debconf. Getting started --------------- First, your package must depend on debconf (or pre-depend on it if it uses debconf in its preinst). This is necessary since debconf isn't part of the base system. 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.) For example, a hypothetical package "foo" has the following postinst: #!/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 It's clear that it asks a question and sometimes outputs a message. We will need to use debconf to do both. The Templates file ------------------- 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: Template: <packagename>/<something> Type: <select,string,boolean,note,text> Default: <an optional default value> 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. Blah blah. <next template here> A short description of the data types: string Holds any arbitrary string of data. boolean Holds "true" or "false". select Holds one of a finite number of possible values. These values must be specified in a field named Choices:. Separate the possible values with commas and spaces, like this: Choices: yes, no, maybe note 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. text This template is a scrap of text that can be displayed to the user. Following laong in our example, we create a templates file with two templates in it: Template: foo/like_debian Type: boolean Description: Do you like Debian? We'd like to know if you like the Debian GNU/Linus system. Template: foo/why_debian_is_great Type: note Description: Poor misguided one. Why are you installing this package, then? Debian is great. As you continue using Debian, we hope you will discover the error in your ways. The Config Script ----------------- 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. Depending on what language you choose to write debian/config in, you have some choices about how to communicate with the frontend: shell script: You can source /usr/share/debconf/confmodule.sh, which will make a number of shell functions available to you. Each shell function corresponds to a command in the protocol (with "db_" prefixed to its name). You pass parameters to it and get a result back in the $RET variable. For details, see confmodule.3. perl: You can use the Debian::DebConf::Client::ConfModule 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 Debian::Debconf::Client::ConfModule.2pm man page. other: You'll have to comminucate with the frontend directly via standard input and standard output. This isn't hard; read the protocol specification for details. A list and description of all the commands you can use to talk to the frontend is at the end of this document in Appendix A. The most common commands you will use in the config script are "input", "go", and "get". Briefly, "input <priority> <variable>" asks the frontend to make sure it has asked the user for the value of a variable, specifying how important it is the user be asked this. The variable names normally correspond to the names of the templates in the template files. "go" tells the frontend to display all accumulated input commands to the user. And "get <variable>" asks the frontend to return to you what value a variable is set to. 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. #!/bin/sh -e # Source debconf library. . /usr/share/debconf/confmodule.sh # Do you like debian? db_input medium foo/like_debian db_go # Check their answer. db_get foo/like_debian if [ "$RET" = "false" ]; then # Poor misguided one.. db_input high foo/why_debian_is_great db_go fi Note that the debian/config script is run before the package is unpacked. It should only use commands that are in the base system. Also, it shouldn't actually edit files on the system, or effect it in any other way. Modifying Existing Maintainer Scripts ------------------------------------- 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 confmodule.sh or Debian::DebConf::Client::ConfModule libraries, or they can speak directly to the frontend on standard output. 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. The only command postinsts normally use to communicate with the frontend is "get" (though in reality they can use any commands, including "input", you are advised not to do so). Typically, the config script prompts the user for input, and the postinst then pulls that input out of the database via the get command. In the example, before debconf, the package's postinst did this: #!/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 Our config script already handles most of this. After debconf, the postinst becomes: #!/bin/sh -e # Source debconf library. . /usr/share/debconf/confmodule.sh deb_get foo/like_debian if [ "$RET" = "false" ]; then /etc/init.d/subliminal_messages start "I like debian." fi Finishing Up ------------ Now you have a config script and a templates file. Install both into debian/tmp/DEBIAN. Make sure to make the config script executable. Your package now uses debconf! Advanced Topics --------------- Now I'll move on to some more complicated areas of debconf. 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: ok='' do while [ ! "$ok" ]; db_input low foo/bar go db_get foo/bar if [ "$RET" ]; then ok=1 fi done 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.... 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 "1", then "db_reset" can just be called before entering the loop. Future versions of debconf may have a command that lets you figure out if the user will see a question, which would allow for more intelligent workarounds. Appendix A. ----------- Here is a complete list of the the commands you can use to communicate with the frontend (remember these are prefixed with "db_" if you are using confmodule.sh). version <number> This exchanges with the frontend the protocol version number that is being used. The current version is 1.0. Versions in the 1.x series will be backwards-compatable. You can specify the protocol version number you are speaking, but note that the perl and shell libraries specify a good default for you. The frontend will return the version of the protocol it speaks. capb <capabilities> This exchanges with the frontend the capabilities that are supported. Capabilities both the frontend and you send will be used. Currently supported capabilities: backup - backing up to a previous step is supported. title <string> You can use this command to set a title in the frontend. This in different ways, depending on the frontend being used, for example it might change the title of the frontend's window. stop This command tells the frontend you're done talking to it. input <priority> <variable> This tells the frontend you are interested in the value of a variable. <variable> is the name of the variable, which should correspond to the Template: line of the template that defines this variable. <priority> is how important it is that the user be prompted for the variable. Supported priorities: low Use this for very trivial items that have defaults that will work in the vast majority of cases. medium Use this for normal items that have a reasonable default. high Use this for items that don't have a reasonable default. critical Use this only for items that will probably break the system without user intervention. Note that the frontend decides if the user is actually prompted or not. If the user has already answered a question, they are normally not asked it again even if input is called again. And if the user is ignoring low priority items, they will not see them. beginblock endblock Some frontends are able to display a number of items to the user at once. To do this, they need to be given blocks of input commands, enclosed in the beginblock and endblock commands. Blocks can be nested and very advanced frontends may use this as a user interface hint. go Shows the current set of accumulated items to the user and lets them fill in values, etc. clear Clears the accumulated set of items without displaying them to the user. get <variable> Ask the frontend to tell you the value of a variable. The value is returned to you. set <variable> <value> Ask the frontend to set a variable to a value. reset <variable> Reset the variable to its default value. subst <variable> <key> <value> Variables can have sibstitutions embedded in their descritions. These substitutions look like "${key}". When the description is displayed, the substitutions are replaced with their values. This command can be used to set the value of a substitution. fget <variable> <flag> Variables can have flags associated with them. The flags have a value of "true" or "false". This command returns the value of a flag. fget <variable> <flag> <value> This sets the value of a flag on a variable. Valid values for the flag are "true" and "false". One common flag is the "isdefault" flag. It is normally only set if the variable is set to its default value and the user has not seen it. Typically, frontends only display questions to users if they have the isdefault flag set. Sometimes you want the user to see a question again -- in these cases you can set the isdefault flag to true to force the frontend to reddisplay it. register <template> <variable> This creates a new variable that is bound to a template. By default each template has an accociated variable with the same name. However, any number of variables can really be associated with a template, and this lets you create more such variables. unregister <variable> This removes a variable from the database. -- see shy jo