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