Line data Source code
1 : /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2 : /*
3 : * libcdpfgl.c
4 : *
5 : * This file is part of "Sauvegarde" project.
6 : *
7 : * (C) Copyright 2014 - 2016 Olivier Delhomme
8 : * e-mail : olivier.delhomme@free.fr
9 : *
10 : * "Sauvegarde" is free software: you can redistribute it and/or modify
11 : * it under the terms of the GNU General Public License as published by
12 : * the Free Software Foundation, either version 3 of the License, or
13 : * (at your option) any later version.
14 : *
15 : * "Sauvegarde" is distributed in the hope that it will be useful,
16 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 : * GNU General Public License for more details.
19 : *
20 : * You should have received a copy of the GNU General Public License
21 : * along with "Sauvegarde". If not, see <http://www.gnu.org/licenses/>
22 : */
23 :
24 : /**
25 : * @file libcdpfgl.c
26 : * This library contains all tools that may be used in cdpfgl's programs.
27 : */
28 :
29 : #include "libcdpfgl.h"
30 :
31 : static void catcher(int sig);
32 : static void print_buffer(gchar *buffer);
33 :
34 :
35 : /**
36 : * Initializing debug_mode by default to the compilation choice.
37 : */
38 : gboolean debug_mode = ENABLE_DEBUG;
39 :
40 :
41 : /**
42 : * Sets debug_mode on or off if mode is TRUE or FALSE.
43 : * @param mode a boolean to say whether we want to have debug enabled
44 : * (TRUE) or not (FALSE).
45 : */
46 41 : void set_debug_mode(gboolean mode)
47 : {
48 41 : if (debug_mode == TRUE && mode == FALSE)
49 : {
50 0 : print_debug(_("Debug mode is disabled.\n"));
51 : }
52 41 : else if (debug_mode == FALSE && mode == TRUE)
53 : {
54 0 : print_debug(_("Debug mode is activated.\n"));
55 : }
56 :
57 41 : debug_mode = mode;
58 41 : }
59 :
60 :
61 : /**
62 : * Sets the debug mode from command line read option
63 : * @param debug is a gint read from the command line and should be 0 or 1
64 : * but is initialized to something different in order to be able to
65 : * detect if the option has been invoked or not.
66 : */
67 17 : void set_debug_mode_upon_cmdl(gint debug)
68 : {
69 17 : if (debug == 0)
70 : {
71 0 : set_debug_mode(FALSE);
72 : }
73 17 : else if (debug == 1)
74 : {
75 0 : set_debug_mode(TRUE);
76 : }
77 17 : }
78 :
79 :
80 : /**
81 : * @returns the debug mode (TRUE if activated and FALSE if not).
82 : */
83 47144 : gboolean get_debug_mode(void)
84 : {
85 47144 : return debug_mode;
86 : }
87 :
88 :
89 : /**
90 : * Prints the buffer to stdout and free its memory !
91 : * @param buffer : the buffer to be printed and then freed
92 : */
93 6 : static void print_buffer(gchar *buffer)
94 : {
95 6 : if (buffer != NULL)
96 : {
97 6 : fprintf(stdout, "%s", buffer);
98 6 : buffer = free_variable(buffer);
99 : }
100 6 : }
101 :
102 :
103 : /**
104 : * @returns a newlly allocated gchar containing MHD version number with
105 : * the following format : major.minor.maint-build. It may me freed
106 : * when no longer needed.
107 : */
108 1 : gchar *make_MHD_version(void)
109 : {
110 1 : gint build = 0;
111 1 : gint maint = 0;
112 1 : gint minor = 0;
113 1 : gint major = 0;
114 1 : gchar *version = NULL;
115 :
116 1 : build = ((MHD_VERSION >> 4) & 15) * 10 + (MHD_VERSION & 15);
117 1 : maint = ((MHD_VERSION >> 12) & 15) * 10 + ((MHD_VERSION >> 8) & 15);
118 1 : minor = ((MHD_VERSION >> 20) & 15) * 10 + ((MHD_VERSION >> 16) & 15);
119 1 : major = ((MHD_VERSION >> 28) & 15) * 10 + ((MHD_VERSION >> 24) & 15);
120 :
121 1 : version = g_strdup_printf("%d.%d.%d-%d", major, minor, maint, build);
122 :
123 1 : return version;
124 : }
125 :
126 :
127 : /**
128 : * Returns a newly allocated buffer that contains all informations about
129 : * the version of the libraries we are using.
130 : * @param name : name of the program of which we want to print the version.
131 : */
132 3 : gchar *buffer_libraries_versions(gchar *name)
133 : {
134 3 : gchar *buffer = NULL;
135 3 : gchar *buf1 = NULL;
136 3 : gchar *comm_version = NULL;
137 :
138 3 : if (name != NULL)
139 : {
140 3 : buffer = g_strdup_printf(_("%s was compiled with the following libraries:\n\t. GLIB version: %d.%d.%d\n"), name, glib_major_version, glib_minor_version, glib_micro_version);
141 :
142 3 : if (g_strcmp0(name, "cdpfglserver") == 0)
143 : {
144 1 : comm_version = make_MHD_version();
145 1 : buf1 = g_strdup_printf("%s\t. LIBMHD: %s\n", buffer, comm_version);
146 1 : buffer = free_variable(buffer);
147 1 : comm_version = free_variable(comm_version);
148 : }
149 : else
150 : {
151 2 : comm_version = get_communication_library_version();
152 :
153 2 : if (comm_version != NULL)
154 : {
155 2 : buf1 = g_strdup_printf("%s%s", buffer, comm_version);
156 2 : comm_version = free_variable(comm_version);
157 2 : buffer = free_variable(buffer);
158 : }
159 : }
160 :
161 3 : if (buf1 == NULL && buffer != NULL)
162 : {
163 0 : buf1 = g_strdup(buffer);
164 0 : buffer = free_variable(buffer);
165 : }
166 :
167 3 : buffer = g_strdup_printf(_("%s\t. %s version: %s\n\t. JANSSON version: %d.%d.%d\n"), buf1, DATABASE_NAME, db_version(), JANSSON_MAJOR_VERSION, JANSSON_MINOR_VERSION, JANSSON_MICRO_VERSION);
168 3 : buf1 = free_variable(buf1);
169 : }
170 :
171 3 : return buffer;
172 : }
173 :
174 :
175 : /**
176 : * Prints version of the libraries we are using.
177 : * @param name : name of the program of which we want to print the version.
178 : */
179 3 : void print_libraries_versions(gchar *name)
180 : {
181 3 : gchar *buffer = NULL;
182 :
183 3 : buffer = buffer_libraries_versions(name);
184 3 : print_buffer(buffer);
185 3 : }
186 :
187 :
188 : /**
189 : * Prints if string is not NULL then prints it to stdout right in the
190 : * 'description' printf format.
191 : * @param description is a fprintf format string that must contain a %s
192 : * in order to include the string 'string'
193 : * @param string is the string to be printed.
194 : */
195 7 : void print_string_option(gchar *description, gchar *string)
196 : {
197 7 : if (string != NULL)
198 : {
199 4 : fprintf(stdout, description, string);
200 : }
201 7 : }
202 :
203 :
204 : /**
205 : * Returns a newly allocated buffer that contains all informations about
206 : * program's version, authors and license.
207 : * @param name : name of the program of which we want to print the version.
208 : * @param date : publication date of this version
209 : * @param version : version of the program.
210 : * @param authors : authors that contributed to this program
211 : * @param license : license in use for this program and its sources
212 : */
213 3 : gchar *buffer_program_version(gchar *name, gchar *date, gchar *version, gchar *authors, gchar *license)
214 : {
215 3 : gchar *buffer = NULL;
216 :
217 3 : if (name != NULL && date != NULL && version != NULL && authors != NULL && license != NULL)
218 : {
219 3 : buffer = g_strdup_printf(_("%s version: %s-%s (%s)\nAuthor(s): %s\nLicense: %s\n\n"), name, version, REVISION, date, authors, license);
220 : }
221 :
222 3 : return buffer;
223 : }
224 :
225 :
226 : /**
227 : * Prints the version of the program.
228 : * All parameters are of (gchar *) type.
229 : * @param name : name of the program of which we want to print the version.
230 : * @param date : publication date of this version
231 : * @param version : version of the program.
232 : * @param authors : authors that contributed to this program
233 : * @param license : license in use for this program and its sources
234 : */
235 3 : void print_program_version(gchar *name, gchar *date, gchar *version, gchar *authors, gchar *license)
236 : {
237 3 : gchar *buffer = NULL;
238 :
239 3 : buffer = buffer_program_version(name, date, version, authors, license);
240 3 : print_buffer(buffer);
241 3 : }
242 :
243 :
244 : /**
245 : * Inits internationalization domain for cdpfgl project
246 : */
247 22 : void init_international_languages(void)
248 : {
249 22 : gchar *result = NULL;
250 22 : gchar *codeset = NULL;
251 22 : gchar *text_domain = NULL;
252 :
253 22 : setlocale(LC_ALL, "");
254 22 : result = bindtextdomain(GETTEXT_PACKAGE, LOCALE_DIR);
255 22 : codeset = bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
256 22 : text_domain = textdomain(GETTEXT_PACKAGE);
257 :
258 22 : print_debug(_("Debug mode is activated.\n"));
259 22 : print_debug(_("Gettext package: %s\n"), GETTEXT_PACKAGE);
260 :
261 22 : if (result != NULL)
262 : {
263 22 : print_debug(_("Bindtextdomain: %s\n"), result);
264 : }
265 :
266 22 : if (codeset != NULL)
267 : {
268 22 : print_debug(_("Code set: %s\n"), codeset);
269 : }
270 :
271 22 : if (text_domain != NULL)
272 : {
273 22 : print_debug(_("Text domain: %s\n"), text_domain);
274 : }
275 22 : }
276 :
277 :
278 : /**
279 : * Sets options parameters
280 : * @param context is the context for options it must have been created
281 : * previously and not NULL.
282 : * @param entries are the entries for the options.
283 : * @param help is a boolean to choose if we want GOption to display
284 : * an automaticaly formatted help.
285 : * @param bugreport is the message we want to display related to bug
286 : * reports. It is displayed at the end of the options help message.
287 : * @param summary is a gchar* string that will be displayed before the
288 : * description of the options. It is supposed to be a summary of
289 : * what the program does.
290 : */
291 22 : void set_option_context_options(GOptionContext *context, GOptionEntry entries[], gboolean help, gchar *bugreport, gchar *summary)
292 : {
293 22 : if (context != NULL && bugreport != NULL && summary != NULL)
294 : {
295 22 : g_option_context_add_main_entries(context, entries, GETTEXT_PACKAGE);
296 22 : g_option_context_set_help_enabled(context, help);
297 22 : g_option_context_set_description(context, bugreport);
298 22 : g_option_context_set_summary(context, summary);
299 : }
300 22 : }
301 :
302 :
303 : /**
304 : * Frees a pointer if it is not NULL and returns NULL
305 : * @param to_free is the pointer to be freed (must have been malloc with
306 : * g_malloc* functions).
307 : * @returns NULL
308 : */
309 41227858 : gpointer free_variable(gpointer to_free)
310 : {
311 41227858 : if (to_free != NULL)
312 : {
313 40236869 : g_free(to_free);
314 40236869 : to_free = NULL;
315 : }
316 :
317 41226829 : return NULL;
318 : }
319 :
320 :
321 : /**
322 : * Wrapper for the g_slist_free_full function in order to free lists
323 : * of gchar *
324 : * @param data is the pointer to a gchar * string to be freed
325 : */
326 8 : void free_gchar_variable(gpointer data)
327 : {
328 8 : free_variable(data);
329 8 : }
330 :
331 :
332 : /**
333 : * Unrefs an object if it is not NULL and returns NULL
334 : * @param object_to_unref is the pointer to be unref'ed.
335 : * @returns NULL
336 : */
337 1071474 : gpointer free_object(gpointer object_to_unref)
338 : {
339 1071474 : if (object_to_unref != NULL)
340 : {
341 1071474 : g_object_unref(object_to_unref);
342 1071474 : object_to_unref = NULL;
343 : }
344 :
345 1071474 : return NULL;
346 : }
347 :
348 :
349 : /**
350 : * Frees an error if it exists and return NULL
351 : * @param error : the error to be freed
352 : * @returns NULL
353 : */
354 21 : gpointer free_error(gpointer error)
355 : {
356 21 : if (error != NULL)
357 : {
358 21 : g_error_free(error);
359 21 : error = NULL;
360 : }
361 :
362 21 : return NULL;
363 : }
364 :
365 :
366 : /**
367 : * Frees all elements of a gchar * GSList
368 : * @param list the list to be freed
369 : * @returns NULL
370 : */
371 2 : gpointer free_list(GSList *list)
372 : {
373 2 : g_slist_free_full(list, free_gchar_variable);
374 :
375 2 : return NULL;
376 : }
377 :
378 :
379 : /**
380 : * Prints a message if the debug flag is set
381 : * @param format : the format of the message (as in printf)
382 : * @param ... : va_list of variable that are to be printed into format.
383 : */
384 863813 : void print_debug(const char *format, ...)
385 : {
386 : va_list ap;
387 :
388 863813 : if (debug_mode == TRUE)
389 : {
390 863813 : va_start(ap, format);
391 863813 : vfprintf(stdout, format, ap);
392 863813 : va_end(ap);
393 : }
394 863813 : }
395 :
396 :
397 : /**
398 : * Prints an error message
399 : * @param char *filename
400 : * @param int lineno
401 : * @param format : the format of the message (as in printf)
402 : * @param ... : va_list of variable that are to be printed into format.
403 : */
404 53 : void print_error(char *filename, int lineno, const char *format, ...)
405 : {
406 : va_list ap;
407 :
408 :
409 53 : fprintf(stderr, "[%s, %d] ", filename, lineno);
410 53 : va_start(ap, format);
411 53 : vfprintf(stderr, format, ap);
412 53 : va_end(ap);
413 :
414 53 : }
415 :
416 :
417 : #if !GLIB_CHECK_VERSION(2, 31, 0)
418 : /**
419 : * defines a wrapper to the g_thread_create function used in glib before
420 : * 2.31
421 : */
422 : GThread *g_thread_new(const gchar *unused, GThreadFunc func, gpointer data)
423 : {
424 : GThread *thread = g_thread_create(func, data, TRUE, NULL);
425 :
426 : if (thread == NULL)
427 : {
428 : g_error(_("g_thread_create failed !"));
429 : }
430 :
431 : return thread;
432 : }
433 : #endif
434 :
435 :
436 : /**
437 : * Tries to create a directory. Does not report an error if the directory
438 : * already exists.
439 : * @param directory is the gchar * string that contains a directory name
440 : * to be created (does nothing if it exists).
441 : */
442 65540 : void create_directory(gchar *directory)
443 : {
444 65540 : GFile *dir = NULL;
445 65540 : GError *error = NULL;
446 :
447 65540 : if (directory != NULL)
448 : {
449 65540 : dir = g_file_new_for_path(directory);
450 65540 : g_file_make_directory_with_parents(dir, NULL, &error);
451 :
452 65540 : if (error != NULL)
453 : {
454 0 : if (error->code != G_IO_ERROR_EXISTS)
455 : {
456 0 : print_error(__FILE__, __LINE__, ("Failed to create directory %s: %s\n"), directory, error->message);
457 : }
458 0 : error = free_error(error);
459 : }
460 :
461 65540 : dir = free_object(dir);
462 : }
463 65540 : }
464 :
465 :
466 : /**
467 : * A signal catcher that does nothing for SIGPIPE (needed by libmicrohttpd
468 : * in order to be portable.
469 : */
470 0 : static void catcher(int sig)
471 : {
472 0 : }
473 :
474 :
475 : /**
476 : * A signal handler for SIGPIPE (needed by libmicrohttpd in order to be
477 : * portable).
478 : */
479 4 : void ignore_sigpipe(void)
480 : {
481 : struct sigaction oldsig;
482 : struct sigaction sig;
483 :
484 4 : sig.sa_handler = &catcher;
485 4 : sigemptyset (&sig.sa_mask);
486 :
487 : #ifdef SA_INTERRUPT
488 4 : sig.sa_flags = SA_INTERRUPT; /* SunOS */
489 : #else
490 : sig.sa_flags = SA_RESTART;
491 : #endif
492 :
493 4 : if (sigaction(SIGPIPE, &sig, &oldsig) != 0)
494 : {
495 0 : print_error(__FILE__, __LINE__, _("Failed to install SIGPIPE handler: %s\n"), strerror(errno));
496 : }
497 4 : }
498 :
499 :
500 : /**
501 : * Waits a number of micro seconds until the number of element in the
502 : * queue is less than the specified number.
503 : * @param queue : the queue to be tested
504 : * @param nbelem : maximum number of element before waiting
505 : * @param usecs : number of micro seconds to wait
506 : */
507 0 : void wait_for_queue_to_flush(GAsyncQueue *queue, guint nbelem, useconds_t usecs)
508 : {
509 0 : if (queue != NULL && usecs < 1000000)
510 : {
511 : /**
512 : * Checks if the queue length is less than 8 before
513 : * continuing because we want to be sure that what we
514 : * provide is processed...
515 : */
516 0 : while (g_async_queue_length(queue) > nbelem)
517 : {
518 0 : usleep(usecs);
519 : }
520 : }
521 0 : }
522 :
523 :
|