Bug#537535: Offer for help, first patch
Hi Joey,
Sorry for the delay. Don't worry, I'm not going to disappear after
offering help, there's just a lot going on real-life wise.
On Sat, 2011-04-16 at 19:40 -0400, Joey Hess wrote:
> Regis Boudin wrote:
> > Last question, how would you like me to provide patche(s) ? Is one for
> > each utility ok ?
>
> If you're going to have a lot of patches, it would probably make sense
> to keep them in git.
As I explained to Christian in private, I'd rather keep my git stuff
"private" for now. It's my first proper attempt at using git and I've
already managed to break things a couple of times on my attempt at
setting up and using my public repository. Once I know better what I can
and can't do, I'll be more than happy to use the official one.
In the meantime I'd like to submit the attached patch. It implements
debconf-escape, debconf-get-selections, and debconf-show. I've done a
fair bit of testing with them, and they seem to give output similar to
their perl versions.
I'd really like to see the patch merged, or get feedback on the changes
needed for it to be merged.
I still need to do more tests on the escape CAPB and get
-set-selections, but hopefully we'll be able to close this bug soon. :)
Regi
diff --git a/debian/cdebconf.install b/debian/cdebconf.install
index aa3b8a5..e48461b 100644
--- a/debian/cdebconf.install
+++ b/debian/cdebconf.install
@@ -4,7 +4,10 @@ deb/usr/lib/cdebconf/debconf usr/lib/cdebconf
deb/usr/lib/cdebconf/debconf-communicate usr/lib/cdebconf
deb/usr/lib/cdebconf/debconf-copydb usr/lib/cdebconf
deb/usr/lib/cdebconf/debconf-dumpdb usr/lib/cdebconf
+deb/usr/lib/cdebconf/debconf-escape usr/lib/cdebconf
+deb/usr/lib/cdebconf/debconf-get-selections usr/lib/cdebconf
deb/usr/lib/cdebconf/debconf-loadtemplate usr/lib/cdebconf
+deb/usr/lib/cdebconf/debconf-show usr/lib/cdebconf
deb/usr/lib/cdebconf/dpkg-reconfigure usr/lib/cdebconf
deb/usr/lib/cdebconf/frontend/passthrough.so usr/lib/cdebconf/frontend
deb/usr/lib/cdebconf/frontend/newt.so usr/lib/cdebconf/frontend
diff --git a/src/.gitignore b/src/.gitignore
index 4bb4aea..71f9df8 100644
--- a/src/.gitignore
+++ b/src/.gitignore
@@ -7,7 +7,10 @@ debconf
debconf-communicate
debconf-copydb
debconf-dumpdb
+debconf-escape
+debconf-get-selections
debconf-loadtemplate
+debconf-show
dpkg-reconfigure
debconf.conf
cdebconf.conf-dist
diff --git a/src/Makefile.in b/src/Makefile.in
index e97bbfb..1273039 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -13,8 +13,9 @@ CLILIBNAME=$(CLILIB).$(MAJOR).$(MINOR).$(MICRO)
CLISONAME=$(CLILIB).$(MAJOR)
DEBCONF=debconf
TOOLS=debconf-loadtemplate debconf-copydb debconf-communicate \
- debconf-dumpdb \
- dpkg-reconfigure #dpkg-preconfigure
+ debconf-dumpdb debconf-escape \
+ debconf-get-selections \
+ dpkg-reconfigure debconf-show #dpkg-preconfigure
BIN=$(DEBCONF) $(TOOLS)
LIBOBJS=commands.opic configuration.opic confmodule.opic debug.opic \
@@ -65,6 +66,9 @@ install:
install -m 755 debconf-copydb debconf-dumpdb $(DESTDIR)${moddir}
ifneq ($(TARGET),udeb)
install -m 755 debconf-communicate $(DESTDIR)${moddir}
+ install -m 755 debconf-escape $(DESTDIR)${moddir}
+ install -m 755 debconf-get-selections $(DESTDIR)${moddir}
+ install -m 755 debconf-show $(DESTDIR)${moddir}
install -m 755 dpkg-reconfigure $(DESTDIR)${moddir}
endif
install -m 644 $(LIBNAME) $(DESTDIR)${moddir}
diff --git a/src/cdebconf.conf-dist.in b/src/cdebconf.conf-dist.in
index 369be94..6036d04 100644
--- a/src/cdebconf.conf-dist.in
+++ b/src/cdebconf.conf-dist.in
@@ -31,6 +31,11 @@ template {
driver "rfc822db";
path "/target/var/cache/debconf/templates.dat";
};
+
+ instance "di_templatedb" {
+ driver "rfc822db";
+ path "/var/log/installer/cdebconf/templates.dat";
+ };
};
config {
@@ -68,5 +73,11 @@ config {
stack { "target_config_gen_db"; "target_config_passwd_db"; };
template "target_templatedb";
};
+
+ instance "di_configdb" {
+ driver "rfc822db";
+ path "/var/log/installer/cdebconf/questions.dat";
+ template "di_templatedb";
+ };
};
diff --git a/src/debconf-escape.c b/src/debconf-escape.c
new file mode 100644
index 0000000..bc83758
--- /dev/null
+++ b/src/debconf-escape.c
@@ -0,0 +1,126 @@
+/**
+ * @file debconf-escape.c
+ * @brief helper when working with debconf's escape capability
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <getopt.h>
+
+static int escape = 0;
+static int unescape = 0;
+
+static struct option options[] = {
+ { "help", 0, 0, 'h' },
+ { "escape", 0, 0, 'e' },
+ { "unescape", 0, 0, 'u' },
+ { 0, 0, 0, 0 },
+};
+
+static void help(FILE *f, const char *exename)
+{
+ fprintf(f, "Usage: %s -e|-u < input-text\n", exename);
+ fputs(" -e, --escape escape text\n"
+ " -u, --unescape unescape text\n"
+ "\n"
+ "Exactly one of -e or -u must be used.\n", f);
+}
+
+static void parsecmdline(int argc, char **argv)
+{
+ int c;
+
+ while ((c = getopt_long(argc, argv, "euh", options, NULL)) >= 0)
+ {
+ switch (c)
+ {
+ case 'h':
+ help(stdout, argv[0]);
+ exit(0);
+ break;
+ case 'e':
+ escape = 1;
+ break;
+ case 'u':
+ unescape = 1;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (optind > argc || escape == unescape)
+ {
+ help(stderr, argv[0]);
+ exit(1);
+ }
+}
+
+int main(int argc, char **argv)
+{
+ char buf[1024];
+ const char *p;
+ size_t r;
+
+ parsecmdline(argc, argv);
+
+ if (escape)
+ {
+ while (!feof(stdin) && !ferror(stdin))
+ {
+ r = fread(buf, sizeof(*buf), 1024, stdin);
+ for (p = buf; p < buf + r; ++p)
+ {
+ switch (*p)
+ {
+ case '\\':
+ fputs("\\\\", stdout);
+ break;
+ case '\n':
+ fputs("\\n", stdout);
+ break;
+ default:
+ fputc(*p, stdout);
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ int unesc = 0;
+ while (!feof(stdin) && !ferror(stdin))
+ {
+ r = fread(buf, sizeof(*buf), 1024, stdin);
+ for (p = buf; p < buf + r; ++p)
+ {
+ if (unesc)
+ {
+ switch (*p)
+ {
+ case 'n':
+ fputc('\n', stdout);
+ break;
+ default:
+ fputc(*p, stdout);
+ break;
+ }
+ unesc = 0;
+ }
+ else if (*p == '\\')
+ unesc = 1;
+ else
+ fputc(*p, stdout);
+ }
+ }
+ }
+
+ if (ferror(stdin))
+ {
+ fprintf(stderr, "%s: error reading stdin\n", argv[0]);
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/src/debconf-get-selections.c b/src/debconf-get-selections.c
new file mode 100644
index 0000000..5e8a985
--- /dev/null
+++ b/src/debconf-get-selections.c
@@ -0,0 +1,112 @@
+/**
+ * @file debconf-get-selections.c
+ * @brief Output contents of debconf database
+ *
+ */
+
+#include "common.h"
+#include "configuration.h"
+#include "database.h"
+#include "question.h"
+#include "template.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <getopt.h>
+#include <locale.h>
+#include <string.h>
+
+static int installer = 0;
+static struct option options[] = {
+ { "installer", 0, &installer, 'i' },
+ { 0, 0, 0, 0 }
+};
+
+static const char *defaultowner = "unknown";
+
+static void parsecmd(int argc, char **argv)
+{
+ int c;
+
+ while ((c = getopt_long(argc, argv, "", options, NULL)) > 0)
+ {
+ switch (c)
+ {
+ case 'i':
+ defaultowner = "d-i";
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+int main(int argc, char **argv)
+{
+ struct configuration *config;
+ struct template_db *tdb;
+ struct question_db *qdb;
+ struct question *q;
+ void *iter;
+
+ parsecmd(argc, argv);
+
+ setlocale(LC_ALL, "");
+
+ config = config_new();
+
+ /* parse the configuration info */
+ if (config->read(config, DEBCONFCONFIG) == 0)
+ DIE("Error reading configuration information");
+
+ /* initialize database modules */
+ if ((tdb = template_db_new(config, installer?"di_templatedb":NULL)) == 0)
+ DIE("Cannot initialize DebConf template database");
+ if ((qdb = question_db_new(config, tdb, installer?"di_configdb":NULL)) == 0)
+ DIE("Cannot initialize DebConf config database");
+
+ /* load database */
+ tdb->methods.load(tdb);
+ qdb->methods.load(qdb);
+
+ iter = 0;
+ while ((q = qdb->methods.iterate(qdb, &iter)) != NULL)
+ {
+ struct questionowner *owner = q->owners;
+ const char *type = template_lget(q->template, NULL, "type");
+
+ if ((type == NULL) ||
+ (strcmp(type, "title") == 0) ||
+ (strcmp(type, "text") == 0))
+ continue;
+
+ printf("# %s\n", q_get_description(0, q));
+ if ((strcmp(type, "select") == 0) ||
+ (strcmp(type, "multiselect") == 0))
+ printf("# Choices: %s\n", q_get_choices(0, q));
+
+ if (!owner)
+ {
+ printf("%s\t%s\t%s\t%s\n", defaultowner, q->tag,
+ type, q->value?q->value:"");
+ }
+ else
+ {
+ while (owner)
+ {
+ printf("%s\t%s\t%s\t%s\n", owner->owner, q->tag,
+ type, q->value?q->value:"");
+ owner = owner->next;
+ }
+ }
+ question_deref(q);
+ }
+
+ template_db_delete(tdb);
+ question_db_delete(qdb);
+
+ config_delete(config);
+
+ return 0;
+}
+
diff --git a/src/debconf-show.c b/src/debconf-show.c
new file mode 100644
index 0000000..db85dbb
--- /dev/null
+++ b/src/debconf-show.c
@@ -0,0 +1,183 @@
+
+#include "common.h"
+#include "configuration.h"
+#include "database.h"
+#include "question.h"
+#include "template.h"
+
+#include <getopt.h>
+#include <locale.h>
+#include <string.h>
+
+int listowners = 0;
+int listdbs = 0;
+static struct option options[] = {
+ { "db", 1, NULL, 'd' },
+ { "listowners", 0, &listowners, 'o' },
+ { "listdbs", 0, &listdbs, 'l' },
+ { 0, 0, 0, 0 }
+};
+
+static void usage(const char *exename)
+{
+ printf("Usage:\n");
+ printf("\t%s packagename [...] [--db=dbname]\n", exename);
+ printf("\t%s --listowners [--db=dbname]\n", exename);
+ printf("\t%s --listdbs\n", exename);
+ exit(0);
+}
+
+int main(int argc, char **argv)
+{
+ struct configuration *config = config_new();
+ struct template_db *tdb;
+ struct question_db *qdb;
+ struct question *q;
+ void *iter = 0;
+ const char *tdbname = NULL;
+
+ int c;
+ const char *dbname = NULL;
+ struct questionowner *owners = NULL;
+
+ setlocale(LC_ALL, "");
+
+ while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
+ {
+ switch (c)
+ {
+ case 'd':
+ dbname = optarg;
+ break;
+ default:
+ break;
+ }
+ }
+
+ config = config_new();
+
+ if (config->read(config, DEBCONFCONFIG) == 0)
+ DIE("Error reading configuration information");
+
+ if (listdbs)
+ {
+ struct configitem *instance, *item;
+
+ instance = config->tree(config,"config::instance");
+ if (instance)
+ {
+ for (item=instance->child; item != NULL; item = item->next)
+ {
+ printf("%s %s\n", item->tag, item->value);
+ }
+ }
+
+ config_delete(config);
+
+ return 0;
+ }
+
+ if (dbname)
+ {
+ /* find out which template databases to load; fall back to global
+ * default if not configured otherwise
+ */
+ char *configpath;
+ if (asprintf(&configpath, "config::instance::%s::template", dbname) == -1)
+ DIE("Out of memory");
+ tdbname = config->get(config, configpath, NULL);
+ free(configpath);
+ }
+
+ /* initialize database modules */
+ if ((tdb = template_db_new(config, tdbname)) == 0)
+ DIE("Cannot initialize debconf template database");
+ if ((qdb = question_db_new(config, tdb, dbname)) == 0)
+ DIE("Cannot initialize debconf database");
+
+ tdb->methods.load(tdb);
+ qdb->methods.load(qdb);
+
+ if (listowners)
+ {
+ while((q = qdb->methods.iterate(qdb, &iter)) != NULL)
+ {
+ struct questionowner *owner = q->owners;
+
+ while (owner)
+ {
+ struct questionowner *o = owners;
+ while (o != NULL)
+ {
+ if (0 == strcmp(o->owner, owner->owner))
+ break;
+ o = o->next;
+ }
+ if (o == NULL)
+ {
+ o = malloc(sizeof(struct questionowner));
+ o->next = owners;
+ o->owner = owner->owner;
+ owners = o;
+ fprintf(stdout, "%s\n", owner->owner);
+ }
+ owner = owner->next;
+ }
+ }
+ }
+ else
+ {
+ for (c = optind; c < argc; c++)
+ {
+ struct questionowner *o = malloc(sizeof(struct questionowner));
+ o->next = owners;
+ o->owner = argv[c];
+ owners = o;
+ }
+
+ if (!owners)
+ {
+ usage(argv[0]);
+ }
+
+ while((q = qdb->methods.iterate(qdb, &iter)) != NULL)
+ {
+ const char seen = (q->flags & DC_QFLAG_SEEN)?'*':' ';
+ const char *type = q->template->type?q->template->type:"";
+ const char *value = strcmp("password", type)?q->value:"(password omitted)";
+
+ const struct questionowner *owner = q->owners;
+ while (owner)
+ {
+ const struct questionowner *o = owners;
+ while (o != NULL)
+ {
+ if (0 == strcmp(o->owner, owner->owner))
+ {
+ fprintf(stdout, "%c %s:", seen, q->tag);
+ if (value)
+ fprintf(stdout, " %s", value);
+ fputc('\n', stdout);
+ break;
+ }
+ o = o->next;
+ }
+ owner = owner->next;
+ }
+ }
+ }
+
+ while (owners)
+ {
+ struct questionowner *o = owners;
+ owners = o->next;
+ free(o);
+ }
+
+ question_db_delete(qdb);
+ template_db_delete(tdb);
+
+ config_delete(config);
+
+ return 0;
+}
Reply to: