80d1037bb6d46a7b65d9dbce8b1f5d643646ebdf
[oweals/gnunet.git] / src / util / getopt_helpers.c
1 /*
2      This file is part of GNUnet
3      Copyright (C) 2006, 2011 GNUnet e.V.
4
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.
9
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.
14     
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/>.
17
18      SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21 /**
22  * @file src/util/getopt_helpers.c
23  * @brief implements command line that sets option
24  * @author Christian Grothoff
25  */
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28
29 #define LOG(kind, ...) GNUNET_log_from (kind, "util-getopt", __VA_ARGS__)
30
31
32 /**
33  * Print out program version (implements --version).
34  *
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)
40  */
41 static int
42 print_version (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
43                void *scls,
44                const char *option,
45                const char *value)
46 {
47   const char *version = scls;
48
49   (void) option;
50   (void) value;
51   printf ("%s v%s\n", ctx->binaryName, version);
52   return GNUNET_NO;
53 }
54
55
56 /**
57  * Define the option to print the version of
58  * the application (-v option)
59  *
60  * @param version string with the version number
61  */
62 struct GNUNET_GETOPT_CommandLineOption
63 GNUNET_GETOPT_option_version (const char *version)
64 {
65   struct GNUNET_GETOPT_CommandLineOption clo = {.shortName = 'v',
66                                                 .name = "version",
67                                                 .description = gettext_noop (
68                                                   "print the version number"),
69                                                 .option_exclusive = 1,
70                                                 .processor = &print_version,
71                                                 .scls = (void *) version};
72   return clo;
73 }
74
75
76 /**
77  * At what offset does the help text start?
78  */
79 #define BORDER 29
80
81 /**
82  * Print out details on command line options (implements --help).
83  *
84  * @param ctx command line processing context
85  * @param scls additional closure (points to about text)
86  * @param option name of the option
87  * @param value not used (NULL)
88  * @return #GNUNET_NO (do not continue, not an error)
89  */
90 static int
91 format_help (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
92              void *scls,
93              const char *option,
94              const char *value)
95 {
96   const char *about = scls;
97   size_t slen;
98   unsigned int i;
99   int j;
100   size_t ml;
101   size_t p;
102   char *scp;
103   const char *trans;
104   const struct GNUNET_GETOPT_CommandLineOption *opt;
105   const struct GNUNET_OS_ProjectData *pd;
106
107   (void) option;
108   (void) value;
109   if (NULL != about)
110   {
111     printf ("%s\n%s\n", ctx->binaryOptions, gettext (about));
112     printf (_ (
113       "Arguments mandatory for long options are also mandatory for short options.\n"));
114   }
115   i = 0;
116   opt = ctx->allOptions;
117   while (NULL != opt[i].description)
118   {
119     if (opt[i].shortName == '\0')
120       printf ("      ");
121     else
122       printf ("  -%c, ", opt[i].shortName);
123     printf ("--%s", opt[i].name);
124     slen = 8 + strlen (opt[i].name);
125     if (NULL != opt[i].argumentHelp)
126     {
127       printf ("=%s", opt[i].argumentHelp);
128       slen += 1 + strlen (opt[i].argumentHelp);
129     }
130     if (slen > BORDER)
131     {
132       printf ("\n%*s", BORDER, "");
133       slen = BORDER;
134     }
135     if (slen < BORDER)
136     {
137       printf ("%*s", (int) (BORDER - slen), "");
138       slen = BORDER;
139     }
140     if (0 < strlen (opt[i].description))
141       trans = gettext (opt[i].description);
142     else
143       trans = "";
144     ml = strlen (trans);
145     p = 0;
146   OUTER:
147     while (ml - p > 78 - slen)
148     {
149       for (j = p + 78 - slen; j > (int) p; j--)
150       {
151         if (isspace ((unsigned char) trans[j]))
152         {
153           scp = GNUNET_malloc (j - p + 1);
154           GNUNET_memcpy (scp, &trans[p], j - p);
155           scp[j - p] = '\0';
156           printf ("%s\n%*s", scp, BORDER + 2, "");
157           GNUNET_free (scp);
158           p = j + 1;
159           slen = BORDER + 2;
160           goto OUTER;
161         }
162       }
163       /* could not find space to break line */
164       scp = GNUNET_malloc (78 - slen + 1);
165       GNUNET_memcpy (scp, &trans[p], 78 - slen);
166       scp[78 - slen] = '\0';
167       printf ("%s\n%*s", scp, BORDER + 2, "");
168       GNUNET_free (scp);
169       slen = BORDER + 2;
170       p = p + 78 - slen;
171     }
172     /* print rest */
173     if (p < ml)
174       printf ("%s\n", &trans[p]);
175     if (strlen (trans) == 0)
176       printf ("\n");
177     i++;
178   }
179   pd = GNUNET_OS_project_data_get ();
180   printf ("Report bugs to %s.\n"
181           "Home page: %s\n",
182           pd->bug_email,
183           pd->homepage);
184
185   if (0 != pd->is_gnu)
186     printf ("General help using GNU software: http://www.gnu.org/gethelp/\n");
187   
188   return GNUNET_NO;
189 }
190
191
192 /**
193  * Defining the option to print the command line
194  * help text (-h option).
195  *
196  * @param about string with brief description of the application
197  */
198 struct GNUNET_GETOPT_CommandLineOption
199 GNUNET_GETOPT_option_help (const char *about)
200 {
201   struct GNUNET_GETOPT_CommandLineOption clo = {.shortName = 'h',
202                                                 .name = "help",
203                                                 .description = gettext_noop (
204                                                   "print this help"),
205                                                 .option_exclusive = 1,
206                                                 .processor = format_help,
207                                                 .scls = (void *) about};
208
209   return clo;
210 }
211
212
213 /**
214  * Set an option of type 'unsigned int' from the command line. Each
215  * time the option flag is given, the value is incremented by one.
216  * A pointer to this function should be passed as part of the
217  * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
218  * of this type.  It should be followed by a pointer to a value of
219  * type 'int'.
220  *
221  * @param ctx command line processing context
222  * @param scls additional closure (will point to the 'unsigned int')
223  * @param option name of the option
224  * @param value not used (NULL)
225  * @return #GNUNET_OK
226  */
227 static int
228 increment_value (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
229                  void *scls,
230                  const char *option,
231                  const char *value)
232 {
233   unsigned int *val = scls;
234
235   (void) ctx;
236   (void) option;
237   (void) value;
238   (*val)++;
239   return GNUNET_OK;
240 }
241
242
243 /**
244  * Increment @a val each time the option flag is given by one.
245  *
246  * @param shortName short name of the option
247  * @param name long name of the option
248  * @param argumentHelp help text for the option argument
249  * @param description long help text for the option
250  * @param[out] val increment by 1 each time the option is present
251  */
252 struct GNUNET_GETOPT_CommandLineOption
253 GNUNET_GETOPT_option_increment_uint (char shortName,
254                                      const char *name,
255                                      const char *description,
256                                      unsigned int *val)
257 {
258   struct GNUNET_GETOPT_CommandLineOption clo = {.shortName = shortName,
259                                                 .name = name,
260                                                 .description = description,
261                                                 .processor = &increment_value,
262                                                 .scls = (void *) val};
263
264   return clo;
265 }
266
267
268 /**
269  * Define the '-V' verbosity option.  Using the option more
270  * than once increments @a level each time.
271  *
272  * @param[out] level set to the verbosity level
273  */
274 struct GNUNET_GETOPT_CommandLineOption
275 GNUNET_GETOPT_option_verbose (unsigned int *level)
276 {
277   struct GNUNET_GETOPT_CommandLineOption clo = {.shortName = 'V',
278                                                 .name = "verbose",
279                                                 .description =
280                                                   gettext_noop ("be verbose"),
281                                                 .processor = &increment_value,
282                                                 .scls = (void *) level};
283
284   return clo;
285 }
286
287
288 /**
289  * Set an option of type 'int' from the command line to 1 if the
290  * given option is present.
291  * A pointer to this function should be passed as part of the
292  * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
293  * of this type.  It should be followed by a pointer to a value of
294  * type 'int'.
295  *
296  * @param ctx command line processing context
297  * @param scls additional closure (will point to the 'int')
298  * @param option name of the option
299  * @param value not used (NULL)
300  * @return #GNUNET_OK
301  */
302 static int
303 set_one (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
304          void *scls,
305          const char *option,
306          const char *value)
307 {
308   int *val = scls;
309
310   (void) ctx;
311   (void) option;
312   (void) value;
313   *val = 1;
314   return GNUNET_OK;
315 }
316
317
318 /**
319  * Allow user to specify a flag (which internally means setting
320  * an integer to 1/#GNUNET_YES/#GNUNET_OK.
321  *
322  * @param shortName short name of the option
323  * @param name long name of the option
324  * @param argumentHelp help text for the option argument
325  * @param description long help text for the option
326  * @param[out] val set to 1 if the option is present
327  */
328 struct GNUNET_GETOPT_CommandLineOption
329 GNUNET_GETOPT_option_flag (char shortName,
330                            const char *name,
331                            const char *description,
332                            int *val)
333 {
334   struct GNUNET_GETOPT_CommandLineOption clo = {.shortName = shortName,
335                                                 .name = name,
336                                                 .description = description,
337                                                 .processor = &set_one,
338                                                 .scls = (void *) val};
339
340   return clo;
341 }
342
343
344 /**
345  * Set an option of type 'char *' from the command line.
346  * A pointer to this function should be passed as part of the
347  * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
348  * of this type.  It should be followed by a pointer to a value of
349  * type 'char *', which will be allocated with the requested string.
350  *
351  * @param ctx command line processing context
352  * @param scls additional closure (will point to the 'char *',
353  *             which will be allocated)
354  * @param option name of the option
355  * @param value actual value of the option (a string)
356  * @return #GNUNET_OK
357  */
358 static int
359 set_string (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
360             void *scls,
361             const char *option,
362             const char *value)
363 {
364   char **val = scls;
365
366   (void) ctx;
367   (void) option;
368   GNUNET_assert (NULL != value);
369   GNUNET_free_non_null (*val);
370   *val = GNUNET_strdup (value);
371   return GNUNET_OK;
372 }
373
374
375 /**
376  * Allow user to specify a string.
377  *
378  * @param shortName short name of the option
379  * @param name long name of the option
380  * @param argumentHelp help text for the option argument
381  * @param description long help text for the option
382  * @param[out] str set to the string
383  */
384 struct GNUNET_GETOPT_CommandLineOption
385 GNUNET_GETOPT_option_string (char shortName,
386                              const char *name,
387                              const char *argumentHelp,
388                              const char *description,
389                              char **str)
390 {
391   struct GNUNET_GETOPT_CommandLineOption clo = {.shortName = shortName,
392                                                 .name = name,
393                                                 .argumentHelp = argumentHelp,
394                                                 .description = description,
395                                                 .require_argument = 1,
396                                                 .processor = &set_string,
397                                                 .scls = (void *) str};
398
399   return clo;
400 }
401
402
403 /**
404  * Define the '-L' log level option.  Note that we do not check
405  * that the log level is valid here.
406  *
407  * @param[out] level set to the log level
408  */
409 struct GNUNET_GETOPT_CommandLineOption
410 GNUNET_GETOPT_option_loglevel (char **level)
411 {
412   struct GNUNET_GETOPT_CommandLineOption clo =
413     {.shortName = 'L',
414      .name = "log",
415      .argumentHelp = "LOGLEVEL",
416      .description = gettext_noop ("configure logging to use LOGLEVEL"),
417      .require_argument = 1,
418      .processor = &set_string,
419      .scls = (void *) level};
420
421   return clo;
422 }
423
424
425 /**
426  * Set an option of type 'char *' from the command line with
427  * filename expansion a la #GNUNET_STRINGS_filename_expand().
428  *
429  * @param ctx command line processing context
430  * @param scls additional closure (will point to the `char *`,
431  *             which will be allocated)
432  * @param option name of the option
433  * @param value actual value of the option (a string)
434  * @return #GNUNET_OK
435  */
436 static int
437 set_filename (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
438               void *scls,
439               const char *option,
440               const char *value)
441 {
442   char **val = scls;
443
444   (void) ctx;
445   (void) option;
446   GNUNET_assert (NULL != value);
447   GNUNET_free_non_null (*val);
448   *val = GNUNET_STRINGS_filename_expand (value);
449   return GNUNET_OK;
450 }
451
452
453 /**
454  * Allow user to specify a filename (automatically path expanded).
455  *
456  * @param shortName short name of the option
457  * @param name long name of the option
458  * @param argumentHelp help text for the option argument
459  * @param description long help text for the option
460  * @param[out] str set to the string
461  */
462 struct GNUNET_GETOPT_CommandLineOption
463 GNUNET_GETOPT_option_filename (char shortName,
464                                const char *name,
465                                const char *argumentHelp,
466                                const char *description,
467                                char **str)
468 {
469   struct GNUNET_GETOPT_CommandLineOption clo = {.shortName = shortName,
470                                                 .name = name,
471                                                 .argumentHelp = argumentHelp,
472                                                 .description = description,
473                                                 .require_argument = 1,
474                                                 .processor = &set_filename,
475                                                 .scls = (void *) str};
476
477   return clo;
478 }
479
480
481 /**
482  * Allow user to specify log file name (-l option)
483  *
484  * @param[out] logfn set to the name of the logfile
485  */
486 struct GNUNET_GETOPT_CommandLineOption
487 GNUNET_GETOPT_option_logfile (char **logfn)
488 {
489   struct GNUNET_GETOPT_CommandLineOption clo =
490     {.shortName = 'l',
491      .name = "logfile",
492      .argumentHelp = "FILENAME",
493      .description =
494        gettext_noop ("configure logging to write logs to FILENAME"),
495      .require_argument = 1,
496      .processor = &set_filename,
497      .scls = (void *) logfn};
498
499   return clo;
500 }
501
502
503 /**
504  * Allow user to specify configuration file name (-c option)
505  *
506  * @param[out] fn set to the name of the configuration file
507  */
508 struct GNUNET_GETOPT_CommandLineOption
509 GNUNET_GETOPT_option_cfgfile (char **fn)
510 {
511   struct GNUNET_GETOPT_CommandLineOption clo =
512     {.shortName = 'c',
513      .name = "config",
514      .argumentHelp = "FILENAME",
515      .description = gettext_noop ("use configuration file FILENAME"),
516      .require_argument = 1,
517      .processor = &set_filename,
518      .scls = (void *) fn};
519
520   return clo;
521 }
522
523
524 /**
525  * Set an option of type 'unsigned long long' from the command line.
526  * A pointer to this function should be passed as part of the
527  * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
528  * of this type.  It should be followed by a pointer to a value of
529  * type 'unsigned long long'.
530  *
531  * @param ctx command line processing context
532  * @param scls additional closure (will point to the 'unsigned long long')
533  * @param option name of the option
534  * @param value actual value of the option as a string.
535  * @return #GNUNET_OK if parsing the value worked
536  */
537 static int
538 set_ulong (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
539            void *scls,
540            const char *option,
541            const char *value)
542 {
543   unsigned long long *val = scls;
544   char dummy[2];
545
546   (void) ctx;
547   if (1 != SSCANF (value, "%llu%1s", val, dummy))
548   {
549     FPRINTF (stderr,
550              _ ("You must pass a number to the `%s' option.\n"),
551              option);
552     return GNUNET_SYSERR;
553   }
554   return GNUNET_OK;
555 }
556
557
558 /**
559  * Allow user to specify an `unsigned long long`
560  *
561  * @param shortName short name of the option
562  * @param name long name of the option
563  * @param argumentHelp help text for the option argument
564  * @param description long help text for the option
565  * @param[out] val set to the value specified at the command line
566  */
567 struct GNUNET_GETOPT_CommandLineOption
568 GNUNET_GETOPT_option_ulong (char shortName,
569                             const char *name,
570                             const char *argumentHelp,
571                             const char *description,
572                             unsigned long long *val)
573 {
574   struct GNUNET_GETOPT_CommandLineOption clo = {.shortName = shortName,
575                                                 .name = name,
576                                                 .argumentHelp = argumentHelp,
577                                                 .description = description,
578                                                 .require_argument = 1,
579                                                 .processor = &set_ulong,
580                                                 .scls = (void *) val};
581
582   return clo;
583 }
584
585
586 /**
587  * Set an option of type 'struct GNUNET_TIME_Relative' from the command line.
588  * A pointer to this function should be passed as part of the
589  * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
590  * of this type.  It should be followed by a pointer to a value of
591  * type 'struct GNUNET_TIME_Relative'.
592  *
593  * @param ctx command line processing context
594  * @param scls additional closure (will point to the 'struct GNUNET_TIME_Relative')
595  * @param option name of the option
596  * @param value actual value of the option as a string.
597  * @return #GNUNET_OK if parsing the value worked
598  */
599 static int
600 set_relative_time (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
601                    void *scls,
602                    const char *option,
603                    const char *value)
604 {
605   struct GNUNET_TIME_Relative *val = scls;
606
607   (void) ctx;
608   if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_relative (value, val))
609   {
610     FPRINTF (stderr,
611              _ ("You must pass relative time to the `%s' option.\n"),
612              option);
613     return GNUNET_SYSERR;
614   }
615   return GNUNET_OK;
616 }
617
618
619 /**
620  * Allow user to specify a `struct GNUNET_TIME_Relative`
621  * (using human-readable "fancy" time).
622  *
623  * @param shortName short name of the option
624  * @param name long name of the option
625  * @param argumentHelp help text for the option argument
626  * @param description long help text for the option
627  * @param[out] val set to the time specified at the command line
628  */
629 struct GNUNET_GETOPT_CommandLineOption
630 GNUNET_GETOPT_option_relative_time (char shortName,
631                                     const char *name,
632                                     const char *argumentHelp,
633                                     const char *description,
634                                     struct GNUNET_TIME_Relative *val)
635 {
636   struct GNUNET_GETOPT_CommandLineOption clo = {.shortName = shortName,
637                                                 .name = name,
638                                                 .argumentHelp = argumentHelp,
639                                                 .description = description,
640                                                 .require_argument = 1,
641                                                 .processor = &set_relative_time,
642                                                 .scls = (void *) val};
643
644   return clo;
645 }
646
647
648 /**
649  * Set an option of type 'struct GNUNET_TIME_Absolute' from the command line.
650  * A pointer to this function should be passed as part of the
651  * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
652  * of this type.  It should be followed by a pointer to a value of
653  * type 'struct GNUNET_TIME_Absolute'.
654  *
655  * @param ctx command line processing context
656  * @param scls additional closure (will point to the `struct GNUNET_TIME_Absolute`)
657  * @param option name of the option
658  * @param value actual value of the option as a string.
659  * @return #GNUNET_OK if parsing the value worked
660  */
661 static int
662 set_absolute_time (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
663                    void *scls,
664                    const char *option,
665                    const char *value)
666 {
667   struct GNUNET_TIME_Absolute *val = scls;
668
669   (void) ctx;
670   if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_absolute (value, val))
671   {
672     FPRINTF (stderr,
673              _ ("You must pass absolute time to the `%s' option.\n"),
674              option);
675     return GNUNET_SYSERR;
676   }
677   return GNUNET_OK;
678 }
679
680
681 /**
682  * Allow user to specify a `struct GNUNET_TIME_Absolute`
683  * (using human-readable "fancy" time).
684  *
685  * @param shortName short name of the option
686  * @param name long name of the option
687  * @param argumentHelp help text for the option argument
688  * @param description long help text for the option
689  * @param[out] val set to the time specified at the command line
690  */
691 struct GNUNET_GETOPT_CommandLineOption
692 GNUNET_GETOPT_option_absolute_time (char shortName,
693                                     const char *name,
694                                     const char *argumentHelp,
695                                     const char *description,
696                                     struct GNUNET_TIME_Absolute *val)
697 {
698   struct GNUNET_GETOPT_CommandLineOption clo = {.shortName = shortName,
699                                                 .name = name,
700                                                 .argumentHelp = argumentHelp,
701                                                 .description = description,
702                                                 .require_argument = 1,
703                                                 .processor = &set_absolute_time,
704                                                 .scls = (void *) val};
705
706   return clo;
707 }
708
709
710 /**
711  * Set an option of type 'unsigned int' from the command line.
712  * A pointer to this function should be passed as part of the
713  * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
714  * of this type.  It should be followed by a pointer to a value of
715  * type 'unsigned int'.
716  *
717  * @param ctx command line processing context
718  * @param scls additional closure (will point to the 'unsigned int')
719  * @param option name of the option
720  * @param value actual value of the option as a string.
721  * @return #GNUNET_OK if parsing the value worked
722  */
723 static int
724 set_uint (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
725           void *scls,
726           const char *option,
727           const char *value)
728 {
729   unsigned int *val = scls;
730   char dummy[2];
731
732   (void) ctx;
733   if ('-' == *value)
734   {
735     FPRINTF (stderr,
736              _ (
737                "Your input for the '%s' option has to be a non negative number \n"),
738              option);
739     return GNUNET_SYSERR;
740   }
741   if (1 != SSCANF (value, "%u%1s", val, dummy))
742   {
743     FPRINTF (stderr,
744              _ ("You must pass a number to the `%s' option.\n"),
745              option);
746     return GNUNET_SYSERR;
747   }
748   return GNUNET_OK;
749 }
750
751
752 /**
753  * Allow user to specify an unsigned integer.
754  *
755  * @param shortName short name of the option
756  * @param name long name of the option
757  * @param argumentHelp help text for the option argument
758  * @param description long help text for the option
759  * @param[out] val set to the value specified at the command line
760  */
761 struct GNUNET_GETOPT_CommandLineOption
762 GNUNET_GETOPT_option_uint (char shortName,
763                            const char *name,
764                            const char *argumentHelp,
765                            const char *description,
766                            unsigned int *val)
767 {
768   struct GNUNET_GETOPT_CommandLineOption clo = {.shortName = shortName,
769                                                 .name = name,
770                                                 .argumentHelp = argumentHelp,
771                                                 .description = description,
772                                                 .require_argument = 1,
773                                                 .processor = &set_uint,
774                                                 .scls = (void *) val};
775
776   return clo;
777 }
778
779
780 /**
781  * Set an option of type 'uint16_t' from the command line.
782  * A pointer to this function should be passed as part of the
783  * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
784  * of this type.  It should be followed by a pointer to a value of
785  * type 'uint16_t'.
786  *
787  * @param ctx command line processing context
788  * @param scls additional closure (will point to the 'unsigned int')
789  * @param option name of the option
790  * @param value actual value of the option as a string.
791  * @return #GNUNET_OK if parsing the value worked
792  */
793 static int
794 set_uint16 (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
795             void *scls,
796             const char *option,
797             const char *value)
798 {
799   uint16_t *val = scls;
800   unsigned int v;
801   char dummy[2];
802
803   (void) ctx;
804   if (1 != SSCANF (value, "%u%1s", &v, dummy))
805   {
806     FPRINTF (stderr,
807              _ ("You must pass a number to the `%s' option.\n"),
808              option);
809     return GNUNET_SYSERR;
810   }
811   if (v > UINT16_MAX)
812   {
813     FPRINTF (stderr,
814              _ ("You must pass a number below %u to the `%s' option.\n"),
815              (unsigned int) UINT16_MAX,
816              option);
817     return GNUNET_SYSERR;
818   }
819   *val = (uint16_t) v;
820   return GNUNET_OK;
821 }
822
823
824 /**
825  * Allow user to specify an uint16_t.
826  *
827  * @param shortName short name of the option
828  * @param name long name of the option
829  * @param argumentHelp help text for the option argument
830  * @param description long help text for the option
831  * @param[out] val set to the value specified at the command line
832  */
833 struct GNUNET_GETOPT_CommandLineOption
834 GNUNET_GETOPT_option_uint16 (char shortName,
835                              const char *name,
836                              const char *argumentHelp,
837                              const char *description,
838                              uint16_t *val)
839 {
840   struct GNUNET_GETOPT_CommandLineOption clo = {.shortName = shortName,
841                                                 .name = name,
842                                                 .argumentHelp = argumentHelp,
843                                                 .description = description,
844                                                 .require_argument = 1,
845                                                 .processor = &set_uint16,
846                                                 .scls = (void *) val};
847
848   return clo;
849 }
850
851
852 /**
853  * Closure for #set_base32().
854  */
855 struct Base32Context
856 {
857   /**
858    * Value to initialize (already allocated)
859    */
860   void *val;
861
862   /**
863    * Number of bytes expected for @e val.
864    */
865   size_t val_size;
866 };
867
868
869 /**
870  * Set an option of type 'unsigned int' from the command line.
871  * A pointer to this function should be passed as part of the
872  * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
873  * of this type.  It should be followed by a pointer to a value of
874  * type 'unsigned int'.
875  *
876  * @param ctx command line processing context
877  * @param scls additional closure (will point to the 'unsigned int')
878  * @param option name of the option
879  * @param value actual value of the option as a string.
880  * @return #GNUNET_OK if parsing the value worked
881  */
882 static int
883 set_base32 (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
884             void *scls,
885             const char *option,
886             const char *value)
887 {
888   struct Base32Context *bc = scls;
889
890   (void) ctx;
891   if (GNUNET_OK != GNUNET_STRINGS_string_to_data (value,
892                                                   strlen (value),
893                                                   bc->val,
894                                                   bc->val_size))
895   {
896     fprintf (
897       stderr,
898       _ (
899         "Argument `%s' malformed. Expected base32 (Crockford) encoded value.\n"),
900       option);
901     return GNUNET_SYSERR;
902   }
903   return GNUNET_OK;
904 }
905
906
907 /**
908  * Helper function to clean up after
909  * #GNUNET_GETOPT_option_base32_fixed_size.
910  *
911  * @param cls value to GNUNET_free()
912  */
913 static void
914 free_bc (void *cls)
915 {
916   GNUNET_free (cls);
917 }
918
919
920 /**
921  * Allow user to specify a binary value using Crockford
922  * Base32 encoding.
923  *
924  * @param shortName short name of the option
925  * @param name long name of the option
926  * @param argumentHelp help text for the option argument
927  * @param description long help text for the option
928  * @param[out] val binary value decoded from Crockford Base32-encoded argument
929  * @param val_size size of @a val in bytes
930  */
931 struct GNUNET_GETOPT_CommandLineOption
932 GNUNET_GETOPT_option_base32_fixed_size (char shortName,
933                                         const char *name,
934                                         const char *argumentHelp,
935                                         const char *description,
936                                         void *val,
937                                         size_t val_size)
938 {
939   struct Base32Context *bc = GNUNET_new (struct Base32Context);
940   struct GNUNET_GETOPT_CommandLineOption clo = {.shortName = shortName,
941                                                 .name = name,
942                                                 .argumentHelp = argumentHelp,
943                                                 .description = description,
944                                                 .require_argument = 1,
945                                                 .processor = &set_base32,
946                                                 .cleaner = &free_bc,
947                                                 .scls = (void *) bc};
948
949   bc->val = val;
950   bc->val_size = val_size;
951   return clo;
952 }
953
954
955 /**
956  * Make the given option mandatory.
957  *
958  * @param opt option to modify
959  * @return @a opt with the mandatory flag set.
960  */
961 struct GNUNET_GETOPT_CommandLineOption
962 GNUNET_GETOPT_option_mandatory (struct GNUNET_GETOPT_CommandLineOption opt)
963 {
964   opt.option_mandatory = 1;
965   return opt;
966 }
967
968
969 /**
970  * Make the given option mutually exclusive with other options.
971  *
972  * @param opt option to modify
973  * @return @a opt with the exclusive flag set.
974  */
975 struct GNUNET_GETOPT_CommandLineOption
976 GNUNET_GETOPT_option_exclusive (struct GNUNET_GETOPT_CommandLineOption opt)
977 {
978   opt.option_exclusive = 1;
979   return opt;
980 }
981
982
983 /* end of getopt_helpers.c */