make some functions static, ensure shutdown tasks could be run repeatedly if 1st...
[oweals/gnunet.git] / src / util / getopt_helpers.c
index a8a800a006fa545fd02a8ece059bc790871c87dc..c836c90550f45b837536c20b62c9e691422387ee 100644 (file)
@@ -1,10 +1,10 @@
 /*
      This file is part of GNUnet
 /*
      This file is part of GNUnet
-     (C) 2006 Christian Grothoff (and other contributing authors)
+     Copyright (C) 2006, 2011 GNUnet e.V.
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 2, or (at your
+     by the Free Software Foundation; either version 3, or (at your
      option) any later version.
 
      GNUnet is distributed in the hope that it will be useful, but
      option) any later version.
 
      GNUnet is distributed in the hope that it will be useful, but
@@ -14,8 +14,8 @@
 
      You should have received a copy of the GNU General Public License
      along with GNUnet; see the file COPYING.  If not, write to the
 
      You should have received a copy of the GNU General Public License
      along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
 */
 
 /**
 */
 
 /**
  * @brief implements command line that sets option
  * @author Christian Grothoff
  */
  * @brief implements command line that sets option
  * @author Christian Grothoff
  */
-
 #include "platform.h"
 #include "platform.h"
-#include "gnunet_common.h"
-#include "gnunet_getopt_lib.h"
+#include "gnunet_util_lib.h"
+
+#define LOG(kind,...) GNUNET_log_from (kind, "util-getopt", __VA_ARGS__)
 
 
 
 
-int
-GNUNET_GETOPT_print_version_ (struct GNUNET_GETOPT_CommandLineProcessorContext
-                              *ctx, void *scls, const char *option,
-                              const char *value)
+/**
+ * Print out program version (implements --version).
+ *
+ * @param ctx command line processing context
+ * @param scls additional closure (points to version string)
+ * @param option name of the option
+ * @param value not used (NULL)
+ * @return #GNUNET_NO (do not continue, not an error)
+ */
+static int
+print_version (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
+               void *scls,
+               const char *option,
+               const char *value)
 {
   const char *version = scls;
 
 {
   const char *version = scls;
 
-  printf ("%s v%s\n", ctx->binaryName, version);
-  return GNUNET_SYSERR;
+  (void) option;
+  (void) value;
+  printf ("%s v%s\n",
+         ctx->binaryName,
+         version);
+  return GNUNET_NO;
 }
 
 
 }
 
 
+/**
+ * Define the option to print the version of
+ * the application (-v option)
+ *
+ * @param version string with the version number
+ */
+struct GNUNET_GETOPT_CommandLineOption
+GNUNET_GETOPT_option_version (const char *version)
+{
+  struct GNUNET_GETOPT_CommandLineOption clo = {
+    .shortName =  'v',
+    .name = "version",
+    .description = gettext_noop("print the version number"),
+    .processor = &print_version,
+    .scls = (void *) version
+  };
+  return clo;
+}
+
 
 
+/**
+ * At what offset does the help text start?
+ */
 #define BORDER 29
 
 #define BORDER 29
 
-int
-GNUNET_GETOPT_format_help_ (struct GNUNET_GETOPT_CommandLineProcessorContext
-                            *ctx, void *scls, const char *option,
-                            const char *value)
+/**
+ * Print out details on command line options (implements --help).
+ *
+ * @param ctx command line processing context
+ * @param scls additional closure (points to about text)
+ * @param option name of the option
+ * @param value not used (NULL)
+ * @return #GNUNET_NO (do not continue, not an error)
+ */
+static int
+format_help (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
+             void *scls,
+             const char *option,
+             const char *value)
 {
   const char *about = scls;
   size_t slen;
 {
   const char *about = scls;
   size_t slen;
@@ -58,142 +104,811 @@ GNUNET_GETOPT_format_help_ (struct GNUNET_GETOPT_CommandLineProcessorContext
   char *scp;
   const char *trans;
   const struct GNUNET_GETOPT_CommandLineOption *opt;
   char *scp;
   const char *trans;
   const struct GNUNET_GETOPT_CommandLineOption *opt;
+  const struct GNUNET_OS_ProjectData *pd;
 
 
-  printf ("%s\n%s\n", ctx->binaryOptions, gettext (about));
-  printf (_
-          ("Arguments mandatory for long options are also mandatory for short options.\n"));
+  (void) option;
+  (void) value;
+  if (NULL != about)
+  {
+    printf ("%s\n%s\n", ctx->binaryOptions, gettext (about));
+    printf (_
+           ("Arguments mandatory for long options are also mandatory for short options.\n"));
+  }
   i = 0;
   opt = ctx->allOptions;
   i = 0;
   opt = ctx->allOptions;
-  while (opt[i].description != NULL)
+  while (NULL != opt[i].description)
+  {
+    if (opt[i].shortName == '\0')
+      printf ("      ");
+    else
+      printf ("  -%c, ", opt[i].shortName);
+    printf ("--%s", opt[i].name);
+    slen = 8 + strlen (opt[i].name);
+    if (NULL != opt[i].argumentHelp)
     {
     {
-      if (opt[i].shortName == '\0')
-        printf ("      ");
-      else
-        printf ("  -%c, ", opt[i].shortName);
-      printf ("--%s", opt[i].name);
-      slen = 8 + strlen (opt[i].name);
-      if (opt[i].argumentHelp != NULL)
-        {
-          printf ("=%s", opt[i].argumentHelp);
-          slen += 1 + strlen (opt[i].argumentHelp);
-        }
-      if (slen > BORDER)
-        {
-          printf ("\n%*s", BORDER, "");
-          slen = BORDER;
-        }
-      if (slen < BORDER)
-        {
-          printf ("%*s", BORDER - slen, "");
-          slen = BORDER;
-        }
+      printf ("=%s", opt[i].argumentHelp);
+      slen += 1 + strlen (opt[i].argumentHelp);
+    }
+    if (slen > BORDER)
+    {
+      printf ("\n%*s", BORDER, "");
+      slen = BORDER;
+    }
+    if (slen < BORDER)
+    {
+      printf ("%*s", (int) (BORDER - slen), "");
+      slen = BORDER;
+    }
+    if (0 < strlen (opt[i].description))
       trans = gettext (opt[i].description);
       trans = gettext (opt[i].description);
-      ml = strlen (trans);
-      p = 0;
-    OUTER:
-      while (ml - p > 78 - slen)
+    else
+      trans = "";
+    ml = strlen (trans);
+    p = 0;
+OUTER:
+    while (ml - p > 78 - slen)
+    {
+      for (j = p + 78 - slen; j > (int) p; j--)
+      {
+        if (isspace ((unsigned char) trans[j]))
         {
         {
-          for (j = p + 78 - slen; j > p; j--)
-            {
-              if (isspace (trans[j]))
-                {
-                  scp = GNUNET_malloc (j - p + 1);
-                  memcpy (scp, &trans[p], j - p);
-                  scp[j - p] = '\0';
-                  printf ("%s\n%*s", scp, BORDER + 2, "");
-                  GNUNET_free (scp);
-                  p = j + 1;
-                  slen = BORDER + 2;
-                  goto OUTER;
-                }
-            }
-          /* could not find space to break line */
-          scp = GNUNET_malloc (78 - slen + 1);
-          memcpy (scp, &trans[p], 78 - slen);
-          scp[78 - slen] = '\0';
+          scp = GNUNET_malloc (j - p + 1);
+          GNUNET_memcpy (scp, &trans[p], j - p);
+          scp[j - p] = '\0';
           printf ("%s\n%*s", scp, BORDER + 2, "");
           GNUNET_free (scp);
           printf ("%s\n%*s", scp, BORDER + 2, "");
           GNUNET_free (scp);
+          p = j + 1;
           slen = BORDER + 2;
           slen = BORDER + 2;
-          p = p + 78 - slen;
+          goto OUTER;
         }
         }
-      /* print rest */
-      if (p < ml)
-        printf ("%s\n", &trans[p]);
-      if (strlen (trans) == 0)
-        printf ("\n");
-      i++;
+      }
+      /* could not find space to break line */
+      scp = GNUNET_malloc (78 - slen + 1);
+      GNUNET_memcpy (scp, &trans[p], 78 - slen);
+      scp[78 - slen] = '\0';
+      printf ("%s\n%*s", scp, BORDER + 2, "");
+      GNUNET_free (scp);
+      slen = BORDER + 2;
+      p = p + 78 - slen;
     }
     }
-  printf ("Report bugs to gnunet-developers@gnu.org.\n"
-          "GNUnet home page: http://www.gnu.org/software/gnunet/\n"
-          "General help using GNU software: http://www.gnu.org/gethelp/\n");
-  return GNUNET_SYSERR;
+    /* print rest */
+    if (p < ml)
+      printf ("%s\n", &trans[p]);
+    if (strlen (trans) == 0)
+      printf ("\n");
+    i++;
+  }
+  pd = GNUNET_OS_project_data_get ();
+  printf ("Report bugs to %s.\n"
+          "GNUnet home page: %s\n"
+          "General help using GNU software: http://www.gnu.org/gethelp/\n",
+          pd->bug_email,
+          pd->homepage);
+  return GNUNET_NO;
 }
 
 
 }
 
 
-int
-GNUNET_GETOPT_increment_value (struct
-                               GNUNET_GETOPT_CommandLineProcessorContext *ctx,
-                               void *scls, const char *cmdLineOption,
-                               const char *value)
+/**
+ * Defining the option to print the command line
+ * help text (-h option).
+ *
+ * @param about string with brief description of the application
+ */
+struct GNUNET_GETOPT_CommandLineOption
+GNUNET_GETOPT_option_help (const char *about)
 {
 {
-  int *val = scls;
+  struct GNUNET_GETOPT_CommandLineOption clo = {
+    .shortName = 'h',
+    .name = "help",
+    .description = gettext_noop("print this help"),
+    .processor = format_help,
+    .scls = (void *) about
+  };
+
+  return clo;
+}
+
+
+/**
+ * Set an option of type 'unsigned int' from the command line. Each
+ * time the option flag is given, the value is incremented by one.
+ * A pointer to this function should be passed as part of the
+ * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
+ * of this type.  It should be followed by a pointer to a value of
+ * type 'int'.
+ *
+ * @param ctx command line processing context
+ * @param scls additional closure (will point to the 'unsigned int')
+ * @param option name of the option
+ * @param value not used (NULL)
+ * @return #GNUNET_OK
+ */
+static int
+increment_value (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
+                 void *scls,
+                 const char *option,
+                 const char *value)
+{
+  unsigned int *val = scls;
+
+  (void) ctx;
+  (void) option;
+  (void) value;
   (*val)++;
   return GNUNET_OK;
 }
 
   (*val)++;
   return GNUNET_OK;
 }
 
-int
-GNUNET_GETOPT_set_one (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
-                       void *scls, const char *option, const char *value)
+
+/**
+ * Increment @a val each time the option flag is given by one.
+ *
+ * @param shortName short name of the option
+ * @param name long name of the option
+ * @param argumentHelp help text for the option argument
+ * @param description long help text for the option
+ * @param[out] val increment by 1 each time the option is present
+ */
+struct GNUNET_GETOPT_CommandLineOption
+GNUNET_GETOPT_option_increment_uint (char shortName,
+                                    const char *name,
+                                    const char *description,
+                                    unsigned int *val)
+{
+  struct GNUNET_GETOPT_CommandLineOption clo = {
+    .shortName =  shortName,
+    .name = name,
+    .description = description,
+    .processor = &increment_value,
+    .scls = (void *) val
+  };
+
+  return clo;
+}
+
+
+/**
+ * Define the '-V' verbosity option.  Using the option more
+ * than once increments @a level each time.
+ *
+ * @param[out] level set to the verbosity level
+ */
+struct GNUNET_GETOPT_CommandLineOption
+GNUNET_GETOPT_option_verbose (unsigned int *level)
+{
+  struct GNUNET_GETOPT_CommandLineOption clo = {
+    .shortName = 'V',
+    .name = "verbose",
+    .description = gettext_noop("be verbose"),
+    .processor = &increment_value,
+    .scls = (void *) level
+  };
+
+  return clo;
+}
+
+
+/**
+ * Set an option of type 'int' from the command line to 1 if the
+ * given option is present.
+ * A pointer to this function should be passed as part of the
+ * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
+ * of this type.  It should be followed by a pointer to a value of
+ * type 'int'.
+ *
+ * @param ctx command line processing context
+ * @param scls additional closure (will point to the 'int')
+ * @param option name of the option
+ * @param value not used (NULL)
+ * @return #GNUNET_OK
+ */
+static int
+set_one (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
+         void *scls,
+         const char *option,
+         const char *value)
 {
   int *val = scls;
 {
   int *val = scls;
+
+  (void) ctx;
+  (void) option;
+  (void) value;
   *val = 1;
   return GNUNET_OK;
 }
 
   *val = 1;
   return GNUNET_OK;
 }
 
-int
-GNUNET_GETOPT_set_string (struct GNUNET_GETOPT_CommandLineProcessorContext
-                          *ctx, void *scls, const char *option,
-                          const char *value)
+
+/**
+ * Allow user to specify a flag (which internally means setting
+ * an integer to 1/#GNUNET_YES/#GNUNET_OK.
+ *
+ * @param shortName short name of the option
+ * @param name long name of the option
+ * @param argumentHelp help text for the option argument
+ * @param description long help text for the option
+ * @param[out] val set to 1 if the option is present
+ */
+struct GNUNET_GETOPT_CommandLineOption
+GNUNET_GETOPT_option_flag (char shortName,
+                          const char *name,
+                          const char *description,
+                          int *val)
+{
+  struct GNUNET_GETOPT_CommandLineOption clo = {
+    .shortName =  shortName,
+    .name = name,
+    .description = description,
+    .processor = &set_one,
+    .scls = (void *) val
+  };
+
+  return clo;
+}
+
+
+/**
+ * Set an option of type 'char *' from the command line.
+ * A pointer to this function should be passed as part of the
+ * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
+ * of this type.  It should be followed by a pointer to a value of
+ * type 'char *', which will be allocated with the requested string.
+ *
+ * @param ctx command line processing context
+ * @param scls additional closure (will point to the 'char *',
+ *             which will be allocated)
+ * @param option name of the option
+ * @param value actual value of the option (a string)
+ * @return #GNUNET_OK
+ */
+static int
+set_string (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
+            void *scls,
+            const char *option,
+            const char *value)
 {
   char **val = scls;
 
 {
   char **val = scls;
 
-  GNUNET_assert (value != NULL);
-  if (NULL != *val)
-    GNUNET_free (*val);
+  (void) ctx;
+  (void) option;
+  GNUNET_assert (NULL != value);
+  GNUNET_free_non_null (*val);
   *val = GNUNET_strdup (value);
   return GNUNET_OK;
 }
 
   *val = GNUNET_strdup (value);
   return GNUNET_OK;
 }
 
-int
-GNUNET_GETOPT_set_ulong (struct GNUNET_GETOPT_CommandLineProcessorContext
-                         *ctx, void *scls, const char *option,
-                         const char *value)
+
+/**
+ * Allow user to specify a string.
+ *
+ * @param shortName short name of the option
+ * @param name long name of the option
+ * @param argumentHelp help text for the option argument
+ * @param description long help text for the option
+ * @param[out] str set to the string
+ */
+struct GNUNET_GETOPT_CommandLineOption
+GNUNET_GETOPT_option_string (char shortName,
+                             const char *name,
+                             const char *argumentHelp,
+                             const char *description,
+                             char **str)
+{
+  struct GNUNET_GETOPT_CommandLineOption clo = {
+    .shortName =  shortName,
+    .name = name,
+    .argumentHelp = argumentHelp,
+    .description = description,
+    .require_argument = 1,
+    .processor = &set_string,
+    .scls = (void *) str
+  };
+
+  return clo;
+}
+
+
+/**
+ * Define the '-L' log level option.  Note that we do not check
+ * that the log level is valid here.
+ *
+ * @param[out] level set to the log level
+ */
+struct GNUNET_GETOPT_CommandLineOption
+GNUNET_GETOPT_option_loglevel (char **level)
+{
+  struct GNUNET_GETOPT_CommandLineOption clo = {
+    .shortName = 'L',
+    .name = "log",
+    .argumentHelp = "LOGLEVEL",
+    .description = gettext_noop("configure logging to use LOGLEVEL"),
+    .require_argument = 1,
+    .processor = &set_string,
+    .scls = (void *) level
+  };
+
+  return clo;
+}
+
+
+/**
+ * Set an option of type 'char *' from the command line with
+ * filename expansion a la #GNUNET_STRINGS_filename_expand().
+ *
+ * @param ctx command line processing context
+ * @param scls additional closure (will point to the `char *`,
+ *             which will be allocated)
+ * @param option name of the option
+ * @param value actual value of the option (a string)
+ * @return #GNUNET_OK
+ */
+static int
+set_filename (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
+              void *scls,
+              const char *option,
+              const char *value)
+{
+  char **val = scls;
+
+  (void) ctx;
+  (void) option;
+  GNUNET_assert (NULL != value);
+  GNUNET_free_non_null (*val);
+  *val = GNUNET_STRINGS_filename_expand (value);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Allow user to specify a filename (automatically path expanded).
+ *
+ * @param shortName short name of the option
+ * @param name long name of the option
+ * @param argumentHelp help text for the option argument
+ * @param description long help text for the option
+ * @param[out] str set to the string
+ */
+struct GNUNET_GETOPT_CommandLineOption
+GNUNET_GETOPT_option_filename (char shortName,
+                              const char *name,
+                              const char *argumentHelp,
+                              const char *description,
+                              char **str)
+{
+  struct GNUNET_GETOPT_CommandLineOption clo = {
+    .shortName =  shortName,
+    .name = name,
+    .argumentHelp = argumentHelp,
+    .description = description,
+    .require_argument = 1,
+    .processor = &set_filename,
+    .scls = (void *) str
+  };
+
+  return clo;
+}
+
+
+/**
+ * Allow user to specify log file name (-l option)
+ *
+ * @param[out] logfn set to the name of the logfile
+ */
+struct GNUNET_GETOPT_CommandLineOption
+GNUNET_GETOPT_option_logfile (char **logfn)
+{
+  struct GNUNET_GETOPT_CommandLineOption clo = {
+    .shortName =  'l',
+    .name = "logfile",
+    .argumentHelp = "FILENAME",
+    .description = gettext_noop ("configure logging to write logs to FILENAME"),
+    .require_argument = 1,
+    .processor = &set_filename,
+    .scls = (void *) logfn
+  };
+
+  return clo;
+}
+
+
+/**
+ * Allow user to specify configuration file name (-c option)
+ *
+ * @param[out] fn set to the name of the configuration file
+ */
+struct GNUNET_GETOPT_CommandLineOption
+GNUNET_GETOPT_option_cfgfile (char **fn)
+{
+  struct GNUNET_GETOPT_CommandLineOption clo = {
+    .shortName =  'c',
+    .name = "config",
+    .argumentHelp = "FILENAME",
+    .description = gettext_noop("use configuration file FILENAME"),
+    .require_argument = 1,
+    .processor = &set_filename,
+    .scls = (void *) fn
+  };
+
+  return clo;
+}
+
+
+/**
+ * Set an option of type 'unsigned long long' from the command line.
+ * A pointer to this function should be passed as part of the
+ * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
+ * of this type.  It should be followed by a pointer to a value of
+ * type 'unsigned long long'.
+ *
+ * @param ctx command line processing context
+ * @param scls additional closure (will point to the 'unsigned long long')
+ * @param option name of the option
+ * @param value actual value of the option as a string.
+ * @return #GNUNET_OK if parsing the value worked
+ */
+static int
+set_ulong (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
+           void *scls,
+           const char *option,
+           const char *value)
 {
   unsigned long long *val = scls;
 {
   unsigned long long *val = scls;
-  if (1 != SSCANF (value, "%llu", val))
-    {
-      fprintf (stderr,
-               _("You must pass a number to the `%s' option.\n"), "-X");
-      return GNUNET_SYSERR;
-    }
+
+  (void) ctx;
+  if (1 != SSCANF (value,
+                   "%llu",
+                   val))
+  {
+    FPRINTF (stderr,
+             _("You must pass a number to the `%s' option.\n"),
+             option);
+    return GNUNET_SYSERR;
+  }
   return GNUNET_OK;
 }
 
 
   return GNUNET_OK;
 }
 
 
-int
-GNUNET_GETOPT_set_uint (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
-                        void *scls, const char *option, const char *value)
+/**
+ * Allow user to specify an `unsigned long long`
+ *
+ * @param shortName short name of the option
+ * @param name long name of the option
+ * @param argumentHelp help text for the option argument
+ * @param description long help text for the option
+ * @param[out] val set to the value specified at the command line
+ */
+struct GNUNET_GETOPT_CommandLineOption
+GNUNET_GETOPT_option_ulong (char shortName,
+                           const char *name,
+                           const char *argumentHelp,
+                           const char *description,
+                           unsigned long long *val)
+{
+  struct GNUNET_GETOPT_CommandLineOption clo = {
+    .shortName =  shortName,
+    .name = name,
+    .argumentHelp = argumentHelp,
+    .description = description,
+    .require_argument = 1,
+    .processor = &set_ulong,
+    .scls = (void *) val
+  };
+
+  return clo;
+}
+
+
+/**
+ * Set an option of type 'struct GNUNET_TIME_Relative' from the command line.
+ * A pointer to this function should be passed as part of the
+ * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
+ * of this type.  It should be followed by a pointer to a value of
+ * type 'struct GNUNET_TIME_Relative'.
+ *
+ * @param ctx command line processing context
+ * @param scls additional closure (will point to the 'struct GNUNET_TIME_Relative')
+ * @param option name of the option
+ * @param value actual value of the option as a string.
+ * @return #GNUNET_OK if parsing the value worked
+ */
+static int
+set_relative_time (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
+                   void *scls,
+                   const char *option,
+                   const char *value)
+{
+  struct GNUNET_TIME_Relative *val = scls;
+  
+  (void) ctx;  
+  if (GNUNET_OK !=
+      GNUNET_STRINGS_fancy_time_to_relative (value,
+                                            val))
+  {
+    FPRINTF (stderr,
+             _("You must pass relative time to the `%s' option.\n"),
+             option);
+    return GNUNET_SYSERR;
+  }
+  return GNUNET_OK;
+}
+
+
+/**
+ * Allow user to specify a `struct GNUNET_TIME_Relative`
+ * (using human-readable "fancy" time).
+ *
+ * @param shortName short name of the option
+ * @param name long name of the option
+ * @param argumentHelp help text for the option argument
+ * @param description long help text for the option
+ * @param[out] val set to the time specified at the command line
+ */
+struct GNUNET_GETOPT_CommandLineOption
+GNUNET_GETOPT_option_relative_time (char shortName,
+                                   const char *name,
+                                   const char *argumentHelp,
+                                   const char *description,
+                                   struct GNUNET_TIME_Relative *val)
+{
+  struct GNUNET_GETOPT_CommandLineOption clo = {
+    .shortName =  shortName,
+    .name = name,
+    .argumentHelp = argumentHelp,
+    .description = description,
+    .require_argument = 1,
+    .processor = &set_relative_time,
+    .scls = (void *) val
+  };
+
+  return clo;
+}
+
+
+/**
+ * Set an option of type 'struct GNUNET_TIME_Absolute' from the command line.
+ * A pointer to this function should be passed as part of the
+ * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
+ * of this type.  It should be followed by a pointer to a value of
+ * type 'struct GNUNET_TIME_Absolute'.
+ *
+ * @param ctx command line processing context
+ * @param scls additional closure (will point to the `struct GNUNET_TIME_Absolute`)
+ * @param option name of the option
+ * @param value actual value of the option as a string.
+ * @return #GNUNET_OK if parsing the value worked
+ */
+static int
+set_absolute_time (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
+                   void *scls,
+                   const char *option,
+                   const char *value)
+{
+  struct GNUNET_TIME_Absolute *val = scls;
+
+  (void) ctx;
+  if (GNUNET_OK !=
+      GNUNET_STRINGS_fancy_time_to_absolute (value,
+                                            val))
+  {
+    FPRINTF (stderr,
+             _("You must pass absolute time to the `%s' option.\n"),
+             option);
+    return GNUNET_SYSERR;
+  }
+  return GNUNET_OK;
+}
+
+
+/**
+ * Allow user to specify a `struct GNUNET_TIME_Absolute`
+ * (using human-readable "fancy" time).
+ *
+ * @param shortName short name of the option
+ * @param name long name of the option
+ * @param argumentHelp help text for the option argument
+ * @param description long help text for the option
+ * @param[out] val set to the time specified at the command line
+ */
+struct GNUNET_GETOPT_CommandLineOption
+GNUNET_GETOPT_option_absolute_time (char shortName,
+                                   const char *name,
+                                   const char *argumentHelp,
+                                   const char *description,
+                                   struct GNUNET_TIME_Absolute *val)
+{
+  struct GNUNET_GETOPT_CommandLineOption clo = {
+    .shortName =  shortName,
+    .name = name,
+    .argumentHelp = argumentHelp,
+    .description = description,
+    .require_argument = 1,
+    .processor = &set_absolute_time,
+    .scls = (void *) val
+  };
+
+  return clo;
+}
+
+
+/**
+ * Set an option of type 'unsigned int' from the command line.
+ * A pointer to this function should be passed as part of the
+ * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
+ * of this type.  It should be followed by a pointer to a value of
+ * type 'unsigned int'.
+ *
+ * @param ctx command line processing context
+ * @param scls additional closure (will point to the 'unsigned int')
+ * @param option name of the option
+ * @param value actual value of the option as a string.
+ * @return #GNUNET_OK if parsing the value worked
+ */
+static int
+set_uint (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
+          void *scls,
+          const char *option,
+          const char *value)
 {
   unsigned int *val = scls;
 
 {
   unsigned int *val = scls;
 
-  if (1 != SSCANF (value, "%u", val))
-    {
-      fprintf (stderr,
-               _("You must pass a number to the `%s' option.\n"), "-X");
-      return GNUNET_SYSERR;
-    }
+  (void) ctx;
+  if (1 != SSCANF (value,
+                   "%u",
+                   val))
+  {
+    FPRINTF (stderr,
+             _("You must pass a number to the `%s' option.\n"),
+             option);
+    return GNUNET_SYSERR;
+  }
+  return GNUNET_OK;
+}
+
+
+/**
+ * Allow user to specify an unsigned integer.
+ *
+ * @param shortName short name of the option
+ * @param name long name of the option
+ * @param argumentHelp help text for the option argument
+ * @param description long help text for the option
+ * @param[out] val set to the value specified at the command line
+ */
+struct GNUNET_GETOPT_CommandLineOption
+GNUNET_GETOPT_option_uint (char shortName,
+                          const char *name,
+                          const char *argumentHelp,
+                          const char *description,
+                          unsigned int *val)
+{
+  struct GNUNET_GETOPT_CommandLineOption clo = {
+    .shortName =  shortName,
+    .name = name,
+    .argumentHelp = argumentHelp,
+    .description = description,
+    .require_argument = 1,
+    .processor = &set_uint,
+    .scls = (void *) val
+  };
+
+  return clo;
+}
+
+
+/**
+ * Closure for #set_base32().
+ */
+struct Base32Context
+{
+  /**
+   * Value to initialize (already allocated)
+   */
+  void *val;
+
+  /**
+   * Number of bytes expected for @e val.
+   */
+  size_t val_size;
+};
+
+
+/**
+ * Set an option of type 'unsigned int' from the command line.
+ * A pointer to this function should be passed as part of the
+ * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
+ * of this type.  It should be followed by a pointer to a value of
+ * type 'unsigned int'.
+ *
+ * @param ctx command line processing context
+ * @param scls additional closure (will point to the 'unsigned int')
+ * @param option name of the option
+ * @param value actual value of the option as a string.
+ * @return #GNUNET_OK if parsing the value worked
+ */
+static int
+set_base32 (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
+            void *scls,
+            const char *option,
+            const char *value)
+{
+  struct Base32Context *bc = scls;
+
+  (void) ctx;
+  if (GNUNET_OK !=
+      GNUNET_STRINGS_string_to_data (value,
+                                     strlen (value),
+                                     bc->val,
+                                     bc->val_size))
+  {
+    fprintf (stderr,
+             _("Argument `%s' malformed. Expected base32 (Crockford) encoded value.\n"),
+             option);
+    return GNUNET_SYSERR;
+  }
   return GNUNET_OK;
 }
 
 
   return GNUNET_OK;
 }
 
 
+/**
+ * Helper function to clean up after
+ * #GNUNET_GETOPT_option_base32_fixed_size.
+ *
+ * @param cls value to GNUNET_free()
+ */
+static void
+free_bc (void *cls)
+{
+  GNUNET_free (cls);
+}
+
+
+/**
+ * Allow user to specify a binary value using Crockford
+ * Base32 encoding.
+ *
+ * @param shortName short name of the option
+ * @param name long name of the option
+ * @param argumentHelp help text for the option argument
+ * @param description long help text for the option
+ * @param[out] val binary value decoded from Crockford Base32-encoded argument
+ * @param val_size size of @a val in bytes
+ */
+struct GNUNET_GETOPT_CommandLineOption
+GNUNET_GETOPT_option_base32_fixed_size (char shortName,
+                                            const char *name,
+                                            const char *argumentHelp,
+                                            const char *description,
+                                            void *val,
+                                            size_t val_size)
+{
+  struct Base32Context *bc = GNUNET_new (struct Base32Context);
+  struct GNUNET_GETOPT_CommandLineOption clo = {
+    .shortName =  shortName,
+    .name = name,
+    .argumentHelp = argumentHelp,
+    .description = description,
+    .require_argument = 1,
+    .processor = &set_base32,
+    .cleaner = &free_bc,
+    .scls = (void *) bc
+  };
+
+  bc->val = val;
+  bc->val_size = val_size;
+  return clo;
+}
+
+
+/**
+ * Make the given option mandatory.
+ *
+ * @param opt option to modify
+ * @return @a opt with the mandatory flag set.
+ */
+struct GNUNET_GETOPT_CommandLineOption
+GNUNET_GETOPT_option_mandatory (struct GNUNET_GETOPT_CommandLineOption opt)
+{
+  opt.option_mandatory = 1;
+  return opt;
+}
+
+
 /* end of getopt_helpers.c */
 /* end of getopt_helpers.c */