[Top][All Lists]
[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 */
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r16520 - in gnunet-gtk/src: . include lib,
gnunet <=