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