aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/include/gnunet_getopt_lib.h17
-rw-r--r--src/include/gnunet_json_lib.h20
-rw-r--r--src/json/json.c73
-rw-r--r--src/util/getopt.c18
-rw-r--r--src/util/getopt_helpers.c18
-rw-r--r--src/util/test_getopt.c13
-rw-r--r--src/util/test_program.c129
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 */
402struct GNUNET_GETOPT_CommandLineOption
403GNUNET_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
427GNUNET_JSON_post_parser_cleanup (void *con_cls); 427GNUNET_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 */
442struct GNUNET_GETOPT_CommandLineOption
443GNUNET_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,
82void 82void
83GNUNET_JSON_parse_free (struct GNUNET_JSON_Specification *spec) 83GNUNET_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 */
104static int
105set_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 */
138struct GNUNET_GETOPT_CommandLineOption
139GNUNET_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 */
887struct GNUNET_GETOPT_CommandLineOption
888GNUNET_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
27static int setme1, setme2; 27
28 28static int setme1;
29static struct GNUNET_GETOPT_CommandLineOption options1[] = { 29
30 {'n', "name", NULL, "description", 0, &GNUNET_GETOPT_set_one, &setme1}, 30static int setme2;
31 GNUNET_GETOPT_OPTION_END 31
32};
33
34static 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
40static 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
46static 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
56static void 36static void
57runner (void *cls, char *const *args, const char *cfgfile, 37runner (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, 52int
72 * checks that "ok" is correct at the end. 53main (int argc, char *argv[])
73 */
74static int
75check ()
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
107int
108main (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 */