diff options
-rw-r--r-- | src/include/gnunet_getopt_lib.h | 17 | ||||
-rw-r--r-- | src/include/gnunet_json_lib.h | 20 | ||||
-rw-r--r-- | src/json/json.c | 73 | ||||
-rw-r--r-- | src/util/getopt.c | 18 | ||||
-rw-r--r-- | src/util/getopt_helpers.c | 18 | ||||
-rw-r--r-- | src/util/test_getopt.c | 13 | ||||
-rw-r--r-- | src/util/test_program.c | 129 |
7 files changed, 222 insertions, 66 deletions
diff --git a/src/include/gnunet_getopt_lib.h b/src/include/gnunet_getopt_lib.h index bc2e079da..c2bd72340 100644 --- a/src/include/gnunet_getopt_lib.h +++ b/src/include/gnunet_getopt_lib.h | |||
@@ -131,6 +131,11 @@ struct GNUNET_GETOPT_CommandLineOption | |||
131 | int require_argument; | 131 | int require_argument; |
132 | 132 | ||
133 | /** | 133 | /** |
134 | * Is the presence of this option mandatory? | ||
135 | */ | ||
136 | int option_mandatory; | ||
137 | |||
138 | /** | ||
134 | * Handler for the option. | 139 | * Handler for the option. |
135 | */ | 140 | */ |
136 | GNUNET_GETOPT_CommandLineOptionProcessor processor; | 141 | GNUNET_GETOPT_CommandLineOptionProcessor processor; |
@@ -389,10 +394,20 @@ GNUNET_GETOPT_OPTION_CFG_FILE (char **fn); | |||
389 | 394 | ||
390 | 395 | ||
391 | /** | 396 | /** |
397 | * Make the given option mandatory. | ||
398 | * | ||
399 | * @param opt option to modify | ||
400 | * @return @a opt with the mandatory flag set. | ||
401 | */ | ||
402 | struct GNUNET_GETOPT_CommandLineOption | ||
403 | GNUNET_GETOPT_OPTION_MANDATORY (struct GNUNET_GETOPT_CommandLineOption opt); | ||
404 | |||
405 | |||
406 | /** | ||
392 | * Marker for the end of the list of options. | 407 | * Marker for the end of the list of options. |
393 | */ | 408 | */ |
394 | #define GNUNET_GETOPT_OPTION_END \ | 409 | #define GNUNET_GETOPT_OPTION_END \ |
395 | { '\0', NULL, NULL, NULL, 0, NULL, NULL, NULL } | 410 | { '\0', NULL, NULL, NULL, 0, 0, NULL, NULL, NULL } |
396 | 411 | ||
397 | 412 | ||
398 | /** | 413 | /** |
diff --git a/src/include/gnunet_json_lib.h b/src/include/gnunet_json_lib.h index 9e5f9e284..ce721d8d8 100644 --- a/src/include/gnunet_json_lib.h +++ b/src/include/gnunet_json_lib.h | |||
@@ -427,6 +427,26 @@ void | |||
427 | GNUNET_JSON_post_parser_cleanup (void *con_cls); | 427 | GNUNET_JSON_post_parser_cleanup (void *con_cls); |
428 | 428 | ||
429 | 429 | ||
430 | /* ****************** GETOPT JSON helper ******************* */ | ||
431 | |||
432 | |||
433 | /** | ||
434 | * Allow user to specify a JSON input value. | ||
435 | * | ||
436 | * @param shortName short name of the option | ||
437 | * @param name long name of the option | ||
438 | * @param argumentHelp help text for the option argument | ||
439 | * @param description long help text for the option | ||
440 | * @param[out] val set to the JSON specified at the command line | ||
441 | */ | ||
442 | struct GNUNET_GETOPT_CommandLineOption | ||
443 | GNUNET_JSON_getopt (char shortName, | ||
444 | const char *name, | ||
445 | const char *argumentHelp, | ||
446 | const char *description, | ||
447 | json_t **json); | ||
448 | |||
449 | |||
430 | #endif | 450 | #endif |
431 | 451 | ||
432 | /* end of gnunet_json_lib.h */ | 452 | /* end of gnunet_json_lib.h */ |
diff --git a/src/json/json.c b/src/json/json.c index a2d1a9608..c182a02f4 100644 --- a/src/json/json.c +++ b/src/json/json.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet | 2 | This file is part of GNUnet |
3 | Copyright (C) 2014, 2015, 2016 GNUnet e.V. | 3 | Copyright (C) 2014-2017 GNUnet e.V. |
4 | 4 | ||
5 | GNUnet is free software; you can redistribute it and/or modify it under the | 5 | GNUnet is free software; you can redistribute it and/or modify it under the |
6 | terms of the GNU General Public License as published by the Free Software | 6 | terms of the GNU General Public License as published by the Free Software |
@@ -82,13 +82,78 @@ GNUNET_JSON_parse (const json_t *root, | |||
82 | void | 82 | void |
83 | GNUNET_JSON_parse_free (struct GNUNET_JSON_Specification *spec) | 83 | GNUNET_JSON_parse_free (struct GNUNET_JSON_Specification *spec) |
84 | { | 84 | { |
85 | unsigned int i; | 85 | for (unsigned int i=0;NULL != spec[i].parser;i++) |
86 | |||
87 | for (i=0;NULL != spec[i].parser;i++) | ||
88 | if (NULL != spec[i].cleaner) | 86 | if (NULL != spec[i].cleaner) |
89 | spec[i].cleaner (spec[i].cls, | 87 | spec[i].cleaner (spec[i].cls, |
90 | &spec[i]); | 88 | &spec[i]); |
91 | } | 89 | } |
92 | 90 | ||
93 | 91 | ||
92 | /** | ||
93 | * Set an option with a JSON value from the command line. | ||
94 | * A pointer to this function should be passed as part of the | ||
95 | * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options | ||
96 | * of this type. | ||
97 | * | ||
98 | * @param ctx command line processing context | ||
99 | * @param scls additional closure (will point to the 'json_t *') | ||
100 | * @param option name of the option | ||
101 | * @param value actual value of the option as a string. | ||
102 | * @return #GNUNET_OK if parsing the value worked | ||
103 | */ | ||
104 | static int | ||
105 | set_json (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, | ||
106 | void *scls, | ||
107 | const char *option, | ||
108 | const char *value) | ||
109 | { | ||
110 | json_t **json = scls; | ||
111 | json_error_t error; | ||
112 | |||
113 | *json = json_loads (value, | ||
114 | JSON_REJECT_DUPLICATES, | ||
115 | &error); | ||
116 | if (NULL == *json) | ||
117 | { | ||
118 | FPRINTF (stderr, | ||
119 | _("Failed to parse JSON in option `%s': %s (%s)\n"), | ||
120 | option, | ||
121 | error.text, | ||
122 | error.source); | ||
123 | return GNUNET_SYSERR; | ||
124 | } | ||
125 | return GNUNET_OK; | ||
126 | } | ||
127 | |||
128 | |||
129 | /** | ||
130 | * Allow user to specify a JSON input value. | ||
131 | * | ||
132 | * @param shortName short name of the option | ||
133 | * @param name long name of the option | ||
134 | * @param argumentHelp help text for the option argument | ||
135 | * @param description long help text for the option | ||
136 | * @param[out] val set to the JSON specified at the command line | ||
137 | */ | ||
138 | struct GNUNET_GETOPT_CommandLineOption | ||
139 | GNUNET_JSON_getopt (char shortName, | ||
140 | const char *name, | ||
141 | const char *argumentHelp, | ||
142 | const char *description, | ||
143 | json_t **json) | ||
144 | { | ||
145 | struct GNUNET_GETOPT_CommandLineOption clo = { | ||
146 | .shortName = shortName, | ||
147 | .name = name, | ||
148 | .argumentHelp = argumentHelp, | ||
149 | .description = description, | ||
150 | .require_argument = 1, | ||
151 | .processor = &set_json, | ||
152 | .scls = (void *) json | ||
153 | }; | ||
154 | |||
155 | return clo; | ||
156 | } | ||
157 | |||
158 | |||
94 | /* end of json.c */ | 159 | /* end of json.c */ |
diff --git a/src/util/getopt.c b/src/util/getopt.c index 85f67500c..036e0f4be 100644 --- a/src/util/getopt.c +++ b/src/util/getopt.c | |||
@@ -881,6 +881,7 @@ GNUNET_GETOPT_run (const char *binaryOptions, | |||
881 | int spos; | 881 | int spos; |
882 | int cont; | 882 | int cont; |
883 | int c; | 883 | int c; |
884 | uint8_t *seen; | ||
884 | 885 | ||
885 | GNUNET_assert (argc > 0); | 886 | GNUNET_assert (argc > 0); |
886 | GNoptind = 0; | 887 | GNoptind = 0; |
@@ -893,6 +894,8 @@ GNUNET_GETOPT_run (const char *binaryOptions, | |||
893 | 894 | ||
894 | long_options = GNUNET_new_array (count + 1, | 895 | long_options = GNUNET_new_array (count + 1, |
895 | struct GNoption); | 896 | struct GNoption); |
897 | seen = GNUNET_new_array (count, | ||
898 | uint8_t); | ||
896 | shorts = GNUNET_malloc (count * 2 + 1); | 899 | shorts = GNUNET_malloc (count * 2 + 1); |
897 | spos = 0; | 900 | spos = 0; |
898 | for (unsigned i = 0; i < count; i++) | 901 | for (unsigned i = 0; i < count; i++) |
@@ -934,6 +937,7 @@ GNUNET_GETOPT_run (const char *binaryOptions, | |||
934 | allOptions[i].scls, | 937 | allOptions[i].scls, |
935 | allOptions[i].name, | 938 | allOptions[i].name, |
936 | GNoptarg); | 939 | GNoptarg); |
940 | seen[i] = 1; | ||
937 | break; | 941 | break; |
938 | } | 942 | } |
939 | } | 943 | } |
@@ -948,6 +952,20 @@ GNUNET_GETOPT_run (const char *binaryOptions, | |||
948 | GNUNET_free (shorts); | 952 | GNUNET_free (shorts); |
949 | GNUNET_free (long_options); | 953 | GNUNET_free (long_options); |
950 | 954 | ||
955 | if (GNUNET_YES == cont) | ||
956 | { | ||
957 | for (count = 0; NULL != allOptions[count].name; count++) | ||
958 | if ( (0 == seen[count]) && | ||
959 | (allOptions[count].option_mandatory) ) | ||
960 | { | ||
961 | FPRINTF (stderr, | ||
962 | _("Missing mandatory option `%s'.\n"), | ||
963 | allOptions[count].name); | ||
964 | cont = GNUNET_SYSERR; | ||
965 | } | ||
966 | } | ||
967 | GNUNET_free (seen); | ||
968 | |||
951 | /* call cleaners, if available */ | 969 | /* call cleaners, if available */ |
952 | for (count = 0; NULL != allOptions[count].name; count++) | 970 | for (count = 0; NULL != allOptions[count].name; count++) |
953 | if (NULL != allOptions[count].cleaner) | 971 | if (NULL != allOptions[count].cleaner) |
diff --git a/src/util/getopt_helpers.c b/src/util/getopt_helpers.c index 31fe093a9..76342a6c9 100644 --- a/src/util/getopt_helpers.c +++ b/src/util/getopt_helpers.c | |||
@@ -357,7 +357,7 @@ set_string (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, | |||
357 | { | 357 | { |
358 | char **val = scls; | 358 | char **val = scls; |
359 | 359 | ||
360 | GNUNET_assert (value != NULL); | 360 | GNUNET_assert (NULL != value); |
361 | GNUNET_free_non_null (*val); | 361 | GNUNET_free_non_null (*val); |
362 | *val = GNUNET_strdup (value); | 362 | *val = GNUNET_strdup (value); |
363 | return GNUNET_OK; | 363 | return GNUNET_OK; |
@@ -654,7 +654,7 @@ GNUNET_GETOPT_OPTION_SET_RELATIVE_TIME (char shortName, | |||
654 | * type 'struct GNUNET_TIME_Absolute'. | 654 | * type 'struct GNUNET_TIME_Absolute'. |
655 | * | 655 | * |
656 | * @param ctx command line processing context | 656 | * @param ctx command line processing context |
657 | * @param scls additional closure (will point to the 'struct GNUNET_TIME_Relative') | 657 | * @param scls additional closure (will point to the `struct GNUNET_TIME_Absolute`) |
658 | * @param option name of the option | 658 | * @param option name of the option |
659 | * @param value actual value of the option as a string. | 659 | * @param value actual value of the option as a string. |
660 | * @return #GNUNET_OK if parsing the value worked | 660 | * @return #GNUNET_OK if parsing the value worked |
@@ -878,4 +878,18 @@ GNUNET_GETOPT_OPTION_SET_BASE32_FIXED_SIZE (char shortName, | |||
878 | } | 878 | } |
879 | 879 | ||
880 | 880 | ||
881 | /** | ||
882 | * Make the given option mandatory. | ||
883 | * | ||
884 | * @param opt option to modify | ||
885 | * @return @a opt with the mandatory flag set. | ||
886 | */ | ||
887 | struct GNUNET_GETOPT_CommandLineOption | ||
888 | GNUNET_GETOPT_OPTION_MANDATORY (struct GNUNET_GETOPT_CommandLineOption opt) | ||
889 | { | ||
890 | opt.option_mandatory = 1; | ||
891 | return opt; | ||
892 | } | ||
893 | |||
894 | |||
881 | /* end of getopt_helpers.c */ | 895 | /* end of getopt_helpers.c */ |
diff --git a/src/util/test_getopt.c b/src/util/test_getopt.c index faa6a07a1..13cedd7f5 100644 --- a/src/util/test_getopt.c +++ b/src/util/test_getopt.c | |||
@@ -136,13 +136,16 @@ testLogOpts () | |||
136 | GNUNET_GETOPT_OPTION_END | 136 | GNUNET_GETOPT_OPTION_END |
137 | }; | 137 | }; |
138 | 138 | ||
139 | if (5 != GNUNET_GETOPT_run ("test_getopt", logoptionlist, 5, myargv)) | 139 | if (5 != GNUNET_GETOPT_run ("test_getopt", |
140 | logoptionlist, | ||
141 | 5, myargv)) | ||
140 | { | 142 | { |
141 | GNUNET_break (0); | 143 | GNUNET_break (0); |
142 | return 1; | 144 | return 1; |
143 | } | 145 | } |
144 | GNUNET_assert (fn != NULL); | 146 | GNUNET_assert (NULL != fn); |
145 | if ((0 != strcmp (level, "WARNING")) || (0 != strcmp (fn, "filename"))) | 147 | if ( (0 != strcmp (level, "WARNING")) || |
148 | (NULL == strstr (fn, "/filename")) ) | ||
146 | { | 149 | { |
147 | GNUNET_break (0); | 150 | GNUNET_break (0); |
148 | GNUNET_free (level); | 151 | GNUNET_free (level); |
@@ -212,7 +215,9 @@ main (int argc, char *argv[]) | |||
212 | { | 215 | { |
213 | int errCnt = 0; | 216 | int errCnt = 0; |
214 | 217 | ||
215 | GNUNET_log_setup ("test_getopt", "WARNING", NULL); | 218 | GNUNET_log_setup ("test_getopt", |
219 | "WARNING", | ||
220 | NULL); | ||
216 | /* suppress output from -h, -v options */ | 221 | /* suppress output from -h, -v options */ |
217 | #ifndef MINGW | 222 | #ifndef MINGW |
218 | GNUNET_break (0 == CLOSE (1)); | 223 | GNUNET_break (0 == CLOSE (1)); |
diff --git a/src/util/test_program.c b/src/util/test_program.c index 669cee7bd..d206952af 100644 --- a/src/util/test_program.c +++ b/src/util/test_program.c | |||
@@ -24,37 +24,19 @@ | |||
24 | #include "platform.h" | 24 | #include "platform.h" |
25 | #include "gnunet_util_lib.h" | 25 | #include "gnunet_util_lib.h" |
26 | 26 | ||
27 | static int setme1, setme2; | 27 | |
28 | 28 | static int setme1; | |
29 | static struct GNUNET_GETOPT_CommandLineOption options1[] = { | 29 | |
30 | {'n', "name", NULL, "description", 0, &GNUNET_GETOPT_set_one, &setme1}, | 30 | static int setme2; |
31 | GNUNET_GETOPT_OPTION_END | 31 | |
32 | }; | ||
33 | |||
34 | static struct GNUNET_GETOPT_CommandLineOption options2[] = { | ||
35 | {'n', "name", NULL, "description", 0, &GNUNET_GETOPT_set_one, &setme1}, | ||
36 | {'N', "number", NULL, "description", 0, &GNUNET_GETOPT_set_one, &setme2}, | ||
37 | GNUNET_GETOPT_OPTION_END | ||
38 | }; | ||
39 | |||
40 | static struct GNUNET_GETOPT_CommandLineOption options3[] = { | ||
41 | {'N', "number", NULL, "description", 0, &GNUNET_GETOPT_set_one, &setme1}, | ||
42 | {'n', "name", NULL, "description", 0, &GNUNET_GETOPT_set_one, &setme2}, | ||
43 | GNUNET_GETOPT_OPTION_END | ||
44 | }; | ||
45 | |||
46 | static struct GNUNET_GETOPT_CommandLineOption options4[] = { | ||
47 | {'n', "name", NULL, "description", 0, &GNUNET_GETOPT_set_one, &setme1}, | ||
48 | {'n', "number", NULL, "description", 0, &GNUNET_GETOPT_set_one, &setme2}, | ||
49 | GNUNET_GETOPT_OPTION_END | ||
50 | }; | ||
51 | 32 | ||
52 | /** | 33 | /** |
53 | * Main function that will be run. | 34 | * Main function that will be run. |
54 | */ | 35 | */ |
55 | |||
56 | static void | 36 | static void |
57 | runner (void *cls, char *const *args, const char *cfgfile, | 37 | runner (void *cls, |
38 | char *const *args, | ||
39 | const char *cfgfile, | ||
58 | const struct GNUNET_CONFIGURATION_Handle *cfg) | 40 | const struct GNUNET_CONFIGURATION_Handle *cfg) |
59 | { | 41 | { |
60 | int *ok = cls; | 42 | int *ok = cls; |
@@ -62,21 +44,16 @@ runner (void *cls, char *const *args, const char *cfgfile, | |||
62 | GNUNET_assert (setme1 == 1); | 44 | GNUNET_assert (setme1 == 1); |
63 | GNUNET_assert (0 == strcmp (args[0], "extra")); | 45 | GNUNET_assert (0 == strcmp (args[0], "extra")); |
64 | GNUNET_assert (args[1] == NULL); | 46 | GNUNET_assert (args[1] == NULL); |
65 | GNUNET_assert (0 == strcmp (cfgfile, "test_program_data.conf")); | 47 | GNUNET_assert (NULL != strstr (cfgfile, "/test_program_data.conf")); |
66 | |||
67 | *ok = 0; | 48 | *ok = 0; |
68 | } | 49 | } |
69 | 50 | ||
70 | /** | 51 | |
71 | * Main method, starts scheduler with task1, | 52 | int |
72 | * checks that "ok" is correct at the end. | 53 | main (int argc, char *argv[]) |
73 | */ | ||
74 | static int | ||
75 | check () | ||
76 | { | 54 | { |
77 | int ok = 1; | 55 | int ok = 1; |
78 | 56 | char *const argvx[] = { | |
79 | char *const argv[] = { | ||
80 | "test_program", | 57 | "test_program", |
81 | "-c", | 58 | "-c", |
82 | "test_program_data.conf", | 59 | "test_program_data.conf", |
@@ -86,33 +63,75 @@ check () | |||
86 | "extra", | 63 | "extra", |
87 | NULL | 64 | NULL |
88 | }; | 65 | }; |
66 | struct GNUNET_GETOPT_CommandLineOption options1[] = { | ||
67 | GNUNET_GETOPT_OPTION_SET_ONE ('n', | ||
68 | "name", | ||
69 | "description", | ||
70 | &setme1), | ||
71 | GNUNET_GETOPT_OPTION_END | ||
72 | }; | ||
73 | struct GNUNET_GETOPT_CommandLineOption options2[] = { | ||
74 | GNUNET_GETOPT_OPTION_SET_ONE ('n', | ||
75 | "name", | ||
76 | "description", | ||
77 | &setme1), | ||
78 | GNUNET_GETOPT_OPTION_SET_ONE ('N', | ||
79 | "number", | ||
80 | "description", | ||
81 | &setme2), | ||
82 | GNUNET_GETOPT_OPTION_END | ||
83 | }; | ||
84 | struct GNUNET_GETOPT_CommandLineOption options3[] = { | ||
85 | GNUNET_GETOPT_OPTION_SET_ONE ('N', | ||
86 | "number", | ||
87 | "description", | ||
88 | &setme1), | ||
89 | GNUNET_GETOPT_OPTION_SET_ONE ('n', | ||
90 | "name", | ||
91 | "description", | ||
92 | &setme2), | ||
93 | GNUNET_GETOPT_OPTION_END | ||
94 | }; | ||
95 | struct GNUNET_GETOPT_CommandLineOption options4[] = { | ||
96 | GNUNET_GETOPT_OPTION_SET_ONE ('n', | ||
97 | "name", | ||
98 | "description", | ||
99 | &setme1), | ||
100 | GNUNET_GETOPT_OPTION_SET_ONE ('n', | ||
101 | "name", | ||
102 | "description", | ||
103 | &setme2), | ||
104 | GNUNET_GETOPT_OPTION_END | ||
105 | }; | ||
89 | 106 | ||
107 | |||
108 | GNUNET_log_setup ("test_program", | ||
109 | "WARNING", | ||
110 | NULL); | ||
90 | GNUNET_assert (GNUNET_OK == | 111 | GNUNET_assert (GNUNET_OK == |
91 | GNUNET_PROGRAM_run (7, argv, "test_program", "A test", | 112 | GNUNET_PROGRAM_run (7, argvx, |
92 | options1, &runner, &ok)); | 113 | "test_program", |
114 | "A test", | ||
115 | options1, | ||
116 | &runner, &ok)); | ||
93 | 117 | ||
94 | GNUNET_assert (GNUNET_OK == | 118 | GNUNET_assert (GNUNET_OK == |
95 | GNUNET_PROGRAM_run (7, argv, "test_program", "A test", | 119 | GNUNET_PROGRAM_run (7, argvx, |
96 | options2, &runner, &ok)); | 120 | "test_program", "A test", |
121 | options2, | ||
122 | &runner, &ok)); | ||
97 | GNUNET_assert (GNUNET_OK == | 123 | GNUNET_assert (GNUNET_OK == |
98 | GNUNET_PROGRAM_run (7, argv, "test_program", "A test", | 124 | GNUNET_PROGRAM_run (7, argvx, |
99 | options3, &runner, &ok)); | 125 | "test_program", "A test", |
126 | options3, | ||
127 | &runner, &ok)); | ||
100 | GNUNET_assert (GNUNET_OK == | 128 | GNUNET_assert (GNUNET_OK == |
101 | GNUNET_PROGRAM_run (7, argv, "test_program", "A test", | 129 | GNUNET_PROGRAM_run (7, argvx, |
102 | options4, &runner, &ok)); | 130 | "test_program", "A test", |
131 | options4, | ||
132 | &runner, &ok)); | ||
103 | 133 | ||
104 | return ok; | 134 | return ok; |
105 | } | 135 | } |
106 | 136 | ||
107 | int | ||
108 | main (int argc, char *argv[]) | ||
109 | { | ||
110 | int ret = 0; | ||
111 | |||
112 | GNUNET_log_setup ("test_program", "WARNING", NULL); | ||
113 | ret += check (); | ||
114 | |||
115 | return ret; | ||
116 | } | ||
117 | |||
118 | /* end of test_program.c */ | 137 | /* end of test_program.c */ |