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

[RFC] Add the new cdebconf-gtk-entropy package



Hi!

This patch will add a cdebconf-gtk-entropy package when building
cdebconf-entropy.

It is currently untested inside d-i as partman-crypto needs some changes
to be able to load whichever entropy plugin is available.  Comments or
advice on how to do so are more than welcome.

New templates should probably be introduced as well, but I was waiting
for Christian's advice on how to do it. :)

---
 packages/cdebconf-entropy/Makefile.in          |    9 +
 packages/cdebconf-entropy/configure.ac         |    6 +
 packages/cdebconf-entropy/debian/changelog     |    2 +
 packages/cdebconf-entropy/debian/control       |   12 +-
 packages/cdebconf-entropy/debian/copyright     |    1 +
 packages/cdebconf-entropy/gtk-plugin-entropy.c |  295 ++++++++++++++++++++++++
 6 files changed, 324 insertions(+), 1 deletions(-)
 create mode 100644 packages/cdebconf-entropy/gtk-plugin-entropy.c

diff --git a/packages/cdebconf-entropy/Makefile.in b/packages/cdebconf-entropy/Makefile.in
index 972c13e..afb049b 100644
--- a/packages/cdebconf-entropy/Makefile.in
+++ b/packages/cdebconf-entropy/Makefile.in
@@ -13,6 +13,8 @@ CFLAGS=@CFLAGS@ -I.
 LDFLAGS=@LDFLAGS@
 
 PLUGIN_MODULES=@PLUGIN_MODULES@
+GTK_CFLAGS=@GTK_CFLAGS@
+GTK_LDFLAGS=@GTK_LDFLAGS@
 
 all: $(PLUGIN_MODULES)
 
@@ -25,6 +27,13 @@ install: $(PLUGIN_MODULES)
 newt-plugin-entropy-text.so: newt-plugin-entropy-text.opic
 	$(CC) $(LDFLAGS) -shared -lnewt -o $@ $<
 
+gtk-plugin-entropy.so: gtk-plugin-entropy.opic
+	$(CC) $(LDFLAGS) $(GTK_LDFLAGS) -shared -o $@ $<
+
+gtk-plugin-entropy.opic: gtk-plugin-entropy.c
+	@echo "Compiling $< to $@"
+	$(CC) $(CFLAGS) $(GTK_CFLAGS) -fPIC -o $@ -c $<
+
 clean:
 	rm -f $(PLUGIN_MODULES)
 	rm -f *.opic
diff --git a/packages/cdebconf-entropy/configure.ac b/packages/cdebconf-entropy/configure.ac
index 79c2d16..9c856a7 100644
--- a/packages/cdebconf-entropy/configure.ac
+++ b/packages/cdebconf-entropy/configure.ac
@@ -16,6 +16,12 @@ AC_CHECK_LIB(newt, newtInit,
  PLUGIN_MODULES="$PLUGIN_MODULES newt-plugin-entropy-text.so",
  echo "*** Cannot build Newt plugin ***")
 
+PKG_CHECK_MODULES(GTK, [gtk+-directfb-2.0],
+ PLUGIN_MODULES="$PLUGIN_MODULES gtk-plugin-entropy.so",
+ echo "*** Cannot build GTK+ plugin ***")
+
 AC_SUBST(PLUGIN_MODULES)
+AC_SUBST(GTK_CFLAGS)
+AC_SUBST(GTK_LDFLAGS)
 
 AC_OUTPUT(Makefile)
diff --git a/packages/cdebconf-entropy/debian/changelog b/packages/cdebconf-entropy/debian/changelog
index 9c51608..b726230 100644
--- a/packages/cdebconf-entropy/debian/changelog
+++ b/packages/cdebconf-entropy/debian/changelog
@@ -8,6 +8,8 @@ cdebconf-entropy (0.5) UNRELEASED; urgency=low
   * Bump Depends on cdebconf accordingly.
   * Rework build system to make room for entropy plugins working with
     frontends other than newt.
+  * Add the new cdebconf-gtk-entropy package, including a plugin to gather
+    entropy when using the GTK+ frontend.
 
  -- Jérémy Bobbio <lunar@debian.org>  Tue, 07 Aug 2007 13:35:56 +0200
 
diff --git a/packages/cdebconf-entropy/debian/control b/packages/cdebconf-entropy/debian/control
index e7864d4..05b11b9 100644
--- a/packages/cdebconf-entropy/debian/control
+++ b/packages/cdebconf-entropy/debian/control
@@ -3,7 +3,7 @@ Priority: extra
 Section: debian-installer
 Maintainer: Debian Install System Team <debian-boot@lists.debian.org>
 Uploaders: Max Vozeler <xam@debian.org>
-Build-Depends: debhelper (>= 4.2), libnewt-dev, libtextwrap-dev, libdebconfclient0-dev (>> 0.119)
+Build-Depends: debhelper (>= 4.2), libnewt-dev, libtextwrap-dev, libdebconfclient0-dev (>> 0.119), libgtk-directfb-2.0-dev
 Standards-Version: 3.7.2
 XS-Vcs-Svn: svn://svn.debian.org/d-i/trunk/packages/cdebconf-entropy
 
@@ -16,3 +16,13 @@ Description: cdebconf newt plugin for reading from /dev/random
  cdebconf plugin to facilitate reading random data from /dev/random.
  Asks the user to enter random characters on the keyboard and shows a
  progressbar with percent-of-data read.
+
+Package: cdebconf-gtk-entropy
+Architecture: any
+Section: debian-installer
+Depends: cdebconf-gtk-udeb, ${shlibs:Depends}
+XC-Package-Type: udeb
+Description: cdebconf gtk plugin for reading from /dev/random
+ cdebconf plugin to facilitate reading random data from /dev/random.
+ Asks the user to enter random characters on the keyboard and random mouse
+ movements while a progressbar shows the amount of entropy already gathered.
diff --git a/packages/cdebconf-entropy/debian/copyright b/packages/cdebconf-entropy/debian/copyright
index 00f53fe..fffb5c6 100644
--- a/packages/cdebconf-entropy/debian/copyright
+++ b/packages/cdebconf-entropy/debian/copyright
@@ -1,4 +1,5 @@
 cdebconf-entropy is Copyright 2005-2006 Max Vozeler <xam@debian.org>
+                    Copyright      2007 Jérémy Bobbio <lunar@debian.org>
 
 Makefile.in, configure.ac and debian/rules were written by
 Tollef Fog Heen <tfheen@debian.org> for cdebconf-keystep. They 
diff --git a/packages/cdebconf-entropy/gtk-plugin-entropy.c b/packages/cdebconf-entropy/gtk-plugin-entropy.c
new file mode 100644
index 0000000..aed0653
--- /dev/null
+++ b/packages/cdebconf-entropy/gtk-plugin-entropy.c
@@ -0,0 +1,295 @@
+/*
+ * cdebconf gtk plugin to get random data
+ *
+ * Copyright © 2007 Jérémy Bobbio <lunar@debian.org>
+ * See debian/copyright for license.
+ *
+ */
+
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <cdebconf/frontend.h>
+#include <cdebconf/cdebconf_gtk.h>
+
+#include <gtk/gtk.h>
+
+#define MODULE "entropy"
+#define FIFO "/var/run/random.fifo"
+#define DEFAULT_KEYSIZE 2925
+
+/* Here's the plugin! */
+int cdebconf_gtk_handler_entropy(struct frontend * fe,
+                                 struct question * question,
+                                 GtkWidget * question_box);
+
+struct entropy {
+    struct frontend * fe;
+    GtkWidget * progress_bar;
+    GtkWidget * continue_button;
+    GtkWidget * entry;
+    guint64 keysize;
+    guint64 bytes_read;
+    int random_fd;
+    int fifo_fd;
+    guint8 random_byte;
+    GThread * gathering_thread;
+};
+
+static void handle_continue(GtkWidget * button, struct entropy * entropy_data)
+{
+    cdebconf_gtk_set_answer_ok(entropy_data->fe);
+}
+
+static GtkWidget * create_entropy_widget(struct entropy * entropy_data)
+{
+    GtkWidget * vbox;
+    GtkWidget * continue_button;
+    GtkWidget * progress_bar;
+    GtkWidget * entry;
+
+    continue_button = cdebconf_gtk_create_continue_button(entropy_data->fe);
+    if (NULL == continue_button) {
+        g_critical("cdebconf_gtk_create_continue_button failed.");
+        return NULL;
+    }
+    gtk_widget_set_sensitive(continue_button, FALSE);
+    g_signal_connect(continue_button, "clicked", G_CALLBACK(handle_continue),
+                     entropy_data);
+    g_object_ref(G_OBJECT(continue_button));
+    entropy_data->continue_button = continue_button;
+
+    vbox = gtk_vbox_new(FALSE /* not homogenous */, DEFAULT_PADDING);
+    if (NULL == vbox) {
+        g_critical("gtk_vbox_new failed.");
+        return NULL;
+    }
+    entry = gtk_entry_new();
+    if (NULL == entry) {
+        g_critical("gtk_entry_new failed.");
+        return NULL;
+    }
+    gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE /* password style */);
+    gtk_entry_set_activates_default(GTK_ENTRY(entry),
+                                    TRUE /* activate on Enter */);
+    gtk_box_pack_start(GTK_BOX(vbox), entry, FALSE /* no expand */,
+                       FALSE /* no fill */, DEFAULT_PADDING);
+    g_object_ref(G_OBJECT(entry));
+    entropy_data->entry = entry;
+
+    if (NULL == (progress_bar = gtk_progress_bar_new())) {
+        g_critical("gtk_progress_bar_new failed.");
+        return NULL;
+    }
+    /* write a space to prepare progress bar height to receive the success
+     * confirmation at the end. */
+    gtk_progress_bar_set_text(GTK_PROGRESS_BAR(progress_bar), " ");
+    gtk_box_pack_start(GTK_BOX(vbox), progress_bar, FALSE /* no expand */,
+                       FALSE /* no fill */, DEFAULT_PADDING);
+    g_object_ref(G_OBJECT(progress_bar));
+    entropy_data->progress_bar = progress_bar;
+
+    return vbox;
+}
+
+static void refresh_progress_bar(struct entropy * entropy_data)
+{
+    gdk_threads_enter();
+    gtk_progress_bar_set_fraction(
+        GTK_PROGRESS_BAR(entropy_data->progress_bar),
+        (gdouble) entropy_data->bytes_read /
+        (gdouble) entropy_data->keysize);
+    gdk_threads_leave();
+}
+
+static gboolean move_byte(struct entropy * entropy_data)
+{
+    gssize n;
+
+    n = read(entropy_data->random_fd, &entropy_data->random_byte,
+             sizeof (guint8));
+    if (1 > n) {
+        g_critical("read failed: %s", strerror(errno));
+        return FALSE;
+    }
+    n = write(entropy_data->fifo_fd, &entropy_data->random_byte,
+              sizeof (guint8));
+    if (1 > n) {
+        g_critical("write failed: %s", strerror(errno));
+        return FALSE;
+    }
+    entropy_data->random_byte = 0;
+    return TRUE;
+}
+
+static void allow_continue(struct entropy * entropy_data)
+{
+    gchar * label;
+
+    label = cdebconf_gtk_get_text(
+        entropy_data->fe, "partman-crypto/entropy-text-success",
+        "Key data has been created successfully.");
+    gtk_progress_bar_set_text(
+        GTK_PROGRESS_BAR(entropy_data->progress_bar), label);
+    g_free(label);
+    gtk_widget_set_sensitive(entropy_data->continue_button, TRUE);
+}
+
+static void * gather_entropy(struct entropy * entropy_data)
+{
+    while (entropy_data->bytes_read < entropy_data->keysize) {
+        if (DC_NO_ANSWER != cdebconf_gtk_get_answer(entropy_data->fe)) {
+            /* answer set by others, let's quit */
+            return NULL;
+        }
+        if (!move_byte(entropy_data)) {
+            cdebconf_gtk_set_answer_notok(entropy_data->fe);
+            return NULL;
+        }
+        entropy_data->bytes_read++;
+        refresh_progress_bar(entropy_data);
+    }
+    allow_continue(entropy_data);
+    return NULL /* no one cares */;
+}
+
+static void destroy_entropy(struct entropy * entropy_data)
+{
+    if (NULL != entropy_data->gathering_thread) {
+        (void) g_thread_join(entropy_data->gathering_thread);
+    }
+    if (0 < entropy_data->fifo_fd) {
+        (void) close(entropy_data->fifo_fd);
+    }
+    (void) unlink(FIFO);
+    if (0 < entropy_data->random_fd) {
+        (void) close(entropy_data->random_fd);
+    }
+    (void) munlock(&entropy_data->random_byte, sizeof (guint8));
+    if (NULL != entropy_data->progress_bar) {
+        g_object_unref(G_OBJECT(entropy_data->progress_bar));
+    }
+    if (NULL != entropy_data->entry) {
+        g_object_unref(G_OBJECT(entropy_data->entry));
+    }
+    if (NULL != entropy_data->continue_button) {
+        g_object_unref(G_OBJECT(entropy_data->continue_button));
+    }
+    g_free(entropy_data);
+}
+
+static struct entropy * init_entropy(struct frontend * fe)
+{
+    struct entropy * entropy_data;
+
+    if (NULL == (entropy_data = g_malloc0(sizeof (struct entropy)))) {
+        g_critical("g_malloc0 failed.");
+        return NULL;
+    }
+    entropy_data->fe = fe;
+    if (-1 == mlock(&entropy_data->random_byte, sizeof (guint8))) {
+        g_critical("mlock failed: %s", strerror(errno));
+        goto failed;
+    }
+    entropy_data->random_fd = open("/dev/random", O_RDONLY);
+    if (-1 == entropy_data->random_fd) {
+        g_critical("open random_fd failed: %s", strerror(errno));
+        goto failed;
+    }
+    if (-1 == mkfifo(FIFO, 0600)) {
+        g_critical("mkfifo failed: %s", strerror(errno));
+        goto failed;
+    }
+    entropy_data->fifo_fd = open(FIFO, O_WRONLY);
+    if (-1 == entropy_data->fifo_fd) {
+        g_critical("open fifo_fd failed: %s", strerror(errno));
+        goto failed;
+    }
+    return entropy_data;
+
+failed:
+    destroy_entropy(entropy_data);
+    return NULL;
+}
+
+static void cleanup(struct question * question, struct entropy * entropy_data)
+{
+    destroy_entropy(entropy_data);
+}
+
+static gboolean set_keysize(struct entropy * entropy_data,
+                            struct question * question) {
+    const char * keysize_string;
+
+    keysize_string = question_get_variable(question, "KEYSIZE");
+    if (NULL == keysize_string) {
+        entropy_data->keysize = DEFAULT_KEYSIZE;
+        return TRUE;
+    }
+    entropy_data->keysize = g_ascii_strtoull(
+        keysize_string, NULL /* don't get last parsed byte */,
+        0 /* default base */);
+    if (G_MAXUINT64 == entropy_data->keysize) {
+        g_critical("keysize out of range");
+        return FALSE;
+    }
+    if (0 == entropy_data->keysize) {
+        g_critical("can't parse KEYSIZE");
+        return FALSE;
+    }
+    return TRUE;
+}
+
+int cdebconf_gtk_handler_entropy(struct frontend * fe,
+                                 struct question * question,
+                                 GtkWidget * question_box)
+{
+    struct entropy * entropy_data;
+    GtkWidget * widget;
+
+    if (!IS_QUESTION_SINGLE(question)) {
+        g_critical("entropy plugin does not work alongside other questions.");
+        return DC_NOTOK;
+    }
+    if (NULL == (entropy_data = init_entropy(fe))) {
+        g_critical("init_entropy failed.");
+        return DC_NOTOK;
+    }
+    if (!set_keysize(entropy_data, question)) {
+        g_critical("set_keysize failed.");
+        goto failed;
+    }
+    if (NULL == (widget = create_entropy_widget(entropy_data))) {
+        g_critical("create_widget failed.");
+        goto failed;
+    }
+
+    entropy_data->gathering_thread = g_thread_create(
+        (GThreadFunc) gather_entropy, entropy_data,
+        TRUE /* joinable */, NULL /* no gerror */);
+    if (NULL == entropy_data->gathering_thread) {
+        g_critical("g_thread_create failed.");
+        goto failed;
+    }
+
+    cdebconf_gtk_add_common_layout(fe, question, question_box, widget);
+
+    gtk_widget_grab_focus(entropy_data->entry);
+
+    cdebconf_gtk_register_setter(fe, SETTER_FUNCTION(cleanup), question,
+                                 entropy_data);
+
+    return DC_OK;
+
+failed:
+    destroy_entropy(entropy_data);
+    return DC_NOTOK;
+}
+
+/* vim: et sw=4 si
+ */

-- 
Jérémy Bobbio                        .''`. 
lunar@debian.org                    : :Ⓐ  :  # apt-get install anarchism
                                    `. `'` 
                                      `-   

Attachment: signature.asc
Description: Digital signature


Reply to: