diff options
author | Christian Grothoff <christian@grothoff.org> | 2011-08-15 12:17:25 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2011-08-15 12:17:25 +0000 |
commit | 3e6963bdcf7ebc28bcae5bce1e2544d19f491657 (patch) | |
tree | b645cb6c94cce4e992416230e644052fee07893d | |
parent | bcf7ddfdbd225608e84b892dd1a970400ba2371e (diff) | |
download | gnunet-gtk-3e6963bdcf7ebc28bcae5bce1e2544d19f491657.tar.gz gnunet-gtk-3e6963bdcf7ebc28bcae5bce1e2544d19f491657.zip |
draft for new libgnunetgtk
-rw-r--r-- | src/include/Makefile.am | 6 | ||||
-rw-r--r-- | src/include/gnunet_gtk.h | 154 | ||||
-rw-r--r-- | src/lib/Makefile.am | 22 | ||||
-rw-r--r-- | src/lib/about.c | 53 | ||||
-rw-r--r-- | src/lib/eventloop.c | 809 | ||||
-rw-r--r-- | src/lib/glade.c | 85 | ||||
-rw-r--r-- | src/lib/nls.c | 58 | ||||
-rw-r--r-- | src/lib/os_installation.c | 435 |
8 files changed, 1622 insertions, 0 deletions
diff --git a/src/include/Makefile.am b/src/include/Makefile.am new file mode 100644 index 00000000..ef58f075 --- /dev/null +++ b/src/include/Makefile.am | |||
@@ -0,0 +1,6 @@ | |||
1 | SUBDIRS = . | ||
2 | |||
3 | gnunetgtkincludedir = $(includedir)/gnunet | ||
4 | |||
5 | gnunetgtkinclude_HEADERS = \ | ||
6 | gnunet_gtk.h | ||
diff --git a/src/include/gnunet_gtk.h b/src/include/gnunet_gtk.h new file mode 100644 index 00000000..4403ab4b --- /dev/null +++ b/src/include/gnunet_gtk.h | |||
@@ -0,0 +1,154 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2011 Christian Grothoff (and other contributing authors) | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 2, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file src/include/gnunet_gtk.h | ||
23 | * @brief Helper library for Gtk user interfaces to GNUnet | ||
24 | * @author Christian Grothoff | ||
25 | */ | ||
26 | #ifndef GNUNET_GTK_H | ||
27 | #define GNUNET_GTK_H | ||
28 | |||
29 | #ifndef HAVE_USED_CONFIG_H | ||
30 | #define HAVE_USED_CONFIG_H | ||
31 | #if HAVE_CONFIG_H | ||
32 | #include "gnunet_gtk_config.h" | ||
33 | #endif | ||
34 | #endif | ||
35 | |||
36 | #include <gnunet/platform.h> | ||
37 | #include <gnunet/gnunet_util_lib.h> | ||
38 | #include <gnunet/gnunet_fs_service.h> | ||
39 | #include <extractor.h> | ||
40 | #include <gladeui/glade.h> | ||
41 | #include <gtk/gtk.h> | ||
42 | |||
43 | |||
44 | /** | ||
45 | * Initialize natural language support. | ||
46 | */ | ||
47 | void | ||
48 | GNUNET_GTK_setup_nls (void); | ||
49 | |||
50 | |||
51 | /** | ||
52 | * Get the name of the directory where all of our package | ||
53 | * data is stored ($PREFIX/share/) | ||
54 | * | ||
55 | * @return name of the data directory | ||
56 | */ | ||
57 | const char * | ||
58 | GNUNET_GTK_get_data_dir (void); | ||
59 | |||
60 | |||
61 | /** | ||
62 | * @brief get the path to a specific GNUnet installation directory or, | ||
63 | * with GNUNET_IPK_SELF_PREFIX, the current running apps installation directory | ||
64 | * @author Milan | ||
65 | * @return a pointer to the dir path (to be freed by the caller) | ||
66 | */ | ||
67 | char * | ||
68 | GNUNET_GTK_installation_get_path (enum GNUNET_OS_InstallationPathKind dirkind); | ||
69 | |||
70 | |||
71 | /** | ||
72 | * Create an initialize a new builder based on the GNUnet-GTK glade | ||
73 | * file. | ||
74 | * | ||
75 | * @param filename name of the resource file to load | ||
76 | * @return NULL on error | ||
77 | */ | ||
78 | GtkBuilder * | ||
79 | GNUNET_GTK_get_new_builder (const char *filename); | ||
80 | |||
81 | |||
82 | /** | ||
83 | * This displays an about dialog. | ||
84 | * | ||
85 | * @param dialogfile name of the glade file containing the dialog | ||
86 | * @param dialogname name of the about dialog in the file | ||
87 | */ | ||
88 | void | ||
89 | GNUNET_GTK_display_about (const char *dialogfile, | ||
90 | const char *dialogname); | ||
91 | |||
92 | |||
93 | /** | ||
94 | * Handle for our main loop. | ||
95 | */ | ||
96 | struct GNUNET_GTK_MainLoop; | ||
97 | |||
98 | |||
99 | /** | ||
100 | * Initialize the main loop. | ||
101 | * | ||
102 | * @param binary_name binary name | ||
103 | * @param binary_help help text for the binary | ||
104 | * @param argc number of command line options | ||
105 | * @param argv command line options | ||
106 | * @param options allowed command line options | ||
107 | * @param main_window_file glade file for the main window | ||
108 | * @param main_task first task to run, closure will be set to the 'struct GNUNET_GTK_MainLoop' | ||
109 | * @return GNUNET_OK on success, GNUNET_SYSERR on error (i.e. bad command-line options, etc) | ||
110 | */ | ||
111 | int | ||
112 | GNUNET_GTK_main_loop_start (const char *binary_name, | ||
113 | const char *binary_help, | ||
114 | int argc, | ||
115 | char *const*argv, | ||
116 | struct GNUNET_GETOPT_CommandLineOption *options, | ||
117 | const char *main_window_file, | ||
118 | GNUNET_SCHEDULER_Task main_task); | ||
119 | |||
120 | |||
121 | /** | ||
122 | * Get an object from the main window. | ||
123 | * | ||
124 | * @param ml handle to the main loop | ||
125 | * @param name name of the object | ||
126 | * @return NULL on error, otherwise the object | ||
127 | */ | ||
128 | GObject * | ||
129 | GNUNET_GTK_main_loop_get_object (struct GNUNET_GTK_MainLoop *ml, | ||
130 | const char *name); | ||
131 | |||
132 | |||
133 | /** | ||
134 | * Get the configuration. | ||
135 | * | ||
136 | * @param ml handle to the main loop | ||
137 | * @return handle to the configuration, never NULL | ||
138 | */ | ||
139 | const struct GNUNET_CONFIGURATION_Handle * | ||
140 | GNUNET_GTK_main_loop_get_configuration (struct GNUNET_GTK_MainLoop *ml); | ||
141 | |||
142 | |||
143 | /** | ||
144 | * Trigger shutdown of the GUI and exit the main loop. | ||
145 | * | ||
146 | * @param ml handle to the main loop | ||
147 | */ | ||
148 | void | ||
149 | GNUNET_GTK_main_loop_quit (struct GNUNET_GTK_MainLoop *ml); | ||
150 | |||
151 | |||
152 | |||
153 | #endif | ||
154 | /* end of gnunet_gtk.h */ | ||
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am new file mode 100644 index 00000000..6a87dc4e --- /dev/null +++ b/src/lib/Makefile.am | |||
@@ -0,0 +1,22 @@ | |||
1 | INCLUDES = \ | ||
2 | -I$(top_srcdir)/ \ | ||
3 | -I$(top_srcdir)/src/include \ | ||
4 | @GTK_CFLAGS@ \ | ||
5 | @GNUNET_CFLAGS@ \ | ||
6 | @GLADE_CFLAGS@ | ||
7 | |||
8 | if MINGW | ||
9 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
10 | endif | ||
11 | |||
12 | lib_LTLIBRARIES = libgnunetgtk.la | ||
13 | |||
14 | libgnunetgtk_la_SOURCES = \ | ||
15 | eventloop.c \ | ||
16 | glade.c \ | ||
17 | os_installation.c \ | ||
18 | nls.c \ | ||
19 | about.c | ||
20 | libgnunetgtk_la_LIBADD = \ | ||
21 | -lgnunetutil $(XLIB) | ||
22 | |||
diff --git a/src/lib/about.c b/src/lib/about.c new file mode 100644 index 00000000..e75e11dc --- /dev/null +++ b/src/lib/about.c | |||
@@ -0,0 +1,53 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | (C) 2005, 2006, 2010, 2011 Christian Grothoff (and other contributing authors) | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 2, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file src/lib/about.c | ||
23 | * @brief code to display an about dialog | ||
24 | * @author Christian Grothoff | ||
25 | * @author Igor Wronsky | ||
26 | */ | ||
27 | #include "gnunet_gtk.h" | ||
28 | |||
29 | /** | ||
30 | * This displays an about dialog. | ||
31 | * | ||
32 | * @param dialogfile name of the glade file containing the dialog | ||
33 | * @param dialogname name of the about dialog in the file | ||
34 | */ | ||
35 | void | ||
36 | GNUNET_GTK_display_about (const char *dialogfile, | ||
37 | const char *dialogname) | ||
38 | { | ||
39 | GtkBuilder *builder; | ||
40 | GtkWidget *ad; | ||
41 | |||
42 | builder = GNUNET_GTK_get_new_builder (dialogfile); | ||
43 | if (builder == NULL) | ||
44 | return; | ||
45 | ad = GTK_WIDGET (gtk_builder_get_object (builder, | ||
46 | dialogname)); | ||
47 | gtk_dialog_run (GTK_DIALOG (ad)); | ||
48 | gtk_widget_destroy (ad); | ||
49 | g_object_unref (G_OBJECT (builder)); | ||
50 | } | ||
51 | |||
52 | |||
53 | /* end of about.c */ | ||
diff --git a/src/lib/eventloop.c b/src/lib/eventloop.c new file mode 100644 index 00000000..7eb7e060 --- /dev/null +++ b/src/lib/eventloop.c | |||
@@ -0,0 +1,809 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2010, 2011 Christian Grothoff (and other contributing authors) | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 2, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file src/lib/eventloop.c | ||
23 | * @brief code for merging GNUnet scheduler and Gtk Main Loop event loops | ||
24 | * @author Christian Grothoff | ||
25 | */ | ||
26 | #include "gnunet_gtk.h" | ||
27 | |||
28 | |||
29 | /** | ||
30 | * Main context for our event loop. | ||
31 | */ | ||
32 | struct GNUNET_GTK_MainLoop | ||
33 | { | ||
34 | |||
35 | /** | ||
36 | * Our configuration. | ||
37 | */ | ||
38 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
39 | |||
40 | /** | ||
41 | * Name of the glade file for the main window | ||
42 | */ | ||
43 | const char *main_window_file; | ||
44 | |||
45 | /** | ||
46 | * Initial task to run to setup the system. | ||
47 | */ | ||
48 | GNUNET_SCHEDULER_Task main_task; | ||
49 | |||
50 | /** | ||
51 | * Builder for the main window. | ||
52 | */ | ||
53 | GtkBuilder *builder; | ||
54 | |||
55 | /** | ||
56 | * Gib's Main loop. | ||
57 | */ | ||
58 | GMainLoop *gml; | ||
59 | |||
60 | /** | ||
61 | * GTK's main context. | ||
62 | */ | ||
63 | GMainContext *gmc; | ||
64 | |||
65 | /** | ||
66 | * Read set. | ||
67 | */ | ||
68 | struct GNUNET_NETWORK_FDSet *rs; | ||
69 | |||
70 | /** | ||
71 | * Write set. | ||
72 | */ | ||
73 | struct GNUNET_NETWORK_FDSet *ws; | ||
74 | |||
75 | /** | ||
76 | * Recycled array of polling descriptors. | ||
77 | */ | ||
78 | GPollFD *cached_poll_array; | ||
79 | |||
80 | /** | ||
81 | * Size of the 'cached_poll_array'. | ||
82 | */ | ||
83 | guint cached_poll_array_size; | ||
84 | |||
85 | /** | ||
86 | * Return value from last g_main_context_query call. | ||
87 | */ | ||
88 | guint poll_array_active; | ||
89 | |||
90 | /** | ||
91 | * Maximum GTK priority. | ||
92 | */ | ||
93 | gint max_priority; | ||
94 | |||
95 | |||
96 | #if WINDOWS | ||
97 | /** | ||
98 | * Array to hold pipe handles during a select() call | ||
99 | */ | ||
100 | struct GNUNET_DISK_FileHandle **read_array; | ||
101 | |||
102 | /** | ||
103 | * Allocated length of read_array | ||
104 | */ | ||
105 | int read_array_length; | ||
106 | |||
107 | /** | ||
108 | * Event to fire when a socket is ready for reading | ||
109 | */ | ||
110 | HANDLE hEventRead; | ||
111 | |||
112 | /** | ||
113 | * Event to fire when a socket is ready for writing | ||
114 | */ | ||
115 | HANDLE hEventWrite; | ||
116 | |||
117 | /** | ||
118 | * Event to fire when a socket had an error | ||
119 | */ | ||
120 | HANDLE hEventException; | ||
121 | |||
122 | /** | ||
123 | * Event that is permanently enabled and is used to signal a pipe | ||
124 | * that is ready for writing (asynchronous pipes are always writable) | ||
125 | */ | ||
126 | HANDLE hEventPipeWrite; | ||
127 | |||
128 | /** | ||
129 | * Event that is permanently enabled and is used to signal a pipe | ||
130 | * that is ready for reading (used to wake up early on a pipe that | ||
131 | * is known to be readable) | ||
132 | */ | ||
133 | HANDLE hEventReadReady; | ||
134 | |||
135 | /** | ||
136 | * A list to hold file handles that are ready for reading | ||
137 | */ | ||
138 | struct GNUNET_CONTAINER_SList *handles_read; | ||
139 | |||
140 | /** | ||
141 | * A list to hold file handles that are ready for writing | ||
142 | */ | ||
143 | struct GNUNET_CONTAINER_SList *handles_write; | ||
144 | |||
145 | /** | ||
146 | * A list to hold file handles that are broken | ||
147 | */ | ||
148 | struct GNUNET_CONTAINER_SList *handles_except; | ||
149 | #endif | ||
150 | |||
151 | }; | ||
152 | |||
153 | |||
154 | /** | ||
155 | * Get the configuration. | ||
156 | * | ||
157 | * @param ml handle to the main loop | ||
158 | * @return handle to the configuration, never NULL | ||
159 | */ | ||
160 | const struct GNUNET_CONFIGURATION_Handle * | ||
161 | GNUNET_GTK_main_loop_get_configuration (struct GNUNET_GTK_MainLoop *ml) | ||
162 | { | ||
163 | return ml->cfg; | ||
164 | } | ||
165 | |||
166 | |||
167 | /** | ||
168 | * Trigger shutdown of the GUI and exit the main loop. | ||
169 | * | ||
170 | * @param ml handle to the main loop | ||
171 | */ | ||
172 | void | ||
173 | GNUNET_GTK_main_loop_quit (struct GNUNET_GTK_MainLoop *ml) | ||
174 | { | ||
175 | g_main_loop_quit (ml->gml); | ||
176 | } | ||
177 | |||
178 | |||
179 | /** | ||
180 | * Get an object from the main window. | ||
181 | * | ||
182 | * @param ml handle to the main loop | ||
183 | * @param name name of the object | ||
184 | * @return NULL on error, otherwise the object | ||
185 | */ | ||
186 | GObject * | ||
187 | GNUNET_GTK_main_loop_get_object (struct GNUNET_GTK_MainLoop *ml, | ||
188 | const char *name) | ||
189 | { | ||
190 | return gtk_builder_get_object (ml->builder, name); | ||
191 | } | ||
192 | |||
193 | |||
194 | /** | ||
195 | * Task to run Gtk events (within a GNUnet scheduler task). | ||
196 | * | ||
197 | * @param cls the main loop handle | ||
198 | * @param tc scheduler context | ||
199 | */ | ||
200 | static void | ||
201 | gnunet_gtk_dispatch_task (void *cls, | ||
202 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
203 | { | ||
204 | struct GNUNET_GTK_MainLoop *ml = cls; | ||
205 | g_main_context_dispatch (ml->gmc); | ||
206 | } | ||
207 | |||
208 | |||
209 | #ifndef FD_COPY | ||
210 | #define FD_COPY(s, d) (memcpy ((d), (s), sizeof (fd_set))) | ||
211 | #endif | ||
212 | |||
213 | /** | ||
214 | * Replacement for the GNUnet scheduler's "select" that integrates the | ||
215 | * Gtk event loop. We merge Gtk's events with those from GNUnet's | ||
216 | * scheduler and then use 'g_poll' on both. Then we process the Gtk | ||
217 | * events (by adding a task to do so to the GNUnet scheduler), and, if | ||
218 | * applicable, return the GNUnet-scheduler events back to GNUnet. | ||
219 | * | ||
220 | * @param cls the 'struct GNUNET_GTK_MainLoop' | ||
221 | * @param rfds set of sockets to be checked for readability | ||
222 | * @param wfds set of sockets to be checked for writability | ||
223 | * @param efds set of sockets to be checked for exceptions | ||
224 | * @param timeout relative value when to return | ||
225 | * @return number of selected sockets, GNUNET_SYSERR on error | ||
226 | */ | ||
227 | static int | ||
228 | gnunet_gtk_select (void *cls, | ||
229 | struct GNUNET_NETWORK_FDSet *rfds, | ||
230 | struct GNUNET_NETWORK_FDSet *wfds, | ||
231 | struct GNUNET_NETWORK_FDSet *efds, | ||
232 | const struct GNUNET_TIME_Relative timeout) | ||
233 | { | ||
234 | struct GNUNET_GTK_MainLoop *ml = cls; | ||
235 | int max_nfds; | ||
236 | gint poll_result; | ||
237 | |||
238 | GPollFD *gfds; | ||
239 | gint delay; | ||
240 | |||
241 | guint i; | ||
242 | guint fd_counter = 0; | ||
243 | |||
244 | guint allocated_nfds, need_gfds; | ||
245 | |||
246 | fd_set aread, awrite, aexcept; | ||
247 | int pre_ret = 0; | ||
248 | int result = 0; | ||
249 | int socks = 0; | ||
250 | int sock_read = 0, sock_write = 0, sock_err = 0; | ||
251 | |||
252 | #if WINDOWS | ||
253 | int always_ready_write_fd = -1; | ||
254 | |||
255 | int select_ret = 0; | ||
256 | |||
257 | int read_handles = 0; | ||
258 | DWORD waitstatus; | ||
259 | #endif | ||
260 | |||
261 | if (TRUE != g_main_loop_is_running (ml->gml)) | ||
262 | return GNUNET_NETWORK_socket_select (rfds, wfds, efds, timeout); | ||
263 | |||
264 | FD_ZERO (&aread); | ||
265 | FD_ZERO (&awrite); | ||
266 | FD_ZERO (&aexcept); | ||
267 | if (rfds) | ||
268 | FD_COPY (&rfds->sds, &aread); | ||
269 | if (wfds) | ||
270 | FD_COPY (&wfds->sds, &awrite); | ||
271 | if (efds) | ||
272 | FD_COPY (&efds->sds, &aexcept); | ||
273 | |||
274 | #if WINDOWS | ||
275 | ResetEvent (ml->hEventRead); | ||
276 | ResetEvent (ml->hEventWrite); | ||
277 | ResetEvent (ml->hEventException); | ||
278 | |||
279 | GNUNET_CONTAINER_slist_clear (ml->handles_read); | ||
280 | GNUNET_CONTAINER_slist_clear (ml->handles_write); | ||
281 | GNUNET_CONTAINER_slist_clear (ml->handles_except); | ||
282 | #endif | ||
283 | |||
284 | |||
285 | if (rfds != NULL) | ||
286 | max_nfds = rfds->nsds; | ||
287 | else | ||
288 | max_nfds = -1; | ||
289 | if (wfds != NULL && max_nfds < wfds->nsds) | ||
290 | max_nfds = wfds->nsds; | ||
291 | if (efds != NULL && max_nfds < efds->nsds) | ||
292 | max_nfds = efds->nsds; | ||
293 | |||
294 | allocated_nfds = ml->cached_poll_array_size; | ||
295 | gfds = ml->cached_poll_array; | ||
296 | if (allocated_nfds == 0) | ||
297 | { | ||
298 | /* TODO: get some statistics, find the maximum number of fds ever | ||
299 | * polled during normal gnunet-gtk operation, and set this to that number. | ||
300 | */ | ||
301 | ml->cached_poll_array = gfds = g_new (GPollFD, 30); | ||
302 | ml->cached_poll_array_size = allocated_nfds = 30; | ||
303 | } | ||
304 | |||
305 | while (1) | ||
306 | { | ||
307 | fd_counter = 0; | ||
308 | #if !WINDOWS | ||
309 | gboolean need_realloc = FALSE; | ||
310 | for (i = 0; !need_realloc && i < max_nfds; i += 1) | ||
311 | { | ||
312 | int isset[3]; | ||
313 | |||
314 | isset[0] = (rfds == NULL) ? 0 : FD_ISSET (i, &rfds->sds); | ||
315 | isset[1] = (wfds == NULL) ? 0 : FD_ISSET (i, &wfds->sds); | ||
316 | isset[2] = (efds == NULL) ? 0 : FD_ISSET (i, &efds->sds); | ||
317 | if (!isset[0] && !isset[1] && !isset[2]) | ||
318 | continue; | ||
319 | if (fd_counter >= allocated_nfds) | ||
320 | { | ||
321 | need_realloc = TRUE; | ||
322 | break; | ||
323 | } | ||
324 | gfds[fd_counter].fd = i; | ||
325 | gfds[fd_counter].events = (isset[0] ? G_IO_IN | G_IO_HUP | G_IO_ERR : 0) | ||
326 | | (isset[1] ? G_IO_OUT | G_IO_ERR : 0) | (isset[2] ? G_IO_ERR : 0); | ||
327 | fd_counter += 1; | ||
328 | } | ||
329 | if (need_realloc) | ||
330 | { | ||
331 | ml->cached_poll_array = gfds = g_renew (GPollFD, gfds, ml->cached_poll_array_size * 2); | ||
332 | ml->cached_poll_array_size = allocated_nfds = ml->cached_poll_array_size * 2; | ||
333 | fd_counter = 0; | ||
334 | need_realloc = FALSE; | ||
335 | } | ||
336 | else | ||
337 | break; | ||
338 | #else | ||
339 | struct GNUNET_CONTAINER_SList_Iterator *t; | ||
340 | /* We might overshoot a little, but that won't hurt very much */ | ||
341 | int need_nfds = (rfds->sds.fd_count + rfds->sds.fd_count + rfds->sds.fd_count > 0 ? 3 : 0) | ||
342 | + (rfds == NULL ? 0 : GNUNET_CONTAINER_slist_count (rfds->handles)) | ||
343 | + (wfds == NULL ? 0 : 1) | ||
344 | + 1; | ||
345 | if (need_nfds >= allocated_nfds) | ||
346 | { | ||
347 | /* Since there are also gmainloop's own fds, just need_nfds won't be | ||
348 | * enough, so make it twice as long. | ||
349 | */ | ||
350 | ml->cached_poll_array = gfds = g_renew (GPollFD, gfds, need_nfds * 2); | ||
351 | ml->cached_poll_array_size = allocated_nfds = need_nfds * 2; | ||
352 | } | ||
353 | if (ml->read_array_length < GNUNET_CONTAINER_slist_count (rfds->handles)) | ||
354 | { | ||
355 | ml->read_array = GNUNET_realloc (ml->read_array, GNUNET_CONTAINER_slist_count (rfds->handles) * sizeof (struct GNUNET_DISK_FileHandle *)); | ||
356 | ml->read_array_length = GNUNET_CONTAINER_slist_count (rfds->handles); | ||
357 | } | ||
358 | if (rfds != NULL) | ||
359 | { | ||
360 | for (t = GNUNET_CONTAINER_slist_begin (rfds->handles), i = 0; | ||
361 | GNUNET_CONTAINER_slist_end (t) != GNUNET_YES; | ||
362 | GNUNET_CONTAINER_slist_next (t), i += 1) | ||
363 | { | ||
364 | struct GNUNET_DISK_FileHandle *fh; | ||
365 | fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (t, NULL); | ||
366 | if (fh->type == GNUNET_PIPE) | ||
367 | { | ||
368 | if (!ReadFile (fh->h, NULL, 0, NULL, fh->oOverlapRead)) | ||
369 | { | ||
370 | DWORD error_code = GetLastError(); | ||
371 | if (error_code == ERROR_IO_PENDING) | ||
372 | { | ||
373 | #if DEBUG_NETWORK | ||
374 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding the pipe's 0x%x overlapped event to the array as %d\n", fh->h, nhandles); | ||
375 | #endif | ||
376 | gfds[fd_counter].fd = (intptr_t) fh->oOverlapRead->hEvent; | ||
377 | /* On W32 .events makes no sense - g_poll will just OR its | ||
378 | * contents into .revents when the .fd event fires. | ||
379 | * So we'll use it in the way that suits us the best. | ||
380 | */ | ||
381 | gfds[fd_counter].events = G_IO_IN; | ||
382 | fd_counter += 1; | ||
383 | ml->read_array[read_handles] = fh; | ||
384 | read_handles += 1; | ||
385 | } | ||
386 | else | ||
387 | { | ||
388 | gfds[fd_counter].fd = (intptr_t) ml->hEventReadReady; | ||
389 | gfds[fd_counter].events = G_IO_HUP; | ||
390 | fd_counter += 1; | ||
391 | ml->read_array[read_handles] = fh; | ||
392 | read_handles += 1; | ||
393 | } | ||
394 | } | ||
395 | else | ||
396 | { | ||
397 | #if DEBUG_NETWORK | ||
398 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding the read ready event to the array as %d\n", nhandles); | ||
399 | #endif | ||
400 | gfds[fd_counter].fd = (intptr_t) ml->hEventReadReady; | ||
401 | gfds[fd_counter].events = G_IO_IN; | ||
402 | fd_counter += 1; | ||
403 | ml->read_array[read_handles] = fh; | ||
404 | read_handles += 1; | ||
405 | } | ||
406 | } | ||
407 | else | ||
408 | { | ||
409 | GNUNET_CONTAINER_slist_add (ml->handles_read, | ||
410 | GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, | ||
411 | fh, sizeof (struct GNUNET_DISK_FileHandle)); | ||
412 | pre_ret += 1; | ||
413 | } | ||
414 | } | ||
415 | } | ||
416 | if (wfds != NULL && GNUNET_CONTAINER_slist_count (wfds->handles) > 0) | ||
417 | { | ||
418 | gfds[fd_counter].fd = (intptr_t) ml->hEventPipeWrite; | ||
419 | gfds[fd_counter].events = G_IO_OUT; | ||
420 | always_ready_write_fd = fd_counter; | ||
421 | fd_counter += 1; | ||
422 | } | ||
423 | if (efds != NULL) | ||
424 | { | ||
425 | for (t = GNUNET_CONTAINER_slist_begin (efds->handles), i = 0; | ||
426 | GNUNET_CONTAINER_slist_end (t) != GNUNET_YES; | ||
427 | GNUNET_CONTAINER_slist_next (t), i += 1) | ||
428 | { | ||
429 | struct GNUNET_DISK_FileHandle *fh; | ||
430 | DWORD dwBytes; | ||
431 | fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (t, NULL); | ||
432 | if (fh->type == GNUNET_PIPE) | ||
433 | { | ||
434 | if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL)) | ||
435 | { | ||
436 | GNUNET_CONTAINER_slist_add (ml->handles_except, | ||
437 | GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, | ||
438 | fh, sizeof (struct GNUNET_DISK_FileHandle)); | ||
439 | pre_ret += 1; | ||
440 | } | ||
441 | } | ||
442 | } | ||
443 | } | ||
444 | GNUNET_CONTAINER_slist_iter_destroy (t); | ||
445 | |||
446 | if (rfds != NULL && rfds->sds.fd_count > 0) | ||
447 | { | ||
448 | #if DEBUG_NETWORK | ||
449 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding the socket read event to the array as %d\n", fd_counter); | ||
450 | #endif | ||
451 | gfds[fd_counter].fd = (intptr_t) ml->hEventRead; | ||
452 | gfds[fd_counter].events = G_IO_IN; | ||
453 | for (i = 0; i < rfds->sds.fd_count; i++) | ||
454 | WSAEventSelect (rfds->sds.fd_array[i], ml->hEventRead, FD_ACCEPT | FD_READ | FD_CLOSE); | ||
455 | fd_counter += 1; | ||
456 | sock_read = rfds->sds.fd_count; | ||
457 | } | ||
458 | if (wfds != NULL && wfds->sds.fd_count > 0) | ||
459 | { | ||
460 | int wakeup = 0; | ||
461 | #if DEBUG_NETWORK | ||
462 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding the socket write event to the array as %d\n", fd_counter); | ||
463 | #endif | ||
464 | gfds[fd_counter].fd = (intptr_t) ml->hEventWrite; | ||
465 | gfds[fd_counter].events = G_IO_OUT; | ||
466 | for (i = 0; i < wfds->sds.fd_count; i++) | ||
467 | { | ||
468 | DWORD error; | ||
469 | int status; | ||
470 | status = send (wfds->sds.fd_array[i], NULL, 0, 0); | ||
471 | error = GetLastError (); | ||
472 | #if DEBUG_NETWORK | ||
473 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "pre-send to the socket %d returned %d (%u)\n", i, status, error); | ||
474 | #endif | ||
475 | if (status == 0 || (error != WSAEWOULDBLOCK && error != WSAENOTCONN)) | ||
476 | wakeup = 1; | ||
477 | WSAEventSelect (wfds->sds.fd_array[i], ml->hEventWrite, FD_WRITE | FD_CONNECT | FD_CLOSE); | ||
478 | } | ||
479 | if (wakeup) | ||
480 | SetEvent (ml->hEventWrite); | ||
481 | fd_counter += 1; | ||
482 | sock_write = wfds->sds.fd_count; | ||
483 | } | ||
484 | if (efds != NULL && efds->sds.fd_count > 0) | ||
485 | { | ||
486 | #if DEBUG_NETWORK | ||
487 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding the socket error event to the array as %d\n", fd_counter); | ||
488 | #endif | ||
489 | gfds[fd_counter].fd = (intptr_t) ml->hEventException; | ||
490 | gfds[fd_counter].events = G_IO_ERR; | ||
491 | for (i = 0; i < efds->sds.fd_count; i++) | ||
492 | WSAEventSelect (efds->sds.fd_array[i], ml->hEventException, FD_OOB | FD_CLOSE); | ||
493 | fd_counter += 1; | ||
494 | sock_err = efds->sds.fd_count; | ||
495 | } | ||
496 | break; | ||
497 | #endif | ||
498 | } | ||
499 | socks = sock_read + sock_write + sock_err; | ||
500 | |||
501 | g_main_context_prepare (ml->gmc, &ml->max_priority); | ||
502 | while (allocated_nfds < (need_gfds = g_main_context_query (ml->gmc, | ||
503 | ml->max_priority, &delay, &gfds[fd_counter], allocated_nfds - fd_counter))) | ||
504 | { | ||
505 | ml->cached_poll_array = gfds = g_renew (GPollFD, gfds, allocated_nfds - fd_counter + need_gfds); | ||
506 | ml->cached_poll_array_size = allocated_nfds = allocated_nfds - fd_counter + need_gfds; | ||
507 | } | ||
508 | ml->poll_array_active = fd_counter + need_gfds; | ||
509 | |||
510 | if (timeout.rel_value != GNUNET_TIME_UNIT_FOREVER_REL.rel_value) | ||
511 | { | ||
512 | if (delay >= 0) | ||
513 | delay = MIN(timeout.rel_value / GNUNET_TIME_UNIT_MILLISECONDS.rel_value, delay); | ||
514 | else | ||
515 | delay = timeout.rel_value / GNUNET_TIME_UNIT_MILLISECONDS.rel_value; | ||
516 | } | ||
517 | |||
518 | if (pre_ret > 0) | ||
519 | { | ||
520 | #if DEBUG_NETWORK | ||
521 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "pre_ret is %d, setting delay to 0\n", pre_ret); | ||
522 | #endif | ||
523 | delay = 0; | ||
524 | } | ||
525 | |||
526 | #if DEBUG_NETWORK | ||
527 | 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); | ||
528 | #endif | ||
529 | |||
530 | poll_result = g_poll (gfds, fd_counter + need_gfds, delay); | ||
531 | |||
532 | #if DEBUG_NETWORK | ||
533 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "g_poll returned : %d\n", poll_result); | ||
534 | #endif | ||
535 | |||
536 | /* Take care of GUI events. | ||
537 | * Dispatching the events here will eventually crash the scheduler, must do this | ||
538 | * from within a task (currently we're not in a task, but in a select() call, remember) | ||
539 | * Startup reason is used to pass the scheduler sanity check. | ||
540 | */ | ||
541 | if (TRUE == g_main_context_check (ml->gmc, ml->max_priority, &gfds[fd_counter], need_gfds)) | ||
542 | GNUNET_SCHEDULER_add_continuation (gnunet_gtk_dispatch_task, ml, | ||
543 | GNUNET_SCHEDULER_REASON_STARTUP); | ||
544 | |||
545 | #if !WINDOWS | ||
546 | if (rfds) | ||
547 | GNUNET_NETWORK_fdset_zero (rfds); | ||
548 | if (wfds) | ||
549 | GNUNET_NETWORK_fdset_zero (wfds); | ||
550 | if (efds) | ||
551 | GNUNET_NETWORK_fdset_zero (efds); | ||
552 | for (i = 0; i < fd_counter; i++) | ||
553 | { | ||
554 | int set[3]; | ||
555 | if ((set[0] = FD_ISSET (gfds[i].fd, &aread))) | ||
556 | FD_SET (gfds[i].fd, &rfds->sds); | ||
557 | if ((set[1] = FD_ISSET (gfds[i].fd, &awrite))) | ||
558 | FD_SET (gfds[i].fd, &wfds->sds); | ||
559 | if ((set[2] = FD_ISSET (gfds[i].fd, &aexcept))) | ||
560 | FD_SET (gfds[i].fd, &efds->sds); | ||
561 | if (set[0] || set[1] || set[2]) | ||
562 | result += 1; | ||
563 | } | ||
564 | #else | ||
565 | if (socks > 0) | ||
566 | { | ||
567 | struct timeval tvslice; | ||
568 | tvslice.tv_sec = 0; | ||
569 | tvslice.tv_usec = 0; | ||
570 | select_ret = select (max_nfds, &aread, &awrite, &aexcept, &tvslice); | ||
571 | if (select_ret == -1) | ||
572 | select_ret = 0; | ||
573 | #if DEBUG_NETWORK | ||
574 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "select() returned %d\n", select_ret); | ||
575 | #endif | ||
576 | } | ||
577 | if (always_ready_write_fd >= 0 && gfds[always_ready_write_fd].revents & G_IO_OUT) | ||
578 | { | ||
579 | GNUNET_CONTAINER_slist_append (ml->handles_write, wfds->handles); | ||
580 | result += GNUNET_CONTAINER_slist_count (ml->handles_write); | ||
581 | #if DEBUG_NETWORK | ||
582 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Added write pipe\n"); | ||
583 | #endif | ||
584 | } | ||
585 | for (i = 0; i < read_handles; i++) | ||
586 | { | ||
587 | DWORD error; | ||
588 | BOOL bret; | ||
589 | if (!(gfds[i].revents & (G_IO_IN | G_IO_HUP | G_IO_ERR))) | ||
590 | continue; | ||
591 | SetLastError (0); | ||
592 | waitstatus = 0; | ||
593 | bret = PeekNamedPipe (ml->read_array[i]->h, NULL, 0, NULL, &waitstatus, NULL); | ||
594 | error = GetLastError (); | ||
595 | #if DEBUG_NETWORK | ||
596 | 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); | ||
597 | #endif | ||
598 | if (bret == 0 || (gfds[i].revents & G_IO_ERR)) | ||
599 | { | ||
600 | if (efds != NULL) | ||
601 | { | ||
602 | struct GNUNET_CONTAINER_SList_Iterator *t; | ||
603 | for (t = GNUNET_CONTAINER_slist_begin (efds->handles), i = 0; | ||
604 | GNUNET_CONTAINER_slist_end (t) != GNUNET_YES; | ||
605 | GNUNET_CONTAINER_slist_next (t), i += 1) | ||
606 | { | ||
607 | struct GNUNET_DISK_FileHandle *fh; | ||
608 | fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (t, NULL); | ||
609 | if (fh == ml->read_array[i]) | ||
610 | { | ||
611 | GNUNET_CONTAINER_slist_add (ml->handles_except, | ||
612 | GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, | ||
613 | fh, sizeof (struct GNUNET_DISK_FileHandle)); | ||
614 | break; | ||
615 | } | ||
616 | } | ||
617 | GNUNET_CONTAINER_slist_iter_destroy (t); | ||
618 | } | ||
619 | } | ||
620 | else if (waitstatus <= 0) | ||
621 | continue; | ||
622 | GNUNET_CONTAINER_slist_add (ml->handles_read, | ||
623 | GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, | ||
624 | ml->read_array[i], sizeof (struct GNUNET_DISK_FileHandle)); | ||
625 | result += 1; | ||
626 | #if DEBUG_NETWORK | ||
627 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n", ml->read_array[i], ml->read_array[i]->h); | ||
628 | #endif | ||
629 | } | ||
630 | waitstatus = WaitForSingleObject (ml->hEventWrite, 0); | ||
631 | #if DEBUG_NETWORK | ||
632 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Wait for the write event returned %d\n", waitstatus); | ||
633 | #endif | ||
634 | if (waitstatus == WAIT_OBJECT_0) | ||
635 | { | ||
636 | for (i = 0; i < wfds->sds.fd_count; i++) | ||
637 | { | ||
638 | DWORD error; | ||
639 | int status; | ||
640 | int so_error = 0; | ||
641 | int sizeof_so_error = sizeof (so_error); | ||
642 | int gso_result = getsockopt (wfds->sds.fd_array[i], SOL_SOCKET, SO_ERROR, (char *) &so_error, &sizeof_so_error); | ||
643 | status = send (wfds->sds.fd_array[i], NULL, 0, 0); | ||
644 | error = GetLastError (); | ||
645 | #if DEBUG_NETWORK | ||
646 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "send to the socket %d returned %d (%u)\n", i, status, error); | ||
647 | #endif | ||
648 | if (status == 0 | ||
649 | || (error != WSAEWOULDBLOCK && error != WSAENOTCONN) | ||
650 | || (status == -1 && gso_result == 0 && error == WSAENOTCONN && so_error == WSAECONNREFUSED)) | ||
651 | { | ||
652 | FD_SET (wfds->sds.fd_array[i], &awrite); | ||
653 | result += 1; | ||
654 | } | ||
655 | } | ||
656 | } | ||
657 | if (rfds) | ||
658 | { | ||
659 | struct GNUNET_CONTAINER_SList_Iterator *t; | ||
660 | for (i = 0; i < rfds->sds.fd_count; i++) | ||
661 | WSAEventSelect (rfds->sds.fd_array[i], ml->hEventRead, 0); | ||
662 | for (t = GNUNET_CONTAINER_slist_begin (rfds->handles); | ||
663 | GNUNET_CONTAINER_slist_end (t) != GNUNET_YES; | ||
664 | GNUNET_CONTAINER_slist_next (t)) | ||
665 | { | ||
666 | struct GNUNET_DISK_FileHandle *fh; | ||
667 | fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (t, NULL); | ||
668 | if (fh->type == GNUNET_PIPE) | ||
669 | CancelIo (fh->h); | ||
670 | } | ||
671 | GNUNET_CONTAINER_slist_iter_destroy (t); | ||
672 | GNUNET_NETWORK_fdset_zero (rfds); | ||
673 | if (select_ret != -1 && socks > 0) | ||
674 | GNUNET_NETWORK_fdset_copy_native (rfds, &aread, select_ret); | ||
675 | GNUNET_CONTAINER_slist_append (rfds->handles, ml->handles_read); | ||
676 | } | ||
677 | if (wfds) | ||
678 | { | ||
679 | for (i = 0; i < wfds->sds.fd_count; i++) | ||
680 | WSAEventSelect (wfds->sds.fd_array[i], ml->hEventWrite, 0); | ||
681 | GNUNET_NETWORK_fdset_zero (wfds); | ||
682 | if (select_ret != -1 && socks > 0) | ||
683 | GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, select_ret); | ||
684 | GNUNET_CONTAINER_slist_append (wfds->handles, ml->handles_write); | ||
685 | } | ||
686 | if (efds) | ||
687 | { | ||
688 | for (i = 0; i < efds->sds.fd_count; i++) | ||
689 | WSAEventSelect (efds->sds.fd_array[i], ml->hEventException, 0); | ||
690 | GNUNET_NETWORK_fdset_zero (efds); | ||
691 | if (select_ret != -1 && socks > 0) | ||
692 | GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, select_ret); | ||
693 | GNUNET_CONTAINER_slist_append (efds->handles, ml->handles_except); | ||
694 | result += GNUNET_CONTAINER_slist_count (ml->handles_except); | ||
695 | } | ||
696 | if (fd_counter > 0) | ||
697 | /* This is not accurate (select_ret counts write-ready sockets, | ||
698 | * and result does as well. Anything out there actually cares | ||
699 | * about this? | ||
700 | */ | ||
701 | return select_ret + result; | ||
702 | else | ||
703 | return 0; | ||
704 | #endif | ||
705 | return result; | ||
706 | } | ||
707 | |||
708 | |||
709 | /** | ||
710 | * Actual main function run right after GNUnet's scheduler | ||
711 | * is initialized. Initializes up GTK and Glade and starts the | ||
712 | * combined event loop. | ||
713 | * | ||
714 | * @param cls the 'struct GNUNET_GTK_MainLoop' | ||
715 | * @param args leftover command line arguments (go to gtk) | ||
716 | * @param cfgfile name of the configuration file | ||
717 | * @param cfg handle to the configuration | ||
718 | */ | ||
719 | static void | ||
720 | run_main_loop (void *cls, | ||
721 | char *const *args, | ||
722 | const char *cfgfile, | ||
723 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
724 | { | ||
725 | struct GNUNET_GTK_MainLoop *ml = cls; | ||
726 | int argc; | ||
727 | |||
728 | /* command-line processing for Gtk arguments */ | ||
729 | argc = 0; | ||
730 | while (args[argc] != NULL) argc++; | ||
731 | gtk_init (&argc, (char ***) &args); | ||
732 | |||
733 | /* setup main context */ | ||
734 | ml->builder = GNUNET_GTK_get_new_builder (ml->main_window_file); | ||
735 | if (ml->builder == NULL) | ||
736 | return; | ||
737 | ml->rs = GNUNET_NETWORK_fdset_create (); | ||
738 | ml->ws = GNUNET_NETWORK_fdset_create (); | ||
739 | ml->gml = g_main_loop_new (NULL, TRUE); | ||
740 | ml->gmc = g_main_loop_get_context (ml->gml); | ||
741 | ml->cfg = cfg; | ||
742 | #if WINDOWS | ||
743 | ml->hEventRead = CreateEvent (NULL, TRUE, FALSE, NULL); | ||
744 | ml->hEventReadReady = CreateEvent (NULL, TRUE, TRUE, NULL); | ||
745 | ml->hEventWrite = CreateEvent (NULL, TRUE, FALSE, NULL); | ||
746 | ml->hEventException = CreateEvent (NULL, TRUE, FALSE, NULL); | ||
747 | ml->hEventPipeWrite = CreateEvent (NULL, TRUE, TRUE, NULL); | ||
748 | ml->handles_read = GNUNET_CONTAINER_slist_create (); | ||
749 | ml->handles_write = GNUNET_CONTAINER_slist_create (); | ||
750 | ml->handles_except = GNUNET_CONTAINER_slist_create (); | ||
751 | ml->read_array = NULL; | ||
752 | ml->read_array_length = 0; | ||
753 | #endif | ||
754 | |||
755 | /* run main task of the application */ | ||
756 | GNUNET_SCHEDULER_add_continuation (ml->main_task, ml, | ||
757 | GNUNET_SCHEDULER_REASON_STARTUP); | ||
758 | |||
759 | /* start the Gtk event loop */ | ||
760 | GNUNET_assert (TRUE == g_main_context_acquire (ml->gmc)); | ||
761 | GNUNET_SCHEDULER_set_select (&gnunet_gtk_select, ml); | ||
762 | } | ||
763 | |||
764 | |||
765 | /** | ||
766 | * Initialize the main loop. | ||
767 | * | ||
768 | * @param binary_name binary name | ||
769 | * @param binary_help help text for the binary | ||
770 | * @param argc number of command line options | ||
771 | * @param argv command line options | ||
772 | * @param options allowed command line options | ||
773 | * @param main_window_file glade file for the main window | ||
774 | * @param main_task first task to run, closure will be set to the 'struct GNUNET_GTK_MainLoop' | ||
775 | * @return GNUNET_OK on success, GNUNET_SYSERR on error (i.e. bad command-line options, etc) | ||
776 | */ | ||
777 | int | ||
778 | GNUNET_GTK_main_loop_start (const char *binary_name, | ||
779 | const char *binary_help, | ||
780 | int argc, | ||
781 | char *const*argv, | ||
782 | struct GNUNET_GETOPT_CommandLineOption *options, | ||
783 | const char *main_window_file, | ||
784 | GNUNET_SCHEDULER_Task main_task) | ||
785 | { | ||
786 | struct GNUNET_GTK_MainLoop ml; | ||
787 | int ret; | ||
788 | |||
789 | ml.main_window_file = main_window_file; | ||
790 | ret = GNUNET_PROGRAM_run (argc, argv, | ||
791 | binary_name, | ||
792 | "GTK GUI for GNUnet", | ||
793 | options, | ||
794 | &run_main_loop, &ml); | ||
795 | if (NULL != ml.cached_poll_array) | ||
796 | g_free (ml.cached_poll_array); | ||
797 | if (NULL != ml.rs) | ||
798 | GNUNET_NETWORK_fdset_destroy (ml.rs); | ||
799 | if (NULL != ml.ws) | ||
800 | GNUNET_NETWORK_fdset_destroy (ml.ws); | ||
801 | if (NULL != ml.builder) | ||
802 | g_object_unref (G_OBJECT (ml.builder)); | ||
803 | if (NULL != ml.gml) | ||
804 | g_main_loop_unref (ml.gml); | ||
805 | return ret; | ||
806 | } | ||
807 | |||
808 | |||
809 | /* end of eventloop.c */ | ||
diff --git a/src/lib/glade.c b/src/lib/glade.c new file mode 100644 index 00000000..386a676b --- /dev/null +++ b/src/lib/glade.c | |||
@@ -0,0 +1,85 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2010 Christian Grothoff (and other contributing authors) | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 2, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file src/lib/glade.c | ||
23 | * @brief code for integration with glade | ||
24 | * @author Christian Grothoff | ||
25 | */ | ||
26 | #include "gnunet_gtk_config.h" | ||
27 | #include "gnunet_gtk.h" | ||
28 | |||
29 | |||
30 | /** | ||
31 | * Get the name of the directory where all of our package | ||
32 | * data is stored ($PREFIX/share/) | ||
33 | * | ||
34 | * @return name of the data directory | ||
35 | */ | ||
36 | const char * | ||
37 | GNUNET_GTK_get_data_dir () | ||
38 | { | ||
39 | static char *dd; | ||
40 | |||
41 | if (dd == NULL) | ||
42 | dd = GNUNET_GTK_installation_get_path (GNUNET_OS_IPK_DATADIR); | ||
43 | return dd; | ||
44 | } | ||
45 | |||
46 | |||
47 | /** | ||
48 | * Create an initialize a new builder based on the | ||
49 | * GNUnet-GTK glade file. | ||
50 | * | ||
51 | * @param filename name of the resource file to load | ||
52 | * @return NULL on error | ||
53 | */ | ||
54 | GtkBuilder * | ||
55 | GNUNET_GTK_get_new_builder (const char *filename) | ||
56 | { | ||
57 | char *glade_path; | ||
58 | GtkBuilder *ret; | ||
59 | GError *error; | ||
60 | |||
61 | ret = gtk_builder_new (); | ||
62 | gtk_builder_set_translation_domain (ret, "gnunet-gtk"); | ||
63 | GNUNET_asprintf (&glade_path, | ||
64 | "%s%s", | ||
65 | GNUNET_GTK_get_data_dir (), | ||
66 | filename); | ||
67 | error = NULL; | ||
68 | if (0 == gtk_builder_add_from_file (ret, glade_path, &error)) | ||
69 | { | ||
70 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
71 | _("Failed to load `%s': %s\n"), | ||
72 | glade_path, | ||
73 | error->message); | ||
74 | g_error_free (error); | ||
75 | GNUNET_free (glade_path); | ||
76 | return NULL; | ||
77 | } | ||
78 | gtk_builder_connect_signals (ret, NULL); | ||
79 | GNUNET_free (glade_path); | ||
80 | return ret; | ||
81 | } | ||
82 | |||
83 | |||
84 | |||
85 | /* end of glade.c */ | ||
diff --git a/src/lib/nls.c b/src/lib/nls.c new file mode 100644 index 00000000..96e44a99 --- /dev/null +++ b/src/lib/nls.c | |||
@@ -0,0 +1,58 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2010, 2011 Christian Grothoff (and other contributing authors) | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 2, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file src/lib/nls.c | ||
23 | * @brief natural language support | ||
24 | * @author Christian Grothoff | ||
25 | */ | ||
26 | #include "gnunet_gtk.h" | ||
27 | |||
28 | #if ENABLE_NLS | ||
29 | #include <locale.h> | ||
30 | #endif | ||
31 | |||
32 | |||
33 | /** | ||
34 | * Initialize GNU gettext for message translation. | ||
35 | */ | ||
36 | void | ||
37 | GNUNET_GTK_setup_nls () | ||
38 | { | ||
39 | #if ENABLE_NLS | ||
40 | char *path; | ||
41 | |||
42 | setlocale (LC_ALL, ""); | ||
43 | GNUNET_asprintf (&path, | ||
44 | "%s/%s/locale/", | ||
45 | GNUNET_GTK_get_data_dir (), | ||
46 | PACKAGE_NAME); | ||
47 | bindtextdomain ("gnunet-gtk", path); | ||
48 | textdomain ("gnunet-gtk"); | ||
49 | bind_textdomain_codeset ("GNUnet", "UTF-8"); | ||
50 | bind_textdomain_codeset ("gnunet-gtk", "UTF-8"); | ||
51 | GNUNET_free (path); | ||
52 | #else | ||
53 | fprintf (stderr, | ||
54 | "WARNING: gnunet-gtk was compiled without i18n support (did CFLAGS contain -Werror?).\n"); | ||
55 | #endif | ||
56 | } | ||
57 | |||
58 | /* end of nls.c */ | ||
diff --git a/src/lib/os_installation.c b/src/lib/os_installation.c new file mode 100644 index 00000000..9a884f27 --- /dev/null +++ b/src/lib/os_installation.c | |||
@@ -0,0 +1,435 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2006, 2010, 2011 Christian Grothoff (and other contributing authors) | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 2, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file src/lib/os_installation.c | ||
23 | * @brief get paths used by the program; this code is almost the | ||
24 | * same as src/util/os_installation.c in libgnunetutil; however, | ||
25 | * it contains sublte changes to detect the installation path | ||
26 | * of gnunet-gtk (which may be different from the path for | ||
27 | * GNUnet itself) and also needs to be replicated anyway since | ||
28 | * some of the methods try to find the location of the binary | ||
29 | * of the test-code itself, which would never yield the | ||
30 | * correct result for gnunet-gtk if the code lives in libgnunetutil. | ||
31 | * @author Milan | ||
32 | * @author Christian Grothoff | ||
33 | */ | ||
34 | #include "gnunet_gtk.h" | ||
35 | #if DARWIN | ||
36 | #include <mach-o/ldsyms.h> | ||
37 | #include <mach-o/dyld.h> | ||
38 | #endif | ||
39 | |||
40 | #if LINUX | ||
41 | /** | ||
42 | * Try to determine path by reading /proc/PID/exe | ||
43 | */ | ||
44 | static char * | ||
45 | get_path_from_proc_maps () | ||
46 | { | ||
47 | char fn[64]; | ||
48 | char line[1024]; | ||
49 | char dir[1024]; | ||
50 | FILE *f; | ||
51 | char *lgu; | ||
52 | |||
53 | GNUNET_snprintf (fn, | ||
54 | sizeof(fn), | ||
55 | "/proc/%u/maps", | ||
56 | getpid ()); | ||
57 | f = fopen (fn, "r"); | ||
58 | if (f == NULL) | ||
59 | return NULL; | ||
60 | while (NULL != fgets (line, sizeof(line), f)) | ||
61 | { | ||
62 | if ((1 == sscanf (line, | ||
63 | "%*x-%*x %*c%*c%*c%*c %*x %*2u:%*2u %*u%*[ ]%s", | ||
64 | dir)) && | ||
65 | (NULL != (lgu = strstr (dir, "gnunet-gtk")))) | ||
66 | { | ||
67 | lgu[0] = '\0'; | ||
68 | fclose (f); | ||
69 | return GNUNET_strdup (dir); | ||
70 | } | ||
71 | } | ||
72 | fclose (f); | ||
73 | return NULL; | ||
74 | } | ||
75 | |||
76 | /** | ||
77 | * Try to determine path by reading /proc/PID/exe | ||
78 | */ | ||
79 | static char * | ||
80 | get_path_from_proc_exe () | ||
81 | { | ||
82 | char fn[64]; | ||
83 | char lnk[1024]; | ||
84 | ssize_t size; | ||
85 | |||
86 | GNUNET_snprintf (fn, | ||
87 | sizeof(fn), "/proc/%u/exe", getpid ()); | ||
88 | size = readlink (fn, lnk, sizeof (lnk)-1); | ||
89 | if (size <= 0) | ||
90 | { | ||
91 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "readlink", fn); | ||
92 | return NULL; | ||
93 | } | ||
94 | GNUNET_assert (size < sizeof (lnk)); | ||
95 | lnk[size] = '\0'; | ||
96 | while ((lnk[size] != '/') && (size > 0)) | ||
97 | size--; | ||
98 | if ((size < 4) || (lnk[size - 4] != '/')) | ||
99 | { | ||
100 | /* not installed in "/bin/" -- binary path probably useless */ | ||
101 | return NULL; | ||
102 | } | ||
103 | lnk[size] = '\0'; | ||
104 | return GNUNET_strdup (lnk); | ||
105 | } | ||
106 | #endif | ||
107 | |||
108 | #if WINDOWS | ||
109 | /** | ||
110 | * Try to determine path with win32-specific function | ||
111 | */ | ||
112 | static char * | ||
113 | get_path_from_module_filename () | ||
114 | { | ||
115 | char path[4097]; | ||
116 | char *idx; | ||
117 | |||
118 | GetModuleFileName (NULL, path, sizeof(path)-1); | ||
119 | idx = path + strlen (path); | ||
120 | while ((idx > path) && (*idx != '\\') && (*idx != '/')) | ||
121 | idx--; | ||
122 | *idx = '\0'; | ||
123 | return GNUNET_strdup (path); | ||
124 | } | ||
125 | #endif | ||
126 | |||
127 | #if DARWIN | ||
128 | typedef int (*MyNSGetExecutablePathProto) (char *buf, size_t * bufsize); | ||
129 | |||
130 | static char * | ||
131 | get_path_from_NSGetExecutablePath () | ||
132 | { | ||
133 | static char zero = '\0'; | ||
134 | char *path; | ||
135 | size_t len; | ||
136 | MyNSGetExecutablePathProto func; | ||
137 | int ret; | ||
138 | |||
139 | path = NULL; | ||
140 | func = | ||
141 | (MyNSGetExecutablePathProto) dlsym (RTLD_DEFAULT, "_NSGetExecutablePath"); | ||
142 | if (!func) | ||
143 | return NULL; | ||
144 | path = &zero; | ||
145 | len = 0; | ||
146 | /* get the path len, including the trailing \0 */ | ||
147 | func (path, &len); | ||
148 | if (len == 0) | ||
149 | return NULL; | ||
150 | path = GNUNET_malloc (len); | ||
151 | ret = func (path, &len); | ||
152 | if (ret != 0) | ||
153 | { | ||
154 | GNUNET_free (path); | ||
155 | return NULL; | ||
156 | } | ||
157 | len = strlen (path); | ||
158 | while ((path[len] != '/') && (len > 0)) | ||
159 | len--; | ||
160 | path[len] = '\0'; | ||
161 | return path; | ||
162 | } | ||
163 | |||
164 | static char * | ||
165 | get_path_from_dyld_image () | ||
166 | { | ||
167 | const char *path; | ||
168 | char *p, *s; | ||
169 | int i; | ||
170 | int c; | ||
171 | |||
172 | p = NULL; | ||
173 | c = _dyld_image_count (); | ||
174 | for (i = 0; i < c; i++) | ||
175 | { | ||
176 | if (_dyld_get_image_header (i) == &_mh_dylib_header) | ||
177 | { | ||
178 | path = _dyld_get_image_name (i); | ||
179 | if (path != NULL && strlen (path) > 0) | ||
180 | { | ||
181 | p = strdup (path); | ||
182 | s = p + strlen (p); | ||
183 | while ((s > p) && (*s != '/')) | ||
184 | s--; | ||
185 | s++; | ||
186 | *s = '\0'; | ||
187 | } | ||
188 | break; | ||
189 | } | ||
190 | } | ||
191 | return p; | ||
192 | } | ||
193 | #endif | ||
194 | |||
195 | static char * | ||
196 | get_path_from_PATH () | ||
197 | { | ||
198 | char *path; | ||
199 | char *pos; | ||
200 | char *end; | ||
201 | char *buf; | ||
202 | const char *p; | ||
203 | |||
204 | p = getenv ("PATH"); | ||
205 | if (p == NULL) | ||
206 | return NULL; | ||
207 | path = GNUNET_strdup (p); /* because we write on it */ | ||
208 | buf = GNUNET_malloc (strlen (path) + 20); | ||
209 | pos = path; | ||
210 | |||
211 | while (NULL != (end = strchr (pos, ':'))) | ||
212 | { | ||
213 | *end = '\0'; | ||
214 | sprintf (buf, "%s/%s", pos, "gnunet-gtk"); | ||
215 | if (GNUNET_DISK_file_test (buf) == GNUNET_YES) | ||
216 | { | ||
217 | pos = GNUNET_strdup (pos); | ||
218 | GNUNET_free (buf); | ||
219 | GNUNET_free (path); | ||
220 | return pos; | ||
221 | } | ||
222 | pos = end + 1; | ||
223 | } | ||
224 | sprintf (buf, "%s/%s", pos, "gnunet-gtk"); | ||
225 | if (GNUNET_DISK_file_test (buf) == GNUNET_YES) | ||
226 | { | ||
227 | pos = GNUNET_strdup (pos); | ||
228 | GNUNET_free (buf); | ||
229 | GNUNET_free (path); | ||
230 | return pos; | ||
231 | } | ||
232 | GNUNET_free (buf); | ||
233 | GNUNET_free (path); | ||
234 | return NULL; | ||
235 | } | ||
236 | |||
237 | static char * | ||
238 | get_path_from_GNUNET_PREFIX () | ||
239 | { | ||
240 | const char *p; | ||
241 | |||
242 | p = getenv ("GNUNET_GTK_PREFIX"); | ||
243 | if (p != NULL) | ||
244 | return GNUNET_strdup (p); | ||
245 | p = getenv ("GNUNET_PREFIX"); | ||
246 | if (p != NULL) | ||
247 | return GNUNET_strdup (p); | ||
248 | return NULL; | ||
249 | } | ||
250 | |||
251 | /* | ||
252 | * @brief get the path to GNUnet bin/ or lib/, prefering the lib/ path | ||
253 | * @author Milan | ||
254 | * | ||
255 | * @return a pointer to the executable path, or NULL on error | ||
256 | */ | ||
257 | static char * | ||
258 | os_get_gnunet_path () | ||
259 | { | ||
260 | char *ret; | ||
261 | |||
262 | ret = get_path_from_GNUNET_PREFIX (); | ||
263 | if (ret != NULL) | ||
264 | return ret; | ||
265 | #if LINUX | ||
266 | ret = get_path_from_proc_maps (); | ||
267 | if (ret != NULL) | ||
268 | return ret; | ||
269 | ret = get_path_from_proc_exe (); | ||
270 | if (ret != NULL) | ||
271 | return ret; | ||
272 | #endif | ||
273 | #if WINDOWS | ||
274 | ret = get_path_from_module_filename (); | ||
275 | if (ret != NULL) | ||
276 | return ret; | ||
277 | #endif | ||
278 | #if DARWIN | ||
279 | ret = get_path_from_dyld_image (); | ||
280 | if (ret != NULL) | ||
281 | return ret; | ||
282 | ret = get_path_from_NSGetExecutablePath (); | ||
283 | if (ret != NULL) | ||
284 | return ret; | ||
285 | #endif | ||
286 | ret = get_path_from_PATH (); | ||
287 | if (ret != NULL) | ||
288 | return ret; | ||
289 | /* other attempts here */ | ||
290 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
291 | _ | ||
292 | ("Could not determine installation path for %s. Set `%s' environment variable.\n"), | ||
293 | "gnunet-gtk", | ||
294 | "GNUNET_GTK_PREFIX"); | ||
295 | return NULL; | ||
296 | } | ||
297 | |||
298 | /* | ||
299 | * @brief get the path to current app's bin/ | ||
300 | * @author Milan | ||
301 | * | ||
302 | * @return a pointer to the executable path, or NULL on error | ||
303 | */ | ||
304 | static char * | ||
305 | os_get_exec_path () | ||
306 | { | ||
307 | char *ret; | ||
308 | |||
309 | ret = NULL; | ||
310 | #if LINUX | ||
311 | ret = get_path_from_proc_exe (); | ||
312 | if (ret != NULL) | ||
313 | return ret; | ||
314 | #endif | ||
315 | #if WINDOWS | ||
316 | ret = get_path_from_module_filename (); | ||
317 | if (ret != NULL) | ||
318 | return ret; | ||
319 | #endif | ||
320 | #if DARWIN | ||
321 | ret = get_path_from_NSGetExecutablePath (); | ||
322 | if (ret != NULL) | ||
323 | return ret; | ||
324 | #endif | ||
325 | /* other attempts here */ | ||
326 | return ret; | ||
327 | } | ||
328 | |||
329 | |||
330 | |||
331 | /** | ||
332 | * @brief get the path to a specific GNUnet installation directory or, | ||
333 | * with GNUNET_IPK_SELF_PREFIX, the current running apps installation directory | ||
334 | * @author Milan | ||
335 | * @return a pointer to the dir path (to be freed by the caller) | ||
336 | */ | ||
337 | char * | ||
338 | GNUNET_GTK_installation_get_path (enum GNUNET_OS_InstallationPathKind dirkind) | ||
339 | { | ||
340 | size_t n; | ||
341 | const char *dirname; | ||
342 | char *execpath = NULL; | ||
343 | char *tmp; | ||
344 | int isbasedir; | ||
345 | |||
346 | /* if wanted, try to get the current app's bin/ */ | ||
347 | if (dirkind == GNUNET_OS_IPK_SELF_PREFIX) | ||
348 | execpath = os_get_exec_path (); | ||
349 | |||
350 | /* try to get GNUnet's bin/ or lib/, or if previous was unsuccessful some | ||
351 | * guess for the current app */ | ||
352 | if (execpath == NULL) | ||
353 | execpath = os_get_gnunet_path (); | ||
354 | |||
355 | if (execpath == NULL) | ||
356 | return NULL; | ||
357 | |||
358 | n = strlen (execpath); | ||
359 | if (n == 0) | ||
360 | { | ||
361 | /* should never happen, but better safe than sorry */ | ||
362 | GNUNET_free (execpath); | ||
363 | return NULL; | ||
364 | } | ||
365 | /* remove filename itself */ | ||
366 | while ((n > 1) && (execpath[n - 1] == DIR_SEPARATOR)) | ||
367 | execpath[--n] = '\0'; | ||
368 | |||
369 | isbasedir = 1; | ||
370 | if ((n > 5) && | ||
371 | ((0 == strcasecmp (&execpath[n - 5], "lib32")) || | ||
372 | (0 == strcasecmp (&execpath[n - 5], "lib64")))) | ||
373 | { | ||
374 | if (dirkind != GNUNET_OS_IPK_LIBDIR) | ||
375 | { | ||
376 | /* strip '/lib32' or '/lib64' */ | ||
377 | execpath[n - 5] = '\0'; | ||
378 | n -= 5; | ||
379 | } | ||
380 | else | ||
381 | isbasedir = 0; | ||
382 | } | ||
383 | else if ((n > 3) && | ||
384 | ((0 == strcasecmp (&execpath[n - 3], "bin")) || | ||
385 | (0 == strcasecmp (&execpath[n - 3], "lib")))) | ||
386 | { | ||
387 | /* strip '/bin' or '/lib' */ | ||
388 | execpath[n - 3] = '\0'; | ||
389 | n -= 3; | ||
390 | } | ||
391 | /* in case this was a directory named foo-bin, remove "foo-" */ | ||
392 | while ((n > 1) && (execpath[n - 1] == DIR_SEPARATOR)) | ||
393 | execpath[--n] = '\0'; | ||
394 | switch (dirkind) | ||
395 | { | ||
396 | case GNUNET_OS_IPK_PREFIX: | ||
397 | case GNUNET_OS_IPK_SELF_PREFIX: | ||
398 | dirname = DIR_SEPARATOR_STR; | ||
399 | break; | ||
400 | case GNUNET_OS_IPK_BINDIR: | ||
401 | dirname = DIR_SEPARATOR_STR "bin" DIR_SEPARATOR_STR; | ||
402 | break; | ||
403 | case GNUNET_OS_IPK_LIBDIR: | ||
404 | if (isbasedir) | ||
405 | dirname = | ||
406 | DIR_SEPARATOR_STR "lib" DIR_SEPARATOR_STR "gnunet-gtk" | ||
407 | DIR_SEPARATOR_STR; | ||
408 | else | ||
409 | dirname = DIR_SEPARATOR_STR "gnunet-gtk" DIR_SEPARATOR_STR; | ||
410 | break; | ||
411 | case GNUNET_OS_IPK_DATADIR: | ||
412 | dirname = | ||
413 | DIR_SEPARATOR_STR "share" DIR_SEPARATOR_STR "gnunet-gtk" | ||
414 | DIR_SEPARATOR_STR; | ||
415 | break; | ||
416 | case GNUNET_OS_IPK_ICONDIR: | ||
417 | dirname = | ||
418 | DIR_SEPARATOR_STR "share" DIR_SEPARATOR_STR "icons" DIR_SEPARATOR_STR; | ||
419 | break; | ||
420 | case GNUNET_OS_IPK_LOCALEDIR: | ||
421 | dirname = | ||
422 | DIR_SEPARATOR_STR "share" DIR_SEPARATOR_STR "locale" | ||
423 | DIR_SEPARATOR_STR; | ||
424 | break; | ||
425 | default: | ||
426 | GNUNET_free (execpath); | ||
427 | return NULL; | ||
428 | } | ||
429 | tmp = GNUNET_malloc (strlen (execpath) + strlen (dirname) + 1); | ||
430 | sprintf (tmp, "%s%s", execpath, dirname); | ||
431 | GNUNET_free (execpath); | ||
432 | return tmp; | ||
433 | } | ||
434 | |||
435 | /* end of os_installation.c */ | ||