gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] r16520 - in gnunet-gtk/src: . include lib


From: gnunet
Subject: [GNUnet-SVN] r16520 - in gnunet-gtk/src: . include lib
Date: Mon, 15 Aug 2011 14:17:25 +0200

Author: grothoff
Date: 2011-08-15 14:17:25 +0200 (Mon, 15 Aug 2011)
New Revision: 16520

Added:
   gnunet-gtk/src/include/
   gnunet-gtk/src/include/Makefile.am
   gnunet-gtk/src/include/gnunet_gtk.h
   gnunet-gtk/src/lib/
   gnunet-gtk/src/lib/Makefile.am
   gnunet-gtk/src/lib/about.c
   gnunet-gtk/src/lib/eventloop.c
   gnunet-gtk/src/lib/glade.c
   gnunet-gtk/src/lib/nls.c
   gnunet-gtk/src/lib/os_installation.c
Log:
draft for new libgnunetgtk

Added: gnunet-gtk/src/include/Makefile.am
===================================================================
--- gnunet-gtk/src/include/Makefile.am                          (rev 0)
+++ gnunet-gtk/src/include/Makefile.am  2011-08-15 12:17:25 UTC (rev 16520)
@@ -0,0 +1,6 @@
+SUBDIRS = .
+
+gnunetgtkincludedir = $(includedir)/gnunet
+
+gnunetgtkinclude_HEADERS = \
+  gnunet_gtk.h 

Added: gnunet-gtk/src/include/gnunet_gtk.h
===================================================================
--- gnunet-gtk/src/include/gnunet_gtk.h                         (rev 0)
+++ gnunet-gtk/src/include/gnunet_gtk.h 2011-08-15 12:17:25 UTC (rev 16520)
@@ -0,0 +1,154 @@
+/*
+     This file is part of GNUnet.
+     (C) 2011 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 2, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file src/include/gnunet_gtk.h
+ * @brief Helper library for Gtk user interfaces to GNUnet
+ * @author Christian Grothoff
+ */
+#ifndef GNUNET_GTK_H
+#define GNUNET_GTK_H
+
+#ifndef HAVE_USED_CONFIG_H
+#define HAVE_USED_CONFIG_H
+#if HAVE_CONFIG_H
+#include "gnunet_gtk_config.h"
+#endif
+#endif
+
+#include <gnunet/platform.h>
+#include <gnunet/gnunet_util_lib.h>
+#include <gnunet/gnunet_fs_service.h>
+#include <extractor.h>
+#include <gladeui/glade.h>
+#include <gtk/gtk.h>
+
+
+/**
+ * Initialize natural language support.
+ */
+void
+GNUNET_GTK_setup_nls (void);
+
+
+/**
+ * Get the name of the directory where all of our package
+ * data is stored ($PREFIX/share/)
+ * 
+ * @return name of the data directory
+ */
+const char *
+GNUNET_GTK_get_data_dir (void);
+
+
+/**
+ * @brief get the path to a specific GNUnet installation directory or,
+ * with GNUNET_IPK_SELF_PREFIX, the current running apps installation directory
+ * @author Milan
+ * @return a pointer to the dir path (to be freed by the caller)
+ */
+char *
+GNUNET_GTK_installation_get_path (enum GNUNET_OS_InstallationPathKind dirkind);
+
+
+/**
+ * Create an initialize a new builder based on the GNUnet-GTK glade
+ * file.
+ *
+ * @param filename name of the resource file to load
+ * @return NULL on error
+ */
+GtkBuilder *
+GNUNET_GTK_get_new_builder (const char *filename);
+
+
+/**
+ * This displays an about dialog.
+ *
+ * @param dialogfile name of the glade file containing the dialog
+ * @param dialogname name of the about dialog in the file
+ */
+void
+GNUNET_GTK_display_about (const char *dialogfile,
+                         const char *dialogname);
+
+
+/**
+ * Handle for our main loop.
+ */
+struct GNUNET_GTK_MainLoop;
+
+
+/**
+ * Initialize the main loop.
+ *
+ * @param binary_name binary name
+ * @param binary_help help text for the binary
+ * @param argc number of command line options
+ * @param argv command line options
+ * @param options allowed command line options
+ * @param main_window_file glade file for the main window
+ * @param main_task first task to run, closure will be set to the 'struct 
GNUNET_GTK_MainLoop'
+ * @return GNUNET_OK on success, GNUNET_SYSERR on error (i.e. bad command-line 
options, etc)
+ */
+int
+GNUNET_GTK_main_loop_start (const char *binary_name,
+                           const char *binary_help,
+                           int argc,
+                           char *const*argv,
+                           struct GNUNET_GETOPT_CommandLineOption *options,
+                           const char *main_window_file,
+                           GNUNET_SCHEDULER_Task main_task);
+
+
+/**
+ * Get an object from the main window.
+ *
+ * @param ml handle to the main loop
+ * @param name name of the object
+ * @return NULL on error, otherwise the object
+ */
+GObject *
+GNUNET_GTK_main_loop_get_object (struct GNUNET_GTK_MainLoop *ml,
+                                const char *name);
+
+
+/**
+ * Get the configuration.
+ *
+ * @param ml handle to the main loop
+ * @return handle to the configuration, never NULL
+ */
+const struct GNUNET_CONFIGURATION_Handle *
+GNUNET_GTK_main_loop_get_configuration (struct GNUNET_GTK_MainLoop *ml);
+
+
+/**
+ * Trigger shutdown of the GUI and exit the main loop.
+ *
+ * @param ml handle to the main loop
+ */
+void
+GNUNET_GTK_main_loop_quit (struct GNUNET_GTK_MainLoop *ml);
+                   
+
+
+#endif
+/* end of gnunet_gtk.h */

Added: gnunet-gtk/src/lib/Makefile.am
===================================================================
--- gnunet-gtk/src/lib/Makefile.am                              (rev 0)
+++ gnunet-gtk/src/lib/Makefile.am      2011-08-15 12:17:25 UTC (rev 16520)
@@ -0,0 +1,22 @@
+INCLUDES = \
+  -I$(top_srcdir)/ \
+  -I$(top_srcdir)/src/include \
+  @GTK_CFLAGS@ \
+  @GNUNET_CFLAGS@ \
+  @GLADE_CFLAGS@
+
+if MINGW
+  WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
+endif
+
+lib_LTLIBRARIES = libgnunetgtk.la
+
+libgnunetgtk_la_SOURCES = \
+  eventloop.c \
+  glade.c \
+  os_installation.c \
+  nls.c \
+  about.c 
+libgnunetgtk_la_LIBADD = \
+ -lgnunetutil $(XLIB)
+

Copied: gnunet-gtk/src/lib/about.c (from rev 16478, gnunet-gtk/src/about.c)
===================================================================
--- gnunet-gtk/src/lib/about.c                          (rev 0)
+++ gnunet-gtk/src/lib/about.c  2011-08-15 12:17:25 UTC (rev 16520)
@@ -0,0 +1,53 @@
+/*
+     This file is part of GNUnet
+     (C) 2005, 2006, 2010, 2011 Christian Grothoff (and other contributing 
authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 2, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file src/lib/about.c
+ * @brief code to display an about dialog
+ * @author Christian Grothoff
+ * @author Igor Wronsky
+ */
+#include "gnunet_gtk.h"
+
+/**
+ * This displays an about dialog.
+ *
+ * @param dialogfile name of the glade file containing the dialog
+ * @param dialogname name of the about dialog in the file
+ */
+void
+GNUNET_GTK_display_about (const char *dialogfile,
+                         const char *dialogname)
+{
+  GtkBuilder *builder;
+  GtkWidget *ad;
+
+  builder = GNUNET_GTK_get_new_builder (dialogfile);
+  if (builder == NULL)
+    return;
+  ad = GTK_WIDGET (gtk_builder_get_object (builder,
+                                          dialogname));
+  gtk_dialog_run (GTK_DIALOG (ad));
+  gtk_widget_destroy (ad);
+  g_object_unref (G_OBJECT (builder));
+}
+
+
+/* end of about.c */

Copied: gnunet-gtk/src/lib/eventloop.c (from rev 16519, 
gnunet-gtk/src/gnunet-gtk.c)
===================================================================
--- gnunet-gtk/src/lib/eventloop.c                              (rev 0)
+++ gnunet-gtk/src/lib/eventloop.c      2011-08-15 12:17:25 UTC (rev 16520)
@@ -0,0 +1,809 @@
+/*
+     This file is part of GNUnet.
+     (C) 2010, 2011 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 2, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file src/lib/eventloop.c
+ * @brief code for merging GNUnet scheduler and Gtk Main Loop event loops
+ * @author Christian Grothoff
+ */
+#include "gnunet_gtk.h"
+
+
+/**
+ * Main context for our event loop.
+ */
+struct GNUNET_GTK_MainLoop
+{
+
+  /**
+   * Our configuration.
+   */
+  const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+  /**
+   * Name of the glade file for the main window
+   */
+  const char *main_window_file;
+
+  /**
+   * Initial task to run to setup the system.
+   */
+  GNUNET_SCHEDULER_Task main_task;
+  
+  /**
+   * Builder for the main window.
+   */
+  GtkBuilder *builder; 
+
+  /**
+   * Gib's Main loop.
+   */
+  GMainLoop *gml;
+
+  /**
+   * GTK's main context.
+   */
+  GMainContext *gmc;
+
+  /**
+   * Read set.
+   */
+  struct GNUNET_NETWORK_FDSet *rs;
+
+  /**
+   * Write set.
+   */
+  struct GNUNET_NETWORK_FDSet *ws;
+
+  /**
+   * Recycled array of polling descriptors.
+   */
+  GPollFD *cached_poll_array;
+
+  /**
+   * Size of the 'cached_poll_array'.
+   */
+  guint cached_poll_array_size;
+
+  /**
+   * Return value from last g_main_context_query call.
+   */
+  guint poll_array_active;
+
+  /**
+   * Maximum GTK priority.
+   */
+  gint max_priority;
+
+
+#if WINDOWS
+  /**
+   * Array to hold pipe handles during a select() call
+   */
+  struct GNUNET_DISK_FileHandle **read_array;
+
+  /**
+   * Allocated length of read_array
+   */
+  int read_array_length;
+
+  /**
+   * Event to fire when a socket is ready for reading
+   */
+  HANDLE hEventRead;
+
+  /**
+   * Event to fire when a socket is ready for writing
+   */
+  HANDLE hEventWrite;
+
+  /**
+   * Event to fire when a socket had an error
+   */
+  HANDLE hEventException;
+
+  /**
+   * Event that is permanently enabled and is used to signal a pipe
+   * that is ready for writing (asynchronous pipes are always writable)
+   */
+  HANDLE hEventPipeWrite;
+
+  /**
+   * Event that is permanently enabled and is used to signal a pipe
+   * that is ready for reading (used to wake up early on a pipe that
+   * is known to be readable)
+   */
+  HANDLE hEventReadReady;
+
+  /**
+   * A list to hold file handles that are ready for reading
+   */
+  struct GNUNET_CONTAINER_SList *handles_read;
+
+  /**
+   * A list to hold file handles that are ready for writing
+   */
+  struct GNUNET_CONTAINER_SList *handles_write;
+
+  /**
+   * A list to hold file handles that are broken
+   */
+  struct GNUNET_CONTAINER_SList *handles_except;
+#endif
+
+};
+
+
+/**
+ * Get the configuration.
+ *
+ * @param ml handle to the main loop
+ * @return handle to the configuration, never NULL
+ */
+const struct GNUNET_CONFIGURATION_Handle *
+GNUNET_GTK_main_loop_get_configuration (struct GNUNET_GTK_MainLoop *ml)
+{
+  return ml->cfg;
+}
+
+
+/**
+ * Trigger shutdown of the GUI and exit the main loop.
+ *
+ * @param ml handle to the main loop
+ */
+void
+GNUNET_GTK_main_loop_quit (struct GNUNET_GTK_MainLoop *ml)
+{
+  g_main_loop_quit (ml->gml);
+}
+
+
+/**
+ * Get an object from the main window.
+ *
+ * @param ml handle to the main loop
+ * @param name name of the object
+ * @return NULL on error, otherwise the object
+ */
+GObject *
+GNUNET_GTK_main_loop_get_object (struct GNUNET_GTK_MainLoop *ml,
+                                const char *name)
+{
+  return gtk_builder_get_object (ml->builder, name);
+}
+
+
+/**
+ * Task to run Gtk events (within a GNUnet scheduler task).
+ *
+ * @param cls the main loop handle
+ * @param tc scheduler context
+ */
+static void
+gnunet_gtk_dispatch_task (void *cls,
+                        const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct GNUNET_GTK_MainLoop *ml = cls;
+  g_main_context_dispatch (ml->gmc);
+}
+
+
+#ifndef FD_COPY
+#define FD_COPY(s, d) (memcpy ((d), (s), sizeof (fd_set)))
+#endif
+
+/**
+ * Replacement for the GNUnet scheduler's "select" that integrates the
+ * Gtk event loop.  We merge Gtk's events with those from GNUnet's
+ * scheduler and then use 'g_poll' on both.  Then we process the Gtk
+ * events (by adding a task to do so to the GNUnet scheduler), and, if
+ * applicable, return the GNUnet-scheduler events back to GNUnet.
+ *
+ * @param cls the 'struct GNUNET_GTK_MainLoop'
+ * @param rfds set of sockets to be checked for readability
+ * @param wfds set of sockets to be checked for writability
+ * @param efds set of sockets to be checked for exceptions
+ * @param timeout relative value when to return
+ * @return number of selected sockets, GNUNET_SYSERR on error
+ */
+static int
+gnunet_gtk_select (void *cls,
+                   struct GNUNET_NETWORK_FDSet *rfds,
+                   struct GNUNET_NETWORK_FDSet *wfds,
+                   struct GNUNET_NETWORK_FDSet *efds,
+                   const struct GNUNET_TIME_Relative timeout)
+{
+  struct GNUNET_GTK_MainLoop *ml = cls;
+  int max_nfds;
+  gint poll_result;
+
+  GPollFD *gfds;
+  gint delay;
+
+  guint i;
+  guint fd_counter = 0;
+
+  guint allocated_nfds, need_gfds;
+
+  fd_set aread, awrite, aexcept;
+  int pre_ret = 0;
+  int result = 0;
+  int socks = 0;
+  int sock_read = 0, sock_write = 0, sock_err = 0;
+
+#if WINDOWS
+  int always_ready_write_fd = -1;
+
+  int select_ret = 0;
+
+  int read_handles = 0;
+  DWORD waitstatus;
+#endif
+
+  if (TRUE != g_main_loop_is_running (ml->gml))
+    return GNUNET_NETWORK_socket_select (rfds, wfds, efds, timeout);
+
+  FD_ZERO (&aread);
+  FD_ZERO (&awrite);
+  FD_ZERO (&aexcept);
+  if (rfds)
+    FD_COPY (&rfds->sds, &aread);
+  if (wfds)
+    FD_COPY (&wfds->sds, &awrite);
+  if (efds)
+    FD_COPY (&efds->sds, &aexcept);
+
+#if WINDOWS
+  ResetEvent (ml->hEventRead);
+  ResetEvent (ml->hEventWrite);
+  ResetEvent (ml->hEventException);
+
+  GNUNET_CONTAINER_slist_clear (ml->handles_read);
+  GNUNET_CONTAINER_slist_clear (ml->handles_write);
+  GNUNET_CONTAINER_slist_clear (ml->handles_except);
+#endif
+
+
+  if (rfds != NULL)
+    max_nfds = rfds->nsds;
+  else
+    max_nfds = -1;
+  if (wfds != NULL && max_nfds < wfds->nsds)
+    max_nfds = wfds->nsds;
+  if (efds != NULL && max_nfds < efds->nsds)
+    max_nfds = efds->nsds;
+
+  allocated_nfds = ml->cached_poll_array_size;
+  gfds = ml->cached_poll_array;
+  if (allocated_nfds == 0)
+  {
+    /* TODO: get some statistics, find the maximum number of fds ever
+     * polled during normal gnunet-gtk operation, and set this to that number.
+     */
+    ml->cached_poll_array = gfds = g_new (GPollFD, 30);
+    ml->cached_poll_array_size = allocated_nfds = 30;
+  }
+
+  while (1)
+  {
+    fd_counter = 0;
+#if !WINDOWS
+    gboolean need_realloc = FALSE;
+    for (i = 0; !need_realloc && i < max_nfds; i += 1)
+    {
+      int isset[3];
+     
+      isset[0] = (rfds == NULL) ? 0 : FD_ISSET (i, &rfds->sds);
+      isset[1] = (wfds == NULL) ? 0 : FD_ISSET (i, &wfds->sds);
+      isset[2] = (efds == NULL) ? 0 : FD_ISSET (i, &efds->sds);
+      if (!isset[0] && !isset[1] && !isset[2])
+        continue;
+      if (fd_counter >= allocated_nfds)
+      {
+        need_realloc = TRUE;
+        break;
+      }
+      gfds[fd_counter].fd = i;
+      gfds[fd_counter].events = (isset[0] ? G_IO_IN | G_IO_HUP | G_IO_ERR : 0)
+       | (isset[1] ? G_IO_OUT | G_IO_ERR : 0) | (isset[2] ? G_IO_ERR : 0);
+      fd_counter += 1;
+    }
+    if (need_realloc)
+    {
+      ml->cached_poll_array = gfds = g_renew (GPollFD, gfds, 
ml->cached_poll_array_size * 2);
+      ml->cached_poll_array_size = allocated_nfds = ml->cached_poll_array_size 
* 2;
+      fd_counter = 0;
+      need_realloc = FALSE;
+    }
+    else
+      break;  
+#else
+    struct GNUNET_CONTAINER_SList_Iterator *t;
+    /* We might overshoot a little, but that won't hurt very much */
+    int need_nfds = (rfds->sds.fd_count + rfds->sds.fd_count + 
rfds->sds.fd_count > 0 ? 3 : 0)
+        + (rfds == NULL ? 0 : GNUNET_CONTAINER_slist_count (rfds->handles))
+        + (wfds == NULL ? 0 : 1)
+        + 1;
+    if (need_nfds >= allocated_nfds)
+    {
+      /* Since there are also gmainloop's own fds, just need_nfds won't be
+       * enough, so make it twice as long.
+       */
+      ml->cached_poll_array = gfds = g_renew (GPollFD, gfds, need_nfds * 2);
+      ml->cached_poll_array_size = allocated_nfds = need_nfds * 2;
+    }
+    if (ml->read_array_length < GNUNET_CONTAINER_slist_count (rfds->handles))
+    {
+      ml->read_array = GNUNET_realloc (ml->read_array, 
GNUNET_CONTAINER_slist_count (rfds->handles) * sizeof (struct 
GNUNET_DISK_FileHandle *));
+      ml->read_array_length = GNUNET_CONTAINER_slist_count (rfds->handles);
+    }
+    if (rfds != NULL)
+    {
+      for (t = GNUNET_CONTAINER_slist_begin (rfds->handles), i = 0;
+          GNUNET_CONTAINER_slist_end (t) != GNUNET_YES;
+          GNUNET_CONTAINER_slist_next (t), i += 1)
+      {
+        struct GNUNET_DISK_FileHandle *fh;
+        fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (t, 
NULL);
+        if (fh->type == GNUNET_PIPE)
+        {
+          if (!ReadFile (fh->h, NULL, 0, NULL, fh->oOverlapRead))
+          {
+            DWORD error_code = GetLastError();
+            if (error_code == ERROR_IO_PENDING)
+            {
+#if DEBUG_NETWORK
+              GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding the pipe's 0x%x 
overlapped event to the array as %d\n", fh->h, nhandles);
+#endif
+              gfds[fd_counter].fd = (intptr_t) fh->oOverlapRead->hEvent;
+              /* On W32 .events makes no sense - g_poll will just OR its
+               * contents into .revents when the .fd event fires.
+               * So we'll use it in the way that suits us the best.
+               */
+              gfds[fd_counter].events = G_IO_IN;
+              fd_counter += 1;
+              ml->read_array[read_handles] = fh;
+              read_handles += 1;
+            }
+            else
+            {
+              gfds[fd_counter].fd = (intptr_t) ml->hEventReadReady;
+              gfds[fd_counter].events = G_IO_HUP;
+              fd_counter += 1;
+              ml->read_array[read_handles] = fh;
+              read_handles += 1;
+            }
+          }
+          else
+          {
+#if DEBUG_NETWORK
+            GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding the read ready event 
to the array as %d\n", nhandles);
+#endif
+            gfds[fd_counter].fd = (intptr_t) ml->hEventReadReady;
+            gfds[fd_counter].events = G_IO_IN;
+            fd_counter += 1;
+            ml->read_array[read_handles] = fh;
+            read_handles += 1;
+          }
+        }
+        else
+        {
+          GNUNET_CONTAINER_slist_add (ml->handles_read,
+              GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
+              fh, sizeof (struct GNUNET_DISK_FileHandle));
+            pre_ret += 1;
+        }
+      }
+    }
+    if (wfds != NULL && GNUNET_CONTAINER_slist_count (wfds->handles) > 0)
+    {
+      gfds[fd_counter].fd = (intptr_t) ml->hEventPipeWrite;
+      gfds[fd_counter].events = G_IO_OUT;
+      always_ready_write_fd = fd_counter;
+      fd_counter += 1;
+    }
+    if (efds != NULL)
+    {
+      for (t = GNUNET_CONTAINER_slist_begin (efds->handles), i = 0;
+          GNUNET_CONTAINER_slist_end (t) != GNUNET_YES;
+          GNUNET_CONTAINER_slist_next (t), i += 1)
+      {
+        struct GNUNET_DISK_FileHandle *fh;
+        DWORD dwBytes;
+        fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (t, 
NULL);
+        if (fh->type == GNUNET_PIPE)
+        {
+          if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
+          {
+            GNUNET_CONTAINER_slist_add (ml->handles_except,
+                GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
+                fh, sizeof (struct GNUNET_DISK_FileHandle));
+            pre_ret += 1;
+          }
+        }
+      }
+    }
+    GNUNET_CONTAINER_slist_iter_destroy (t);
+
+    if (rfds != NULL && rfds->sds.fd_count > 0)
+    {
+#if DEBUG_NETWORK
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding the socket read event to 
the array as %d\n", fd_counter);
+#endif
+      gfds[fd_counter].fd = (intptr_t) ml->hEventRead;
+      gfds[fd_counter].events = G_IO_IN;
+      for (i = 0; i < rfds->sds.fd_count; i++)
+        WSAEventSelect (rfds->sds.fd_array[i], ml->hEventRead, FD_ACCEPT | 
FD_READ | FD_CLOSE);
+      fd_counter += 1;
+      sock_read = rfds->sds.fd_count;
+    }
+    if (wfds != NULL && wfds->sds.fd_count > 0)
+    {
+      int wakeup = 0;
+#if DEBUG_NETWORK
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding the socket write event to 
the array as %d\n", fd_counter);
+#endif
+      gfds[fd_counter].fd = (intptr_t) ml->hEventWrite;
+      gfds[fd_counter].events = G_IO_OUT;
+      for (i = 0; i < wfds->sds.fd_count; i++)
+      {
+        DWORD error;
+        int status;
+        status = send (wfds->sds.fd_array[i], NULL, 0, 0);
+        error = GetLastError ();
+#if DEBUG_NETWORK
+        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "pre-send to the socket %d 
returned %d (%u)\n", i, status, error);
+#endif
+        if (status == 0 || (error != WSAEWOULDBLOCK && error != WSAENOTCONN))
+          wakeup = 1;
+        WSAEventSelect (wfds->sds.fd_array[i], ml->hEventWrite, FD_WRITE | 
FD_CONNECT | FD_CLOSE);
+      }
+      if (wakeup)
+        SetEvent (ml->hEventWrite);
+      fd_counter += 1;
+      sock_write = wfds->sds.fd_count;
+    }
+    if (efds != NULL && efds->sds.fd_count > 0)
+    {
+#if DEBUG_NETWORK
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding the socket error event to 
the array as %d\n", fd_counter);
+#endif
+      gfds[fd_counter].fd = (intptr_t) ml->hEventException;
+      gfds[fd_counter].events = G_IO_ERR;
+      for (i = 0; i < efds->sds.fd_count; i++)
+        WSAEventSelect (efds->sds.fd_array[i], ml->hEventException, FD_OOB | 
FD_CLOSE);
+      fd_counter += 1;
+      sock_err = efds->sds.fd_count;
+    }
+    break;
+#endif
+  }
+  socks = sock_read + sock_write + sock_err;
+
+  g_main_context_prepare (ml->gmc, &ml->max_priority);
+  while (allocated_nfds < (need_gfds = g_main_context_query (ml->gmc,
+      ml->max_priority, &delay, &gfds[fd_counter], allocated_nfds - 
fd_counter)))
+  {
+    ml->cached_poll_array = gfds = g_renew (GPollFD, gfds, allocated_nfds - 
fd_counter + need_gfds);
+    ml->cached_poll_array_size = allocated_nfds = allocated_nfds - fd_counter 
+ need_gfds;
+  }
+  ml->poll_array_active = fd_counter + need_gfds;
+
+  if (timeout.rel_value != GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
+  {
+    if (delay >= 0)
+      delay = MIN(timeout.rel_value / GNUNET_TIME_UNIT_MILLISECONDS.rel_value, 
delay);
+    else
+      delay = timeout.rel_value / GNUNET_TIME_UNIT_MILLISECONDS.rel_value;
+  }
+
+  if (pre_ret > 0)
+  {
+#if DEBUG_NETWORK
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "pre_ret is %d, setting delay to 
0\n", pre_ret);
+#endif
+    delay = 0;
+  }
+
+#if DEBUG_NETWORK
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "We have %d of our FDs and %d of GMC 
ones, going to wait %6dms\n", fd_counter, need_gfds, delay);
+#endif
+
+  poll_result = g_poll (gfds, fd_counter + need_gfds, delay);
+
+#if DEBUG_NETWORK
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "g_poll returned : %d\n", poll_result);
+#endif
+
+  /* Take care of GUI events.
+   * Dispatching the events here will eventually crash the scheduler, must do 
this
+   * from within a task (currently we're not in a task, but in a select() 
call, remember)
+   * Startup reason is used to pass the scheduler sanity check.
+   */
+  if (TRUE == g_main_context_check (ml->gmc, ml->max_priority, 
&gfds[fd_counter], need_gfds))
+    GNUNET_SCHEDULER_add_continuation (gnunet_gtk_dispatch_task, ml,
+                                      GNUNET_SCHEDULER_REASON_STARTUP);
+
+#if !WINDOWS
+  if (rfds)
+    GNUNET_NETWORK_fdset_zero (rfds);
+  if (wfds)
+    GNUNET_NETWORK_fdset_zero (wfds);
+  if (efds)
+    GNUNET_NETWORK_fdset_zero (efds);
+  for (i = 0; i < fd_counter; i++)
+  {
+    int set[3];
+    if ((set[0] = FD_ISSET (gfds[i].fd, &aread)))
+      FD_SET (gfds[i].fd, &rfds->sds);
+    if ((set[1] = FD_ISSET (gfds[i].fd, &awrite)))
+      FD_SET (gfds[i].fd, &wfds->sds);
+    if ((set[2] = FD_ISSET (gfds[i].fd, &aexcept)))
+      FD_SET (gfds[i].fd, &efds->sds);
+    if (set[0] || set[1] || set[2])
+      result += 1;
+  }
+#else
+  if (socks > 0)
+  {
+    struct timeval tvslice;
+    tvslice.tv_sec = 0;
+    tvslice.tv_usec = 0;
+    select_ret = select (max_nfds, &aread, &awrite, &aexcept, &tvslice);
+    if (select_ret == -1)
+      select_ret = 0;
+#if DEBUG_NETWORK
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "select() returned %d\n", select_ret);
+#endif
+  }
+  if (always_ready_write_fd >= 0 && gfds[always_ready_write_fd].revents & 
G_IO_OUT)
+  {
+    GNUNET_CONTAINER_slist_append (ml->handles_write, wfds->handles);
+    result += GNUNET_CONTAINER_slist_count (ml->handles_write);
+#if DEBUG_NETWORK
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Added write pipe\n");
+#endif
+  }
+  for (i = 0; i < read_handles; i++)
+  {
+    DWORD error;
+    BOOL bret;
+    if (!(gfds[i].revents & (G_IO_IN | G_IO_HUP | G_IO_ERR)))
+      continue;
+    SetLastError (0);
+    waitstatus = 0;
+    bret = PeekNamedPipe (ml->read_array[i]->h, NULL, 0, NULL, &waitstatus, 
NULL);
+    error = GetLastError ();
+#if DEBUG_NETWORK
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peek at read pipe %d (0x%x) returned 
%d (%d bytes available) GLE %u\n", i, ml->read_array[i]->h, bret, waitstatus, 
error);
+#endif
+    if (bret == 0 || (gfds[i].revents & G_IO_ERR))
+    {
+      if (efds != NULL)
+      {
+        struct GNUNET_CONTAINER_SList_Iterator *t;
+        for (t = GNUNET_CONTAINER_slist_begin (efds->handles), i = 0;
+            GNUNET_CONTAINER_slist_end (t) != GNUNET_YES;
+            GNUNET_CONTAINER_slist_next (t), i += 1)
+        {
+          struct GNUNET_DISK_FileHandle *fh;
+          fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get 
(t, NULL);
+          if (fh == ml->read_array[i])
+          {
+            GNUNET_CONTAINER_slist_add (ml->handles_except,
+                GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
+                fh, sizeof (struct GNUNET_DISK_FileHandle));
+            break;
+          }
+        }
+        GNUNET_CONTAINER_slist_iter_destroy (t);
+      }
+    }
+    else if (waitstatus <= 0)
+      continue;
+    GNUNET_CONTAINER_slist_add (ml->handles_read,
+        GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
+        ml->read_array[i], sizeof (struct GNUNET_DISK_FileHandle));
+    result += 1;
+#if DEBUG_NETWORK
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n", 
ml->read_array[i], ml->read_array[i]->h);
+#endif
+  }
+  waitstatus = WaitForSingleObject (ml->hEventWrite, 0);
+#if DEBUG_NETWORK
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Wait for the write event returned 
%d\n", waitstatus);
+#endif
+  if (waitstatus == WAIT_OBJECT_0)
+  {
+    for (i = 0; i < wfds->sds.fd_count; i++)
+    {
+      DWORD error;
+      int status;
+      int so_error = 0;
+      int sizeof_so_error = sizeof (so_error);
+      int gso_result = getsockopt (wfds->sds.fd_array[i], SOL_SOCKET, 
SO_ERROR, (char *) &so_error, &sizeof_so_error);
+      status = send (wfds->sds.fd_array[i], NULL, 0, 0);
+      error = GetLastError ();
+#if DEBUG_NETWORK
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "send to the socket %d returned %d 
(%u)\n", i, status, error);
+#endif
+      if (status == 0
+          || (error != WSAEWOULDBLOCK && error != WSAENOTCONN)
+          || (status == -1 && gso_result == 0 && error == WSAENOTCONN && 
so_error == WSAECONNREFUSED))
+      {
+        FD_SET (wfds->sds.fd_array[i], &awrite);
+        result += 1;
+      }
+    }
+  }
+  if (rfds)
+  {
+    struct GNUNET_CONTAINER_SList_Iterator *t;
+    for (i = 0; i < rfds->sds.fd_count; i++)
+      WSAEventSelect (rfds->sds.fd_array[i], ml->hEventRead, 0);
+    for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
+        GNUNET_CONTAINER_slist_end (t) != GNUNET_YES;
+        GNUNET_CONTAINER_slist_next (t))
+    {
+      struct GNUNET_DISK_FileHandle *fh;
+      fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (t, 
NULL);
+      if (fh->type == GNUNET_PIPE)
+        CancelIo (fh->h);
+    }
+    GNUNET_CONTAINER_slist_iter_destroy (t);
+    GNUNET_NETWORK_fdset_zero (rfds);
+    if (select_ret != -1 && socks > 0)
+      GNUNET_NETWORK_fdset_copy_native (rfds, &aread, select_ret);
+    GNUNET_CONTAINER_slist_append (rfds->handles, ml->handles_read);
+  }
+  if (wfds)
+  {
+    for (i = 0; i < wfds->sds.fd_count; i++)
+      WSAEventSelect (wfds->sds.fd_array[i], ml->hEventWrite, 0);
+    GNUNET_NETWORK_fdset_zero (wfds);
+    if (select_ret != -1 && socks > 0)
+      GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, select_ret);
+    GNUNET_CONTAINER_slist_append (wfds->handles, ml->handles_write);
+  }
+  if (efds)
+  {
+    for (i = 0; i < efds->sds.fd_count; i++)
+      WSAEventSelect (efds->sds.fd_array[i], ml->hEventException, 0);
+    GNUNET_NETWORK_fdset_zero (efds);
+    if (select_ret != -1 && socks > 0)
+      GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, select_ret);
+    GNUNET_CONTAINER_slist_append (efds->handles, ml->handles_except);
+    result += GNUNET_CONTAINER_slist_count (ml->handles_except);
+  }
+  if (fd_counter > 0)
+    /* This is not accurate (select_ret counts write-ready sockets,
+     * and result does as well. Anything out there actually cares
+     * about this?
+     */
+    return select_ret + result;
+  else
+    return 0;
+#endif
+  return result;
+}
+
+
+/**
+ * Actual main function run right after GNUnet's scheduler
+ * is initialized.  Initializes up GTK and Glade and starts the
+ * combined event loop.
+ *
+ * @param cls the 'struct GNUNET_GTK_MainLoop'
+ * @param args leftover command line arguments (go to gtk)
+ * @param cfgfile name of the configuration file
+ * @param cfg handle to the configuration
+ */                  
+static void
+run_main_loop (void *cls,
+              char *const *args,
+              const char *cfgfile,
+              const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  struct GNUNET_GTK_MainLoop *ml = cls;
+  int argc;
+ 
+  /* command-line processing for Gtk arguments */
+  argc = 0;
+  while (args[argc] != NULL) argc++;
+  gtk_init (&argc, (char ***) &args);
+
+  /* setup main context */
+  ml->builder = GNUNET_GTK_get_new_builder (ml->main_window_file);
+  if (ml->builder == NULL)
+    return;
+  ml->rs = GNUNET_NETWORK_fdset_create ();
+  ml->ws = GNUNET_NETWORK_fdset_create ();
+  ml->gml = g_main_loop_new (NULL, TRUE);
+  ml->gmc = g_main_loop_get_context (ml->gml);
+  ml->cfg = cfg;
+#if WINDOWS
+  ml->hEventRead = CreateEvent (NULL, TRUE, FALSE, NULL);
+  ml->hEventReadReady = CreateEvent (NULL, TRUE, TRUE, NULL);
+  ml->hEventWrite = CreateEvent (NULL, TRUE, FALSE, NULL);
+  ml->hEventException = CreateEvent (NULL, TRUE, FALSE, NULL);
+  ml->hEventPipeWrite = CreateEvent (NULL, TRUE, TRUE, NULL);
+  ml->handles_read = GNUNET_CONTAINER_slist_create ();
+  ml->handles_write = GNUNET_CONTAINER_slist_create ();
+  ml->handles_except = GNUNET_CONTAINER_slist_create ();
+  ml->read_array = NULL;
+  ml->read_array_length = 0;
+#endif
+
+  /* run main task of the application */
+  GNUNET_SCHEDULER_add_continuation (ml->main_task, ml,
+                                    GNUNET_SCHEDULER_REASON_STARTUP);
+
+  /* start the Gtk event loop */
+  GNUNET_assert (TRUE == g_main_context_acquire (ml->gmc));
+  GNUNET_SCHEDULER_set_select (&gnunet_gtk_select, ml);
+}
+
+
+/**
+ * Initialize the main loop.
+ *
+ * @param binary_name binary name
+ * @param binary_help help text for the binary
+ * @param argc number of command line options
+ * @param argv command line options
+ * @param options allowed command line options
+ * @param main_window_file glade file for the main window
+ * @param main_task first task to run, closure will be set to the 'struct 
GNUNET_GTK_MainLoop'
+ * @return GNUNET_OK on success, GNUNET_SYSERR on error (i.e. bad command-line 
options, etc)
+ */
+int
+GNUNET_GTK_main_loop_start (const char *binary_name,
+                           const char *binary_help,
+                           int argc,
+                           char *const*argv,
+                           struct GNUNET_GETOPT_CommandLineOption *options,
+                           const char *main_window_file,
+                           GNUNET_SCHEDULER_Task main_task)
+{
+  struct GNUNET_GTK_MainLoop ml;
+  int ret;
+
+  ml.main_window_file = main_window_file;
+  ret = GNUNET_PROGRAM_run (argc, argv,
+                           binary_name,
+                           "GTK GUI for GNUnet",
+                           options,
+                           &run_main_loop, &ml);
+  if (NULL != ml.cached_poll_array)
+    g_free (ml.cached_poll_array);
+  if (NULL != ml.rs)
+    GNUNET_NETWORK_fdset_destroy (ml.rs);
+  if (NULL != ml.ws)
+    GNUNET_NETWORK_fdset_destroy (ml.ws);
+  if (NULL != ml.builder)
+    g_object_unref (G_OBJECT (ml.builder));
+  if (NULL != ml.gml)
+    g_main_loop_unref (ml.gml);
+  return ret;
+}
+
+
+/* end of eventloop.c */

Copied: gnunet-gtk/src/lib/glade.c (from rev 16519, gnunet-gtk/src/gnunet-gtk.c)
===================================================================
--- gnunet-gtk/src/lib/glade.c                          (rev 0)
+++ gnunet-gtk/src/lib/glade.c  2011-08-15 12:17:25 UTC (rev 16520)
@@ -0,0 +1,85 @@
+/*
+     This file is part of GNUnet.
+     (C) 2010 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 2, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file src/lib/glade.c
+ * @brief code for integration with glade
+ * @author Christian Grothoff
+ */
+#include "gnunet_gtk_config.h"
+#include "gnunet_gtk.h"
+
+
+/**
+ * Get the name of the directory where all of our package
+ * data is stored ($PREFIX/share/)
+ * 
+ * @return name of the data directory
+ */
+const char *
+GNUNET_GTK_get_data_dir ()
+{
+  static char *dd;
+
+  if (dd == NULL)
+    dd = GNUNET_GTK_installation_get_path (GNUNET_OS_IPK_DATADIR);
+  return dd;
+}
+
+
+/**
+ * Create an initialize a new builder based on the
+ * GNUnet-GTK glade file.
+ *
+ * @param filename name of the resource file to load
+ * @return NULL on error
+ */
+GtkBuilder *
+GNUNET_GTK_get_new_builder (const char *filename)
+{
+  char *glade_path;
+  GtkBuilder *ret;
+  GError *error;
+
+  ret = gtk_builder_new ();
+  gtk_builder_set_translation_domain (ret, "gnunet-gtk");
+  GNUNET_asprintf (&glade_path,
+                  "%s%s",
+                  GNUNET_GTK_get_data_dir (),
+                  filename);
+  error = NULL;
+  if (0 == gtk_builder_add_from_file (ret, glade_path, &error))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                 _("Failed to load `%s': %s\n"),
+                 glade_path,
+                 error->message);
+      g_error_free (error);
+      GNUNET_free (glade_path);
+      return NULL;
+    }
+  gtk_builder_connect_signals (ret, NULL);
+  GNUNET_free (glade_path);
+  return ret;
+}
+
+
+
+/* end of glade.c */

Added: gnunet-gtk/src/lib/nls.c
===================================================================
--- gnunet-gtk/src/lib/nls.c                            (rev 0)
+++ gnunet-gtk/src/lib/nls.c    2011-08-15 12:17:25 UTC (rev 16520)
@@ -0,0 +1,58 @@
+/*
+     This file is part of GNUnet.
+     (C) 2010, 2011 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 2, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file src/lib/nls.c
+ * @brief natural language support
+ * @author Christian Grothoff
+ */
+#include "gnunet_gtk.h"
+
+#if ENABLE_NLS
+#include <locale.h>
+#endif
+
+
+/**
+ * Initialize GNU gettext for message translation.
+ */
+void
+GNUNET_GTK_setup_nls ()
+{
+#if ENABLE_NLS
+  char *path;
+
+  setlocale (LC_ALL, "");
+  GNUNET_asprintf (&path,
+                  "%s/%s/locale/",
+                  GNUNET_GTK_get_data_dir (),
+                  PACKAGE_NAME);
+  bindtextdomain ("gnunet-gtk", path);
+  textdomain ("gnunet-gtk");
+  bind_textdomain_codeset ("GNUnet", "UTF-8");
+  bind_textdomain_codeset ("gnunet-gtk", "UTF-8");
+  GNUNET_free (path);
+#else
+  fprintf (stderr,
+          "WARNING: gnunet-gtk was compiled without i18n support (did CFLAGS 
contain -Werror?).\n");
+#endif
+}
+
+/* end of nls.c */

Copied: gnunet-gtk/src/lib/os_installation.c (from rev 16478, 
gnunet-gtk/src/os_installation.c)
===================================================================
--- gnunet-gtk/src/lib/os_installation.c                                (rev 0)
+++ gnunet-gtk/src/lib/os_installation.c        2011-08-15 12:17:25 UTC (rev 
16520)
@@ -0,0 +1,435 @@
+/*
+     This file is part of GNUnet.
+     (C) 2006, 2010, 2011 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 2, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file src/lib/os_installation.c
+ * @brief get paths used by the program; this code is almost the
+ *        same as src/util/os_installation.c in libgnunetutil; however,
+ *        it contains sublte changes to detect the installation path
+ *        of gnunet-gtk (which may be different from the path for
+ *        GNUnet itself) and also needs to be replicated anyway since
+ *        some of the methods try to find the location of the binary
+ *        of the test-code itself, which would never yield the
+ *        correct result for gnunet-gtk if the code lives in libgnunetutil.
+ * @author Milan
+ * @author Christian Grothoff
+ */
+#include "gnunet_gtk.h"
+#if DARWIN
+#include <mach-o/ldsyms.h>
+#include <mach-o/dyld.h>
+#endif
+
+#if LINUX
+/**
+ * Try to determine path by reading /proc/PID/exe
+ */
+static char *
+get_path_from_proc_maps ()
+{
+  char fn[64];
+  char line[1024];
+  char dir[1024];
+  FILE *f;
+  char *lgu;
+
+  GNUNET_snprintf (fn,
+                  sizeof(fn), 
+                  "/proc/%u/maps", 
+                  getpid ());
+  f = fopen (fn, "r");
+  if (f == NULL)
+    return NULL;
+  while (NULL != fgets (line, sizeof(line), f))
+    {
+      if ((1 == sscanf (line,
+                       "%*x-%*x %*c%*c%*c%*c %*x %*2u:%*2u %*u%*[ ]%s",
+                       dir)) &&
+         (NULL != (lgu = strstr (dir, "gnunet-gtk"))))
+       {
+         lgu[0] = '\0';
+         fclose (f);
+         return GNUNET_strdup (dir);
+       }
+    }
+  fclose (f);
+  return NULL;
+}
+
+/**
+ * Try to determine path by reading /proc/PID/exe
+ */
+static char *
+get_path_from_proc_exe ()
+{
+  char fn[64];
+  char lnk[1024];
+  ssize_t size;
+
+  GNUNET_snprintf (fn, 
+                  sizeof(fn), "/proc/%u/exe", getpid ());
+  size = readlink (fn, lnk, sizeof (lnk)-1);
+  if (size <= 0)
+    {
+      GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "readlink", fn);
+      return NULL;
+    }
+  GNUNET_assert (size < sizeof (lnk));
+  lnk[size] = '\0';
+  while ((lnk[size] != '/') && (size > 0))
+    size--;
+  if ((size < 4) || (lnk[size - 4] != '/'))
+    {
+      /* not installed in "/bin/" -- binary path probably useless */
+      return NULL;
+    }
+  lnk[size] = '\0';
+  return GNUNET_strdup (lnk);
+}
+#endif
+
+#if WINDOWS
+/**
+ * Try to determine path with win32-specific function
+ */
+static char *
+get_path_from_module_filename ()
+{
+  char path[4097];
+  char *idx;
+
+  GetModuleFileName (NULL, path, sizeof(path)-1);
+  idx = path + strlen (path);
+  while ((idx > path) && (*idx != '\\') && (*idx != '/'))
+    idx--;
+  *idx = '\0';
+  return GNUNET_strdup (path);
+}
+#endif
+
+#if DARWIN
+typedef int (*MyNSGetExecutablePathProto) (char *buf, size_t * bufsize);
+
+static char *
+get_path_from_NSGetExecutablePath ()
+{
+  static char zero = '\0';
+  char *path;
+  size_t len;
+  MyNSGetExecutablePathProto func;
+  int ret;
+
+  path = NULL;
+  func =
+    (MyNSGetExecutablePathProto) dlsym (RTLD_DEFAULT, "_NSGetExecutablePath");
+  if (!func)
+    return NULL;
+  path = &zero;
+  len = 0;
+  /* get the path len, including the trailing \0 */
+  func (path, &len);
+  if (len == 0)
+    return NULL;
+  path = GNUNET_malloc (len);
+  ret = func (path, &len);
+  if (ret != 0)
+    {
+      GNUNET_free (path);
+      return NULL;
+    }
+  len = strlen (path);
+  while ((path[len] != '/') && (len > 0))
+    len--;
+  path[len] = '\0';
+  return path;
+}
+
+static char *
+get_path_from_dyld_image ()
+{
+  const char *path;
+  char *p, *s;
+  int i;
+  int c;
+
+  p = NULL;
+  c = _dyld_image_count ();
+  for (i = 0; i < c; i++)
+    {
+      if (_dyld_get_image_header (i) == &_mh_dylib_header)
+        {
+          path = _dyld_get_image_name (i);
+          if (path != NULL && strlen (path) > 0)
+            {
+              p = strdup (path);
+              s = p + strlen (p);
+              while ((s > p) && (*s != '/'))
+                s--;
+              s++;
+              *s = '\0';
+            }
+          break;
+        }
+    }
+  return p;
+}
+#endif
+
+static char *
+get_path_from_PATH ()
+{
+  char *path;
+  char *pos;
+  char *end;
+  char *buf;
+  const char *p;
+
+  p = getenv ("PATH");
+  if (p == NULL)
+    return NULL;
+  path = GNUNET_strdup (p);     /* because we write on it */
+  buf = GNUNET_malloc (strlen (path) + 20);
+  pos = path;
+
+  while (NULL != (end = strchr (pos, ':')))
+    {
+      *end = '\0';
+      sprintf (buf, "%s/%s", pos, "gnunet-gtk");
+      if (GNUNET_DISK_file_test (buf) == GNUNET_YES)
+        {
+          pos = GNUNET_strdup (pos);
+          GNUNET_free (buf);
+          GNUNET_free (path);
+          return pos;
+        }
+      pos = end + 1;
+    }
+  sprintf (buf, "%s/%s", pos, "gnunet-gtk");
+  if (GNUNET_DISK_file_test (buf) == GNUNET_YES)
+    {
+      pos = GNUNET_strdup (pos);
+      GNUNET_free (buf);
+      GNUNET_free (path);
+      return pos;
+    }
+  GNUNET_free (buf);
+  GNUNET_free (path);
+  return NULL;
+}
+
+static char *
+get_path_from_GNUNET_PREFIX ()
+{
+  const char *p;
+
+  p = getenv ("GNUNET_GTK_PREFIX");
+  if (p != NULL)
+    return GNUNET_strdup (p);
+  p = getenv ("GNUNET_PREFIX");
+  if (p != NULL)
+    return GNUNET_strdup (p);
+  return NULL;
+}
+
+/*
+ * @brief get the path to GNUnet bin/ or lib/, prefering the lib/ path
+ * @author Milan
+ *
+ * @return a pointer to the executable path, or NULL on error
+ */
+static char *
+os_get_gnunet_path ()
+{
+  char *ret;
+
+  ret = get_path_from_GNUNET_PREFIX ();
+  if (ret != NULL)
+    return ret;
+#if LINUX
+  ret = get_path_from_proc_maps ();
+  if (ret != NULL)
+    return ret;
+  ret = get_path_from_proc_exe ();
+  if (ret != NULL)
+    return ret;
+#endif
+#if WINDOWS
+  ret = get_path_from_module_filename ();
+  if (ret != NULL)
+    return ret;
+#endif
+#if DARWIN
+  ret = get_path_from_dyld_image ();
+  if (ret != NULL)
+    return ret;
+  ret = get_path_from_NSGetExecutablePath ();
+  if (ret != NULL)
+    return ret;
+#endif
+  ret = get_path_from_PATH ();
+  if (ret != NULL)
+    return ret;
+  /* other attempts here */
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+              _
+              ("Could not determine installation path for %s.  Set `%s' 
environment variable.\n"),
+             "gnunet-gtk",
+              "GNUNET_GTK_PREFIX");
+  return NULL;
+}
+
+/*
+ * @brief get the path to current app's bin/
+ * @author Milan
+ *
+ * @return a pointer to the executable path, or NULL on error
+ */
+static char *
+os_get_exec_path ()
+{
+  char *ret;
+
+  ret = NULL;
+#if LINUX
+  ret = get_path_from_proc_exe ();
+  if (ret != NULL)
+    return ret;
+#endif
+#if WINDOWS
+  ret = get_path_from_module_filename ();
+  if (ret != NULL)
+    return ret;
+#endif
+#if DARWIN
+  ret = get_path_from_NSGetExecutablePath ();
+  if (ret != NULL)
+    return ret;
+#endif
+  /* other attempts here */
+  return ret;
+}
+
+
+
+/**
+ * @brief get the path to a specific GNUnet installation directory or,
+ * with GNUNET_IPK_SELF_PREFIX, the current running apps installation directory
+ * @author Milan
+ * @return a pointer to the dir path (to be freed by the caller)
+ */
+char *
+GNUNET_GTK_installation_get_path (enum GNUNET_OS_InstallationPathKind dirkind)
+{
+  size_t n;
+  const char *dirname;
+  char *execpath = NULL;
+  char *tmp;
+  int isbasedir;
+
+  /* if wanted, try to get the current app's bin/ */
+  if (dirkind == GNUNET_OS_IPK_SELF_PREFIX)
+    execpath = os_get_exec_path ();
+
+  /* try to get GNUnet's bin/ or lib/, or if previous was unsuccessful some
+   * guess for the current app */
+  if (execpath == NULL)
+    execpath = os_get_gnunet_path ();
+
+  if (execpath == NULL)
+    return NULL;
+
+  n = strlen (execpath);
+  if (n == 0)
+    {
+      /* should never happen, but better safe than sorry */
+      GNUNET_free (execpath);
+      return NULL;
+    }
+  /* remove filename itself */
+  while ((n > 1) && (execpath[n - 1] == DIR_SEPARATOR))
+    execpath[--n] = '\0';
+
+  isbasedir = 1;
+  if ((n > 5) &&
+      ((0 == strcasecmp (&execpath[n - 5], "lib32")) ||
+       (0 == strcasecmp (&execpath[n - 5], "lib64"))))
+    {
+      if (dirkind != GNUNET_OS_IPK_LIBDIR)
+        {
+          /* strip '/lib32' or '/lib64' */
+          execpath[n - 5] = '\0';
+          n -= 5;
+        }
+      else
+        isbasedir = 0;
+    }
+  else if ((n > 3) &&
+           ((0 == strcasecmp (&execpath[n - 3], "bin")) ||
+            (0 == strcasecmp (&execpath[n - 3], "lib"))))
+    {
+      /* strip '/bin' or '/lib' */
+      execpath[n - 3] = '\0';
+      n -= 3;
+    }
+  /* in case this was a directory named foo-bin, remove "foo-" */
+  while ((n > 1) && (execpath[n - 1] == DIR_SEPARATOR))
+    execpath[--n] = '\0';
+  switch (dirkind)
+    {
+    case GNUNET_OS_IPK_PREFIX:
+    case GNUNET_OS_IPK_SELF_PREFIX:
+      dirname = DIR_SEPARATOR_STR;
+      break;
+    case GNUNET_OS_IPK_BINDIR:
+      dirname = DIR_SEPARATOR_STR "bin" DIR_SEPARATOR_STR;
+      break;
+    case GNUNET_OS_IPK_LIBDIR:
+      if (isbasedir)
+        dirname =
+          DIR_SEPARATOR_STR "lib" DIR_SEPARATOR_STR "gnunet-gtk"
+          DIR_SEPARATOR_STR;
+      else
+        dirname = DIR_SEPARATOR_STR "gnunet-gtk" DIR_SEPARATOR_STR;
+      break;
+    case GNUNET_OS_IPK_DATADIR:
+      dirname =
+        DIR_SEPARATOR_STR "share" DIR_SEPARATOR_STR "gnunet-gtk"
+        DIR_SEPARATOR_STR;
+      break;
+    case GNUNET_OS_IPK_ICONDIR:
+      dirname =
+        DIR_SEPARATOR_STR "share" DIR_SEPARATOR_STR "icons" DIR_SEPARATOR_STR;
+      break;
+   case GNUNET_OS_IPK_LOCALEDIR:
+      dirname =
+        DIR_SEPARATOR_STR "share" DIR_SEPARATOR_STR "locale"
+        DIR_SEPARATOR_STR;
+      break;
+    default:
+      GNUNET_free (execpath);
+      return NULL;
+    }
+  tmp = GNUNET_malloc (strlen (execpath) + strlen (dirname) + 1);
+  sprintf (tmp, "%s%s", execpath, dirname);
+  GNUNET_free (execpath);
+  return tmp;
+}
+
+/* end of os_installation.c */




reply via email to

[Prev in Thread] Current Thread [Next in Thread]