2 This file is part of GNUnet
3 Copyright (C) 2006, 2011, 2020 GNUnet e.V.
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.
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 Affero General Public License for more details.
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/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
22 * @file src/util/getopt_helpers.c
23 * @brief implements command line that sets option
24 * @author Christian Grothoff
27 #include "gnunet_util_lib.h"
29 #define LOG(kind, ...) GNUNET_log_from (kind, "util-getopt", __VA_ARGS__)
33 * Print out program version (implements --version).
35 * @param ctx command line processing context
36 * @param scls additional closure (points to version string)
37 * @param option name of the option
38 * @param value not used (NULL)
39 * @return #GNUNET_NO (do not continue, not an error)
42 print_version (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
47 const char *version = scls;
51 printf ("%s v%s\n", ctx->binaryName, version);
57 * Define the option to print the version of
58 * the application (-v option)
60 * @param version string with the version number
62 struct GNUNET_GETOPT_CommandLineOption
63 GNUNET_GETOPT_option_version (const char *version)
65 struct GNUNET_GETOPT_CommandLineOption clo = {
68 .description = gettext_noop (
69 "print the version number"),
70 .option_exclusive = 1,
71 .processor = &print_version,
72 .scls = (void *) version
80 * At what offset does the help text start?
85 * Print out details on command line options (implements --help).
87 * @param ctx command line processing context
88 * @param scls additional closure (points to about text)
89 * @param option name of the option
90 * @param value not used (NULL)
91 * @return #GNUNET_NO (do not continue, not an error)
94 format_help (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
99 const char *about = scls;
107 const struct GNUNET_GETOPT_CommandLineOption *opt;
108 const struct GNUNET_OS_ProjectData *pd;
114 printf ("%s\n%s\n", ctx->binaryOptions, gettext (about));
116 "Arguments mandatory for long options are also mandatory for short options.\n"));
119 opt = ctx->allOptions;
120 while (NULL != opt[i].description)
122 if (opt[i].shortName == '\0')
125 printf (" -%c, ", opt[i].shortName);
126 printf ("--%s", opt[i].name);
127 slen = 8 + strlen (opt[i].name);
128 if (NULL != opt[i].argumentHelp)
130 printf ("=%s", opt[i].argumentHelp);
131 slen += 1 + strlen (opt[i].argumentHelp);
135 printf ("\n%*s", BORDER, "");
140 printf ("%*s", (int) (BORDER - slen), "");
143 if (0 < strlen (opt[i].description))
144 trans = gettext (opt[i].description);
150 while (ml - p > 78 - slen)
152 for (j = p + 78 - slen; j > (int) p; j--)
154 if (isspace ((unsigned char) trans[j]))
156 scp = GNUNET_malloc (j - p + 1);
157 GNUNET_memcpy (scp, &trans[p], j - p);
159 printf ("%s\n%*s", scp, BORDER + 2, "");
166 /* could not find space to break line */
167 scp = GNUNET_malloc (78 - slen + 1);
168 GNUNET_memcpy (scp, &trans[p], 78 - slen);
169 scp[78 - slen] = '\0';
170 printf ("%s\n%*s", scp, BORDER + 2, "");
177 printf ("%s\n", &trans[p]);
178 if (strlen (trans) == 0)
182 pd = GNUNET_OS_project_data_get ();
183 printf ("Report bugs to %s.\n"
189 printf ("General help using GNU software: http://www.gnu.org/gethelp/\n");
196 * Defining the option to print the command line
197 * help text (-h option).
199 * @param about string with brief description of the application
201 struct GNUNET_GETOPT_CommandLineOption
202 GNUNET_GETOPT_option_help (const char *about)
204 struct GNUNET_GETOPT_CommandLineOption clo = {
207 .description = gettext_noop (
209 .option_exclusive = 1,
210 .processor = format_help,
211 .scls = (void *) about
219 * Set an option of type 'unsigned int' from the command line. Each
220 * time the option flag is given, the value is incremented by one.
221 * A pointer to this function should be passed as part of the
222 * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
223 * of this type. It should be followed by a pointer to a value of
226 * @param ctx command line processing context
227 * @param scls additional closure (will point to the 'unsigned int')
228 * @param option name of the option
229 * @param value not used (NULL)
233 increment_value (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
238 unsigned int *val = scls;
249 * Increment @a val each time the option flag is given by one.
251 * @param shortName short name of the option
252 * @param name long name of the option
253 * @param argumentHelp help text for the option argument
254 * @param description long help text for the option
255 * @param[out] val increment by 1 each time the option is present
257 struct GNUNET_GETOPT_CommandLineOption
258 GNUNET_GETOPT_option_increment_uint (char shortName,
260 const char *description,
263 struct GNUNET_GETOPT_CommandLineOption clo = {
264 .shortName = shortName,
266 .description = description,
267 .processor = &increment_value,
276 * Define the '-V' verbosity option. Using the option more
277 * than once increments @a level each time.
279 * @param[out] level set to the verbosity level
281 struct GNUNET_GETOPT_CommandLineOption
282 GNUNET_GETOPT_option_verbose (unsigned int *level)
284 struct GNUNET_GETOPT_CommandLineOption clo = {
288 gettext_noop ("be verbose"),
289 .processor = &increment_value,
290 .scls = (void *) level
298 * Set an option of type 'int' from the command line to 1 if the
299 * given option is present.
300 * A pointer to this function should be passed as part of the
301 * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
302 * of this type. It should be followed by a pointer to a value of
305 * @param ctx command line processing context
306 * @param scls additional closure (will point to the 'int')
307 * @param option name of the option
308 * @param value not used (NULL)
312 set_one (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
328 * Allow user to specify a flag (which internally means setting
329 * an integer to 1/#GNUNET_YES/#GNUNET_OK.
331 * @param shortName short name of the option
332 * @param name long name of the option
333 * @param argumentHelp help text for the option argument
334 * @param description long help text for the option
335 * @param[out] val set to 1 if the option is present
337 struct GNUNET_GETOPT_CommandLineOption
338 GNUNET_GETOPT_option_flag (char shortName,
340 const char *description,
343 struct GNUNET_GETOPT_CommandLineOption clo = {
344 .shortName = shortName,
346 .description = description,
347 .processor = &set_one,
356 * Set an option of type 'char *' from the command line.
357 * A pointer to this function should be passed as part of the
358 * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
359 * of this type. It should be followed by a pointer to a value of
360 * type 'char *', which will be allocated with the requested string.
362 * @param ctx command line processing context
363 * @param scls additional closure (will point to the 'char *',
364 * which will be allocated)
365 * @param option name of the option
366 * @param value actual value of the option (a string)
370 set_string (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
379 GNUNET_assert (NULL != value);
380 GNUNET_free_non_null (*val);
381 *val = GNUNET_strdup (value);
387 * Allow user to specify a string.
389 * @param shortName short name of the option
390 * @param name long name of the option
391 * @param argumentHelp help text for the option argument
392 * @param description long help text for the option
393 * @param[out] str set to the string
395 struct GNUNET_GETOPT_CommandLineOption
396 GNUNET_GETOPT_option_string (char shortName,
398 const char *argumentHelp,
399 const char *description,
402 struct GNUNET_GETOPT_CommandLineOption clo = {
403 .shortName = shortName,
405 .argumentHelp = argumentHelp,
406 .description = description,
407 .require_argument = 1,
408 .processor = &set_string,
417 * Define the '-L' log level option. Note that we do not check
418 * that the log level is valid here.
420 * @param[out] level set to the log level
422 struct GNUNET_GETOPT_CommandLineOption
423 GNUNET_GETOPT_option_loglevel (char **level)
425 struct GNUNET_GETOPT_CommandLineOption clo = {
428 .argumentHelp = "LOGLEVEL",
429 .description = gettext_noop ("configure logging to use LOGLEVEL"),
430 .require_argument = 1,
431 .processor = &set_string,
432 .scls = (void *) level
440 * Set an option of type 'char *' from the command line with
441 * filename expansion a la #GNUNET_STRINGS_filename_expand().
443 * @param ctx command line processing context
444 * @param scls additional closure (will point to the `char *`,
445 * which will be allocated)
446 * @param option name of the option
447 * @param value actual value of the option (a string)
451 set_filename (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
460 GNUNET_assert (NULL != value);
461 GNUNET_free_non_null (*val);
462 *val = GNUNET_STRINGS_filename_expand (value);
468 * Allow user to specify a filename (automatically path expanded).
470 * @param shortName short name of the option
471 * @param name long name of the option
472 * @param argumentHelp help text for the option argument
473 * @param description long help text for the option
474 * @param[out] str set to the string
476 struct GNUNET_GETOPT_CommandLineOption
477 GNUNET_GETOPT_option_filename (char shortName,
479 const char *argumentHelp,
480 const char *description,
483 struct GNUNET_GETOPT_CommandLineOption clo = {
484 .shortName = shortName,
486 .argumentHelp = argumentHelp,
487 .description = description,
488 .require_argument = 1,
489 .processor = &set_filename,
498 * Allow user to specify log file name (-l option)
500 * @param[out] logfn set to the name of the logfile
502 struct GNUNET_GETOPT_CommandLineOption
503 GNUNET_GETOPT_option_logfile (char **logfn)
505 struct GNUNET_GETOPT_CommandLineOption clo = {
508 .argumentHelp = "FILENAME",
510 gettext_noop ("configure logging to write logs to FILENAME"),
511 .require_argument = 1,
512 .processor = &set_filename,
513 .scls = (void *) logfn
521 * Allow user to specify configuration file name (-c option)
523 * @param[out] fn set to the name of the configuration file
525 struct GNUNET_GETOPT_CommandLineOption
526 GNUNET_GETOPT_option_cfgfile (char **fn)
528 struct GNUNET_GETOPT_CommandLineOption clo = {
531 .argumentHelp = "FILENAME",
532 .description = gettext_noop ("use configuration file FILENAME"),
533 .require_argument = 1,
534 .processor = &set_filename,
543 * Set an option of type 'unsigned long long' from the command line.
544 * A pointer to this function should be passed as part of the
545 * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
546 * of this type. It should be followed by a pointer to a value of
547 * type 'unsigned long long'.
549 * @param ctx command line processing context
550 * @param scls additional closure (will point to the 'unsigned long long')
551 * @param option name of the option
552 * @param value actual value of the option as a string.
553 * @return #GNUNET_OK if parsing the value worked
556 set_ulong (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
561 unsigned long long *val = scls;
565 if (1 != sscanf (value, "%llu%1s", val, dummy))
568 _ ("You must pass a number to the `%s' option.\n"),
570 return GNUNET_SYSERR;
577 * Allow user to specify an `unsigned long long`
579 * @param shortName short name of the option
580 * @param name long name of the option
581 * @param argumentHelp help text for the option argument
582 * @param description long help text for the option
583 * @param[out] val set to the value specified at the command line
585 struct GNUNET_GETOPT_CommandLineOption
586 GNUNET_GETOPT_option_ulong (char shortName,
588 const char *argumentHelp,
589 const char *description,
590 unsigned long long *val)
592 struct GNUNET_GETOPT_CommandLineOption clo = {
593 .shortName = shortName,
595 .argumentHelp = argumentHelp,
596 .description = description,
597 .require_argument = 1,
598 .processor = &set_ulong,
607 * Set an option of type 'struct GNUNET_TIME_Relative' from the command line.
608 * A pointer to this function should be passed as part of the
609 * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
610 * of this type. It should be followed by a pointer to a value of
611 * type 'struct GNUNET_TIME_Relative'.
613 * @param ctx command line processing context
614 * @param scls additional closure (will point to the 'struct GNUNET_TIME_Relative')
615 * @param option name of the option
616 * @param value actual value of the option as a string.
617 * @return #GNUNET_OK if parsing the value worked
620 set_timetravel_time (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
629 if (1 != sscanf (value,
634 _ ("You must pass a number to the `%s' option.\n"),
636 return GNUNET_SYSERR;
638 GNUNET_TIME_set_offset (delta);
644 * Allow user to specify a `long long` with an offset to add to the current
645 * system time to construct the time seen by the application. Used for
646 * debugging / testing.
648 * @param shortName short name of the option
649 * @param name long name of the option
650 * @param[out] val set to the time specified at the command line
652 struct GNUNET_GETOPT_CommandLineOption
653 GNUNET_GETOPT_option_timetravel (char shortName,
656 struct GNUNET_GETOPT_CommandLineOption clo = {
657 .shortName = shortName,
659 .argumentHelp = _ ("[+/-]MICROSECONDS"),
661 "modify system time by given offset (for debugging/testing only)"),
662 .require_argument = 1,
672 * Set an option of type 'struct GNUNET_TIME_Relative' from the command line.
673 * A pointer to this function should be passed as part of the
674 * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
675 * of this type. It should be followed by a pointer to a value of
676 * type 'struct GNUNET_TIME_Relative'.
678 * @param ctx command line processing context
679 * @param scls additional closure (will point to the 'struct GNUNET_TIME_Relative')
680 * @param option name of the option
681 * @param value actual value of the option as a string.
682 * @return #GNUNET_OK if parsing the value worked
685 set_relative_time (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
690 struct GNUNET_TIME_Relative *val = scls;
693 if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_relative (value, val))
696 _ ("You must pass relative time to the `%s' option.\n"),
698 return GNUNET_SYSERR;
705 * Allow user to specify a `struct GNUNET_TIME_Relative`
706 * (using human-readable "fancy" time).
708 * @param shortName short name of the option
709 * @param name long name of the option
710 * @param argumentHelp help text for the option argument
711 * @param description long help text for the option
712 * @param[out] val set to the time specified at the command line
714 struct GNUNET_GETOPT_CommandLineOption
715 GNUNET_GETOPT_option_relative_time (char shortName,
717 const char *argumentHelp,
718 const char *description,
719 struct GNUNET_TIME_Relative *val)
721 struct GNUNET_GETOPT_CommandLineOption clo = {
722 .shortName = shortName,
724 .argumentHelp = argumentHelp,
725 .description = description,
726 .require_argument = 1,
737 * Set an option of type 'struct GNUNET_TIME_Absolute' from the command line.
738 * A pointer to this function should be passed as part of the
739 * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
740 * of this type. It should be followed by a pointer to a value of
741 * type 'struct GNUNET_TIME_Absolute'.
743 * @param ctx command line processing context
744 * @param scls additional closure (will point to the `struct GNUNET_TIME_Absolute`)
745 * @param option name of the option
746 * @param value actual value of the option as a string.
747 * @return #GNUNET_OK if parsing the value worked
750 set_absolute_time (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
755 struct GNUNET_TIME_Absolute *val = scls;
758 if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_absolute (value, val))
761 _ ("You must pass absolute time to the `%s' option.\n"),
763 return GNUNET_SYSERR;
770 * Allow user to specify a `struct GNUNET_TIME_Absolute`
771 * (using human-readable "fancy" time).
773 * @param shortName short name of the option
774 * @param name long name of the option
775 * @param argumentHelp help text for the option argument
776 * @param description long help text for the option
777 * @param[out] val set to the time specified at the command line
779 struct GNUNET_GETOPT_CommandLineOption
780 GNUNET_GETOPT_option_absolute_time (char shortName,
782 const char *argumentHelp,
783 const char *description,
784 struct GNUNET_TIME_Absolute *val)
786 struct GNUNET_GETOPT_CommandLineOption clo = {
787 .shortName = shortName,
789 .argumentHelp = argumentHelp,
790 .description = description,
791 .require_argument = 1,
802 * Set an option of type 'unsigned int' from the command line.
803 * A pointer to this function should be passed as part of the
804 * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
805 * of this type. It should be followed by a pointer to a value of
806 * type 'unsigned int'.
808 * @param ctx command line processing context
809 * @param scls additional closure (will point to the 'unsigned int')
810 * @param option name of the option
811 * @param value actual value of the option as a string.
812 * @return #GNUNET_OK if parsing the value worked
815 set_uint (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
820 unsigned int *val = scls;
828 "Your input for the '%s' option has to be a non negative number\n"),
830 return GNUNET_SYSERR;
832 if (1 != sscanf (value, "%u%1s", val, dummy))
835 _ ("You must pass a number to the `%s' option.\n"),
837 return GNUNET_SYSERR;
844 * Allow user to specify an unsigned integer.
846 * @param shortName short name of the option
847 * @param name long name of the option
848 * @param argumentHelp help text for the option argument
849 * @param description long help text for the option
850 * @param[out] val set to the value specified at the command line
852 struct GNUNET_GETOPT_CommandLineOption
853 GNUNET_GETOPT_option_uint (char shortName,
855 const char *argumentHelp,
856 const char *description,
859 struct GNUNET_GETOPT_CommandLineOption clo = {
860 .shortName = shortName,
862 .argumentHelp = argumentHelp,
863 .description = description,
864 .require_argument = 1,
865 .processor = &set_uint,
874 * Set an option of type 'uint16_t' from the command line.
875 * A pointer to this function should be passed as part of the
876 * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
877 * of this type. It should be followed by a pointer to a value of
880 * @param ctx command line processing context
881 * @param scls additional closure (will point to the 'unsigned int')
882 * @param option name of the option
883 * @param value actual value of the option as a string.
884 * @return #GNUNET_OK if parsing the value worked
887 set_uint16 (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
892 uint16_t *val = scls;
897 if (1 != sscanf (value, "%u%1s", &v, dummy))
900 _ ("You must pass a number to the `%s' option.\n"),
902 return GNUNET_SYSERR;
907 _ ("You must pass a number below %u to the `%s' option.\n"),
908 (unsigned int) UINT16_MAX,
910 return GNUNET_SYSERR;
918 * Allow user to specify an uint16_t.
920 * @param shortName short name of the option
921 * @param name long name of the option
922 * @param argumentHelp help text for the option argument
923 * @param description long help text for the option
924 * @param[out] val set to the value specified at the command line
926 struct GNUNET_GETOPT_CommandLineOption
927 GNUNET_GETOPT_option_uint16 (char shortName,
929 const char *argumentHelp,
930 const char *description,
933 struct GNUNET_GETOPT_CommandLineOption clo = {
934 .shortName = shortName,
936 .argumentHelp = argumentHelp,
937 .description = description,
938 .require_argument = 1,
939 .processor = &set_uint16,
948 * Closure for #set_base32().
953 * Value to initialize (already allocated)
958 * Number of bytes expected for @e val.
965 * Set an option of type 'unsigned int' from the command line.
966 * A pointer to this function should be passed as part of the
967 * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
968 * of this type. It should be followed by a pointer to a value of
969 * type 'unsigned int'.
971 * @param ctx command line processing context
972 * @param scls additional closure (will point to the 'unsigned int')
973 * @param option name of the option
974 * @param value actual value of the option as a string.
975 * @return #GNUNET_OK if parsing the value worked
978 set_base32 (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
983 struct Base32Context *bc = scls;
986 if (GNUNET_OK != GNUNET_STRINGS_string_to_data (value,
994 "Argument `%s' malformed. Expected base32 (Crockford) encoded value.\n"),
996 return GNUNET_SYSERR;
1003 * Helper function to clean up after
1004 * #GNUNET_GETOPT_option_base32_fixed_size.
1006 * @param cls value to GNUNET_free()
1016 * Allow user to specify a binary value using Crockford
1019 * @param shortName short name of the option
1020 * @param name long name of the option
1021 * @param argumentHelp help text for the option argument
1022 * @param description long help text for the option
1023 * @param[out] val binary value decoded from Crockford Base32-encoded argument
1024 * @param val_size size of @a val in bytes
1026 struct GNUNET_GETOPT_CommandLineOption
1027 GNUNET_GETOPT_option_base32_fixed_size (char shortName,
1029 const char *argumentHelp,
1030 const char *description,
1034 struct Base32Context *bc = GNUNET_new (struct Base32Context);
1035 struct GNUNET_GETOPT_CommandLineOption clo = {
1036 .shortName = shortName,
1038 .argumentHelp = argumentHelp,
1039 .description = description,
1040 .require_argument = 1,
1041 .processor = &set_base32,
1042 .cleaner = &free_bc,
1047 bc->val_size = val_size;
1053 * Make the given option mandatory.
1055 * @param opt option to modify
1056 * @return @a opt with the mandatory flag set.
1058 struct GNUNET_GETOPT_CommandLineOption
1059 GNUNET_GETOPT_option_mandatory (struct GNUNET_GETOPT_CommandLineOption opt)
1061 opt.option_mandatory = 1;
1067 * Make the given option mutually exclusive with other options.
1069 * @param opt option to modify
1070 * @return @a opt with the exclusive flag set.
1072 struct GNUNET_GETOPT_CommandLineOption
1073 GNUNET_GETOPT_option_exclusive (struct GNUNET_GETOPT_CommandLineOption opt)
1075 opt.option_exclusive = 1;
1080 /* end of getopt_helpers.c */