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