[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#212881: Noninteractive patch for cdebconf



Package: cdebconf
Version: 0.74
Followup-For: Bug #212881


I developed a patch to cdebconf that provides noninteractive support
for unattended installs.  It automatically uses the default setting
for every question and is based on the text installer.  I'll include
it below, but it's also available from
http://mnl.cs.sunysb.edu/~amohr/cdebconf-noninteractive-patch

It's been tested with a few different configurations and doesn't
seem to have any problems.

Alex

diff -uwrN cdebconf/debian/cdebconf-noninteractive-udeb.install cdebconf-noninteractive/debian/cdebconf-noninteractive-udeb.install
--- cdebconf/debian/cdebconf-noninteractive-udeb.install	1969-12-31 19:00:00.000000000 -0500
+++ cdebconf-noninteractive/debian/cdebconf-noninteractive-udeb.install	2005-02-04 22:44:37.000000000 -0500
@@ -0,0 +1 @@
+udeb/usr/lib/cdebconf/frontend/noninteractive* usr/lib/cdebconf/frontend
diff -uwrN cdebconf/debian/cdebconf-noninteractive-udeb.templates cdebconf-noninteractive/debian/cdebconf-noninteractive-udeb.templates
--- cdebconf/debian/cdebconf-noninteractive-udeb.templates	1969-12-31 19:00:00.000000000 -0500
+++ cdebconf-noninteractive/debian/cdebconf-noninteractive-udeb.templates	2005-02-04 22:39:17.000000000 -0500
@@ -0,0 +1,27 @@
+Template: debconf/noninteractive-error
+Type: text
+_Description: !! ERROR: %s
+
+Template: debconf/yes
+Type: text
+_Description: Yes
+
+Template: debconf/no
+Type: text
+_Description: No
+
+Template: debconf/noninteractive-prompt-default
+Type: text
+_Description: Using default '%d'
+
+Template: debconf/noninteractive-prompt-default-string
+Type: text
+_Description: Using default '%s'
+
+Template: debconf/noninteractive-prompt-default-password
+Type: text
+_Description: Using default password (not shown)
+
+Template: debconf/cont-prompt
+Type: text
+_Description: Continuing.
diff -uwrN cdebconf/debian/changelog cdebconf-noninteractive/debian/changelog
--- cdebconf/debian/changelog	2005-01-11 13:27:56.000000000 -0500
+++ cdebconf-noninteractive/debian/changelog	2005-02-04 22:49:56.000000000 -0500
@@ -1,3 +1,10 @@
+cdebconf (0.75) unstable; urgency=low
+
+  * Alexander Mohr
+    - Add new frontend, noninteractive, based on the plain text frontend.
+
+ -- Colin Watson <cjwatson@debian.org>  Fri, 04 Feb 2005 23:43:21 +0000
+
 cdebconf (0.74) unstable; urgency=low
 
   * Colin Watson
diff -uwrN cdebconf/debian/control cdebconf-noninteractive/debian/control
--- cdebconf/debian/control	2005-01-11 13:21:05.000000000 -0500
+++ cdebconf-noninteractive/debian/control	2005-02-04 22:48:09.000000000 -0500
@@ -134,6 +134,21 @@
  cdebconf-text-udeb is a basic plain text frontend cdebconf package used
  by the debian-installer.
 
+Package: cdebconf-noninteractive-udeb
+Architecture: any
+Section: debian-installer
+Priority: optional
+Depends: cdebconf-udeb, ${shlibs:Depends}
+XC-Package-Type: udeb
+Description: Noninteractive frontend for Debian Configuration Management System
+ Debconf is a configuration management system for Debian packages. It is
+ used by some packages to prompt you for information before they are
+ installed. This is a reimplementation of the original debconf version
+ in C.
+ .
+ cdebconf-noninteractive-udeb is a noninteractive version of a basic plain
+ text frontend cdebconf package used by the debian-installer.
+
 Package: cdebconf-gtk-udeb
 Architecture: disabled
 Section: debian-installer
diff -uwrN cdebconf/debian/rules cdebconf-noninteractive/debian/rules
--- cdebconf/debian/rules	2005-01-11 13:21:05.000000000 -0500
+++ cdebconf-noninteractive/debian/rules	2005-02-04 22:46:58.000000000 -0500
@@ -15,8 +15,8 @@
 LIBDEBCONFDEV=libdebconfclient0-dev
 LIBDEBCONF=libdebconfclient0
 
-DEB_FRONTENDS=text newt
-UDEB_FRONTENDS=text newt
+DEB_FRONTENDS=text noninteractive newt
+UDEB_FRONTENDS=text noninteractive newt
 
 SIZEOPTFLAG=-Os
 SPEEDOPTFLAG=-O2
diff -uwrN cdebconf/src/modules/frontend/Makefile cdebconf-noninteractive/src/modules/frontend/Makefile
--- cdebconf/src/modules/frontend/Makefile	2005-01-11 13:21:14.000000000 -0500
+++ cdebconf-noninteractive/src/modules/frontend/Makefile	2005-02-04 22:42:47.000000000 -0500
@@ -27,7 +27,8 @@
    $(srcdir)/debian/cdebconf-gtk-udeb.templates \
    $(srcdir)/debian/cdebconf-newt-udeb.templates \
    $(srcdir)/debian/cdebconf-slang-udeb.templates \
-   $(srcdir)/debian/cdebconf-text-udeb.templates
+   $(srcdir)/debian/cdebconf-text-udeb.templates \
+   $(srcdir)/debian/cdebconf-noninteractive-udeb.templates
 
 templates: $(TEMPLATES)
 
@@ -35,6 +36,7 @@
 $(srcdir)/debian/cdebconf-newt-udeb.templates: newt/newt.c
 $(srcdir)/debian/cdebconf-slang-udeb.templates: slang/slang.c
 $(srcdir)/debian/cdebconf-text-udeb.templates: text/text.c
+$(srcdir)/debian/cdebconf-noninteractive-udeb.templates: noninteractive/noninteractive.c
 
 $(TEMPLATES):
 	$(XGETTEXT) -c --keyword=get_text:2,3 --omit-header --no-location $? -o - | $(srcdir)/debian/po2templates > $@
diff -uwrN cdebconf/src/modules/frontend/noninteractive/Makefile cdebconf-noninteractive/src/modules/frontend/noninteractive/Makefile
--- cdebconf/src/modules/frontend/noninteractive/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ cdebconf-noninteractive/src/modules/frontend/noninteractive/Makefile	2005-02-04 22:10:35.000000000 -0500
@@ -0,0 +1,5 @@
+MODULE=noninteractive
+SOBJ=noninteractive.so
+OBJS=noninteractive.opic
+
+include ../modules.mak
diff -uwrN cdebconf/src/modules/frontend/noninteractive/noninteractive.c cdebconf-noninteractive/src/modules/frontend/noninteractive/noninteractive.c
--- cdebconf/src/modules/frontend/noninteractive/noninteractive.c	1969-12-31 19:00:00.000000000 -0500
+++ cdebconf-noninteractive/src/modules/frontend/noninteractive/noninteractive.c	2005-02-05 00:33:45.000000000 -0500
@@ -0,0 +1,732 @@
+/***********************************************************************
+ *
+ * cdebconf - An implementation of the Debian Configuration Management
+ *            System
+ *
+ * File: noninteractive.c
+ *
+ * Description: noninteractive text UI for cdebconf
+ * Some notes on the implementation - this is meant to be an accessibility-
+ * friendly implementation. I've taken care to make the prompts work well
+ * with screen readers and the like.
+ * Note: This shares much of its structure with the text frontend.
+ *
+ * $Id: noninteractive.c 24226 2004-12-06 07:36:11Z cjwatson $
+ *
+ * Noninteractive frontend developed by Alexander Mohr, by deriving from
+ * the text frontend.
+ * 
+ * cdebconf is (c) 2000-2001 Randolph Chung and others under the following
+ * license.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ ***********************************************************************/
+#include "common.h"
+#include "template.h"
+#include "question.h"
+#include "frontend.h"
+#include "database.h"
+#include "strutl.h"
+
+#include <ctype.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <string.h>
+#include <limits.h>
+#include <wchar.h>
+#include <stdlib.h>
+#include <termios.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#define q_get_extended_description(q)   question_get_field((q), "", "extended_description")
+#define q_get_description(q)		question_get_field((q), "", "description")
+#define q_get_choices(q)		question_get_field((q), "", "choices")
+#define q_get_choices_vals(q)		question_get_field((q), NULL, "choices")
+#define q_get_indices(q)		question_get_field((q), "", "indices")
+
+#define MAKE_UPPER(C) do { if (islower((int) C)) { C = (char) toupper((int) C); } } while(0)
+
+#if defined(__s390__) || defined (__s390x__)
+#define ISEMPTY(buf) (buf[0] == 0 || (buf[0] == '.' && buf[1] == 0))
+#else
+#define ISEMPTY(buf) (buf[0] == 0)
+#endif
+
+/*  This function will be moved to strutl.c  */
+/*
+ * Add spaces at the end of string so that strwidth(that) == maxsize
+ * Input string must have been allocated with enough space.
+ */
+int
+strpad (char *what, size_t maxsize)
+{
+    size_t pos;
+    int k;
+    char *p;
+    wchar_t c;
+
+    pos = 0;
+    for (p = what; (k = mbtowc (&c, p, MB_LEN_MAX)) > 0; p += k)
+        pos += wcwidth (c);
+    if (pos > maxsize)
+        return 0;
+    for (k = pos; k < maxsize; k++, p++)
+        *p = ' ';
+    *p = '\0';
+    return 1;
+}  
+
+/*
+ * Function: getwidth
+ * Input: none
+ * Output: int - width of screen
+ * Description: get the width of the current terminal
+ * Assumptions: doesn't handle resizing; caches value on first call
+ */
+static const int getwidth(void)
+{
+	static int res = 80;
+	static int inited = 0;
+	int fd;
+	struct winsize ws;
+
+	if (inited == 0)
+	{
+		inited = 1;
+		if ((fd = open("/dev/tty", O_RDONLY)) > 0)
+		{
+			if (ioctl(fd, TIOCGWINSZ, &ws) == 0 && ws.ws_col > 0)
+				res = ws.ws_col;
+			close(fd);
+		}
+	}
+	return res;
+}
+
+/*
+ * Function: get_text
+ * Input: struct frontend *obj - frontend object
+ *        const char *template - template name
+ *        const char *fallback - string to use if not available
+ * Output: const char * - ptr to string, translated if possible
+ * Description: get the translated version of a string
+ * Assumptions: None.
+ */
+static const char *
+get_text(struct frontend *obj, const char *template, const char *fallback)
+{
+	struct question *q = obj->qdb->methods.get(obj->qdb, template);
+	return q ? q_get_description(q) : fallback;
+}
+
+/*
+ * Function: wrap_print
+ * Input: const char *str - string to display
+ * Output: none
+ * Description: prints a string to the screen with word wrapping 
+ * Assumptions: string fits in <500 lines
+ */
+static void wrap_print(const char *str)
+{
+	/* Simple greedy line-wrapper */
+	int i, lc;
+	char *lines[500];
+
+	lc = strwrap(str, getwidth() - 1, lines, DIM(lines));
+
+	for (i = 0; i < lc; i++)
+	{
+		printf("%s\n", lines[i]);
+		DELETE(lines[i]);
+	}
+}
+
+/*
+ * Function: noninteractive_handler_displaydesc
+ * Input: struct frontend *obj - UI object
+ *        struct question *q - question for which to display the description
+ * Output: none
+ * Description: displays the description for a given question 
+ * Assumptions: none
+ */
+static void noninteractive_handler_displaydesc(struct frontend *obj, struct question *q) 
+{
+	char *descr = q_get_description(q);
+	char *ext_descr = q_get_extended_description(q);
+	if (strcmp(q->template->type, "note") == 0 ||
+	    strcmp(q->template->type, "error") == 0)
+	{
+		if (strcmp(q->template->type, "error") == 0)
+			printf(get_text(obj, "debconf/text-error", "!! ERROR: %s"), descr);
+		else
+			printf("%s", descr);
+		printf("\n\n");
+		if (*ext_descr)
+			wrap_print(ext_descr);
+	}
+	else
+	{
+		if (*ext_descr)
+			wrap_print(ext_descr);
+		wrap_print(descr);
+	}
+	free(descr);
+	free(ext_descr);
+}
+
+static void
+printlist (struct frontend *obj, struct question *q, int count, char **choices_translated, int *tindex, char *selected)
+{
+	int choice_min = -1;
+	int num_cols, num_lines;
+	int i, k, l;
+	int logcount = 0;
+	int *col_width;
+	int total_width = 0;
+	char **output;
+	int line = 0, max_len = 0, col = 0;
+	int width = getwidth();
+	char **fchoices = malloc(sizeof(char *) * count);
+	i = count;
+	do {
+		i /= 10;
+		logcount++;
+	} while (i > 0);
+
+	/*  Set string arrays  */
+	for (i=0; i < count; i++)
+	{
+		/*  Trailing spaces are a placeholder to add [*] for
+		    selected values */
+		asprintf(&(fchoices[i]), "  %d. %s    ", i+1, choices_translated[i]);
+		if (selected[tindex[i]])
+			strcpy(fchoices[i]+strlen(fchoices[i])-3, "[*]");
+		if (strwidth(fchoices[i]) < choice_min || choice_min == -1)
+			choice_min = strwidth(fchoices[i]);
+		if (strwidth(fchoices[i]) > width)
+			width = strwidth(fchoices[i]);
+	}
+	num_cols = width / choice_min;
+	if (num_cols > count)
+		num_cols = count;
+	col_width = malloc (sizeof(int) * num_cols);
+	num_cols++;
+	while (1)
+	{
+  COLUMN:
+		num_cols--;
+		if (num_cols == 0)
+			break;
+		num_lines = (count - 1) / num_cols + 1;
+		for (i = 0; i < num_cols; i++)
+			col_width[i] = 0;
+		for (i = 0; i < count; i++)
+		{
+			int current_col = i / num_lines;
+			if (strwidth(fchoices[i]) > col_width[current_col])
+			{
+				col_width[current_col] = strwidth(fchoices[i]);
+				total_width = 0;
+				for (k = 0; k < num_cols; k++)
+					total_width += col_width[k];
+				if (total_width > width)
+					goto COLUMN;
+			}
+		}
+		break;
+	}
+	if (num_cols == 0)
+	{
+		num_lines = count;
+		num_cols = 1;
+	}
+	output = malloc(sizeof(char *) * num_lines);
+	for (i = 0; i < num_lines; i++)
+	{
+		output[i] = malloc(MB_LEN_MAX * width + 1);
+		*(output[i]) = '\0';
+	}
+	for (i = 0; i < count; i++)
+	{
+		strcat(output[line], fchoices[i]);
+		if (strwidth(output[line]) > max_len)
+			max_len = strwidth(output[line]);
+		line++;
+		if (line >= num_lines)
+		{
+			col++;
+			if (col != num_cols)
+			{
+				for (l = 0; l < num_lines; l++)
+					strpad(output[l], max_len);
+			}
+
+			line = 0;
+			max_len = 0;
+		}
+	}
+	for (l = 0; l < num_lines; l++)
+	{
+		printf("%s\n", output[l]);
+		free(output[l]);
+	}
+	free(output);
+	free(col_width);
+	for (i = 0; i < count; i++)
+		free(fchoices[i]);
+	free(fchoices);
+}
+
+/*
+ * Function: noninteractive_handler_boolean
+ * Input: struct frontend *obj - frontend object
+ *        struct question *q - question to ask
+ * Output: int - DC_OK, DC_NOTOK, DC_GOBACK
+ * Description: handler for the boolean question type
+ * Assumptions: none
+ */
+static int noninteractive_handler_boolean(struct frontend *obj, struct question *q)
+{
+	int ans = 0;
+	int def = 0;
+	const char *defval;
+
+	defval = question_getvalue(q, "");
+	if (defval)
+	{
+		if (strcmp(defval, "true") == 0)
+			def = 1;
+		else 
+			def = 2;
+	}
+	else
+	{
+	 	def = 1;
+	}
+
+	printf("  %d. %s%s", 1, get_text(obj, "debconf/yes", "Yes"), (1 == def ? " [*]" : "    "));
+	printf("  %d. %s%s", 2, get_text(obj, "debconf/no", "No"), (2 == def ? " [*]" : ""));
+	printf("\n");
+	printf(get_text(obj, "debconf/noninteractive-prompt-default", "Using default '%d'"), def);
+	printf("\n");
+	
+	ans = def;
+
+	question_setvalue(q, (ans == 1 ? "true" : "false"));
+	return DC_OK;
+}
+
+/*
+ * Function: noninteractive_handler_multiselect
+ * Input: struct frontend *obj - frontend object
+ *        struct question *q - question to ask
+ * Output: int - DC_OK, DC_NOTOK
+ * Description: handler for the multiselect question type
+ * Assumptions: none
+ *
+ * TODO: factor common code with select
+ */
+static int noninteractive_handler_multiselect(struct frontend *obj, struct question *q)
+{
+	char **choices;
+	char **choices_translated;
+	char **defaults;
+	char *selected, *defval;
+	char answer[4096] = {0};
+	int i, j, count = 0, dcount;
+	int *tindex = NULL;
+	int ret = DC_OK;
+	const char *indices = q_get_indices(q);
+
+	count = strgetargc(q_get_choices_vals(q));
+	if (count <= 0)
+		return DC_NOTOK;
+	choices = malloc(sizeof(char *) * count);
+	choices_translated = malloc(sizeof(char *) * count);
+	tindex = malloc(sizeof(int) * count);
+	if (strchoicesplitsort(q_get_choices_vals(q), q_get_choices(q), indices, choices, choices_translated, tindex, count) != count)
+	{
+		ret = DC_NOTOK;
+		goto CleanUp_TINDEX;
+	}
+
+	defaults = malloc(sizeof(char *) * count);
+	dcount = strchoicesplit(question_getvalue(q, ""), defaults, count);
+	selected = calloc(1, sizeof(char) * count);
+
+	for (j = 0; j < dcount; j++)
+		for (i = 0; i < count; i++) {
+			if (strcmp(choices[tindex[i]], defaults[j]) == 0)
+				selected[tindex[i]] = 1;
+		}
+
+	i = 0;
+
+	defval = malloc(10*count);
+	*defval = '\0';
+	for (i = 0; i < count; i++)
+		if (selected[tindex[i]])
+		{
+			char buf[10];
+			if (*defval != '\0')
+				strcat(defval, " ");
+			sprintf(buf, "%d", i+1);
+			strcat(defval, buf);
+		}
+
+	printlist (obj, q, count, choices_translated, tindex, selected);
+	printf(get_text(obj, "debconf/noninteractive-prompt-default-string", 
+			"Using default '%s'"), defval);
+	printf("\n");
+
+	answer[0] = 0;
+	for (i = 0; i < count; i++)
+	{
+		if (selected[i])
+		{
+			if (answer[0] != 0)
+				strvacat(answer, sizeof(answer), ", ", NULL);
+			strvacat(answer, sizeof(answer), choices[i], NULL);
+		}
+	}
+	question_setvalue(q, answer);
+
+	free(defval);
+	free(selected);
+	for (i = 0; i < dcount; i++)
+		free(defaults[i]);
+	free(defaults);
+  CleanUp_TINDEX:
+	free(tindex);
+	for (i = 0; i < count; i++)
+	{
+		free(choices_translated[i]);
+		free(choices[i]);
+	}
+	free(choices_translated);
+	free(choices);
+	
+	return ret;
+}
+
+/*
+ * Function: noninteractive_handler_select
+ * Input: struct frontend *obj - frontend object
+ *        struct question *q - question to ask
+ * Output: int - DC_OK, DC_NOTOK
+ * Description: handler for the select question type
+ * Assumptions: none
+ *
+ * TODO: factor common code with multiselect
+ */
+static int noninteractive_handler_select(struct frontend *obj, struct question *q)
+{
+	char **choices;
+	char **choices_translated;
+	char *selected;
+	int i, count = 0, choice = 1, def = -1;
+	const char *defval = question_getvalue(q, "");
+	int *tindex = NULL;
+	int ret = DC_OK;
+	const char *indices = q_get_indices(q);
+
+	count = strgetargc(q_get_choices_vals(q));
+	if (count <= 0)
+		return DC_NOTOK;
+	choices = malloc(sizeof(char *) * count);
+	choices_translated = malloc(sizeof(char *) * count);
+	tindex = malloc(sizeof(int) * count);
+	if (strchoicesplitsort(q_get_choices_vals(q), q_get_choices(q), indices, choices, choices_translated, tindex, count) != count)
+	{
+		ret = DC_NOTOK;
+		goto CleanUp_TINDEX;
+	}
+
+	selected = calloc(1, sizeof(char) * count);
+	if (count == 1 || defval == NULL)
+		defval = choices[0];
+
+	for (i = 0; i < count; i++)
+	  if (strcmp(choices[tindex[i]], defval) == 0)
+	    {
+	      selected[tindex[i]] = 1;
+	      def = i;
+	    }
+
+	if ( def < 0 || def >= count )
+	  def = 0;
+
+	i = 0;
+	choice = -1;
+
+	printlist (obj, q, count, choices_translated, tindex, selected);
+	printf(get_text(obj, "debconf/noninteractive-prompt-default", 
+			"Using default '%d'"), def+1);
+	printf("\n");
+	choice = def;
+
+	question_setvalue(q, choices[tindex[choice]]);
+
+	free(selected);
+
+  CleanUp_TINDEX:
+	free(tindex);
+	for (i = 0; i < count; i++) 
+	{
+		free(choices_translated[i]);
+		free(choices[i]);
+	}
+	free(choices_translated);
+	free(choices);
+	
+	return ret;
+}
+
+/*
+ * Function: noninteractive_handler_note
+ * Input: struct frontend *obj - frontend object
+ *        struct question *q - question to ask
+ * Output: int - DC_OK, DC_NOTOK, DC_GOBACK
+ * Description: handler for the note question type
+ * Assumptions: none
+ */
+static int noninteractive_handler_note(struct frontend *obj, struct question *q)
+{
+	printf("%s\n", get_text(obj, "debconf/cont-prompt",
+				"Continuing."));
+	return DC_OK;
+}
+
+/*
+ * Function: noninteractive_handler_password
+ * Input: struct frontend *obj - frontend object
+ *        struct question *q - question to ask
+ * Output: int - DC_OK, DC_NOTOK
+ * Description: handler for the password question type
+ * Assumptions: none
+ *
+ * TODO: this can be *MUCH* improved. no editing is possible right now
+ */
+static int noninteractive_handler_password(struct frontend *obj, struct question *q)
+{
+	const char *defval = question_getvalue(q, "");
+
+	if (defval == NULL)
+	  defval = "";
+
+	printf(get_text(obj, "debconf/noninteractive-prompt-default-password", "Using default password (not shown)"));
+	printf("\n");
+
+	question_setvalue(q, defval);
+
+	return DC_OK;
+}
+
+/*
+ * Function: noninteractive_handler_string
+ * Input: struct frontend *obj - frontend object
+ *        struct question *q - question to ask
+ * Output: int - DC_OK, DC_NOTOK
+ * Description: handler for the string question type
+ * Assumptions: none
+ */
+static int noninteractive_handler_string(struct frontend *obj, struct question *q)
+{
+	const char *defval = question_getvalue(q, "");
+
+	if (defval == NULL)
+	  defval = "";
+
+	printf(get_text(obj, "debconf/noninteractive-prompt-default-string", "Using default '%s'"), defval);
+	printf("\n");
+
+	question_setvalue(q, defval);
+
+	return DC_OK;
+}
+
+/*
+ * Function: noninteractive_handler_text
+ * Input: struct frontend *obj - frontend object
+ *        struct question *q - question to ask
+ * Output: int - DC_OK, DC_NOTOK, DC_GOBACK
+ * Description: handler for the text question type
+ * Assumptions: none
+ */
+static int noninteractive_handler_text(struct frontend *obj, struct question *q)
+{
+	return noninteractive_handler_note(obj, q);
+}
+
+/*
+ * Function: noninteractive_handler_error
+ * Input: struct frontend *obj - frontend object
+ *        struct question *q - question to ask
+ * Output: int - DC_OK, DC_NOTOK, DC_GOBACK
+ * Description: handler for the error question type. Currently equal to _note
+ * Assumptions: none
+ */
+static int noninteractive_handler_error(struct frontend *obj, struct question *q)
+{
+	return noninteractive_handler_note(obj, q);
+}
+
+/* ----------------------------------------------------------------------- */
+struct question_handlers {
+	const char *type;
+	int (*handler)(struct frontend *obj, struct question *q);
+} question_handlers[] = {
+	{ "boolean",	noninteractive_handler_boolean },
+	{ "multiselect", noninteractive_handler_multiselect },
+	{ "note",	noninteractive_handler_note },
+	{ "password",	noninteractive_handler_password },
+	{ "select",	noninteractive_handler_select },
+	{ "string",	noninteractive_handler_string },
+	{ "text",	noninteractive_handler_text },
+	{ "error",	noninteractive_handler_error },
+};
+
+/*
+ * Function: noninteractive_initialize
+ * Input: struct frontend *obj - frontend UI object
+ *        struct configuration *cfg - configuration parameters
+ * Output: int - DC_OK, DC_NOTOK
+ * Description: initializes the noninteractive text UI
+ * Assumptions: none
+ *
+ * TODO: SIGINT is ignored by the noninteractive text UI, otherwise it interferes with
+ * the way question/answers are handled. this is probably not optimal
+ */
+static int noninteractive_initialize(struct frontend *obj, struct configuration *conf)
+{
+	obj->interactive = 1;
+	signal(SIGINT, SIG_IGN);
+	return DC_OK;
+}
+
+/*
+ * Function: noninteractive_can_go_back
+ * Input: struct frontend *obj - frontend object
+ *        struct question *q - question object
+ * Output: int - DC_OK, DC_NOTOK
+ * Description: tells whether confmodule supports backing up
+ * Assumptions: none
+ */
+static bool
+noninteractive_can_go_back(struct frontend *obj, struct question *q)
+{
+	return (obj->capability & DCF_CAPB_BACKUP);
+}
+
+/*
+ * Function: noninteractive_go
+ * Input: struct frontend *obj - frontend object
+ * Output: int - DC_OK, DC_NOTOK
+ * Description: asks all pending questions
+ * Assumptions: none
+ */
+static int noninteractive_go(struct frontend *obj)
+{
+	struct question *q = obj->questions;
+	int i;
+	int ret = DC_OK;
+	int display_title = 1;
+
+	while (q != NULL) {
+		for (i = 0; i < DIM(question_handlers); i++) {
+			if (strcmp(q->template->type, question_handlers[i].type) == 0) 
+			{
+
+				if (display_title)
+				{
+					printf("%s\n\n", obj->title);
+					display_title = 0;
+				}
+				noninteractive_handler_displaydesc(obj, q);
+				ret = question_handlers[i].handler(obj, q);
+				if (ret == DC_OK)
+					obj->qdb->methods.set(obj->qdb, q);
+				else if (ret == DC_GOBACK && q->prev != NULL)
+					q = q->prev;
+				else
+					return ret;
+				break;
+			}
+		}
+		if (ret == DC_OK)
+			q = q->next;
+	}
+	return DC_OK;
+}
+
+static void noninteractive_progress_start(struct frontend *obj, int min, int max, const char *title)
+{
+	DELETE(obj->progress_title);
+	obj->progress_title = STRDUP(title);
+	obj->progress_min = min;
+	obj->progress_max = max;
+	obj->progress_cur = min;
+
+	printf("%s  ", title);
+	fflush(stdout);
+}
+
+static void noninteractive_progress_set(struct frontend *obj, int val)
+{
+	static int last = 0;
+	int new;
+
+	obj->progress_cur = val;
+	new = ((double)(obj->progress_cur - obj->progress_min) / 
+		(double)(obj->progress_max - obj->progress_min) * 100.0);
+	if (new < last)
+		last = 0;
+	/*  Prevent verbose output  */
+	if (new / 10 == last / 10)
+		return;
+	last = new;
+	printf("..%d%%", new);
+	fflush(stdout);
+}
+
+static void noninteractive_progress_stop(struct frontend *obj)
+{
+	INFO(INFO_DEBUG, "%s\n", __FUNCTION__);
+	printf("\n");
+	fflush(stdout);
+}
+
+struct frontend_module debconf_frontend_module =
+{
+	initialize: noninteractive_initialize,
+	can_go_back: noninteractive_can_go_back,
+	go: noninteractive_go,
+	progress_start: noninteractive_progress_start,
+	progress_set: noninteractive_progress_set,
+	progress_stop: noninteractive_progress_stop,
+};


-- System Information:
Debian Release: 3.1
  APT prefers testing
  APT policy: (800, 'testing'), (500, 'unstable')
Architecture: i386 (i686)
Kernel: Linux 2.6.10-1-686
Locale: LANG=en_US, LC_CTYPE=en_US (charmap=ISO-8859-1)



Reply to: