aboutsummaryrefslogtreecommitdiff
path: root/src/util
diff options
context:
space:
mode:
Diffstat (limited to 'src/util')
-rw-r--r--src/util/getopt.c56
-rw-r--r--src/util/getopt_helpers.c105
-rw-r--r--src/util/test_getopt.c30
3 files changed, 161 insertions, 30 deletions
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;