GNUnet 0.22.0
program.c
Go to the documentation of this file.
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009-2013 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your 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 PURPROSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
28#include "platform.h"
29#include "gnunet_util_lib.h"
31#include "gnunet_constants.h"
32#include "speedup.h"
33#include <gcrypt.h>
34
35#define LOG(kind, ...) GNUNET_log_from (kind, "util-program", __VA_ARGS__)
36
37#define LOG_STRERROR_FILE(kind, syscall, filename) \
38 GNUNET_log_from_strerror_file (kind, "util-program", syscall, filename)
39
44{
48 char *const *args;
49
53 char *cfgfile;
54
59
63 void *task_cls;
64
69};
70
71
75static void
76shutdown_task (void *cls)
77{
78 (void) cls;
80}
81
82
87static void
88program_main (void *cls)
89{
90 struct CommandContext *cc = cls;
91
94 NULL);
96 cc->task (cc->task_cls,
97 cc->args,
98 cc->cfgfile,
99 cc->cfg);
100}
101
102
110static int
111cmd_sorter (const void *a1,
112 const void *a2)
113{
114 const struct GNUNET_GETOPT_CommandLineOption *c1 = a1;
115 const struct GNUNET_GETOPT_CommandLineOption *c2 = a2;
116
117 if (toupper ((unsigned char) c1->shortName) >
118 toupper ((unsigned char) c2->shortName))
119 return 1;
120 if (toupper ((unsigned char) c1->shortName) <
121 toupper ((unsigned char) c2->shortName))
122 return -1;
123 if (c1->shortName > c2->shortName)
124 return 1;
125 if (c1->shortName < c2->shortName)
126 return -1;
127 return 0;
128}
129
130
133 char *const *argv,
134 const char *binaryName,
135 const char *binaryHelp,
138 void *task_cls,
139 int run_without_scheduler)
140{
141 struct CommandContext cc;
142
143#if ENABLE_NLS
144 char *path;
145#endif
146 char *loglev;
147 char *logfile;
148 char *cfg_fn;
150 int iret;
151 unsigned int cnt;
152 unsigned long long skew_offset;
153 unsigned long long skew_variance;
154 long long clock_offset;
157 const struct GNUNET_GETOPT_CommandLineOption defoptions[] = {
159 GNUNET_GETOPT_option_help (binaryHelp),
163 };
164 unsigned int deflen = sizeof(defoptions) / sizeof(defoptions[0]);
165 struct GNUNET_GETOPT_CommandLineOption *allopts;
166 const char *gargs;
167 char *lpfx;
168 char *spc;
169
170 logfile = NULL;
171 gargs = getenv ("GNUNET_ARGS");
172 if (NULL != gargs)
173 {
174 char **gargv;
175 unsigned int gargc;
176 char *cargs;
177
178 gargv = NULL;
179 gargc = 0;
180 for (int i = 0; i < argc; i++)
181 GNUNET_array_append (gargv,
182 gargc,
183 GNUNET_strdup (argv[i]));
184 cargs = GNUNET_strdup (gargs);
185 for (char *tok = strtok (cargs, " ");
186 NULL != tok;
187 tok = strtok (NULL, " "))
188 GNUNET_array_append (gargv, gargc, GNUNET_strdup (tok));
189 GNUNET_free (cargs);
190 GNUNET_array_append (gargv, gargc, NULL);
191 argv = (char *const *) gargv;
192 argc = gargc - 1;
193 }
194 memset (&cc, 0, sizeof(cc));
195 loglev = NULL;
196 cc.task = task;
197 cc.task_cls = task_cls;
199 /* prepare */
200#if ENABLE_NLS
201 if (NULL != pd->gettext_domain)
202 {
203 setlocale (LC_ALL, "");
204 path = (NULL == pd->gettext_path)
207 if (NULL != path)
208 {
209 bindtextdomain (pd->gettext_domain, path);
210 GNUNET_free (path);
211 }
213 }
214#endif
215 cnt = 0;
216 while (NULL != options[cnt].name)
217 cnt++;
218 allopts = GNUNET_new_array (cnt + deflen + 1,
220 GNUNET_memcpy (allopts,
221 options,
222 cnt * sizeof(struct GNUNET_GETOPT_CommandLineOption));
223 {
224 unsigned int xtra = 0;
225
226 for (unsigned int i = 0;
227 i<sizeof (defoptions) / sizeof(struct GNUNET_GETOPT_CommandLineOption);
228 i++)
229 {
230 bool found = false;
231
232 for (unsigned int j = 0; j<cnt; j++)
233 {
234 found |= ( (options[j].shortName == defoptions[i].shortName) &&
235 (0 != options[j].shortName) );
236 found |= ( (NULL != options[j].name) &&
237 (NULL != defoptions[i].name) &&
238 (0 == strcmp (options[j].name,
239 defoptions[i].name)) );
240 if (found)
241 break;
242 }
243 if (found)
244 continue;
245 GNUNET_memcpy (&allopts[cnt + xtra],
246 &defoptions[i],
247 sizeof (struct GNUNET_GETOPT_CommandLineOption));
248 xtra++;
249 }
250 cnt += xtra;
251 }
252 qsort (allopts,
253 cnt,
254 sizeof(struct GNUNET_GETOPT_CommandLineOption),
255 &cmd_sorter);
256 loglev = NULL;
257 if ((NULL != pd->config_file) && (NULL != pd->user_config_file))
259 else
260 cfg_fn = NULL;
261 lpfx = GNUNET_strdup (binaryName);
262 if (NULL != (spc = strstr (lpfx, " ")))
263 *spc = '\0';
264 iret = GNUNET_GETOPT_run (binaryName,
265 allopts,
266 (unsigned int) argc,
267 argv);
268 if ((GNUNET_OK > iret) ||
269 (GNUNET_OK != GNUNET_log_setup (lpfx,
270 loglev,
271 logfile)))
272 {
273 GNUNET_free (allopts);
274 GNUNET_free (lpfx);
275 ret = (enum GNUNET_GenericReturnValue) iret;
276 goto cleanup;
277 }
278 if (NULL != cc.cfgfile)
279 {
281 "Loading configuration from entry point specified as option (%s)\n",
282 cc.cfgfile);
283 if (GNUNET_YES !=
285 {
287 _ ("Unreadable configuration file `%s', exiting ...\n"),
288 cc.cfgfile);
290 GNUNET_free (allopts);
291 GNUNET_free (lpfx);
292 goto cleanup;
293 }
294 if (GNUNET_SYSERR ==
296 cc.cfgfile))
297 {
299 _ ("Malformed configuration file `%s', exiting ...\n"),
300 cc.cfgfile);
302 GNUNET_free (allopts);
303 GNUNET_free (lpfx);
304 goto cleanup;
305 }
306 }
307 else
308 {
309 if ( (NULL != cfg_fn) &&
310 (GNUNET_YES !=
311 GNUNET_DISK_file_test (cfg_fn)) )
312 {
314 _ ("Unreadable configuration file `%s'. Exiting ...\n"),
315 cfg_fn);
317 GNUNET_free (allopts);
318 GNUNET_free (lpfx);
319 goto cleanup;
320 }
322 "Loading configuration from entry point `%s'\n",
323 cc.cfgfile);
324 if (GNUNET_SYSERR ==
326 cfg_fn))
327 {
329 _ ("Malformed configuration. Exiting ...\n"));
331 GNUNET_free (allopts);
332 GNUNET_free (lpfx);
333 goto cleanup;
334 }
335 }
336 GNUNET_free (allopts);
337 GNUNET_free (lpfx);
338 if ((GNUNET_OK ==
340 "testing",
341 "skew_offset",
342 &skew_offset)) &&
343 (GNUNET_OK ==
345 "testing",
346 "skew_variance",
347 &skew_variance)))
348 {
349 clock_offset = skew_offset - skew_variance;
350 GNUNET_TIME_set_offset (clock_offset);
351 }
352 /* ARM needs to know which configuration file to use when starting
353 services. If we got a command-line option *and* if nothing is
354 specified in the configuration, remember the command-line option
355 in "cfg". This is typically really only having an effect if we
356 are running code in src/arm/, as obviously the rest of the code
357 has little business with ARM-specific options. */
358 if (GNUNET_YES !=
360 "arm",
361 "CONFIG"))
362 {
363 if (NULL != cc.cfgfile)
365 "arm",
366 "CONFIG",
367 cc.cfgfile);
368 else if (NULL != cfg_fn)
370 "arm",
371 "CONFIG",
372 cfg_fn);
373 }
374
375 /* run */
376 cc.args = &argv[iret];
377 if ((NULL == cc.cfgfile) && (NULL != cfg_fn))
378 cc.cfgfile = GNUNET_strdup (cfg_fn);
379 if (GNUNET_NO == run_without_scheduler)
380 {
382 }
383 else
384 {
386 cc.task (cc.task_cls, cc.args, cc.cfgfile, cc.cfg);
387 }
388 ret = GNUNET_OK;
389cleanup:
391 GNUNET_free (cc.cfgfile);
392 GNUNET_free (cfg_fn);
393 GNUNET_free (loglev);
394 GNUNET_free (logfile);
395 return ret;
396}
397
398
401 char *const *argv,
402 const char *binaryName,
403 const char *binaryHelp,
406 void *task_cls)
407{
408 return GNUNET_PROGRAM_run2 (argc,
409 argv,
410 binaryName,
411 binaryHelp,
412 options,
413 task,
414 task_cls,
415 GNUNET_NO);
416}
417
418
421 char *const *argv,
423{
424 char *cfg_filename;
425 char *opt_cfg_filename;
426 char *logfile;
427 char *loglev;
428 const char *xdg;
429 int do_daemonize;
430 int ret;
432 struct GNUNET_GETOPT_CommandLineOption service_options[] = {
433 GNUNET_GETOPT_option_cfgfile (&opt_cfg_filename),
435 "daemonize",
437 "do daemonize (detach from terminal)"),
438 &do_daemonize),
444 };
445
446 xdg = getenv ("XDG_CONFIG_HOME");
447 if (NULL != xdg)
449 "%s%s%s",
450 xdg,
452 pd->config_file);
453 else
455
456 loglev = NULL;
457 logfile = NULL;
458 opt_cfg_filename = NULL;
459 // FIXME we need to set this up for each service!
460 ret = GNUNET_GETOPT_run ("libgnunet",
461 service_options,
462 argc,
463 argv);
464 if (GNUNET_SYSERR == ret)
465 goto error;
466 if (GNUNET_NO == ret)
467 {
468 goto error;
469 }
470 // FIXME we need to set this up for each service!
471 // NOTE: that was not the idea. What are you proposing? -CG
472 if (GNUNET_OK !=
473 GNUNET_log_setup ("libgnunet",
474 "DEBUG",// loglev,
475 logfile))
476 {
477 GNUNET_break (0);
478 goto error;
479 }
480 if (NULL == cfg)
481 {
483 if (NULL != opt_cfg_filename)
484 {
485 if ( (GNUNET_YES !=
486 GNUNET_DISK_file_test (opt_cfg_filename)) ||
487 (GNUNET_SYSERR ==
489 opt_cfg_filename)) )
490 {
492 _ ("Malformed configuration file `%s', exit ...\n"),
493 opt_cfg_filename);
494 goto error;
495 }
496 }
497 else
498 {
499 if (GNUNET_YES ==
501 {
502 if (GNUNET_SYSERR ==
505 {
507 _ ("Malformed configuration file `%s', exit ...\n"),
510 goto error;;
511 }
512 }
513 else
514 {
515 if (GNUNET_SYSERR ==
517 NULL))
518 {
520 _ ("Malformed configuration, exit ...\n"));
522 goto error;
523 }
524 }
525 }
526 }
527
528 GNUNET_free (logfile);
529 GNUNET_free (loglev);
531 GNUNET_free (opt_cfg_filename);
532
533 return GNUNET_OK;
534
535error:
538 GNUNET_free (logfile);
539 GNUNET_free (loglev);
541 GNUNET_free (opt_cfg_filename);
542
543 return GNUNET_SYSERR;
544}
545
546
547static void
548monolith_main (void *cls)
549{
550 struct GNUNET_CONFIGURATION_Handle *cfg = cls;
551
553 NULL,
554 cfg,
555 GNUNET_NO);
557 NULL,
558 cfg,
559 GNUNET_NO);
560}
561
562
563void
565 char *const *argv,
567{
568
570 argv,
571 cfg))
572 return;
574 cfg);
575}
576
577
578/* A list of daemons to be launched when GNUNET_main()
579 * is called
580 */
582{
583 /* DLL */
585
586 /* DLL */
588
589 /* Program to launch */
591
593
594 const char *daemon_name;
595};
596
597/* The daemon list */
598static struct DaemonHandleList *hll_head = NULL;
599
600/* The daemon list */
601static struct DaemonHandleList *hll_tail = NULL;
602
603static void
604launch_daemon (void *cls)
605{
606 struct DaemonHandleList *hll = cls;
607
608 // FIXME read from config argv argc?
609 hll->d (NULL, NULL, NULL, hll->cfg);
610}
611
612
613static void
614launch_daemons (void *cls)
615{
616 struct GNUNET_CONFIGURATION_Handle *cfg = cls;
617
618 for (struct DaemonHandleList *hll = hll_head;
619 NULL != hll;
620 hll = hll->next)
621 {
623 "Launching daemon %s\n",
624 hll->daemon_name);
625 hll->cfg = cfg;
627 hll);
628 }
629}
630
631
632void
634 char *const *argv,
636 enum GNUNET_GenericReturnValue with_scheduler)
637{
639 "Entering GNUNET_DAEMON_main\n");
640 if (GNUNET_YES == with_scheduler)
641 {
643 argv,
644 cfg))
645 return;
647 cfg);
648 }
649 else
651}
652
653
655GNUNET_DAEMON_register (const char *daemon_name,
656 const char *daemon_help,
658{
659 struct DaemonHandleList *hle;
660
662 "registering daemon %s\n",
664 hle = GNUNET_new (struct DaemonHandleList);
665 hle->d = task;
668 return GNUNET_OK;
669}
670
671
672/* end of program.c */
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_OPTION_END
Definition: 002.c:13
struct GNUNET_GETOPT_CommandLineOption options[]
Definition: 002.c:5
char * getenv()
#define gettext_noop(String)
Definition: gettext.h:74
#define textdomain(Domainname)
Definition: gettext.h:61
#define bindtextdomain(Domainname, Dirname)
Definition: gettext.h:62
static int ret
Final status code.
Definition: gnunet-arm.c:93
static struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
Definition: gnunet-arm.c:108
static char * cfg_filename
Name of the configuration file.
static void cleanup(void *cls)
Disconnect and shutdown.
Definition: gnunet-did.c:130
static char * name
Name (label) of the records to list.
Functions related to doing DNS lookups.
void GNUNET_CONFIGURATION_set_value_string(struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, const char *value)
Set a configuration value that should be a string.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_number(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long *number)
Get a configuration value that should be a number.
void GNUNET_CONFIGURATION_destroy(struct GNUNET_CONFIGURATION_Handle *cfg)
Destroy configuration object.
char * GNUNET_CONFIGURATION_default_filename(void)
Return the filename of the default configuration filename that is used when no explicit configuration...
struct GNUNET_CONFIGURATION_Handle * GNUNET_CONFIGURATION_create(void)
Create a new configuration object.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_load(struct GNUNET_CONFIGURATION_Handle *cfg, const char *filename)
Load configuration.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_have_value(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Test if we have a value for a particular option.
enum GNUNET_GenericReturnValue GNUNET_DISK_file_test(const char *fil)
Check that fil corresponds to a filename (of a file that exists and that is not a directory).
Definition: disk.c:483
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_option_cfgfile(char **fn)
Allow user to specify configuration file name (-c option)
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_option_logfile(char **logfn)
Allow user to specify log file name (-l option)
int GNUNET_GETOPT_run(const char *binaryOptions, const struct GNUNET_GETOPT_CommandLineOption *allOptions, unsigned int argc, char *const *argv)
Parse the command line.
Definition: getopt.c:884
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_option_help(const char *about)
Defining the option to print the command line help text (-h option).
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_option_loglevel(char **level)
Define the '-L' log level option.
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_option_flag(char shortName, const char *name, const char *description, int *val)
Allow user to specify a flag (which internally means setting an integer to 1/GNUNET_YES/GNUNET_OK.
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_option_version(const char *version)
Define the option to print the version of the application (-v option)
#define GNUNET_log(kind,...)
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
GNUNET_GenericReturnValue
Named constants for return values.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
enum GNUNET_GenericReturnValue GNUNET_log_setup(const char *comp, const char *loglevel, const char *logfile)
Setup logging.
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_new_array(n, type)
Allocate a size n array with structs or unions of the given type.
#define GNUNET_array_append(arr, len, element)
Append an element to an array (growing the array by one).
#define GNUNET_free(ptr)
Wrapper around free.
char * GNUNET_OS_installation_get_path(enum GNUNET_OS_InstallationPathKind dirkind)
Get the path to a specific GNUnet installation directory or, with GNUNET_OS_IPK_SELF_PREFIX,...
const struct GNUNET_OS_ProjectData * GNUNET_OS_project_data_get(void)
@ GNUNET_OS_IPK_LOCALEDIR
Return the directory where translations are installed (share/locale/)
enum GNUNET_GenericReturnValue GNUNET_DAEMON_register(const char *daemon_name, const char *daemon_help, GNUNET_PROGRAM_Main task)
Definition: program.c:655
void GNUNET_DAEMON_main(int argc, char *const *argv, struct GNUNET_CONFIGURATION_Handle *cfg, enum GNUNET_GenericReturnValue with_scheduler)
Run the mainloop in a monolithic libgnunet.
Definition: program.c:633
enum GNUNET_GenericReturnValue GNUNET_PROGRAM_run2(int argc, char *const *argv, const char *binaryName, const char *binaryHelp, const struct GNUNET_GETOPT_CommandLineOption *options, GNUNET_PROGRAM_Main task, void *task_cls, int run_without_scheduler)
Run a standard GNUnet command startup sequence (initialize loggers and configuration,...
Definition: program.c:132
void(* GNUNET_PROGRAM_Main)(void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg)
Main function that will be run.
void GNUNET_PROGRAM_monolith_main(int argc, char *const *argv, struct GNUNET_CONFIGURATION_Handle *cfg)
Start all services and daemons in a single process.
Definition: program.c:564
enum GNUNET_GenericReturnValue GNUNET_PROGRAM_run(int argc, char *const *argv, const char *binaryName, const char *binaryHelp, const struct GNUNET_GETOPT_CommandLineOption *options, GNUNET_PROGRAM_Main task, void *task_cls)
Run a standard GNUnet command startup sequence (initialize loggers and configuration,...
Definition: program.c:400
enum GNUNET_GenericReturnValue GNUNET_PROGRAM_conf_and_options(int argc, char *const *argv, struct GNUNET_CONFIGURATION_Handle *cfg)
Create configuration handle from options and configuration file.
Definition: program.c:420
void GNUNET_RESOLVER_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Create the connection to the resolver service.
Definition: resolver_api.c:258
void GNUNET_SCHEDULER_run(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Initialize and run scheduler.
Definition: scheduler.c:724
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received,...
Definition: scheduler.c:1338
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition: scheduler.c:1303
void GNUNET_SERVICE_main(int argc, char *const *argv, struct GNUNET_CONFIGURATION_Handle *cfg, enum GNUNET_GenericReturnValue with_scheduler)
Run the mainloop in a monolithic libgnunet.
Definition: service.c:2270
void GNUNET_TIME_set_offset(long long offset)
Set the timestamp offset for this instance.
Definition: time.c:49
#define DIR_SEPARATOR_STR
Definition: platform.h:166
#define _(String)
GNU gettext support macro.
Definition: platform.h:178
static void launch_daemon(void *cls)
Definition: program.c:604
static struct DaemonHandleList * hll_tail
Definition: program.c:601
static void monolith_main(void *cls)
Definition: program.c:548
static struct DaemonHandleList * hll_head
Definition: program.c:598
static void shutdown_task(void *cls)
task run when the scheduler shuts down
Definition: program.c:76
static void launch_daemons(void *cls)
Definition: program.c:614
static void program_main(void *cls)
Initial task called by the scheduler for each program.
Definition: program.c:88
static int cmd_sorter(const void *a1, const void *a2)
Compare function for 'qsort' to sort command-line arguments by the short option.
Definition: program.c:111
#define LOG(kind,...)
Definition: program.c:35
int GNUNET_SPEEDUP_start_(const struct GNUNET_CONFIGURATION_Handle *cfg)
Start task that may speed up our system clock artificially.
Definition: speedup.c:60
void GNUNET_SPEEDUP_stop_()
Stop tasks that modify clock behavior.
Definition: speedup.c:100
Context for the command.
Definition: program.c:44
void * task_cls
Closure for task.
Definition: program.c:63
char *const * args
Argv argument.
Definition: program.c:48
const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration to use.
Definition: program.c:68
GNUNET_PROGRAM_Main task
Main function to run.
Definition: program.c:58
char * cfgfile
Name of the configuration file used, can be NULL!
Definition: program.c:53
const struct GNUNET_CONFIGURATION_Handle * cfg
Definition: program.c:592
GNUNET_PROGRAM_Main d
Definition: program.c:590
struct DaemonHandleList * next
Definition: program.c:587
struct DaemonHandleList * prev
Definition: program.c:584
const char * daemon_name
Definition: program.c:594
Definition of a command line option.
const char * name
Long name of the option (may not be NULL)
const char shortName
Short name of the option.
Project-specific data used to help the OS subsystem find installation paths.
const char * gettext_path
Gettext directory, e.g.
const char * gettext_domain
Gettext domain for localisation, e.g.
const char * user_config_file
Configuration file name to use (if $XDG_CONFIG_HOME is not set).
const char * config_file
Configuration file name (in $XDG_CONFIG_HOME) to use.
const char * version
String identifying the current project version.