aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/include/gnunet_getopt_lib.h46
-rw-r--r--src/util/getopt.c56
-rw-r--r--src/util/getopt_helpers.c105
-rw-r--r--src/util/test_getopt.c30
4 files changed, 205 insertions, 32 deletions
diff --git a/src/include/gnunet_getopt_lib.h b/src/include/gnunet_getopt_lib.h
index cd546905e..0acf15679 100644
--- a/src/include/gnunet_getopt_lib.h
+++ b/src/include/gnunet_getopt_lib.h
@@ -136,6 +136,12 @@ struct GNUNET_GETOPT_CommandLineOption
136 GNUNET_GETOPT_CommandLineOptionProcessor processor; 136 GNUNET_GETOPT_CommandLineOptionProcessor processor;
137 137
138 /** 138 /**
139 * Function to call on @e scls to clean up after processing all
140 * the arguments. Can be NULL.
141 */
142 void (*cleaner)(void *cls);
143
144 /**
139 * Specific closure to pass to the processor. 145 * Specific closure to pass to the processor.
140 */ 146 */
141 void *scls; 147 void *scls;
@@ -207,6 +213,42 @@ GNUNET_GETOPT_OPTION_FILENAME (char shortName,
207 213
208 214
209/** 215/**
216 * Allow user to specify a binary value using Crockford
217 * Base32 encoding.
218 *
219 * @param shortName short name of the option
220 * @param name long name of the option
221 * @param argumentHelp help text for the option argument
222 * @param description long help text for the option
223 * @param[out] val binary value decoded from Crockford Base32-encoded argument
224 * @param val_size size of @a val in bytes
225 */
226struct GNUNET_GETOPT_CommandLineOption
227GNUNET_GETOPT_OPTION_SET_BASE32_FIXED_SIZE (char shortName,
228 const char *name,
229 const char *argumentHelp,
230 const char *description,
231 void *val,
232 size_t val_size);
233
234
235/**
236 * Allow user to specify a binary value using Crockford
237 * Base32 encoding where the size of the binary value is
238 * automatically determined from its type.
239 *
240 * @param shortName short name of the option
241 * @param name long name of the option
242 * @param argumentHelp help text for the option argument
243 * @param description long help text for the option
244 * @param[out] val binary value decoded from Crockford Base32-encoded argument;
245 * size is determined by type (sizeof (*val)).
246 */
247#define GNUNET_GETOPT_OPTION_SET_BASE32_AUTO(shortName,name,argumentHelp,description,val) \
248 GNUNET_GETOPT_OPTION_SET_BASE32_FIXED_SIZE(shortName,name,argumentHelp,description,val,sizeof(*val))
249
250
251/**
210 * Allow user to specify a flag (which internally means setting 252 * Allow user to specify a flag (which internally means setting
211 * an integer to 1/#GNUNET_YES/#GNUNET_OK. 253 * an integer to 1/#GNUNET_YES/#GNUNET_OK.
212 * 254 *
@@ -307,7 +349,7 @@ GNUNET_GETOPT_OPTION_LOGLEVEL (char **level);
307 * @param[out] level set to the verbosity level 349 * @param[out] level set to the verbosity level
308 */ 350 */
309struct GNUNET_GETOPT_CommandLineOption 351struct GNUNET_GETOPT_CommandLineOption
310GNUNET_GETOPT_OPTION_VERBOSE (int *level); 352GNUNET_GETOPT_OPTION_VERBOSE (unsigned int *level);
311 353
312 354
313/** 355/**
@@ -332,7 +374,7 @@ GNUNET_GETOPT_OPTION_CFG_FILE (char **fn);
332 * Marker for the end of the list of options. 374 * Marker for the end of the list of options.
333 */ 375 */
334#define GNUNET_GETOPT_OPTION_END \ 376#define GNUNET_GETOPT_OPTION_END \
335 { '\0', NULL, NULL, NULL, 0, NULL, NULL } 377 { '\0', NULL, NULL, NULL, 0, NULL, NULL, NULL }
336 378
337 379
338/** 380/**
diff --git a/src/util/getopt.c b/src/util/getopt.c
index ff62dba9b..85f67500c 100644
--- a/src/util/getopt.c
+++ b/src/util/getopt.c
@@ -26,7 +26,7 @@ USA.
26 26
27 27
28This code was heavily modified for GNUnet. 28This code was heavily modified for GNUnet.
29Copyright Copyright (C) 2006 Christian Grothoff 29Copyright Copyright (C) 2006, 2017 Christian Grothoff
30*/ 30*/
31 31
32/** 32/**
@@ -845,9 +845,13 @@ GN_getopt_internal (int argc, char *const *argv, const char *optstring,
845 } 845 }
846} 846}
847 847
848
848static int 849static int
849GNgetopt_long (int argc, char *const *argv, const char *options, 850GNgetopt_long (int argc,
850 const struct GNoption *long_options, int *opt_index) 851 char *const *argv,
852 const char *options,
853 const struct GNoption *long_options,
854 int *opt_index)
851{ 855{
852 return GN_getopt_internal (argc, argv, options, long_options, opt_index, 0); 856 return GN_getopt_internal (argc, argv, options, long_options, opt_index, 0);
853} 857}
@@ -867,12 +871,12 @@ GNgetopt_long (int argc, char *const *argv, const char *options,
867int 871int
868GNUNET_GETOPT_run (const char *binaryOptions, 872GNUNET_GETOPT_run (const char *binaryOptions,
869 const struct GNUNET_GETOPT_CommandLineOption *allOptions, 873 const struct GNUNET_GETOPT_CommandLineOption *allOptions,
870 unsigned int argc, char *const *argv) 874 unsigned int argc,
875 char *const *argv)
871{ 876{
872 struct GNoption *long_options; 877 struct GNoption *long_options;
873 struct GNUNET_GETOPT_CommandLineProcessorContext clpc; 878 struct GNUNET_GETOPT_CommandLineProcessorContext clpc;
874 int count; 879 int count;
875 int i;
876 char *shorts; 880 char *shorts;
877 int spos; 881 int spos;
878 int cont; 882 int cont;
@@ -885,13 +889,13 @@ GNUNET_GETOPT_run (const char *binaryOptions,
885 clpc.allOptions = allOptions; 889 clpc.allOptions = allOptions;
886 clpc.argv = argv; 890 clpc.argv = argv;
887 clpc.argc = argc; 891 clpc.argc = argc;
888 count = 0; 892 for (count = 0; NULL != allOptions[count].name; count++) ;
889 while (allOptions[count].name != NULL) 893
890 count++; 894 long_options = GNUNET_new_array (count + 1,
891 long_options = GNUNET_malloc (sizeof (struct GNoption) * (count + 1)); 895 struct GNoption);
892 shorts = GNUNET_malloc (count * 2 + 1); 896 shorts = GNUNET_malloc (count * 2 + 1);
893 spos = 0; 897 spos = 0;
894 for (i = 0; i < count; i++) 898 for (unsigned i = 0; i < count; i++)
895 { 899 {
896 long_options[i].name = allOptions[i].name; 900 long_options[i].name = allOptions[i].name;
897 long_options[i].has_arg = allOptions[i].require_argument; 901 long_options[i].has_arg = allOptions[i].require_argument;
@@ -907,13 +911,17 @@ GNUNET_GETOPT_run (const char *binaryOptions,
907 long_options[count].val = '\0'; 911 long_options[count].val = '\0';
908 shorts[spos] = '\0'; 912 shorts[spos] = '\0';
909 cont = GNUNET_OK; 913 cont = GNUNET_OK;
914
910 /* main getopt loop */ 915 /* main getopt loop */
911 while (cont == GNUNET_OK) 916 while (GNUNET_OK == cont)
912 { 917 {
913 int option_index = 0; 918 int option_index = 0;
919 unsigned int i;
914 920
915 c = GNgetopt_long (argc, argv, shorts, long_options, &option_index); 921 c = GNgetopt_long (argc, argv,
916 922 shorts,
923 long_options,
924 &option_index);
917 if (c == GNUNET_SYSERR) 925 if (c == GNUNET_SYSERR)
918 break; /* No more flags to process */ 926 break; /* No more flags to process */
919 927
@@ -922,25 +930,31 @@ GNUNET_GETOPT_run (const char *binaryOptions,
922 clpc.currentArgument = GNoptind - 1; 930 clpc.currentArgument = GNoptind - 1;
923 if ((char) c == allOptions[i].shortName) 931 if ((char) c == allOptions[i].shortName)
924 { 932 {
925 cont = 933 cont = allOptions[i].processor (&clpc,
926 allOptions[i].processor (&clpc, allOptions[i].scls, 934 allOptions[i].scls,
927 allOptions[i].name, GNoptarg); 935 allOptions[i].name,
936 GNoptarg);
928 break; 937 break;
929 } 938 }
930 } 939 }
931 if (i == count) 940 if (i == count)
932 { 941 {
933 FPRINTF (stderr, _("Use %s to get a list of options.\n"), "--help"); 942 FPRINTF (stderr,
943 _("Use %s to get a list of options.\n"),
944 "--help");
934 cont = GNUNET_SYSERR; 945 cont = GNUNET_SYSERR;
935 } 946 }
936 } 947 }
937
938 GNUNET_free (shorts); 948 GNUNET_free (shorts);
939 GNUNET_free (long_options); 949 GNUNET_free (long_options);
940 if (cont != GNUNET_OK) 950
941 { 951 /* call cleaners, if available */
952 for (count = 0; NULL != allOptions[count].name; count++)
953 if (NULL != allOptions[count].cleaner)
954 allOptions[count].cleaner (allOptions[count].scls);
955
956 if (GNUNET_OK != cont)
942 return cont; 957 return cont;
943 }
944 return GNoptind; 958 return GNoptind;
945} 959}
946 960
diff --git a/src/util/getopt_helpers.c b/src/util/getopt_helpers.c
index 234f5371f..9f6f4c764 100644
--- a/src/util/getopt_helpers.c
+++ b/src/util/getopt_helpers.c
@@ -266,7 +266,7 @@ GNUNET_GETOPT_OPTION_INCREMENT_VALUE (char shortName,
266 * @param[out] level set to the verbosity level 266 * @param[out] level set to the verbosity level
267 */ 267 */
268struct GNUNET_GETOPT_CommandLineOption 268struct GNUNET_GETOPT_CommandLineOption
269GNUNET_GETOPT_OPTION_VERBOSE (int *level) 269GNUNET_GETOPT_OPTION_VERBOSE (unsigned int *level)
270{ 270{
271 struct GNUNET_GETOPT_CommandLineOption clo = { 271 struct GNUNET_GETOPT_CommandLineOption clo = {
272 .shortName = 'V', 272 .shortName = 'V',
@@ -710,4 +710,107 @@ GNUNET_GETOPT_OPTION_SET_UINT (char shortName,
710} 710}
711 711
712 712
713/**
714 * Closure for #set_base32().
715 */
716struct Base32Context
717{
718 /**
719 * Value to initialize (already allocated)
720 */
721 void *val;
722
723 /**
724 * Number of bytes expected for @e val.
725 */
726 size_t val_size;
727};
728
729
730/**
731 * Set an option of type 'unsigned int' from the command line.
732 * A pointer to this function should be passed as part of the
733 * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
734 * of this type. It should be followed by a pointer to a value of
735 * type 'unsigned int'.
736 *
737 * @param ctx command line processing context
738 * @param scls additional closure (will point to the 'unsigned int')
739 * @param option name of the option
740 * @param value actual value of the option as a string.
741 * @return #GNUNET_OK if parsing the value worked
742 */
743static int
744set_base32 (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
745 void *scls,
746 const char *option,
747 const char *value)
748{
749 struct Base32Context *bc = scls;
750
751 if (GNUNET_OK !=
752 GNUNET_STRINGS_string_to_data (value,
753 strlen (value),
754 bc->val,
755 bc->val_size))
756 {
757 fprintf (stderr,
758 _("Argument `%s' malformed. Expected base32 (Crockford) encoded value.\n"),
759 option);
760 return GNUNET_SYSERR;
761 }
762 return GNUNET_OK;
763}
764
765
766/**
767 * Helper function to clean up after
768 * #GNUNET_GETOPT_OPTION_SET_BASE32_FIXED_SIZE.
769 *
770 * @param cls value to GNUNET_free()
771 */
772static void
773free_bc (void *cls)
774{
775 GNUNET_free (cls);
776}
777
778
779/**
780 * Allow user to specify a binary value using Crockford
781 * Base32 encoding.
782 *
783 * @param shortName short name of the option
784 * @param name long name of the option
785 * @param argumentHelp help text for the option argument
786 * @param description long help text for the option
787 * @param[out] val binary value decoded from Crockford Base32-encoded argument
788 * @param val_size size of @a val in bytes
789 */
790struct GNUNET_GETOPT_CommandLineOption
791GNUNET_GETOPT_OPTION_SET_BASE32_FIXED_SIZE (char shortName,
792 const char *name,
793 const char *argumentHelp,
794 const char *description,
795 void *val,
796 size_t val_size)
797{
798 struct Base32Context *bc = GNUNET_new (struct Base32Context);
799 struct GNUNET_GETOPT_CommandLineOption clo = {
800 .shortName = shortName,
801 .name = name,
802 .argumentHelp = argumentHelp,
803 .description = description,
804 .require_argument = 1,
805 .processor = &set_base32,
806 .cleaner = &free_bc,
807 .scls = (void *) bc
808 };
809
810 bc->val = val;
811 bc->val_size = val_size;
812 return clo;
813}
814
815
713/* end of getopt_helpers.c */ 816/* end of getopt_helpers.c */
diff --git a/src/util/test_getopt.c b/src/util/test_getopt.c
index 8e578640d..faa6a07a1 100644
--- a/src/util/test_getopt.c
+++ b/src/util/test_getopt.c
@@ -170,21 +170,35 @@ testFlagNum ()
170 unsigned long long lnum = 0; 170 unsigned long long lnum = 0;
171 171
172 const struct GNUNET_GETOPT_CommandLineOption logoptionlist[] = { 172 const struct GNUNET_GETOPT_CommandLineOption logoptionlist[] = {
173 {'f', "--flag", NULL, "helptext", 0, &GNUNET_GETOPT_set_one, 173 GNUNET_GETOPT_OPTION_SET_ONE ('f',
174 (void *) &flag}, 174 "--flag",
175 {'n', "--num", "ARG", "helptext", 1, &GNUNET_GETOPT_set_uint, 175 "helptext",
176 (void *) &num}, 176 &flag),
177 {'N', "--lnum", "ARG", "helptext", 1, &GNUNET_GETOPT_set_ulong, 177 GNUNET_GETOPT_OPTION_SET_UINT ('n',
178 (void *) &lnum}, 178 "--num",
179 "ARG",
180 "helptext",
181 &num),
182 GNUNET_GETOPT_OPTION_SET_ULONG ('N',
183 "--lnum",
184 "ARG",
185 "helptext",
186 &lnum),
179 GNUNET_GETOPT_OPTION_END 187 GNUNET_GETOPT_OPTION_END
180 }; 188 };
181 189
182 if (6 != GNUNET_GETOPT_run ("test_getopt", logoptionlist, 6, myargv)) 190 if (6 !=
191 GNUNET_GETOPT_run ("test_getopt",
192 logoptionlist,
193 6,
194 myargv))
183 { 195 {
184 GNUNET_break (0); 196 GNUNET_break (0);
185 return 1; 197 return 1;
186 } 198 }
187 if ((1 != flag) || (42 != num) || (42 != lnum)) 199 if ( (1 != flag) ||
200 (42 != num) ||
201 (42 != lnum))
188 { 202 {
189 GNUNET_break (0); 203 GNUNET_break (0);
190 return 1; 204 return 1;