commit-mailutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[SCM] GNU Mailutils branch, master, updated. release-2.2-769-gd56b824


From: Sergey Poznyakoff
Subject: [SCM] GNU Mailutils branch, master, updated. release-2.2-769-gd56b824
Date: Wed, 12 Oct 2016 06:23:03 +0000 (UTC)

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU Mailutils".

http://git.savannah.gnu.org/cgit/mailutils.git/commit/?id=d56b82437f909ff323d9cd87f2ed9f04322f9966

The branch, master has been updated
       via  d56b82437f909ff323d9cd87f2ed9f04322f9966 (commit)
       via  260b113a1e75989b4e460712f16af10d93fe19e8 (commit)
       via  bc73fc65600b6021dfe7a9fa1fba7e9b823993e2 (commit)
      from  6e8147334cf9ffe36367760c06002a1e5b7ae0d5 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit d56b82437f909ff323d9cd87f2ed9f04322f9966
Author: Sergey Poznyakoff <address@hidden>
Date:   Wed Oct 12 09:15:47 2016 +0300

    Convert to mu_cli: frm, from, messages, mimeview, movemail, readmsg, sieve
    
    * configure.ac (MU_APP_NEW_LIBRARIES): New temp variable.
    
    * include/mailutils/sieve.h (mu_cli_capa_sieve): New extern.
    * include/mailutils/tls.h (mu_cli_capa_tls): New extern.
    
    * libmailutils/cli/cli.c: Minor change.
    * libmailutils/cli/stdcapa.c: Add "auth" capability.
    
    * libmu_auth/tls.c: provide mu_cli_capa_tls
    
    * dotlock/Makefile.am: Link with MU_APP_NEW_LIBRARIES
    * dotlock/dotlock.c
    
    * frm/Makefile.am: Link with MU_APP_NEW_LIBRARIES
    * frm/frm.h: Fix includes.
    * frm/frm.c: Use mu_cli for optionr&config parsing.
    * frm/from.c: Likewise.
    
    * messages/Makefile.am: Link with MU_APP_NEW_LIBRARIES
    * messages/messages.c: Use mu_cli for optionr&config parsing.
    
    * mimeview/Makefile.am: Link with MU_APP_NEW_LIBRARIES
    * mimeview/mimeview.c: Use mu_cli for optionr&config parsing.
    
    * movemail/Makefile.am: Link with MU_APP_NEW_LIBRARIES
    * movemail/movemail.c: Use mu_cli for optionr&config parsing.
    
    * readmsg/Makefile.am: Link with MU_APP_NEW_LIBRARIES
    * readmsg/readmsg.c: Use mu_cli for optionr&config parsing.
    
    * sieve/Makefile.am: Link with MU_APP_NEW_LIBRARIES
    * sieve/sieve.c: Use mu_cli for optionr&config parsing.

commit 260b113a1e75989b4e460712f16af10d93fe19e8
Author: Sergey Poznyakoff <address@hidden>
Date:   Tue Oct 11 18:02:33 2016 +0300

    Bugfix
    
    * libmailutils/opt/opt.c (find_long_option): Don't mark ambiguity
    if the matching option unaliases to the same option as the found one.

commit bc73fc65600b6021dfe7a9fa1fba7e9b823993e2
Author: Sergey Poznyakoff <address@hidden>
Date:   Tue Oct 11 17:20:38 2016 +0300

    Introduce new CLI/configuration code for mailutils applications.
    
    The new API is to replace libmu_cfg and libmu_argp.  A smooth transition
    is scheduled, during which the two APIs will coexist,
    
    * configure.ac: Build libmailutils/cli/Makefile
    * include/mailutils/cli.h: New file.
    * include/mailutils/Makefile.am: Add cli.h
    * libmailutils/cli/Makefile.am: New file.
    * libmailutils/cli/capa.c: New file.
    * libmailutils/cli/cli.c: New file.
    * libmailutils/cli/stdcapa.c: New file.
    * libmailutils/Makefile.am (SUBDIRS): Add cli.
    
    * include/mailutils/cfg.h (mu_cfg_parse_hints): New members: append_tree
    and data.
    (MU_PARSE_CONFIG_LINT): New flag.
    * include/mailutils/diag.h (mu_program_name)
    (mu_full_program_name): Remove const qualifier.
    * include/mailutils/locker.h (mu_locker_set_default_external_program):
    Argument is const.
    * libmailutils/base/locker.c: Likewise.
    
    * include/mailutils/opt.h (mu_progname, mu_absprogname): Replace
    with mu_program_name and mu_full_program_name.
    (mu_set_progname): Rename to mu_set_program_name.
    (mu_parseopt) <po_data>: Change type to void *.
    (po_help_hook, po_version_hook): Change signatures.
    (mu_parseopt_error): New function.
    * libmailutils/opt/progname.c (mu_progname, mu_absprogname): Replace
    with mu_program_name and mu_full_program_name.
    (mu_set_progname): Rename to mu_set_program_name.
    * libmailutils/opt/help.c: Minor changes
    * libmailutils/opt/opt.c (parse_error): Rename to mu_parse_error (extern).
    (next_opt): Fix permutations.
    * libmailutils/tests/parseopt.c: Reflect changes.
    * libmailutils/tests/parseopt17.at: Improve test case
    * libmailutils/tests/parseopt_help05.at: Reflect changes.
    * libmailutils/tests/parseopt_help07.at: Reflect changes.
    
    * include/mailutils/stdstream.h (mu_program_name): Remove qualifier.
    
    * libmailutils/cfg/driver.c (mu_cfg_tree_reduce): Remove useless condition
    
    * libmailutils/cfg/lexer.l (mu_cfg_parse_file): Additional info messages.
    * libmailutils/cfg/parser.y (mu_cfg_parse_config): Join in
    the append_tree.
    * libmailutils/diag/diag.c (mu_program_name, mu_full_program_name)
    (mu_set_program_name): Remove. Declared elsewhere.
    * libmu_sieve/conf.c: Add new configuration code. Mark old text for
    removal.
    * libmailutils/tests/tcli.c: New program.
    * libmailutils/tests/Makefile.am: Add tcli.c

-----------------------------------------------------------------------

Summary of changes:
 configure.ac                          |    2 +
 dotlock/Makefile.am                   |    2 +-
 dotlock/dotlock.c                     |  146 +++------
 frm/Makefile.am                       |    2 +-
 frm/frm.c                             |  190 +++++------
 frm/frm.h                             |    2 +-
 frm/from.c                            |   83 ++---
 include/mailutils/Makefile.am         |    1 +
 include/mailutils/cfg.h               |    5 +-
 include/mailutils/cli.h               |   55 ++++
 include/mailutils/diag.h              |    4 +-
 include/mailutils/locker.h            |    2 +-
 include/mailutils/opt.h               |   16 +-
 include/mailutils/sieve.h             |    3 +
 include/mailutils/stdstream.h         |    2 +-
 include/mailutils/tls.h               |    3 +
 libmailutils/Makefile.am              |    3 +-
 libmailutils/base/locker.c            |    2 +-
 libmailutils/cfg/driver.c             |   12 +-
 libmailutils/cfg/lexer.l              |    6 +
 libmailutils/cfg/parser.y             |    5 +-
 libmailutils/{opt => cli}/Makefile.am |   10 +-
 libmailutils/cli/capa.c               |   96 ++++++
 libmailutils/cli/cli.c                |  420 ++++++++++++++++++++++++
 libmailutils/cli/stdcapa.c            |  568 +++++++++++++++++++++++++++++++++
 libmailutils/diag/diag.c              |   26 --
 libmailutils/opt/help.c               |    8 +-
 libmailutils/opt/opt.c                |   26 +-
 libmailutils/opt/progname.c           |   14 +-
 libmailutils/tests/.gitignore         |    1 +
 libmailutils/tests/Makefile.am        |    1 +
 libmailutils/tests/parseopt.c         |    4 +-
 libmailutils/tests/parseopt17.at      |   20 ++
 libmailutils/tests/parseopt_help05.at |    2 +-
 libmailutils/tests/parseopt_help07.at |    2 +-
 libmailutils/tests/tcli.c             |   75 +++++
 libmu_auth/tls.c                      |  111 ++++++-
 libmu_sieve/conf.c                    |  171 +++++++++-
 messages/Makefile.am                  |    2 +-
 messages/messages.c                   |   89 ++----
 mimeview/Makefile.am                  |    2 +-
 mimeview/mimeview.c                   |  169 +++++-----
 movemail/Makefile.am                  |    2 +-
 movemail/movemail.c                   |  294 ++++++++---------
 readmsg/Makefile.am                   |    2 +-
 readmsg/readmsg.c                     |  140 +++-----
 sieve/Makefile.am                     |    2 +-
 sieve/sieve.c                         |  265 ++++++---------
 48 files changed, 2123 insertions(+), 945 deletions(-)
 create mode 100644 include/mailutils/cli.h
 copy libmailutils/{opt => cli}/Makefile.am (91%)
 create mode 100644 libmailutils/cli/capa.c
 create mode 100644 libmailutils/cli/cli.c
 create mode 100644 libmailutils/cli/stdcapa.c
 create mode 100644 libmailutils/tests/tcli.c

diff --git a/configure.ac b/configure.ac
index dc244de..d9f1b58 100644
--- a/configure.ac
+++ b/configure.ac
@@ -58,6 +58,7 @@ AC_SUBST(MU_SIEVE_MODDIR,'$(libdir)/$(PACKAGE)')
 
 AC_SUBST(MU_COMMON_LIBRARIES,'$(LTLIBINTL) $(LTLIBICONV)')
 AC_SUBST(MU_APP_LIBRARIES,'${top_builddir}/libmu_argp/libmu_argp.la 
${top_builddir}/libmu_cfg/libmu_cfg.la ${top_builddir}/lib/libmuaux.la')
+AC_SUBST(MU_APP_NEW_LIBRARIES,'${top_builddir}/lib/libmuaux.la')
 
 # There are two sets of include directories: MU_LIB_COMMON_INCLUDES, used
 # by the libraries, and MU_APP_COMMON_INCLUDES, which is used by applications.
@@ -1506,6 +1507,7 @@ AC_CONFIG_FILES([
  libmailutils/address/Makefile
  libmailutils/sockaddr/Makefile
  libmailutils/cidr/Makefile
+ libmailutils/cli/Makefile
  libmailutils/cfg/Makefile
  libmailutils/datetime/Makefile
  libmailutils/diag/Makefile
diff --git a/dotlock/Makefile.am b/dotlock/Makefile.am
index 3425b0f..0ab3f34 100644
--- a/dotlock/Makefile.am
+++ b/dotlock/Makefile.am
@@ -20,7 +20,7 @@ AM_CPPFLAGS = @MU_APP_COMMON_INCLUDES@
 bin_PROGRAMS = dotlock
 
 dotlock_LDADD = \
- ${MU_APP_LIBRARIES}\
+ ${MU_APP_NEW_LIBRARIES}\
  ${MU_LIB_MAILUTILS}\
  @MU_COMMON_LIBRARIES@
 
diff --git a/dotlock/dotlock.c b/dotlock/dotlock.c
index c6a96c5..0a8cfec 100644
--- a/dotlock/dotlock.c
+++ b/dotlock/dotlock.c
@@ -20,49 +20,12 @@
 #endif
 
 #include <stdlib.h>
-#ifdef __EXT_QNX
-# undef __EXT_QNX
-#endif
 #include <unistd.h>
 
 #include <mailutils/errno.h>
 #include <mailutils/locker.h>
 #include <mailutils/nls.h>
-
-#include "mailutils/libargp.h"
-
-static char doc[] =
-N_("GNU dotlock -- lock mail spool files.")
-"\v"
-N_("Returns 0 on success, 3 if locking the file fails because\
- it's already locked, and 1 if some other kind of error occurred.");
-
-static char args_doc[] = N_("FILE");
-
-static struct argp_option options[] = {
-  {"unlock", 'u', NULL, 0,
-   N_("unlock"), 0},
-
-  {"force", 'f', N_("MINUTES"), OPTION_ARG_OPTIONAL,
-   N_("forcibly break an existing lock older than a certain time"), 0},
-
-  {"retry", 'r', N_("RETRIES"), OPTION_ARG_OPTIONAL,
-   N_("retry the lock a few times"), 0},
-
-  {"debug", 'd', NULL, 0,
-   N_("print details of failure reasons to stderr"), 0},
-
-  {NULL, 0, NULL, 0, NULL, 0}
-};
-
-static error_t parse_opt (int key, char *arg, struct argp_state *state);
-
-static struct argp argp = {
-  options,
-  parse_opt,
-  args_doc,
-  doc,
-};
+#include "mailutils/cli.h"
 
 static const char *file;
 static int unlock;
@@ -71,55 +34,25 @@ static int retries;
 static time_t force;
 static int debug;
 
-static error_t
-parse_opt (int key, char *arg, struct argp_state *state)
-{
-  static mu_list_t lst;
-
-  switch (key)
-    {
-    case 'd':
-      mu_argp_node_list_new (lst, "debug", "yes");
-      break;
-
-    case 'u':
-      unlock = 1;
-      break;
-
-    case 'r':
-      if (arg)
-       mu_argp_node_list_new (lst, "retry", arg);
-      break;
-
-    case 'f':
-      mu_argp_node_list_new (lst, "force", arg ? arg : "0");
-      break;
-
-    case ARGP_KEY_ARG:
-      if (file)
-       argp_error (state, _("only one FILE can be specified"));
-      file = arg;
-      break;
-
-    case ARGP_KEY_NO_ARGS:
-      if (!mu_help_config_mode)
-       argp_error (state, _("FILE must be specified"));
-      return ARGP_ERR_UNKNOWN;
-      
-    case ARGP_KEY_INIT:
-      mu_argp_node_list_init (&lst);
-      break;
-      
-    case ARGP_KEY_FINI:
-      mu_argp_node_list_finish (lst, NULL, NULL);
-      break;
-      
-    default:
-      return ARGP_ERR_UNKNOWN;
-    }
-  return 0;
-}
-
+static struct mu_option dotlock_options[] = {
+  { "unlock", 'u', NULL, MU_OPTION_DEFAULT,
+    N_("unlock"),
+    mu_c_bool, &unlock },
+
+  { "force",  'f', N_("MINUTES"), MU_OPTION_ARG_OPTIONAL,
+    N_("forcibly break an existing lock older than a certain time"),
+    mu_c_time, &force },//FIXME: Default value
+ 
+  { "retry",  'r', N_("RETRIES"), MU_OPTION_ARG_OPTIONAL,
+    N_("retry the lock a few times"),
+    mu_c_int, &retries },
+
+  { "debug",  'd', NULL, MU_OPTION_DEFAULT,
+    N_("print details of failure reasons to stderr"), 
+    mu_c_bool, &debug },
+
+  MU_OPTION_END
+}, *options[] = { dotlock_options, NULL };
 
 struct mu_cfg_param dotlock_cfg_param[] = {
   { "force", mu_c_time, &force, 0, NULL,
@@ -130,12 +63,22 @@ struct mu_cfg_param dotlock_cfg_param[] = {
     N_("Print details of failure reasons to stderr.") },
   { NULL }
 };
+
+static struct mu_cli_setup cli = {
+  options,
+  dotlock_cfg_param,
+  N_("GNU dotlock -- lock mail spool files."),
+  //FIXME:
+  /*
+  N_("Returns 0 on success, 3 if locking the file fails because\
+ it's already locked, and 1 if some other kind of error occurred.");
+  */
+  N_("FILE")
+};
 
 
 
-const char *dotlock_capa[] = {
-  "mailutils",
-  "common",
+char *capa[] = {
   "debug",
   NULL
 };
@@ -156,13 +99,24 @@ main (int argc, char *argv[])
   if (setegid (usergid) < 0)
     return MU_DL_EX_ERROR;
 
-  argp_err_exit_status = MU_DL_EX_ERROR;
-  
-  mu_argp_init (NULL, NULL);
-  if (mu_app_init (&argp, dotlock_capa, dotlock_cfg_param, 
-                  argc, argv, 0, NULL, NULL))
-    exit (1);
+  /* FIXME: Force mu_cli to exit with MU_DL_EX_ERROR on errors? */
+
+  mu_cli (argc, argv, &cli, capa, NULL, &argc, &argv);
+
+  switch (argc)
+    {
+    case 0:
+      mu_error (_("FILE must be specified"));
+      exit (MU_DL_EX_ERROR);
+
+    case 1:
+      file = argv[0];
+      break;
 
+    default:
+      mu_error (_("only one FILE can be specified"));
+    }
+  
   if (force)
     {
       force *= 60;
diff --git a/frm/Makefile.am b/frm/Makefile.am
index 7861b51..8678e2f 100644
--- a/frm/Makefile.am
+++ b/frm/Makefile.am
@@ -27,7 +27,7 @@ frm_LDADD =  $(common_ldadd)
 from_LDADD = $(common_ldadd)
 
 common_ldadd = \
- ${MU_APP_LIBRARIES}\
+ ${MU_APP_NEW_LIBRARIES}\
  ${MU_LIB_MBOX}\
  ${MU_LIB_IMAP}\
  ${MU_LIB_POP}\
diff --git a/frm/frm.c b/frm/frm.c
index 4df0d87..99db191 100644
--- a/frm/frm.c
+++ b/frm/frm.c
@@ -29,8 +29,6 @@ static int align = 0;      /* Tidy mode. -t option. */
 #define IS_NEW  0x100
 static int select_attribute;
 
-static char doc[] = N_("GNU frm -- display From: lines.");
-
 static struct attr_tab {
   char *name;      /* Attribute name */
   int code;        /* Corresponding IS_.* flag */
@@ -84,7 +82,7 @@ prepare_attrs (void)
 /* Translates the textual status representation to the corresponding
    IS_.* flag */
 static int
-decode_attr (char *arg)
+decode_attr (char const *arg)
 {
   struct attr_tab *p;
   int len = strlen (arg);
@@ -111,105 +109,82 @@ decode_attr (char *arg)
 }
 
 
+static void
+cli_show_field (struct mu_parseopt *po, struct mu_option *opt, char const *arg)
+{
+  show_field = mu_strdup (arg);
+  align = 0;
+}
 
-static struct argp_option options[] = {
-  {"debug",  'd', NULL,   0, N_("enable debugging output"), 0},
-  {"field",  'f', N_("NAME"), 0, N_("header field to display"), 0},
-  {"to",     'l', NULL,   0, N_("include the To: information"), 0},
-  {"number", 'n', NULL,   0, N_("display message numbers"), 0},
-  {"Quiet",  'Q', NULL,   0, N_("do not display headers"), 0},
-  {"query",  'q', NULL,   0, N_("print a message if the mailbox contains some 
unread mail"), 0},
-  {"summary",'S', NULL,   0, N_("print a summary of messages"), 0},
-  {"status", 's', N_("STATUS"), 0,
-   /* TRANSLATORS: Please do *not* translate the words "new", "unread",
-      "old" and "read". They are keywords. */
-   N_("select messages with the specific attribute:"
-      " new, unread, old (same as unread) or read (or any unambiguous"
-      " abbreviation of these)"),
-   0},
-  {"align",  't', NULL,   0, N_("tidy mode: align subject lines"), 0},
-  {0, 0, 0, 0}
-};
+static void
+cli_Quiet (struct mu_parseopt *po, struct mu_option *opt, char const *arg)
+{
+  be_quiet += 2;
+}
 
-static error_t
-parse_opt (int key, char *arg, struct argp_state *state)
+static void
+cli_query (struct mu_parseopt *po, struct mu_option *opt, char const *arg)
 {
-  switch (key)
-    {
-    case 'd':
-      frm_debug++;
-      break;
-
-    case 'f':
-      show_field = arg;
-      align = 0;
-      break;
-
-    case 'l':
-      show_to = 1;
-      break;
-
-    case 'n':
-      show_number = 1;
-      break;
-
-    case 'Q':
-      /* Very silent.  */
-      be_quiet += 2;
-      break;
-
-    case 'q':
-      be_quiet++;
-      show_query = 1;
-      break;
-
-    case 'S':
-      show_summary = 1;
-      break;
-
-    case 's':
-      select_attribute = decode_attr (arg);
-      break;
-      
-    case 't':
-      align = 1;
-      break;
-
-    case ARGP_KEY_FINI:
-      {
-       size_t s;
-       if (align && (s = util_getcols ()))
-         init_output (s);
-       else
-         init_output (0);
-      }
-      break;
-      
-    default: 
-      return ARGP_ERR_UNKNOWN;
-    }
-  return 0;
+  be_quiet++;
+  show_query = 1;
+}
+
+static void
+cli_status (struct mu_parseopt *po, struct mu_option *opt, char const *arg)
+{
+  select_attribute = decode_attr (arg);
 }
 
-static struct argp argp = {
+static struct mu_option frm_options[] = {
+  { "debug",  'd', NULL,   MU_OPTION_DEFAULT,
+    N_("enable debugging output"),
+    mu_c_incr, &frm_debug },
+  { "field",  'f', N_("NAME"), MU_OPTION_DEFAULT,
+    N_("header field to display"),
+    mu_c_string, &show_field, cli_show_field },
+  { "to",     'l', NULL,   MU_OPTION_DEFAULT,
+    N_("include the To: information"),
+    mu_c_bool, &show_to },
+  { "number", 'n', NULL,   MU_OPTION_DEFAULT,
+    N_("display message numbers"),
+    mu_c_bool, &show_number },
+  { "Quiet",  'Q', NULL,   MU_OPTION_DEFAULT,
+    N_("do not display headers"),
+    mu_c_int, &be_quiet, cli_Quiet },
+  { "query",  'q', NULL,   MU_OPTION_DEFAULT,
+    N_("print a message if the mailbox contains some unread mail"),
+    mu_c_int, &be_quiet, cli_query },
+  { "summary",'S', NULL,   MU_OPTION_DEFAULT,
+    N_("print a summary of messages"), 
+    mu_c_bool, &show_summary },
+  { "status", 's', N_("STATUS"), 0,
+    /* TRANSLATORS: Please do *not* translate the words "new", "unread",
+       "old" and "read". They are keywords. */
+    N_("select messages with the specific attribute:"
+       " new, unread, old (same as unread) or read (or any unambiguous"
+       " abbreviation of these)"),
+    mu_c_string, NULL, cli_status},
+  { "align",  't', NULL,   MU_OPTION_DEFAULT,
+    N_("tidy mode: align subject lines"),
+    mu_c_bool, &align },
+  MU_OPTION_END
+}, *options[] = { frm_options, NULL };
+
+static struct mu_cli_setup cli = {
   options,
-  parse_opt,
-  N_("[URL ...]"),
-  doc,
   NULL,
-  NULL, NULL
+  N_("GNU frm -- display From: lines."),
+  N_("[URL ...]"),
 };
 
-static const char *frm_argp_capa[] = {
-  "mailutils",
-  "common",
+static char *frm_argp_capa[] = {
   "debug",
   "mailbox",
   "locking",
+  "tls",
   NULL
 };
-
-
+
 static struct
 {
   size_t new;
@@ -342,8 +317,8 @@ frm (char *mailbox_name)
 int
 main (int argc, char **argv)
 {
-  int c;
   int status = 0;
+  size_t s;
 
   /* Native Language Support */
   MU_APP_INIT_NLS ();
@@ -352,25 +327,30 @@ main (int argc, char **argv)
   
   /* register the formats.  */
   mu_register_all_mbox_formats ();
-#ifdef WITH_TLS
-  mu_gocs_register ("tls", mu_tls_module_init);
-#endif
-  
-  mu_argp_init (NULL, NULL);
-  if (mu_app_init (&argp, frm_argp_capa, NULL, argc, argv, 0, &c, NULL))
-    exit (1);
 
+  mu_cli_capa_register (&mu_cli_capa_tls);
+  mu_cli (argc, argv, &cli, frm_argp_capa, NULL, &argc, &argv);
+
+  if (align && (s = util_getcols ()))
+    init_output (s);
+  else
+    init_output (0);
+  
   /* have an argument */
-  if (c == argc)
+  if (argc == 0)
     status = frm (NULL);
-  else if (c + 1 == argc)
-    status = frm (argv[c]);
+  else if (argc == 1)
+    status = frm (argv[0]);
   else
-    for (; c < argc; c++)
-      {
-       mu_printf ("%s:\n", argv[c]);
-       status = frm (argv[c]);
-      }
-
+    {
+      int i;
+      
+      for (i = 0; i < argc; i++)
+       {
+         mu_printf ("%s:\n", argv[i]);
+         status = frm (argv[i]);
+       }
+    }
+  
   return status;
 }
diff --git a/frm/frm.h b/frm/frm.h
index 44e2652..60b10a0 100644
--- a/frm/frm.h
+++ b/frm/frm.h
@@ -64,7 +64,7 @@
 #include <mailutils/util.h>
 #include <mailutils/mime.h>
 
-#include "mailutils/libargp.h"
+#include "mailutils/cli.h"
 
 typedef int (*frm_select_t) (size_t index, mu_message_t msg);
 
diff --git a/frm/from.c b/frm/from.c
index 270221f..7995bb4 100644
--- a/frm/from.c
+++ b/frm/from.c
@@ -21,58 +21,34 @@ int count_only;
 char *sender_option;
 char *mailbox_name;
 
-static char doc[] = N_("GNU from -- display from and subject.");
-
-static struct argp_option options[] = {
-  {"count",  'c', NULL,   0, N_("just print a count of messages and exit")},
-  {"sender", 's', N_("ADDRESS"), 0,
-   N_("print only mail from addresses containing the supplied string") },
-  {"file",   'f', N_("FILE"), 0,
-   N_("read mail from FILE") },
-  {"debug",  'd', NULL,   0, N_("enable debugging output"), 0},
-  {0, 0, 0, 0}
-};
-
-static error_t
-parse_opt (int key, char *arg, struct argp_state *state)
-{
-  switch (key)
-    {
-    case 'c':
-      count_only = 1;
-      break;
-      
-    case 's':
-      sender_option = arg;
-      break;
-      
-    case 'f':
-      mailbox_name = arg;
-      break;
-      
-    case 'd':
-      frm_debug++;
-      break;
-
-    default: 
-      return ARGP_ERR_UNKNOWN;
-    }
-  return 0;
-}
-
-static struct argp argp = {
+static struct mu_option from_options[] = {
+  { "count",  'c', NULL,   MU_OPTION_DEFAULT,
+    N_("just print a count of messages and exit"),
+    mu_c_bool, &count_only },
+  { "sender", 's', N_("ADDRESS"), MU_OPTION_DEFAULT,
+    N_("print only mail from addresses containing the supplied string"),
+    mu_c_string, &sender_option },
+  { "file",   'f', N_("FILE"), MU_OPTION_DEFAULT,
+    N_("read mail from FILE"), 
+    mu_c_string, &mailbox_name },
+  { "debug",  'd', NULL,   MU_OPTION_DEFAULT,
+    N_("enable debugging output"),
+    mu_c_incr, &frm_debug },
+  MU_OPTION_END
+}, *options[] = { from_options, NULL };
+
+static struct mu_cli_setup cli = {
   options,
-  parse_opt,
+  NULL,
+  N_("GNU from -- display from and subject."),
   N_("[OPTIONS] [USER]"),
-  doc,
 };
 
-static const char *capa[] = {
-  "mailutils",
-  "common",
+static char *capa[] = {
   "debug",
   "mailbox",
   "locking",
+  "tls",
   NULL
 };
 
@@ -105,7 +81,6 @@ from_select (size_t index, mu_message_t msg)
 int
 main (int argc, char **argv)
 {
-  int c;
   size_t total;
   
   /* Native Language Support */
@@ -113,20 +88,16 @@ main (int argc, char **argv)
 
   /* register the formats.  */
   mu_register_all_mbox_formats ();
-#ifdef WITH_TLS
-  mu_gocs_register ("tls", mu_tls_module_init);
-#endif
 
-  mu_argp_init (NULL, NULL);
-  if (mu_app_init (&argp, capa, NULL, argc, argv, 0, &c, NULL))
-    exit (1);
+  mu_cli_capa_register (&mu_cli_capa_tls);
+  mu_cli (argc, argv, &cli, capa, NULL, &argc, &argv);
 
-  if (argc - c > 1)
+  if (argc > 1)
     {
       mu_error (_("too many arguments"));
       exit (1);
     }
-  else if (argc - c > 0)
+  else if (argc > 0)
     {
       if (mailbox_name)
        {
@@ -134,9 +105,9 @@ main (int argc, char **argv)
          exit (1);
        }
 
-      mailbox_name = mu_alloc (strlen (argv[c]) + 2);
+      mailbox_name = mu_alloc (strlen (argv[0]) + 2);
       mailbox_name[0] = '%';
-      strcpy (mailbox_name + 1, argv[c]);
+      strcpy (mailbox_name + 1, argv[0]);
     }
 
   init_output (0);
diff --git a/include/mailutils/Makefile.am b/include/mailutils/Makefile.am
index ba87486..9ae3929 100644
--- a/include/mailutils/Makefile.am
+++ b/include/mailutils/Makefile.am
@@ -36,6 +36,7 @@ pkginclude_HEADERS = \
  cctype.h\
  cfg.h\
  cidr.h\
+ cli.h\
  cstr.h\
  datetime.h\
  daemon.h\
diff --git a/include/mailutils/cfg.h b/include/mailutils/cfg.h
index 7ea8e08..e9f3587 100644
--- a/include/mailutils/cfg.h
+++ b/include/mailutils/cfg.h
@@ -79,6 +79,8 @@ struct mu_cfg_parse_hints
   char *site_rcfile;
   char *custom_rcfile;
   char *program;
+  struct mu_cfg_tree *append_tree;
+  void *data;
 };
 
 struct mu_cfg_tree
@@ -238,7 +240,8 @@ int mu_config_register_plain_section (const char 
*parent_path,
 #define MU_CFG_FMT_LOCUS           0x080
 #define MU_CFG_FMT_VALUE_ONLY      0x100
 #define MU_CFG_FMT_PARAM_PATH      0x200
-
+#define MU_PARSE_CONFIG_LINT       0x400
+  
 #ifdef MU_CFG_COMPATIBILITY
 # define MU_CFG_DEPRECATED
 #else
diff --git a/include/mailutils/cli.h b/include/mailutils/cli.h
new file mode 100644
index 0000000..2943bc4
--- /dev/null
+++ b/include/mailutils/cli.h
@@ -0,0 +1,55 @@
+/* opt.h -- general-purpose command line option parser 
+   Copyright (C) 2016 Free Software Foundation, Inc.
+
+   GNU Mailutils 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 3, or (at
+   your option) any later version.
+
+   GNU Mailutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _MAILUTILS_CLI_H
+#define _MAILUTILS_CLI_H
+#include <stdio.h>
+#include <mailutils/types.h>
+#include <mailutils/cfg.h>
+#include <mailutils/opt.h>
+
+typedef void (*mu_cli_capa_commit_fp) (void *);
+
+struct mu_cli_capa
+{
+  char *name;
+  struct mu_option *opt;
+  struct mu_cfg_param *cfg;
+  mu_cfg_section_fp parser;
+  mu_cli_capa_commit_fp commit;
+};
+
+void mu_cli_capa_init (void);
+void mu_cli_capa_register (struct mu_cli_capa *capa);
+void mu_cli_capa_apply (char const *name, mu_list_t opts, mu_list_t commits);
+
+struct mu_cli_setup
+{
+  struct mu_option **optv;
+  struct mu_cfg_param *cfg;
+  char *prog_doc;
+  char *prog_args;
+};
+
+void mu_version_func (struct mu_parseopt *po, FILE *stream);
+void mu_cli (int argc, char **argv, struct mu_cli_setup *setup,
+            char **capa, void *data,
+            int *ret_argc, char ***ret_argv);
+
+char *mu_site_config_file (void);
+
+#endif
diff --git a/include/mailutils/diag.h b/include/mailutils/diag.h
index 3e2bc51..0a5ebd2 100644
--- a/include/mailutils/diag.h
+++ b/include/mailutils/diag.h
@@ -29,8 +29,8 @@
 extern "C" {
 #endif
 
-extern const char *mu_program_name;
-extern const char *mu_full_program_name;
+extern char *mu_program_name;
+extern char *mu_full_program_name;
 
 #define MU_DIAG_EMERG    MU_LOG_EMERG
 #define MU_DIAG_ALERT    MU_LOG_ALERT
diff --git a/include/mailutils/locker.h b/include/mailutils/locker.h
index b8c4a93..718338f 100644
--- a/include/mailutils/locker.h
+++ b/include/mailutils/locker.h
@@ -103,7 +103,7 @@ extern int mu_locker_set_default_flags (int flags, enum 
mu_locker_set_mode mode)
 extern void mu_locker_set_default_retry_timeout (time_t to);
 extern void mu_locker_set_default_retry_count (size_t n);
 extern void mu_locker_set_default_expire_timeout (time_t t);
-extern int mu_locker_set_default_external_program (char *path);
+extern int mu_locker_set_default_external_program (char const *path);
 
 /* A flags of 0 means that the default will be used. */
 extern int mu_locker_create (mu_locker_t *, const char *filename, int flags);
diff --git a/include/mailutils/opt.h b/include/mailutils/opt.h
index 8e3b03b..cc56342 100644
--- a/include/mailutils/opt.h
+++ b/include/mailutils/opt.h
@@ -23,10 +23,10 @@
 #include <mailutils/util.h>
 #include <mailutils/cctype.h>
 
-extern char *mu_progname;
-extern char *mu_absprogname;
+extern char *mu_program_name;
+extern char *mu_full_program_name;
 
-void mu_set_progname (char const *arg);
+void mu_set_program_name (char const *arg);
 
 #define MU_OPTION_DEFAULT        0
 #define MU_OPTION_ARG_OPTIONAL   0x01
@@ -118,7 +118,7 @@ struct mu_parseopt
   struct mu_option **po_optv;      /* Array of ptrs to option structures */ 
   int po_flags;                        
 
-  char *po_data;                   /* Call-specific data */
+  void *po_data;                   /* Call-specific data */
 
   int po_exit_error;               /* Exit on error with this code */
   
@@ -130,9 +130,10 @@ struct mu_parseopt
   char const *po_package_name;
   char const *po_package_url;
   char const *po_extra_info;
-  
-  void (*po_help_hook) (FILE *stream); /* FIXME: should take mu_stream_t ?*/
-  void (*po_version_hook) (FILE *stream);
+
+  /* FIXME: should these take mu_stream_t ?*/
+  void (*po_help_hook) (struct mu_parseopt *po, FILE *stream); 
+  void (*po_version_hook) (struct mu_parseopt *po, FILE *stream);
   
   /* Output data */
   int po_ind;                      /* Index of the next option */
@@ -162,6 +163,7 @@ struct mu_parseopt
 int mu_parseopt (struct mu_parseopt *p,
                 int argc, char **argv, struct mu_option **optv,
                 int flags);
+void mu_parseopt_error (struct mu_parseopt *po, char const *fmt, ...);
 
 int mu_parseopt_apply (struct mu_parseopt *p);
 void mu_parseopt_free (struct mu_parseopt *p);
diff --git a/include/mailutils/sieve.h b/include/mailutils/sieve.h
index 7123095..1ba1a72 100644
--- a/include/mailutils/sieve.h
+++ b/include/mailutils/sieve.h
@@ -22,6 +22,7 @@
 #include <sys/types.h>
 #include <stdarg.h>
 #include <mailutils/mailutils.h>
+#include <mailutils/cli.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -282,6 +283,8 @@ struct mu_gocs_sieve
 
 int mu_sieve_module_init (enum mu_gocs_op, void *);
 
+extern struct mu_cli_capa mu_cli_capa_sieve;
+  
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/mailutils/stdstream.h b/include/mailutils/stdstream.h
index ac35ff7..9771881 100644
--- a/include/mailutils/stdstream.h
+++ b/include/mailutils/stdstream.h
@@ -28,7 +28,7 @@ extern mu_stream_t mu_strin;
 extern mu_stream_t mu_strout;
 extern mu_stream_t mu_strerr;
 
-extern const char *mu_program_name;
+extern char *mu_program_name;
   
 #define MU_STRERR_STDERR  0
 #define MU_STRERR_SYSLOG  1
diff --git a/include/mailutils/tls.h b/include/mailutils/tls.h
index 08e00e9..db6e420 100644
--- a/include/mailutils/tls.h
+++ b/include/mailutils/tls.h
@@ -20,6 +20,7 @@
 #define _MAILUTILS_TLS_H
 
 #include <mailutils/types.h>
+#include <mailutils/cli.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -55,6 +56,8 @@ extern int mu_init_tls_libs (int x509);
 extern void mu_deinit_tls_libs (void);
 
 extern int mu_tls_enable;
+
+extern struct mu_cli_capa mu_cli_capa_tls;
   
 #ifdef __cplusplus
 }
diff --git a/libmailutils/Makefile.am b/libmailutils/Makefile.am
index 7a5270c..82550c2 100644
--- a/libmailutils/Makefile.am
+++ b/libmailutils/Makefile.am
@@ -17,7 +17,7 @@
 # <http://www.gnu.org/licenses/>.
 
 SUBDIRS = \
- auth base address list sockaddr cidr cfg diag\
+ auth base address list sockaddr cidr cfg cli diag\
  filter mailbox mailer mime msgset opt server string stream stdstream\
  property url imapio datetime . tests 
 
@@ -33,6 +33,7 @@ libmailutils_la_LIBADD = \
  sockaddr/libsockaddr.la\
  cidr/libcidr.la\
  cfg/libcfg.la\
+ cli/libcli.la\
  datetime/libdatetime.la\
  diag/libdiag.la\
  filter/libfilter.la\
diff --git a/libmailutils/base/locker.c b/libmailutils/base/locker.c
index b4663b9..c4fe993 100644
--- a/libmailutils/base/locker.c
+++ b/libmailutils/base/locker.c
@@ -242,7 +242,7 @@ mu_locker_set_default_expire_timeout (time_t t)
 }
 
 int
-mu_locker_set_default_external_program (char *path)
+mu_locker_set_default_external_program (char const *path)
 {
   char *p = strdup (path);
   if (!p)
diff --git a/libmailutils/cfg/driver.c b/libmailutils/cfg/driver.c
index c0cd2d5..f2a43a3 100644
--- a/libmailutils/cfg/driver.c
+++ b/libmailutils/cfg/driver.c
@@ -463,7 +463,7 @@ mu_cfg_tree_reduce (mu_cfg_tree_t *parse_tree,
                    void *target_ptr)
 {
   int rc = 0;
-
+  struct mu_cfg_cont *cont;
   if (!parse_tree)
     return 0;
   if (hints && (hints->flags & MU_PARSE_CONFIG_DUMP))
@@ -477,13 +477,9 @@ mu_cfg_tree_reduce (mu_cfg_tree_t *parse_tree,
       mu_stream_destroy (&stream);
     }
 
-  if (root_container)
-    {
-      struct mu_cfg_cont *cont = mu_build_container (progparam);
-      rc = mu_cfg_scan_tree (parse_tree, &cont->v.section, target_ptr,
-                            NULL);
-      mu_config_destroy_container (&cont);
-    }
+  cont = mu_build_container (progparam);
+  rc = mu_cfg_scan_tree (parse_tree, &cont->v.section, target_ptr, NULL);
+  mu_config_destroy_container (&cont);
 
   return rc;
 }
diff --git a/libmailutils/cfg/lexer.l b/libmailutils/cfg/lexer.l
index 40598a1..b6c49ec 100644
--- a/libmailutils/cfg/lexer.l
+++ b/libmailutils/cfg/lexer.l
@@ -330,10 +330,16 @@ mu_cfg_parse_file (mu_cfg_tree_t **return_tree, const 
char *file, int flags)
   int rc;
   char *full_name = mu_tilde_expansion (file, MU_HIERARCHY_DELIMITER, NULL);
 
+  if (flags & MU_PARSE_CONFIG_VERBOSE)
+    mu_diag_output (MU_DIAG_INFO, _("opening configuration file %s"),
+                   full_name);
   if (stat (full_name, &st))
     {
       if (errno != ENOENT)
        mu_error (_("cannot stat `%s': %s"), full_name, mu_strerror (errno));
+      else if (flags & MU_PARSE_CONFIG_VERBOSE)
+       mu_diag_output (MU_DIAG_INFO, _("configuration file %s doesn't exist"),
+                       full_name);
       free (full_name);
       return ENOENT;
     }
diff --git a/libmailutils/cfg/parser.y b/libmailutils/cfg/parser.y
index e36b513..043f7e0 100644
--- a/libmailutils/cfg/parser.y
+++ b/libmailutils/cfg/parser.y
@@ -1589,7 +1589,10 @@ mu_cfg_parse_config (mu_cfg_tree_t **ptree, struct 
mu_cfg_parse_hints *hints)
          mu_cfg_tree_union (&tree, &tmp);
        }
     }
-  
+
+  if (hints->append_tree)
+    mu_cfg_tree_union (&tree, &hints->append_tree);
+
   *ptree = tree;
   return rc;
 }
diff --git a/libmailutils/opt/Makefile.am b/libmailutils/cli/Makefile.am
similarity index 91%
copy from libmailutils/opt/Makefile.am
copy to libmailutils/cli/Makefile.am
index d229c45..48770e8 100644
--- a/libmailutils/opt/Makefile.am
+++ b/libmailutils/cli/Makefile.am
@@ -15,12 +15,12 @@
 # Public License along with this library.  If not, see
 # <http://www.gnu.org/licenses/>.
 
-noinst_LTLIBRARIES = libopt.la
+noinst_LTLIBRARIES = libcli.la
 
-libopt_la_SOURCES = \
- opt.c\
- help.c\
- progname.c
+libcli_la_SOURCES = \
+ capa.c\
+ cli.c\
+ stdcapa.c
 
 AM_CPPFLAGS = \
   @MU_LIB_COMMON_INCLUDES@ -I/libmailutils
diff --git a/libmailutils/cli/capa.c b/libmailutils/cli/capa.c
new file mode 100644
index 0000000..bd5c557
--- /dev/null
+++ b/libmailutils/cli/capa.c
@@ -0,0 +1,96 @@
+/* capa.c -- CLI capabilities for GNU Mailutils
+   Copyright (C) 2016 Free Software Foundation, Inc.
+
+   GNU Mailutils 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 3, or (at
+   your option) any later version.
+
+   GNU Mailutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <mailutils/cli.h>
+#include <mailutils/list.h>
+#include <mailutils/alloc.h>
+#include <mailutils/nls.h>
+
+static mu_list_t capa_list;
+
+static void
+capa_free (void *ptr)
+{
+  struct mu_cli_capa *cp = ptr;
+  free (cp->name);
+  free (cp);
+}   
+
+void
+mu_cli_capa_register (struct mu_cli_capa *capa)
+{
+  struct mu_cli_capa *cp = mu_alloc (sizeof (*cp));
+  cp->name = mu_strdup (capa->name);
+  cp->opt = capa->opt;
+  cp->cfg = capa->cfg;
+  cp->parser = capa->parser;
+  cp->commit = capa->commit;
+  if (!capa_list)
+    {
+      mu_list_create (&capa_list);
+      mu_list_set_destroy_item (capa_list, capa_free);
+    }
+  mu_list_append (capa_list, cp);
+}
+
+struct capa_apply
+{
+  char const *name;
+  mu_list_t opts;
+  mu_list_t commits;
+  int found;
+};
+
+static int
+capa_apply (void *item, void *data)
+{
+  struct mu_cli_capa *cp = item;
+  struct capa_apply *ap = data;
+
+  if (strcmp (cp->name, ap->name) == 0)
+    {
+      ap->found = 1;
+      if (cp->opt)
+        mu_list_append (ap->opts, cp->opt);
+      if (cp->commit)
+        mu_list_append (ap->commits, cp->commit);
+      if (cp->parser || cp->cfg)
+        mu_config_root_register_section (NULL, cp->name, NULL,
+                                        cp->parser, cp->cfg);
+    }
+  return 0;
+}
+
+void
+mu_cli_capa_apply (char const *name, mu_list_t opts, mu_list_t commits)
+{
+  struct capa_apply app;
+  app.name = name;
+  app.opts = opts;
+  app.commits = commits;
+  app.found = 0;
+  mu_list_foreach (capa_list, capa_apply, &app);
+  if (!app.found)
+    mu_error (_("INTERNAL ERROR at %s:%d: unknown standard capability `%s'"),
+             __FILE__, __LINE__, name);
+}
+
+    
diff --git a/libmailutils/cli/cli.c b/libmailutils/cli/cli.c
new file mode 100644
index 0000000..597ac91
--- /dev/null
+++ b/libmailutils/cli/cli.c
@@ -0,0 +1,420 @@
+/* cli.c -- Command line interface for GNU Mailutils
+   Copyright (C) 2016 Free Software Foundation, Inc.
+
+   GNU Mailutils 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 3, or (at
+   your option) any later version.
+
+   GNU Mailutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <stdlib.h>
+#include <sysexits.h>
+#include <mailutils/cfg.h>
+#include <mailutils/opt.h>
+#include <mailutils/cli.h>
+#include <mailutils/list.h>
+#include <mailutils/alloc.h>
+#include <mailutils/nls.h>
+#include <mailutils/errno.h>
+#include <mailutils/version.h>
+#include <mailutils/stream.h>
+#include <mailutils/stdstream.h>
+#include <mailutils/io.h>
+#include <mailutils/syslog.h>
+
+#ifndef MU_SITE_CONFIG_FILE
+# define MU_SITE_CONFIG_FILE SYSCONFDIR "/mailutils.rc"
+#endif
+
+char *
+mu_site_config_file (void)
+{
+  char *p = getenv ("MU_SITE_CONFIG_FILE");
+  if (p)
+    return p;
+  return MU_SITE_CONFIG_FILE;
+}
+
+
+const char mu_version_copyright[] =
+  /* Do *not* mark this string for translation.  %s is a copyright
+     symbol suitable for this locale, and %d is the copyright
+     year.  */
+  "Copyright %s 2007-2016 Free Software Foundation, inc.";
+
+void
+mu_version_func (struct mu_parseopt *po, FILE *stream)
+{
+#ifdef GIT_DESCRIBE
+  fprintf (stream, "%s (%s) %s [%s]\n",
+          mu_program_name, PACKAGE_NAME, PACKAGE_VERSION, GIT_DESCRIBE);
+#else
+  fprintf (stream, "%s (%s) %s\n", mu_program_name,
+          PACKAGE_NAME, PACKAGE_VERSION);
+#endif
+  /* TRANSLATORS: Translate "(C)" to the copyright symbol
+     (C-in-a-circle), if this symbol is available in the user's
+     locale.  Otherwise, do not translate "(C)"; leave it as-is.  */
+  fprintf (stream, mu_version_copyright, _("(C)"));
+  fputs (_("\
+\n\
+License GPLv3+: GNU GPL version 3 or later 
<http://gnu.org/licenses/gpl.html>\nThis is free software: you are free to 
change and redistribute it.\n\
+There is NO WARRANTY, to the extent permitted by law.\n\
+\n\
+"),
+        stream);
+}
+
+static char gnu_general_help_url[] =
+  N_("General help using GNU software: <http://www.gnu.org/gethelp/>");
+
+
+static void
+change_progname (struct mu_parseopt *po, struct mu_option *opt,
+                char const *arg)
+{
+  po->po_prog_name = mu_strdup (arg);
+}
+
+static void
+no_user_config (struct mu_parseopt *po, struct mu_option *opt,
+               char const *arg)
+{
+  struct mu_cfg_parse_hints *hints = po->po_data;
+  hints->flags &= ~MU_CFG_PARSE_PROGRAM;
+}
+
+static void
+no_site_config (struct mu_parseopt *po, struct mu_option *opt,
+               char const *arg)
+{
+  struct mu_cfg_parse_hints *hints = po->po_data;
+  hints->flags &= ~MU_CFG_PARSE_SITE_RCFILE;
+}
+
+static void
+config_file (struct mu_parseopt *po, struct mu_option *opt,
+            char const *arg)
+{
+  struct mu_cfg_parse_hints *hints = po->po_data;
+  hints->flags |= MU_CFG_PARSE_CUSTOM_RCFILE;
+  hints->custom_rcfile = mu_strdup (arg);
+}
+
+static void
+config_verbose (struct mu_parseopt *po, struct mu_option *opt,
+               char const *arg)
+{
+  struct mu_cfg_parse_hints *hints = po->po_data;
+  if (hints->flags & MU_PARSE_CONFIG_VERBOSE)
+    hints->flags |= MU_PARSE_CONFIG_DUMP;
+  else
+    hints->flags |= MU_PARSE_CONFIG_VERBOSE;
+}
+
+static void
+config_lint (struct mu_parseopt *po, struct mu_option *opt,
+               char const *arg)
+{
+  struct mu_cfg_parse_hints *hints = po->po_data;
+  hints->flags |= MU_PARSE_CONFIG_VERBOSE|MU_PARSE_CONFIG_LINT;
+}
+
+static void
+param_set (struct mu_parseopt *po, struct mu_option *opt, char const *arg)
+{
+  struct mu_cfg_parse_hints *hints = po->po_data;
+  mu_cfg_node_t *node;
+  int rc = mu_cfg_create_subtree (arg, &node);
+  if (rc)
+    mu_parseopt_error (po, "%s: cannot create node: %s",
+                      arg, mu_strerror (rc));
+  if (!hints->append_tree)
+    mu_cfg_tree_create (&hints->append_tree);
+  mu_cfg_tree_add_node (hints->append_tree, node);
+}
+
+struct mu_option mu_common_options[] = {
+  MU_OPTION_GROUP(N_("Common options")),
+  { "program-name",   0,  N_("NAME"),  MU_OPTION_IMMEDIATE|MU_OPTION_HIDDEN,
+    N_("set program name"),
+    mu_c_string, NULL, change_progname },
+
+  { "no-user-config", 0,  NULL,        MU_OPTION_IMMEDIATE,
+    N_("do not load user configuration file"),
+    mu_c_string, NULL, no_user_config },
+  { "no-user-rcfile", 0,  NULL,        MU_OPTION_ALIAS },
+  
+  { "no-site-config", 0,  NULL,        MU_OPTION_IMMEDIATE,
+    N_("do not load user configuration file"),
+    mu_c_string, NULL, no_site_config },
+  { "no-site-rcfile", 0,  NULL,        MU_OPTION_ALIAS },
+  
+  { "config-file",    0,  N_("FILE"),  MU_OPTION_IMMEDIATE,
+    N_("load this configuration file"),
+    mu_c_string, NULL, config_file },
+  { "rcfile",         0,  NULL,        MU_OPTION_ALIAS },
+  
+  { "config-verbose", 0,  NULL,        MU_OPTION_IMMEDIATE,
+    N_("verbosely log parsing of the configuration files"),
+    mu_c_string, NULL, config_verbose },
+  { "rcfile-verbose", 0,  NULL,        MU_OPTION_ALIAS },
+  
+  { "config-lint",    0,  NULL,        MU_OPTION_IMMEDIATE,
+    N_("check configuration file syntax and exit"),
+    mu_c_string, NULL, config_lint },
+  { "rcfile-lint",    0,  NULL,        MU_OPTION_ALIAS },
+
+  { "set",            0,  N_("PARAM=VALUE"), MU_OPTION_IMMEDIATE,
+    N_("set configuration parameter"),
+    mu_c_string, NULL, param_set },
+  
+  MU_OPTION_END
+};
+
+static void
+show_comp_defaults (struct mu_parseopt *po, struct mu_option *opt,
+                   char const *unused)
+{
+  mu_print_options ();
+  exit (0);
+}
+
+static void
+show_config_help (struct mu_parseopt *po, struct mu_option *opt,
+                 char const *unused)
+{
+  struct mu_cfg_parse_hints *hints = po->po_data;
+
+  char *comment;
+  mu_stream_t stream;
+  struct mu_cfg_cont *cont;
+  static struct mu_cfg_param dummy_include_param[] = {
+    { "include", mu_c_string, NULL, 0, NULL,
+      N_("Include contents of the given file.  If a directory is given, "
+        "include contents of the file <file>/<program>, where "
+        "<program> is the name of the program.  This latter form is "
+        "allowed only in the site-wide configuration file."),
+      N_("file-or-directory") },
+    { NULL }
+  };
+
+  mu_stdio_stream_create (&stream, MU_STDOUT_FD, 0);
+
+  mu_asprintf (&comment,
+              "Configuration file structure for %s utility.",
+              po->po_prog_name);
+  mu_cfg_format_docstring (stream, comment, 0);
+  free (comment);
+  
+  mu_asprintf (&comment,
+              "For use in global configuration file (%s), enclose it "
+              "in `program %s { ... };",
+              mu_site_config_file (),
+              po->po_prog_name);                  
+  mu_cfg_format_docstring (stream, comment, 0);
+  free (comment);
+
+  /* FIXME: %s should be replaced by the canonical utility name */
+  mu_asprintf (&comment, "For more information, use `info %s'.",
+              po->po_prog_name);
+  mu_cfg_format_docstring (stream, comment, 0);
+  free (comment);
+
+  cont = mu_config_clone_root_container ();
+  mu_config_container_register_section (&cont, NULL, NULL, NULL, NULL,
+                                       dummy_include_param, NULL);
+  if (hints->data)
+    mu_config_container_register_section (&cont, NULL, NULL, NULL, NULL,
+                                         hints->data, NULL);
+  mu_cfg_format_container (stream, cont);
+  mu_config_destroy_container (&cont);
+      
+  mu_stream_destroy (&stream);
+  exit (0);
+}  
+
+struct mu_option mu_extra_help_options[] = {
+  MU_OPTION_GROUP (N_("Informational options")),
+  { "show-config-options",   0,  NULL,  MU_OPTION_IMMEDIATE,
+    N_("show compilation options"),
+    mu_c_string, NULL, show_comp_defaults },
+  { "config-help",           0,  NULL,  MU_OPTION_IMMEDIATE,
+    N_("show configuration file summary"),
+    mu_c_string, NULL, show_config_help },
+  MU_OPTION_END
+};
+
+
+static int
+add_opt_group (void *item, void *data)
+{
+  struct mu_parseopt *po = data;
+  struct mu_option *opt = item;
+  po->po_optv[po->po_optc++] = opt;
+  return 0;
+}
+
+/* Build the list of option groups and configuration sections */
+static struct mu_option **
+init_options (char **capa, struct mu_cli_setup *setup,
+             mu_list_t *ret_comlist)
+{
+  size_t i, s;
+  mu_list_t oplist;
+  struct mu_parseopt po;
+  
+  mu_list_create (&oplist);
+  if (setup->optv)
+    {
+      for (i = 0; setup->optv[i]; i++)
+       mu_list_append (oplist, setup->optv[i]);
+    }
+  if (capa)
+    {
+      mu_list_t comlist;
+      mu_list_create (&comlist);
+      for (i = 0; capa[i]; i++)
+       mu_cli_capa_apply (capa[i], oplist, comlist);
+      *ret_comlist = comlist;
+    }
+  else
+    *ret_comlist = NULL;
+  
+  mu_list_append (oplist, mu_common_options);
+  mu_list_append (oplist, mu_extra_help_options);
+  
+  mu_list_count (oplist, &s);
+
+  po.po_optv = mu_calloc (s + 1, sizeof (po.po_optv[0]));
+  po.po_optc = 0;
+  mu_list_foreach (oplist, add_opt_group, &po);
+  if (po.po_optc != s)
+    abort ();
+  po.po_optv[po.po_optc] = NULL;
+  mu_list_destroy (&oplist);
+  return po.po_optv;
+}
+
+static int
+run_commit (void *item, void *data)
+{
+  mu_cli_capa_commit_fp commit = item;
+  commit (data);
+  return 0;
+}
+  
+void
+mu_cli (int argc, char **argv, struct mu_cli_setup *setup, char **capa,
+       void *data,
+       int *ret_argc, char ***ret_argv)
+{
+  struct mu_parseopt po;
+  int flags = 0;
+  struct mu_cfg_tree *parse_tree = NULL;
+  struct mu_cfg_parse_hints hints;
+  struct mu_option **optv;
+  mu_list_t com_list;
+  
+  /* Set program name */
+  mu_set_program_name (argv[0]);
+
+  if (!mu_log_tag)
+    mu_log_tag = (char*)mu_program_name;
+
+  /* Initialize standard streams */
+  mu_stdstream_setup (MU_STDSTREAM_RESET_NONE);
+
+  /* Initialize standard capabilities */
+  mu_cli_capa_init ();
+  
+  /* Initialize hints */
+  memset (&hints, 0, sizeof (hints));
+  hints.flags |= MU_CFG_PARSE_SITE_RCFILE;
+  hints.site_rcfile = mu_site_config_file ();
+
+  hints.flags |= MU_CFG_PARSE_PROGRAM;
+  hints.program = (char*) mu_program_name;
+
+  hints.data = setup->cfg;
+  
+  /* Initialize po */
+  if (setup->prog_doc)
+    {
+      po.po_prog_doc = setup->prog_doc;
+      flags |= MU_PARSEOPT_PROG_DOC;
+    }
+
+  if (setup->prog_args)
+    {
+      po.po_prog_args = setup->prog_args;
+      flags |= MU_PARSEOPT_PROG_ARGS;
+    }
+  
+  po.po_package_name = PACKAGE_NAME;
+  flags |= MU_PARSEOPT_PACKAGE_NAME;
+
+  po.po_package_url = PACKAGE_URL;
+  flags |= MU_PARSEOPT_PACKAGE_URL;
+
+  po.po_bug_address = PACKAGE_BUGREPORT;
+  flags |= MU_PARSEOPT_BUG_ADDRESS;
+
+  po.po_extra_info = gnu_general_help_url;
+  flags |= MU_PARSEOPT_EXTRA_INFO;
+
+  po.po_version_hook = mu_version_func;
+  flags |= MU_PARSEOPT_VERSION_HOOK;
+
+  po.po_data = &hints;
+  flags |= MU_PARSEOPT_DATA;
+
+  po.po_exit_error = EX_USAGE;
+
+  optv = init_options (capa, setup, &com_list);
+
+  if (mu_parseopt (&po, argc, argv, optv, flags))
+    exit (po.po_exit_error);
+
+  argc -= po.po_arg_start;
+  argv += po.po_arg_start;
+  
+  if (ret_argc)
+    {
+      *ret_argc = argc;
+      *ret_argv = argv;
+    }
+  else if (argc)
+    mu_parseopt_error (&po, "%s", _("unexpected arguments"));
+
+  if (mu_cfg_parse_config (&parse_tree, &hints))
+    exit (EX_CONFIG);
+
+  if (mu_cfg_tree_reduce (parse_tree, &hints, setup->cfg, data))
+    exit (EX_CONFIG);
+
+  if (mu_cfg_error_count) //FIXME
+    exit (EX_CONFIG);
+  
+  mu_parseopt_apply (&po);
+
+  mu_list_foreach (com_list, run_commit, NULL);
+  mu_list_destroy (&com_list);
+  
+  if (hints.flags & MU_PARSE_CONFIG_LINT)
+    exit (0);
+
+  mu_cfg_destroy_tree (&parse_tree);
+  free (optv);
+  mu_parseopt_free (&po);  
+}
diff --git a/libmailutils/cli/stdcapa.c b/libmailutils/cli/stdcapa.c
new file mode 100644
index 0000000..05a761f
--- /dev/null
+++ b/libmailutils/cli/stdcapa.c
@@ -0,0 +1,568 @@
+/* stdcapa.c -- Standard CLI capabilities for GNU Mailutils
+   Copyright (C) 2016 Free Software Foundation, Inc.
+
+   GNU Mailutils 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 3, or (at
+   your option) any later version.
+
+   GNU Mailutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <stdlib.h>
+#include <mailutils/cli.h>
+#include <mailutils/cfg.h>
+#include <mailutils/nls.h>
+#include <mailutils/syslog.h>
+#include <mailutils/stdstream.h>
+#include <mailutils/mailer.h>
+#include <mailutils/errno.h>
+#include <mailutils/mailbox.h>
+#include <mailutils/registrar.h>
+#include <mailutils/locker.h>
+#include <mailutils/mu_auth.h>
+
+/* ************************************************************************* 
+ * Logging section
+ * ************************************************************************* */
+static void
+cli_log_facility (struct mu_parseopt *po, struct mu_option *opt,
+                 char const *arg)
+{
+  if (mu_string_to_syslog_facility (arg, &mu_log_facility))
+    mu_parseopt_error (po, _("unknown syslog facility `%s'"), arg);
+}
+  
+static int
+cb_facility (void *data, mu_config_value_t *val)
+{
+  if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
+    return 1;
+  
+  if (mu_string_to_syslog_facility (val->v.string, &mu_log_facility))
+    {
+      mu_error (_("unknown syslog facility `%s'"), val->v.string);
+      return 1;
+    }
+   return 0;
+}
+
+static int
+cb_severity (void *data, mu_config_value_t *val)
+{
+  unsigned n;
+  
+  if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
+    return 1;
+  if (mu_severity_from_string (val->v.string, &n))
+    {
+      mu_error (_("unknown severity `%s'"), val->v.string);
+      return 1;
+    }
+  mu_log_severity_threshold = n;
+  return 0;
+}      
+
+static struct mu_cfg_param logging_cfg[] = {
+  { "syslog", mu_c_bool, &mu_log_syslog, 0, NULL,
+    N_("Send diagnostics to syslog.") },
+  { "print-severity", mu_c_bool, &mu_log_print_severity, 0, NULL,
+    N_("Print message severity levels.") },
+  { "severity", mu_cfg_callback, NULL, 0, cb_severity,
+    N_("Output only messages with a severity equal to or greater than "
+       "this one."),
+    N_("arg: string")},
+  { "facility", mu_cfg_callback, NULL, 0, cb_facility,
+    N_("Set syslog facility. Arg is one of the following: user, daemon, "
+       "auth, authpriv, mail, cron, local0 through local7 (case-insensitive), "
+       "or a facility number."), 
+    N_("arg: string") },
+  { "session-id", mu_c_bool, &mu_log_session_id, 0, NULL,
+    N_("Log session ID") },
+  { "tag", mu_c_string, &mu_log_tag, 0, NULL,
+    N_("Tag syslog messages with this string.") },
+  { NULL }
+};
+
+static struct mu_option logging_option[] = {
+  { "log-facility", 0, N_("FACILITY"), MU_OPTION_DEFAULT,
+    N_("output logs to syslog FACILITY"),
+    mu_c_int, &mu_log_facility, cli_log_facility },
+  MU_OPTION_END
+};
+
+static void
+logging_commit (void *unused)
+{
+  if (mu_log_syslog >= 0)
+    mu_stdstream_strerr_setup (mu_log_syslog ?
+                              MU_STRERR_SYSLOG : MU_STRERR_STDERR);
+}
+
+/* ************************************************************************* 
+ * Mailer                                                                    
+ * ************************************************************************* */
+static void
+cli_mailer (struct mu_parseopt *po, struct mu_option *opt, char const *arg)
+{
+  int rc = mu_mailer_set_url_default (arg);
+  if (rc != 0)
+    mu_parseopt_error (po, _("invalid mailer URL `%s': %s"),
+                      arg, mu_strerror (rc));
+}
+
+static struct mu_option mailer_option[] = {
+  { "mailer", 'M', N_("MAILER"), MU_OPTION_DEFAULT,
+    N_("use specified URL as the default mailer"),
+    mu_c_string, NULL, cli_mailer },
+  MU_OPTION_END
+};
+
+static int
+cb_mailer (void *data, mu_config_value_t *val)
+{
+  int rc;
+  
+  if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
+    return 1;
+  rc = mu_mailer_set_url_default (val->v.string);
+  if (rc != 0)
+    mu_error (_("%s: invalid mailer URL: %s"),
+               val->v.string, mu_strerror (rc));
+  return rc;
+}
+
+static struct mu_cfg_param mailer_cfg[] = {
+  { "url", mu_cfg_callback, NULL, 0, cb_mailer,
+    N_("Use this URL as the default mailer"),
+    N_("url: string") },
+  { NULL }
+};
+
+/* ************************************************************************* 
+ * Debugging
+ * ************************************************************************* */
+static void
+cli_debug_level (struct mu_parseopt *po, struct mu_option *opt,
+                char const *arg)
+{
+  mu_debug_clear_all ();
+  mu_debug_parse_spec (arg);
+  /* FIXME: Error handling */
+}
+
+static struct mu_option debug_option[] = {
+  MU_OPTION_GROUP (N_("Global debugging settings")),
+  { "debug-level", 0, N_("LEVEL"), MU_OPTION_DEFAULT,
+    N_("set Mailutils debugging level"),
+    mu_c_string, NULL, cli_debug_level },
+  { "debug-line-info", 0, NULL,    MU_OPTION_DEFAULT,
+    N_("show source info with debugging messages"),
+    mu_c_bool, &mu_debug_line_info },
+  MU_OPTION_END
+};
+
+static int
+cb_debug_level (void *data, mu_config_value_t *val)
+{
+  if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
+    return 1;
+  mu_debug_parse_spec (val->v.string);
+  return 0;
+}
+
+static struct mu_cfg_param debug_cfg[] = {
+  { "level", mu_cfg_callback, NULL, 0, &cb_debug_level,
+    N_("Set Mailutils debugging level.  Argument is a colon-separated list "
+       "of debugging specifications in the form:\n"
+       "   <object: string>[[:]=<level: number>]."),
+    N_("arg: string") },
+  { "line-info", mu_c_bool, &mu_debug_line_info, 0, NULL,
+    N_("Prefix debug messages with Mailutils source locations.") },
+  { NULL }
+};
+
+/* ************************************************************************* *
+ * Mailbox                                                                   *
+ * ************************************************************************* */
+
+static int
+cb_mail_spool (void *data, mu_config_value_t *val)
+{
+  int rc;
+  if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
+    return 1;
+  rc = mu_set_mail_directory (val->v.string);
+  if (rc)
+    mu_error (_("cannot set mail directory name to `%s': %s"),
+             val->v.string, mu_strerror (rc));
+  return rc;
+}
+
+static int
+cb_mailbox_pattern (void *data, mu_config_value_t *val)
+{
+  int rc;
+  if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
+    return 1;
+
+  rc = mu_set_mailbox_pattern (val->v.string);
+  if (rc)
+    mu_error (_("cannot set mailbox pattern to `%s': %s"),
+             val->v.string, mu_strerror (rc));
+  return rc;
+}
+
+static int
+cb_mailbox_type (void *data, mu_config_value_t *val)
+{
+  if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
+    return 1;
+  if (mu_registrar_set_default_scheme (val->v.string))
+    mu_error (_("invalid mailbox type: %s"), val->v.string);
+  return 0;
+}
+  
+static int
+cb_folder (void *data, mu_config_value_t *val)
+{
+  if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
+    return 1;
+  mu_set_folder_directory (val->v.string);
+  return 0;
+}
+
+static struct mu_cfg_param mailbox_cfg[] = {
+  { "mail-spool", mu_cfg_callback, NULL, 0, cb_mail_spool,
+    N_("Use specified URL as a mailspool directory."),
+    N_("url: string") },
+  { "mailbox-pattern", mu_cfg_callback, NULL, 0, cb_mailbox_pattern,
+    N_("Create mailbox URL using <pattern>."),
+    N_("pattern: string") },
+  { "mailbox-type", mu_cfg_callback, NULL, 0, cb_mailbox_type,
+    N_("Default mailbox type."),
+    N_("protocol: string") },
+  { "folder", mu_cfg_callback, NULL, 0, cb_folder,
+    N_("Default user mail folder"),
+    N_("dir: string") },
+  { NULL }
+};
+
+/* ************************************************************************* *
+ * Locking                                                                   *
+ * ************************************************************************* */
+static int
+cb_locker_flags (void *data, mu_config_value_t *val)
+{
+  int flags = 0;
+  char const *s;
+  
+  if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
+    return 1;
+
+  for (s = val->v.string; *s; s++)
+    {
+      switch (*s)
+       {
+       case 'E':
+         flags |= MU_LOCKER_EXTERNAL;
+         break;
+             
+       case 'R':
+         flags |= MU_LOCKER_RETRY;
+         break;
+             
+       case 'T':
+         flags |= MU_LOCKER_TIME;
+         break;
+             
+       case 'P':
+         flags |= MU_LOCKER_PID;
+         break;
+             
+       default:
+         mu_error (_("invalid lock flag `%c'"), *s);
+       }
+    }
+  mu_locker_set_default_flags (flags, mu_locker_assign);
+  return 0;
+}
+
+static int
+cb_locker_retry_timeout (void *data, mu_config_value_t *val)
+{
+  int rc;
+  time_t t;
+  char *errmsg;
+  
+  if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
+    return 1;
+  rc = mu_str_to_c (val->v.string, mu_c_time, &t, &errmsg);
+  if (rc)
+    {
+      mu_error (_("conversion failed: %s"), errmsg ? errmsg :
+               mu_strerror (rc));
+      free (errmsg);
+    }
+  else
+    {
+      mu_locker_set_default_retry_timeout (t);
+      mu_locker_set_default_flags (MU_LOCKER_RETRY, mu_locker_set_bit);
+    }
+  return 0;
+}
+
+static int
+cb_locker_retry_count (void *data, mu_config_value_t *val)
+{
+  int rc;
+  size_t n;
+  char *errmsg;
+  
+  if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
+    return 1;
+  rc = mu_str_to_c (val->v.string, mu_c_size, &n, &errmsg);
+  if (rc)
+    {
+      mu_error (_("conversion failed: %s"), errmsg ? errmsg :
+               mu_strerror (rc));
+      free (errmsg);
+    }
+  else
+    {
+      mu_locker_set_default_retry_count (n);
+      mu_locker_set_default_flags (MU_LOCKER_RETRY, mu_locker_set_bit);
+    }
+  return 0;
+}
+
+static int
+cb_locker_expire_timeout (void *data, mu_config_value_t *val)
+{
+  int rc;
+  time_t t;
+  char *errmsg;
+  
+  if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
+    return 1;
+  rc = mu_str_to_c (val->v.string, mu_c_time, &t, &errmsg);
+  if (rc)
+    {
+      mu_error (_("conversion failed: %s"), errmsg ? errmsg :
+               mu_strerror (rc));
+      free (errmsg);
+    }
+  else
+    {
+      mu_locker_set_default_expire_timeout (t);
+      mu_locker_set_default_flags (MU_LOCKER_EXTERNAL, mu_locker_set_bit);
+    }
+  return 0;
+}
+
+static int
+cb_locker_external (void *data, mu_config_value_t *val)
+{
+  if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
+    return 1;
+  mu_locker_set_default_external_program (val->v.string);
+  mu_locker_set_default_flags (MU_LOCKER_TIME, mu_locker_set_bit);
+  return 0;
+}
+  
+static struct mu_cfg_param locking_cfg[] = {
+  /* FIXME: Flags are superfluous. */
+  { "flags", mu_cfg_callback, NULL, 0, cb_locker_flags,
+    N_("Default locker flags (E=external, R=retry, T=time, P=pid)."),
+    N_("arg: string") },
+  { "retry-timeout", mu_cfg_callback, NULL, 0, cb_locker_retry_timeout,
+    N_("Set timeout for acquiring the lock."),
+    N_("arg: interval")},
+  { "retry-count", mu_cfg_callback, NULL, 0, cb_locker_retry_count,
+    N_("Set the maximum number of times to retry acquiring the lock."),
+    N_("arg: integer") },
+  { "expire-timeout", mu_cfg_callback, NULL, 0, cb_locker_expire_timeout,
+    N_("Expire locks older than this amount of time."),
+    N_("arg: interval")},
+  { "external-locker", mu_cfg_callback, NULL, 0, cb_locker_external,
+    N_("Use external locker program."),
+    N_("prog: string") },
+  { NULL, }
+};
+
+/* ************************************************************************* *
+ * Address                                                                   *
+ * ************************************************************************* */
+static int
+cb_email_addr (void *data, mu_config_value_t *val)
+{
+  int rc;
+  
+  if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
+    return 1;
+
+  rc = mu_set_user_email (val->v.string);
+  if (rc)
+    mu_error (_("invalid email address `%s': %s"),
+             val->v.string, mu_strerror (rc));
+  return 0;
+}
+
+static int
+cb_email_domain (void *data, mu_config_value_t *val)
+{
+  int rc;
+  
+  if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
+    return 1;
+
+  rc = mu_set_user_email_domain (val->v.string);
+  if (rc)
+    mu_error (_("invalid email domain `%s': %s"),
+             val->v.string, mu_strerror (rc));
+  return 0;
+}
+
+static struct mu_cfg_param address_cfg[] = {
+  { "email-addr", mu_cfg_callback, NULL, 0, cb_email_addr,
+    N_("Set the current user email address (default is "
+       "address@hidden)."),
+    N_("email: address") },
+  { "email-domain", mu_cfg_callback, NULL, 0, cb_email_domain,
+    N_("Set e-mail domain for unqualified user names (default is this host)"),
+    N_("domain: string") },
+  { NULL }
+};
+
+/* ************************************************************************* *
+ * Authentication & Authorization                                            *
+ * ************************************************************************* */
+static int
+cb_authentication (void *data, mu_config_value_t *val)
+{
+  if (val->type == MU_CFG_STRING)
+    {
+      if (strcmp (val->v.string, "clear") == 0)
+       mu_authentication_clear_list ();
+      else
+       /*FIXME: use err for error reporting*/
+       mu_authentication_add_module_list (val->v.string);
+    }
+  else if (val->type == MU_CFG_LIST)
+    {
+      int i;
+      for (i = 0; i < val->v.arg.c; i++)
+       {
+         if (mu_cfg_assert_value_type (&val->v.arg.v[i], MU_CFG_STRING))
+           return 1;
+         if (strcmp (val->v.arg.v[i].v.string, "clear") == 0)
+           mu_authentication_clear_list ();
+         else
+           mu_authentication_add_module (val->v.arg.v[i].v.string);
+       }
+    }
+  else
+    {
+      mu_error (_("expected string value"));
+      return 1;
+    }
+  return 0;
+}
+
+static int
+cb_authorization (void *data, mu_config_value_t *val)
+{
+  if (val->type == MU_CFG_STRING)
+    {
+      if (strcmp (val->v.string, "clear") == 0)
+       mu_authorization_clear_list ();
+      else
+       /*FIXME: use err for error reporting*/
+       mu_authorization_add_module_list (val->v.string);
+    }
+  else if (val->type == MU_CFG_LIST)
+    {
+      int i;
+      for (i = 0; i < val->v.arg.c; i++)
+       {
+         if (mu_cfg_assert_value_type (&val->v.arg.v[i], MU_CFG_STRING))
+           return 1;
+         if (strcmp (val->v.arg.v[i].v.string, "clear") == 0)
+           mu_authorization_clear_list ();
+         else
+           mu_authorization_add_module (val->v.arg.v[i].v.string);
+       }
+    }
+  else
+    {
+      mu_error (_("expected string value"));
+      return 1;
+    }
+  return 0;
+}
+
+static struct mu_cfg_param mu_auth_param[] = {
+  { "authentication", mu_cfg_callback, NULL, 0, cb_authentication,
+    /* FIXME: The description is incomplete. MU-list is also allowed as
+       argument */
+    N_("Set a list of modules for authentication. Modlist is a "
+       "colon-separated list of module names or a word `clear' to "
+       "clear the previously set up values."),
+    N_("modlist") },
+  { "authorization", mu_cfg_callback, NULL, 0, cb_authorization,
+    N_("Set a list of modules for authorization. Modlist is a "
+       "colon-separated list of module names or a word `clear' to "
+       "clear the previously set up values."),
+    N_("modlist") },
+  { NULL }
+};
+
+int
+mu_auth_section_parser
+   (enum mu_cfg_section_stage stage, const mu_cfg_node_t *node,
+    const char *section_label, void **section_data, void *call_data,
+    mu_cfg_tree_t *tree)
+{
+  switch (stage)
+    {
+    case mu_cfg_section_start:
+      break;
+
+    case mu_cfg_section_end:
+      mu_auth_finish_setup ();
+    }
+  return 0;
+}
+
+/* ************************************************************************* *
+ * Registry of standard mailutils' capabilities                              *
+ * ************************************************************************* */
+struct mu_cli_capa mu_cli_std_capa[] = {
+  { "mailutils" }, /* Dummy */
+  { "logging", logging_option, logging_cfg, NULL, logging_commit },
+  { "mailer",  mailer_option, mailer_cfg, NULL, NULL },
+  { "debug", debug_option, debug_cfg, NULL, NULL },
+  { "mailbox", NULL, mailbox_cfg, NULL, NULL },
+  { "locking", NULL, locking_cfg, NULL, NULL },
+  { "address", NULL, address_cfg, NULL, NULL },
+  { "auth",    NULL, mu_auth_param, mu_auth_section_parser },
+
+  { NULL }
+};
+
+void
+mu_cli_capa_init (void)
+{
+  size_t i;
+
+  for (i = 0; mu_cli_std_capa[i].name; i++)
+    mu_cli_capa_register (&mu_cli_std_capa[i]);
+}
diff --git a/libmailutils/diag/diag.c b/libmailutils/diag/diag.c
index ba055b2..3f10356 100644
--- a/libmailutils/diag/diag.c
+++ b/libmailutils/diag/diag.c
@@ -30,32 +30,6 @@
 #include <mailutils/stdstream.h>
 #include <mailutils/stream.h>
 
-const char *mu_program_name;
-const char *mu_full_program_name;
-
-void
-mu_set_program_name (const char *name)
-{
-  const char *progname;
-
-  mu_full_program_name = name;
-  if (!name)
-    progname = name;
-  else
-    {
-      progname = strrchr (name, '/');
-      if (progname)
-       progname++;
-      else
-       progname = name;
-      
-      if (strlen (progname) > 3 && memcmp (progname, "lt-", 3) == 0)
-       progname += 3;
-    }
-  
-  mu_program_name = progname;
-}
-
 void
 mu_diag_init ()
 {
diff --git a/libmailutils/opt/help.c b/libmailutils/opt/help.c
index b106d9a..f91c126 100644
--- a/libmailutils/opt/help.c
+++ b/libmailutils/opt/help.c
@@ -155,7 +155,7 @@ init_usage_vars (struct mu_parseopt *po)
   fmt = getenv ("ARGP_HELP_FMT");
   if (!fmt)
     return;
-  ws.ws_delim=",";
+  ws.ws_delim = ",";
   if (mu_wordsplit (fmt, &ws, 
                    MU_WRDSF_DELIM | MU_WRDSF_NOVAR | MU_WRDSF_NOCMD
                    | MU_WRDSF_WS | MU_WRDSF_SHOWERR))
@@ -346,20 +346,20 @@ mu_program_help (struct mu_parseopt *po)
   mu_option_describe_options (po->po_optv, po->po_optc);
 
   if (po->po_help_hook)
-    po->po_help_hook (stdout);
+    po->po_help_hook (po, stdout);
 
   if (po->po_bug_address)
     /* TRANSLATORS: The placeholder indicates the bug-reporting address
        for this package.  Please add _another line_ saying
        "Report translation bugs to <...>\n" with the address for translation
        bugs (typically your translation team's web or email address).  */
-    printf (_("Report bugs to %s.\n"), po->po_bug_address);
+    printf (_("Report bugs to <%s>.\n"), po->po_bug_address);
 
   if (po->po_package_name && po->po_package_url)
     printf (_("%s home page: <%s>\n"),
            po->po_package_name, po->po_package_url);
   if (po->po_flags & MU_PARSEOPT_EXTRA_INFO)
-    print_option_descr (po->po_extra_info, 0, rmargin);
+    print_option_descr (_(po->po_extra_info), 0, rmargin);
 }
 
 static struct mu_option **option_tab;
diff --git a/libmailutils/opt/opt.c b/libmailutils/opt/opt.c
index 61bd00f..37c22ab 100644
--- a/libmailutils/opt/opt.c
+++ b/libmailutils/opt/opt.c
@@ -85,7 +85,7 @@ fn_usage (struct mu_parseopt *po, struct mu_option *opt, char 
const *unused)
 static void
 fn_version (struct mu_parseopt *po, struct mu_option *opt, char const *unused)
 {
-  po->po_version_hook (stdout);
+  po->po_version_hook (po, stdout);
   exit (EXIT_SUCCESS);
 }
 
@@ -107,8 +107,8 @@ struct mu_option mu_version_options[] = {
 };
 
 /* Output error message */
-static void
-parse_error (struct mu_parseopt *po, char const *fmt, ...)
+void
+mu_parseopt_error (struct mu_parseopt *po, char const *fmt, ...)
 {
   va_list ap;
 
@@ -176,7 +176,7 @@ find_short_option (struct mu_parseopt *po, int chr)
          && po->po_optv[i]->opt_short == chr)
        return option_unalias (po, i);
     }
-  parse_error (po, _("unrecognized option '-%c'"), chr);
+  mu_parseopt_error (po, _("unrecognized option '-%c'"), chr);
   return NULL;
 }
 
@@ -207,9 +207,11 @@ find_long_option (struct mu_parseopt *po, char const 
*optstr,
              break;
 
            case 1:
+             if (option_unalias (po, i) == option_unalias (po, ind))
+               continue;
              if (po->po_flags & MU_PARSEOPT_IGNORE_ERRORS)
                return NULL;
-             parse_error (po,
+             mu_parseopt_error (po,
                           _("option '--%*.*s' is ambiguous; possibilities:"),
                           optlen, optlen, optstr);
              fprintf (stderr, "--%s\n", po->po_optv[ind]->opt_long);
@@ -224,7 +226,7 @@ find_long_option (struct mu_parseopt *po, char const 
*optstr,
   switch (found)
     {
     case 0:
-      parse_error (po, _("unrecognized option '--%s'"), optstr);
+      mu_parseopt_error (po, _("unrecognized option '--%s'"), optstr);
       break;
       
     case 1:
@@ -303,7 +305,7 @@ next_opt (struct mu_parseopt *po)
            break;
          if (!(po->po_flags & MU_PARSEOPT_IN_ORDER))
            {
-             if (!po->po_permuted)
+             if (!po->po_permuted && po->po_arg_count == 0)
                po->po_arg_start = po->po_ind - 1;
              po->po_arg_count++;
              continue;
@@ -405,11 +407,11 @@ parse (struct mu_parseopt *po)
              else
                {
                  if (long_opt)
-                   parse_error (po,
+                   mu_parseopt_error (po,
                                 _("option '--%s' requires an argument"),
                                 long_opt);
                  else
-                   parse_error (po,
+                   mu_parseopt_error (po,
                                 _("option '-%c' requires an argument"),
                                 po->po_chr);
                  po->po_opterr = po->po_ind;
@@ -428,7 +430,7 @@ parse (struct mu_parseopt *po)
                  && po->po_cur[0]
                  && !(po->po_flags & MU_OPTION_ARG_OPTIONAL))
                {
-                 parse_error (po,
+                 mu_parseopt_error (po,
                               _("option '--%s' doesn't allow an argument"),
                               long_opt);
                  po->po_opterr = po->po_ind;
@@ -661,9 +663,9 @@ mu_option_set_value (struct mu_parseopt *po, struct 
mu_option *opt,
            errtext = mu_strerror (rc);
 
          if (opt->opt_long)
-           parse_error (po, "--%s: %s", opt->opt_long, errtext);
+           mu_parseopt_error (po, "--%s: %s", opt->opt_long, errtext);
          else
-           parse_error (po, "-%c: %s", opt->opt_short, errtext);
+           mu_parseopt_error (po, "-%c: %s", opt->opt_short, errtext);
          free (errmsg);
 
          if (!(po->po_flags & MU_PARSEOPT_NO_ERREXIT))
diff --git a/libmailutils/opt/progname.c b/libmailutils/opt/progname.c
index 19d430e..0d19773 100644
--- a/libmailutils/opt/progname.c
+++ b/libmailutils/opt/progname.c
@@ -22,16 +22,16 @@
 #include <mailutils/alloc.h>
 #include <mailutils/opt.h>
 
-char *mu_progname;
-char *mu_absprogname;
+char *mu_program_name;
+char *mu_full_program_name;
 
 void
-mu_set_progname (char const *arg)
+mu_set_program_name (const char *arg)
 {
   char *p;
 
-  free (mu_absprogname);
-  mu_absprogname = mu_strdup (arg);
+  free (mu_full_program_name);
+  mu_full_program_name = mu_strdup (arg);
   
   p = strrchr (arg, '/');
   if (p)
@@ -40,6 +40,6 @@ mu_set_progname (char const *arg)
     p = (char*) arg;
   if (strlen (p) > 3 && memcmp (p, "lt-", 3) == 0)
     p += 3;
-  free (mu_progname);
-  mu_progname = mu_strdup (p);
+  free (mu_program_name);
+  mu_program_name = mu_strdup (p);
 }
diff --git a/libmailutils/tests/.gitignore b/libmailutils/tests/.gitignore
index 51e4e68..62b06b4 100644
--- a/libmailutils/tests/.gitignore
+++ b/libmailutils/tests/.gitignore
@@ -27,6 +27,7 @@ strftime
 strin
 strout
 strtoc
+tcli
 tempfile
 url-comp
 url-parse
diff --git a/libmailutils/tests/Makefile.am b/libmailutils/tests/Makefile.am
index 349eb24..728eaec 100644
--- a/libmailutils/tests/Makefile.am
+++ b/libmailutils/tests/Makefile.am
@@ -64,6 +64,7 @@ noinst_PROGRAMS = \
  strout\
  strtoc\
  tempfile\
+ tcli\
  url-comp\
  url-parse\
  wicket\
diff --git a/libmailutils/tests/parseopt.c b/libmailutils/tests/parseopt.c
index bef57ee..f25aabf 100644
--- a/libmailutils/tests/parseopt.c
+++ b/libmailutils/tests/parseopt.c
@@ -64,7 +64,7 @@ struct mu_option group_b[] = {
 struct mu_option *optv[] = { group_a, group_b, NULL };
 
 static void
-version_func (FILE *fp)
+version_hook (struct mu_parseopt *po, FILE *fp)
 {
   fputs ("version hook called\n", fp);
 }
@@ -144,7 +144,7 @@ main (int argc, char *argv[])
            }
        }
       if (flags & MU_PARSEOPT_VERSION_HOOK)
-       po.po_version_hook = version_func;
+       po.po_version_hook = version_hook;
     }
   
   rc = mu_parseopt (&po, argc, argv, optv, flags);
diff --git a/libmailutils/tests/parseopt17.at b/libmailutils/tests/parseopt17.at
index 2823e0a..b57a070 100644
--- a/libmailutils/tests/parseopt17.at
+++ b/libmailutils/tests/parseopt17.at
@@ -35,4 +35,24 @@ argv:
 2: follow
 3: options
 ])
+
+AT_CHECK([
+PARSEOPT_DEFAULT
+parseopt --file=file more arguments follow -x -o options
+],
+[0],
+[rc=0
+file_name=file
+opt_value=(null)
+x_option=1
+a_option=0
+find_value=(null)
+d_option=0
+jobs=0
+argv:
+0: more
+1: arguments
+2: follow
+3: options
+])
 AT_CLEANUP
diff --git a/libmailutils/tests/parseopt_help05.at 
b/libmailutils/tests/parseopt_help05.at
index 9a0c1ed..4fe6960 100644
--- a/libmailutils/tests/parseopt_help05.at
+++ b/libmailutils/tests/parseopt_help05.at
@@ -18,7 +18,7 @@ AT_SETUP([MU_PARSEOPT_BUG_ADDRESS])
 AT_KEYWORDS([parseopt parseopt_help parseopt_help05])
 AT_CHECK([
 PARSEOPT_DEFAULT
-MU_PARSEOPT_BUG_ADDRESS='<address@hidden>' parseopt --help
+MU_PARSEOPT_BUG_ADDRESS='address@hidden' parseopt --help
 ],
 [0],
 [Usage: parseopt [[OPTION]]...
diff --git a/libmailutils/tests/parseopt_help07.at 
b/libmailutils/tests/parseopt_help07.at
index 265acb4..91c3c19 100644
--- a/libmailutils/tests/parseopt_help07.at
+++ b/libmailutils/tests/parseopt_help07.at
@@ -20,7 +20,7 @@ AT_CHECK([
 PARSEOPT_DEFAULT
 MU_PARSEOPT_PROG_DOC="Tests option parsing"\
  MU_PARSEOPT_PROG_ARGS="SOME MORE ARGS"\ 
- MU_PARSEOPT_BUG_ADDRESS='<address@hidden>'\
+ MU_PARSEOPT_BUG_ADDRESS='address@hidden'\
  MU_PARSEOPT_PACKAGE_NAME='GNU Mailutils'\
  MU_PARSEOPT_PACKAGE_URL='http://mailutils.org'\
  MU_PARSEOPT_EXTRA_INFO='General help using GNU software: 
<http://www.gnu.org/gethelp/>'\
diff --git a/libmailutils/tests/tcli.c b/libmailutils/tests/tcli.c
new file mode 100644
index 0000000..9a640d5
--- /dev/null
+++ b/libmailutils/tests/tcli.c
@@ -0,0 +1,75 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+   Copyright (C) 2016 Free Software Foundation, Inc.
+
+   GNU Mailutils 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 3, or (at your option)
+   any later version.
+
+   GNU Mailutils is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <mailutils/mailutils.h>
+#include <mailutils/cli.h>
+
+int dtrt_option;
+
+struct mu_option group_a[] = {
+  { "dtrt", 'd', "VALUE", MU_OPTION_DEFAULT,
+    "do the right thing",
+    mu_c_int, &dtrt_option },
+  MU_OPTION_END
+};
+
+struct mu_option *options[] = { group_a, NULL };
+
+static struct mu_cfg_param config[] = {
+  { "do-the-right-thing", mu_c_int, &dtrt_option, 0, NULL,
+    "do the right thing" },
+  { NULL }
+};
+
+struct mu_cli_setup cli = {
+  options,
+  config,
+  "Tests standard command line interface",
+  "ARGUMENTS"
+};
+
+static char **
+getcapa (void)
+{
+  struct mu_wordsplit ws;
+  char *p;
+  
+  p = getenv ("MU_CLI_CAPA");
+  if (!p)
+    return NULL;
+  ws.ws_delim = ",";
+  if (mu_wordsplit (p, &ws, 
+                   MU_WRDSF_DELIM | MU_WRDSF_NOVAR | MU_WRDSF_NOCMD
+                   | MU_WRDSF_WS | MU_WRDSF_SHOWERR))
+    exit (1);
+  return ws.ws_wordv;
+}
+  
+int
+main (int argc, char **argv)
+{
+  int i;
+  
+  mu_cli (argc, argv, &cli, getcapa (), NULL, &argc, &argv);
+  printf ("DTRT=%d\n", dtrt_option);
+  printf ("%d arguments:\n", argc);
+  for (i = 0; i < argc; i++)
+    printf ("%d: %s\n", i, argv[i]);
+  return 0;
+}
diff --git a/libmu_auth/tls.c b/libmu_auth/tls.c
index 331370c..89e3b52 100644
--- a/libmu_auth/tls.c
+++ b/libmu_auth/tls.c
@@ -35,15 +35,36 @@
 #include <mailutils/errno.h>
 #include <mailutils/util.h>
 #include <mailutils/property.h>
+#include <mailutils/cli.h>
+
+#define SSL_CERT_FILE_CHECKS  (MU_FILE_SAFETY_GROUP_WRITABLE |         \
+                              MU_FILE_SAFETY_GROUP_WRITABLE |          \
+                              MU_FILE_SAFETY_LINKED_WRDIR)
+
+#define SSL_KEY_FILE_CHECKS   (MU_FILE_SAFETY_ALL & \
+                              ~MU_FILE_SAFETY_OWNER_MISMATCH)
+
+#define SSL_CA_FILE_CHECKS    (MU_FILE_SAFETY_GROUP_WRITABLE |         \
+                              MU_FILE_SAFETY_GROUP_WRITABLE |          \
+                              MU_FILE_SAFETY_LINKED_WRDIR)
 
 struct mu_tls_module_config mu_tls_module_config = {
 #ifdef WITH_TLS
-  1 /* enable by default */
+    1, /* enable by default */
+      
+    NULL,                /* Certificate file */
+    SSL_CERT_FILE_CHECKS,
+
+    NULL,                /* Key file */ 
+    SSL_KEY_FILE_CHECKS, /* Stringent safety checks for keys */
+
+    NULL,                /* CA file */
+    SSL_CA_FILE_CHECKS
 #else
   0
 #endif
 };
-  
+//FIXME: REMOVE  
 int
 mu_tls_module_init (enum mu_gocs_op op, void *data)
 {
@@ -774,8 +795,92 @@ mu_tls_client_stream_create (mu_stream_t *pstream,
                                _tls_client_open,
                                strin, strout, flags);
 }
+
+static int
+cb2_safety_checks (const char *name, void *data)
+{
+  int defval;
+  
+  if (data == &mu_tls_module_config.ssl_key_safety_checks)
+    defval = SSL_KEY_FILE_CHECKS;
+  else if (data == &mu_tls_module_config.ssl_cert_safety_checks)
+    defval = SSL_CERT_FILE_CHECKS;
+  else if (data == &mu_tls_module_config.ssl_cafile_safety_checks)
+    defval = SSL_CA_FILE_CHECKS;
+  else
+    {
+      mu_error (_("INTERNAL ERROR at %s:%d: unknown default value?"),
+               __FILE__, __LINE__);
+      defval = MU_FILE_SAFETY_ALL;
+    }
+  if (mu_file_safety_compose (data, name, defval))
+    mu_error (_("unknown keyword: %s"), name);
+  return 0;
+}
 
-
+static int
+cb_safety_checks (void *data, mu_config_value_t *arg)
+{
+  return mu_cfg_string_value_cb (arg, cb2_safety_checks, data);
+}
+
+static struct mu_cfg_param mu_tls_param[] = {
+  { "enable", mu_c_bool, &mu_tls_module_config.enable, 0, NULL,
+    N_("Enable TLS encryption.") },
+  { "ssl-cert", mu_c_string, &mu_tls_module_config.ssl_cert, 0, NULL,
+    N_("Specify SSL certificate file."),
+    N_("file") },
+  { "ssl-key", mu_c_string, &mu_tls_module_config.ssl_key, 0, NULL,
+    N_("Specify SSL certificate key file."),
+    N_("file") },
+  { "ssl-cafile", mu_c_string, &mu_tls_module_config.ssl_cafile, 0, NULL,
+    N_("Specify trusted CAs file."),
+    N_("file") },
+  { "ssl-priorities", mu_c_string, &mu_tls_module_config.priorities, 0, NULL,
+    N_("Set the priorities to use on the ciphers, key exchange methods, "
+       "macs and compression methods."),
+    NULL },
+  { "key-file-safety-checks", mu_cfg_callback,
+    &mu_tls_module_config.ssl_key_safety_checks, 0,
+    cb_safety_checks,
+    N_("Configure safety checks for SSL key file.  Argument is a list or "
+       "sequence of check names optionally prefixed with '+' to enable or "
+       "'-' to disable the corresponding check.  Valid check names are:\n"
+       "\n"
+       "  none          disable all checks\n"
+       "  all           enable all checks\n"
+       "  gwrfil        forbid group writable files\n"
+       "  awrfil        forbid world writable files\n"
+       "  grdfil        forbid group readable files\n"
+       "  ardfil        forbid world writable files\n"
+       "  linkwrdir     forbid symbolic links in group or world writable 
directories\n"
+       "  gwrdir        forbid files in group writable directories\n"
+       "  awrdir        forbid files in world writable directories\n"),
+    N_("arg: list") },  
+  { "cert-file-safety-checks", mu_cfg_callback,
+    &mu_tls_module_config.ssl_cert_safety_checks, 0,
+    cb_safety_checks,
+    N_("Configure safety checks for SSL certificate.  See above for a 
description of <arg>."),
+    N_("arg: list") },  
+  { "ca-file-safety-checks", mu_cfg_callback,
+    &mu_tls_module_config.ssl_cafile_safety_checks, 0,
+    cb_safety_checks,
+    N_("Configure safety checks for SSL certificate authority file.  See above 
for a description of <arg>."),
+    N_("arg: list") },  
+  { NULL }
+}; 
+
+struct mu_cli_capa mu_cli_capa_tls = {
+  "tls",
+  NULL,
+  mu_tls_param,
+  NULL, NULL
+};
+#else
+struct mu_cli_capa mu_cli_capa_tls = {
+  "tls",
+  NULL
+};
 #endif /* WITH_TLS */
 
 /* EOF */
diff --git a/libmu_sieve/conf.c b/libmu_sieve/conf.c
index 0f9283a..15b33aa 100644
--- a/libmu_sieve/conf.c
+++ b/libmu_sieve/conf.c
@@ -18,23 +18,28 @@
 
 #ifdef HAVE_CONFIG_H
 # include <config.h>
-#endif  
+#endif
+#include <stdlib.h>
 #include <sieve-priv.h>
 #include <string.h>
+#include <mailutils/cli.h>
 
 mu_list_t mu_sieve_include_path = NULL;
 mu_list_t mu_sieve_library_path = NULL;
 mu_list_t mu_sieve_library_path_prefix = NULL;
-
 mu_debug_handle_t mu_sieve_debug_handle;
 
+//FIXME: provide definition (from gocs.h)
+static struct mu_gocs_sieve sieve_settings;
+
 void
-mu_sieve_debug_init ()
+mu_sieve_debug_init (void)
 {
   if (!mu_sieve_debug_handle)
     mu_sieve_debug_handle = mu_debug_register_category ("sieve");
 }
 
+/*FIXME: REMOVE BEGIN */
 static int
 _path_append (void *item, void *data)
 {
@@ -73,7 +78,7 @@ mu_sieve_module_init (enum mu_gocs_op op, void *data)
       mu_list_destroy (&mu_sieve_library_path_prefix);
     }
   mu_list_foreach (p->library_path_prefix, _path_append,
-             &mu_sieve_library_path_prefix);
+                  &mu_sieve_library_path_prefix);
   mu_list_foreach (p->library_path, _path_append, &mu_sieve_library_path);
   mu_list_destroy (&p->library_path);
   mu_list_destroy (&p->library_path_prefix);
@@ -81,3 +86,161 @@ mu_sieve_module_init (enum mu_gocs_op op, void *data)
   mu_sieve_debug_init ();
   return 0;
 }
+/* FIXME: REMOVE END */
+
+static int
+cb_clear_library_path (void *data, mu_config_value_t *val)
+{
+  int flag;
+
+  if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
+    return 1;
+  if (mu_str_to_c (val->v.string, mu_c_bool, &flag, NULL))
+    {
+      mu_error (_("not a boolean"));
+      return 1;
+    }
+  if (flag)
+    sieve_settings.clearflags |= MU_SIEVE_CLEAR_LIBRARY_PATH;
+  return 0;
+}
+
+static int
+cb_clear_include_path (void *data, mu_config_value_t *val)
+{
+  int flag;
+  
+  if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
+    return 1;
+  if (mu_str_to_c (val->v.string, mu_c_bool, &flag, NULL))
+    {
+      mu_error (_("not a boolean"));
+      return 1;
+    }
+  if (flag)
+    sieve_settings.clearflags |= MU_SIEVE_CLEAR_INCLUDE_PATH;
+  return 0;
+}
+
+static int
+_add_path (const char *arg, void *data)
+{
+  mu_list_t *plist = data;
+    
+  if (!*plist)
+    {
+      int rc = mu_list_create (plist);
+      if (rc)
+       {
+         mu_error (_("cannot create list: %s"), mu_strerror (rc));
+         exit (1);
+       }
+      mu_list_set_destroy_item (*plist, mu_list_free_item);
+    }
+  return mu_string_split (arg, ":", *plist);
+}
+
+static int
+cb_include_path (void *data, mu_config_value_t *val)
+{
+  return mu_cfg_string_value_cb (val, _add_path,
+                                &sieve_settings.include_path);
+}  
+
+static int
+cb_library_path (void *data, mu_config_value_t *val)
+{
+  return mu_cfg_string_value_cb (val, _add_path,
+                                &sieve_settings.library_path);
+}
+
+static int
+cb_library_path_prefix (void *data, mu_config_value_t *val)
+{
+  return mu_cfg_string_value_cb (val, _add_path,
+                                &sieve_settings.library_path_prefix);
+}
+
+static struct mu_cfg_param mu_sieve_param[] = {
+  { "clear-library-path", mu_cfg_callback, NULL, 0, cb_clear_library_path,
+     N_("Clear library search path.") },
+  { "clear-include-path", mu_cfg_callback, NULL, 0, cb_clear_include_path,
+     N_("Clear include search path.") },
+  { "library-path", mu_cfg_callback, NULL, 0, cb_library_path,
+    N_("Add directories to the library search path.  Argument is a "
+       "colon-separated list of directories."),
+    N_("list") },
+  { "library-path-prefix", mu_cfg_callback, NULL, 0, cb_library_path_prefix,
+    N_("Add directories to the beginning of the library search path.  "
+       "Argument is a colon-separated list of directories."),
+    N_("list") },
+  { "include-path", mu_cfg_callback, NULL, 0, cb_include_path,
+    N_("Add directories to the include search path.  Argument is a "
+       "colon-separated list of directories."),
+    N_("list") },
+  { NULL }
+};
+
+/* New capability support */
+static void
+cli_includedir (struct mu_parseopt *po, struct mu_option *opt,
+               char const *arg)
+{
+  _add_path (arg, &sieve_settings.include_path);
+}
+
+static void
+cli_libdir  (struct mu_parseopt *po, struct mu_option *opt, char const *arg)
+{
+  _add_path (arg, &sieve_settings.library_path);
+}
+
+static void
+cli_libdir_prefix (struct mu_parseopt *po, struct mu_option *opt,
+                  char const *arg)
+{
+  _add_path (arg, &sieve_settings.library_path_prefix);
+}
+
+static void
+cli_clear_include_path (struct mu_parseopt *po, struct mu_option *opt,
+                       char const *arg)
+{
+  sieve_settings.clearflags |= MU_SIEVE_CLEAR_INCLUDE_PATH;
+}
+
+static void
+cli_clear_library_path (struct mu_parseopt *po, struct mu_option *opt,
+                       char const *arg)
+{
+  sieve_settings.clearflags |= MU_SIEVE_CLEAR_LIBRARY_PATH;
+}
+
+static struct mu_option sieve_option[] = {
+  MU_OPTION_GROUP (N_("Sieve options")),
+  { "includedir", 'I', N_("DIR"), MU_OPTION_DEFAULT,
+    N_("append DIR to the list of directories searched for include files"),
+    mu_c_string, NULL, cli_includedir },
+  { "libdir", 'L', N_("DIR"), MU_OPTION_DEFAULT,
+    N_("append DIR to the list of directories searched for library files"),
+    mu_c_string, NULL, cli_libdir },
+  { "libdir-prefix", 0, N_("DIR"), MU_OPTION_DEFAULT,
+    N_("add DIR to the beginning of the list of directories searched for "
+       "library files"),
+    mu_c_string, NULL, cli_libdir_prefix },
+  { "clear-include-path", 0, NULL, MU_OPTION_DEFAULT,
+    N_("clear Sieve include path"),
+    mu_c_string, NULL, cli_clear_include_path },
+  { "clear-library-path", 0, NULL, MU_OPTION_DEFAULT,
+    N_("clear Sieve library path"),
+    mu_c_string, NULL, cli_clear_library_path },
+  { "clearpath", 0, NULL, MU_OPTION_ALIAS },
+  MU_OPTION_END
+};
+
+struct mu_cli_capa mu_cli_capa_sieve = {
+  "sieve",
+  sieve_option,
+  mu_sieve_param,
+  NULL, NULL
+};
diff --git a/messages/Makefile.am b/messages/Makefile.am
index d611b2c..56ff5e7 100644
--- a/messages/Makefile.am
+++ b/messages/Makefile.am
@@ -22,7 +22,7 @@ SUBDIRS = . tests
 bin_PROGRAMS = messages
 messages_SOURCES = messages.c
 messages_LDADD =\
- ${MU_APP_LIBRARIES}\
+ ${MU_APP_NEW_LIBRARIES}\
  ${MU_LIB_MBOX}\
  ${MU_LIB_IMAP}\
  ${MU_LIB_POP}\
diff --git a/messages/messages.c b/messages/messages.c
index 4f5c614..84cf4bf 100644
--- a/messages/messages.c
+++ b/messages/messages.c
@@ -20,85 +20,44 @@
 #endif
 
 #include <stdio.h>
-#ifdef HAVE_MALLOC_H
-# include <malloc.h>
-#endif
 
 #include <mailutils/mailutils.h>
-#include "mailutils/libargp.h"
+#include <mailutils/cli.h>
 
 static int messages_count (const char *);
 
-static char doc[] = N_("GNU messages -- count the number of messages in a 
mailbox");
-static char args_doc[] = N_("[mailbox...]");
+/* are we loud or quiet? */
+static int silent = 0;
 
-static struct argp_option options[] = {
-  { NULL,         0, NULL,  0,
-    /* TRANSLATORS: 'messages' is a program name. Do not translate it! */
-    N_("messages specific switches:"), 0},
-  {"quiet",    'q',    NULL,   0,      N_("only display number of messages")},
-  {"silent",   's',    NULL,   OPTION_ALIAS, NULL },
-  { 0 }
+static struct mu_option messages_options[] = {
+  { "quiet",   'q',    NULL,   MU_OPTION_DEFAULT,
+    N_("only display number of messages"),
+    mu_c_bool, &silent },
+  {"silent",   's',    NULL,   MU_OPTION_ALIAS },
+  MU_OPTION_END
 };
 
-static const char *argp_capa[] = {
-  "mailutils",
-  "common",
+static char *capa[] = {
   "debug",
   "mailbox",
   "locking",
+  "tls",
   NULL
 };
 
-struct arguments
-{
-  int argc;
-  char **argv;
-};
+static struct mu_option *options[] = { messages_options, NULL };
 
-/* are we loud or quiet? */
-static int silent = 0;
-
-static error_t
-parse_opt (int key, char *arg, struct argp_state *state)
-{
-  struct arguments *args = state->input;
-  switch (key)
-    {
-    case 'q':
-    case 's':
-      silent = 1;
-      break;
-      
-    case ARGP_KEY_ARG:
-      args->argv = realloc (args->argv,
-                           sizeof (char *) * (state->arg_num + 2));
-      args->argv[state->arg_num] = arg;
-      args->argv[state->arg_num + 1] = NULL;
-      args->argc++;
-      break;
-      
-    default:
-      return ARGP_ERR_UNKNOWN;
-    }
-  return 0;
-}
-
-static struct argp argp = {
+struct mu_cli_setup cli = {
   options,
-  parse_opt,
-  args_doc,
-  doc,
   NULL,
-  NULL, NULL
+  N_("GNU messages -- count the number of messages in a mailbox"),
+  N_("[mailbox...]")
 };
 
 int
 main (int argc, char **argv)
 {
-  int i = 1;
   int err = 0;
-  struct arguments args = {0, NULL};
 
   /* Native Language Support */
   MU_APP_INIT_NLS ();
@@ -106,20 +65,18 @@ main (int argc, char **argv)
   /* register the formats.  */
   mu_register_all_mbox_formats ();
 
-#ifdef WITH_TLS
-  mu_gocs_register ("tls", mu_tls_module_init);
-#endif
-  mu_argp_init (NULL, NULL);
-  if (mu_app_init (&argp, argp_capa, NULL, argc, argv, 0, NULL, &args))
-    exit (1);
+  mu_cli_capa_register (&mu_cli_capa_tls);
+  mu_cli (argc, argv, &cli, capa, NULL, &argc, &argv);
 
-  if (args.argc < 1 && messages_count (NULL) < 0)
+  if (argc == 0 && messages_count (NULL) < 0)
     err = 1;
-  else if (args.argc >= 1)
+  else if (argc >= 1)
     {
-      for (i = 0; i < args.argc; i++)
+      size_t i;
+      
+      for (i = 0; i < argc; i++)
        {
-         if (messages_count (args.argv[i]) < 0)
+         if (messages_count (argv[i]) < 0)
            err = 1;
        }
     }
diff --git a/mimeview/Makefile.am b/mimeview/Makefile.am
index b4c9108..d85eebb 100644
--- a/mimeview/Makefile.am
+++ b/mimeview/Makefile.am
@@ -47,7 +47,7 @@ mimetypes-lex.c: $(srcdir)/mimetypes.l mimetypes-decl.h
 BUILT_SOURCES = mimetypes-gram.c mimetypes-lex.c mimetypes-decl.h
 
 mimeview_LDADD = \
- ${MU_APP_LIBRARIES}\
+ ${MU_APP_NEW_LIBRARIES}\
  ${MU_LIB_MAILUTILS}\
  @LTLIBINTL@
  
diff --git a/mimeview/mimeview.c b/mimeview/mimeview.c
index 4a7810c..0100f50 100644
--- a/mimeview/mimeview.c
+++ b/mimeview/mimeview.c
@@ -26,38 +26,11 @@
 #include <unistd.h>
 #include <fcntl.h>
 
-#include "mailutils/libargp.h"
+#include "mailutils/cli.h"
 #include "mailutils/argcv.h"
 
 #include "mailcap.h"
 
-static char doc[] = N_("GNU mimeview -- display files, using mailcap 
mechanism.")
-"\v"     
-N_("Default mime.types file is ") DEFAULT_CUPS_CONFDIR "/mime.types"
-N_("\n\nDebug flags are:\n\
-  g - Mime.types parser traces\n\
-  l - Mime.types lexical analyzer traces\n\
-  0-9 - Set debugging level\n");
-
-#define OPT_METAMAIL 256
-
-static struct argp_option options[] = {
-  {"no-ask", 'a', N_("TYPE-LIST"), OPTION_ARG_OPTIONAL,
-   N_("do not ask for confirmation before displaying files, or, if TYPE-LIST 
is given, do not ask for confirmation before displaying such files whose MIME 
type matches one of the patterns from TYPE-LIST"), 0},
-  {"no-interactive", 'h', NULL, 0,
-   N_("disable interactive mode"), 0 },
-  {"print", 0, NULL, OPTION_ALIAS, NULL, 0 },
-  {"debug",  'd', N_("FLAGS"),  OPTION_ARG_OPTIONAL,
-   N_("enable debugging output"), 0},
-  {"mimetypes", 't', N_("FILE"), 0,
-   N_("use this mime.types file"), 0},
-  {"dry-run", 'n', NULL, 0,
-   N_("do nothing, just print what would have been done"), 0},
-  {"metamail", OPT_METAMAIL, N_("FILE"), OPTION_ARG_OPTIONAL,
-   N_("use metamail to display files"), 0},
-  {0, 0, 0, 0}
-};
-
 int debug_level;       /* Debugging level set by --debug option */
 static int dry_run;    /* Dry run mode */
 static char *metamail; /* Name of metamail program, if requested */
@@ -88,68 +61,62 @@ set_debug_flags (const char *arg)
        }
     }
 }  
-
-static error_t
-parse_opt (int key, char *arg, struct argp_state *state)
+
+static void
+cli_no_ask (struct mu_parseopt *po, struct mu_option *opt, char const *arg)
 {
-  static mu_list_t lst;
-
-  switch (key)
-    {
-    case ARGP_KEY_INIT:
-      mimetypes_lex_debug (0);
-      mimetypes_gram_debug (0);
-      if (interactive == -1)
-       interactive = isatty (fileno (stdin));
-      mu_argp_node_list_init (&lst);
-      break;
-
-    case ARGP_KEY_FINI:
-      if (dry_run && !debug_level)
-       debug_level = 1;
-      mu_argp_node_list_finish (lst, NULL, NULL);
-      break;
+  no_ask_types = mu_strdup (arg ? arg : "*");
+  setenv ("MM_NOASK", arg, 1); /* In case we are given --metamail option */
+}
 
-    case 'a':
-      no_ask_types = arg ? arg : "*";
-      setenv ("MM_NOASK", arg, 1); /* In case we are given --metamail option */
-      break;
-      
-    case 'd':
-      mu_argp_node_list_new (lst, "debug", arg ? arg : "9");
-      break;
+static void
+cli_no_interactive (struct mu_parseopt *po, struct mu_option *opt,
+                   char const *arg)
+{
+  interactive = 0;
+}
 
-    case 'h':
-      interactive = 0;
-      break;
-      
-    case 'n':
-      dry_run = 1;
-      break;
-      
-    case 't':
-      mu_argp_node_list_new (lst, "mimetypes", arg);
-      break;
+static void
+cli_debug (struct mu_parseopt *po, struct mu_option *opt,
+          char const *arg)
+{
+  set_debug_flags (arg);
+}
 
-    case OPT_METAMAIL:
-      mu_argp_node_list_new (lst, "metamail", arg ? arg : "metamail");
-      break;
-      
-    default: 
-      return ARGP_ERR_UNKNOWN;
-    }
-  return 0;
+static void
+cli_metamail (struct mu_parseopt *po, struct mu_option *opt,
+             char const *arg)
+{
+  if (!arg)
+    arg = "metamail";
+  metamail = mu_strdup (arg);
 }
 
-static struct argp argp = {
-  options,
-  parse_opt,
-  N_("FILE [FILE ...]"),
-  doc,
-  NULL,
-  NULL, NULL
-};
+static struct mu_option mimeview_options[] = {
+  { "no-ask", 'a', N_("TYPE-LIST"), MU_OPTION_ARG_OPTIONAL,
+    N_("do not ask for confirmation before displaying files, or, if TYPE-LIST 
is given, do not ask for confirmation before displaying such files whose MIME 
type matches one of the patterns from TYPE-LIST"),
+    mu_c_string, NULL, cli_no_ask },
+  { "no-interactive", 'h', NULL, MU_OPTION_DEFAULT,
+   N_("disable interactive mode"),
+    mu_c_string, NULL, cli_no_interactive },
+  { "print",  0, NULL, MU_OPTION_ALIAS },
+  { "debug", 'd', N_("FLAGS"),  MU_OPTION_ARG_OPTIONAL,
+    N_("enable debugging output"),
+    mu_c_string, NULL, cli_debug },
+  { "mimetypes", 't', N_("FILE"), MU_OPTION_DEFAULT,
+    N_("use this mime.types file"),
+    mu_c_string, &mimetypes_config },
+  
+  { "dry-run",   'n', NULL, MU_OPTION_DEFAULT,
+    N_("do nothing, just print what would have been done"),
+    mu_c_bool, &dry_run },
+  
+  { "metamail",    0, N_("FILE"), MU_OPTION_ARG_OPTIONAL,
+    N_("use metamail to display files"),
+    mu_c_string, NULL, cli_metamail },
 
+  MU_OPTION_END
+}, *options[] = { mimeview_options, NULL };
 
 static int
 cb_debug (void *data, mu_config_value_t *val)
@@ -172,12 +139,23 @@ struct mu_cfg_param mimeview_cfg_param[] = {
     N_("prog") },
   { NULL }
 };
-
 
-
-static const char *capa[] = {
-  "mailutils",
-  "common",
+struct mu_cli_setup cli = {
+  options,
+  mimeview_cfg_param,
+  N_("GNU mimeview -- display files, using mailcap mechanism."),
+  //FIXME:
+  /*
+  N_("Default mime.types file is ") DEFAULT_CUPS_CONFDIR "/mime.types"
+N_("\n\nDebug flags are:\n\
+  g - Mime.types parser traces\n\
+  l - Mime.types lexical analyzer traces\n\
+  0-9 - Set debugging level\n");
+  */
+  N_("FILE [FILE ...]")
+};
+
+static char *capa[] = {
   "debug",
   NULL
 };
@@ -267,16 +245,15 @@ display_file (const char *type)
 int
 main (int argc, char **argv)
 {
-  int index;
-  
   MU_APP_INIT_NLS ();
-  mu_argp_init (NULL, NULL);
-  if (mu_app_init (&argp, capa, mimeview_cfg_param, 
-                  argc, argv, 0, &index, NULL))
-    exit (1);
 
-  argc -= index;
-  argv += index;
+  mimetypes_lex_debug (0);
+  mimetypes_gram_debug (0);
+  interactive = isatty (fileno (stdin));
+  
+  mu_cli (argc, argv, &cli, capa, NULL, &argc, &argv);
+  if (dry_run && !debug_level)
+    debug_level = 1;
 
   if (argc == 0)
     {
diff --git a/movemail/Makefile.am b/movemail/Makefile.am
index e166b81..5d0b5c6 100644
--- a/movemail/Makefile.am
+++ b/movemail/Makefile.am
@@ -19,7 +19,7 @@ AM_CPPFLAGS = @MU_APP_COMMON_INCLUDES@ @MU_AUTHINCS@
 bin_PROGRAMS = movemail
 
 movemail_LDADD = \
- ${MU_APP_LIBRARIES}\
+ ${MU_APP_NEW_LIBRARIES}\
  ${MU_LIB_MBOX}\
  ${MU_LIB_IMAP}\
  ${MU_LIB_POP}\
diff --git a/movemail/movemail.c b/movemail/movemail.c
index 67b721f..8fdaf90 100644
--- a/movemail/movemail.c
+++ b/movemail/movemail.c
@@ -27,46 +27,9 @@
 #include <unistd.h>
 #include <mailutils/mailutils.h>
 #include <mailutils/tls.h>
-#include "mailutils/libargp.h"
+#include "mailutils/cli.h"
 #include <muaux.h>
 
-static char doc[] = N_("GNU movemail -- move messages across mailboxes.");
-static char args_doc[] = N_("inbox-url destfile [POP-password]");
-
-enum {
-  EMACS_OPTION=256,
-  IGNORE_ERRORS_OPTION,
-  PROGRAM_ID_OPTION,
-  MAX_MESSAGES_OPTION,
-  ONERROR_OPTION,
-  NOTIFY_OPTION
-};
-
-static struct argp_option options[] = {
-  { "preserve", 'p', NULL, 0, N_("preserve the source mailbox") },
-  { "keep-messages", 0, NULL, OPTION_ALIAS, NULL },
-  { "reverse",  'r', NULL, 0, N_("reverse the sorting order") },
-  { "emacs", EMACS_OPTION, NULL, 0,
-    N_("output information used by Emacs rmail interface") },
-  { "uidl", 'u', NULL, 0,
-    N_("use UIDLs to avoid downloading the same message twice") },
-  { "verbose", 'v', NULL, 0,
-    N_("increase verbosity level") },
-  { "owner", 'P', N_("MODELIST"), 0,
-    N_("control mailbox ownership") },
-  { "ignore-errors", IGNORE_ERRORS_OPTION, NULL, 0,
-    N_("try to continue after errors") },
-  { "onerror", ONERROR_OPTION, N_("KW[,KW...]"), 0,
-    N_("what to do on errors") },
-  { "program-id", PROGRAM_ID_OPTION, N_("FMT"), 0,
-    N_("set program identifier for diagnostics (default: program name)") },
-  { "max-messages", MAX_MESSAGES_OPTION, N_("NUMBER"), 0,
-    N_("process at most NUMBER messages") },
-  { "notify",  NOTIFY_OPTION, NULL,   0,
-    N_("enable biff notification") },  
-  { NULL,      0, NULL, 0, NULL, 0 }
-};
-
 static int reverse_order;
 static int preserve_mail; 
 static int emacs_mode;
@@ -135,84 +98,9 @@ mu_kwd_t method_kwd[] = {
   { "set-id", set_owner_id },
   { NULL }
 };
-
-static error_t
-parse_opt (int key, char *arg, struct argp_state *state)
-{
-  static mu_list_t lst;
-
-  switch (key)
-    {
-    case 'r':
-      mu_argp_node_list_new (lst, "reverse", "yes");
-      break;
-
-    case 'p':
-      mu_argp_node_list_new (lst, "preserve", "yes");
-      break;
-
-    case 'P':
-      mu_argp_node_list_new (lst, "mailbox-ownership", arg);
-      break;
-
-    case 'u':
-      mu_argp_node_list_new (lst, "uidl", "yes");
-      break;
-
-    case 'v':
-      verbose_option++;
-      break;
-      
-    case EMACS_OPTION:
-      mu_argp_node_list_new (lst, "emacs", "yes");
-      break;
-
-    case IGNORE_ERRORS_OPTION:
-      mu_argp_node_list_new (lst, "ignore-errors", "yes");
-      break;
-
-    case NOTIFY_OPTION:
-      notify = 1;
-      break;
-      
-    case ONERROR_OPTION:
-      mu_argp_node_list_new (lst, "onerror", arg);
-      break;
-      
-    case MAX_MESSAGES_OPTION:
-      mu_argp_node_list_new (lst, "max-messages", arg);
-      break;
-      
-    case PROGRAM_ID_OPTION:
-      mu_argp_node_list_new (lst, "program-id", arg);
-      break;
-      
-    case ARGP_KEY_INIT:
-      mu_argp_node_list_init (&lst);
-      break;
-      
-    case ARGP_KEY_FINI:
-      mu_argp_node_list_finish (lst, NULL, NULL);
-      break;
-      
-    default:
-      return ARGP_ERR_UNKNOWN;
-    }
-  return 0;
-}
-
-static struct argp argp = {
-  options,
-  parse_opt,
-  args_doc,
-  doc,
-  NULL,
-  NULL, NULL
-};
-
 
 static int
-_cb_mailbox_ownership (const char *str)
+set_mailbox_ownership (const char *str)
 {
   if (strcmp (str, "clear") == 0)
     so_method_num = 0;
@@ -280,50 +168,33 @@ _cb_mailbox_ownership (const char *str)
 }
 
 static int
-cb_mailbox_ownership (void *data, mu_config_value_t *val)
+set_mailbox_ownership_list (char const *str)
 {
-  int i;
-  
-  if (val->type == MU_CFG_STRING)
+  if (!strchr (str, ','))
+    return set_mailbox_ownership (str);
+  else
     {
-      const char *str = val->v.string;
-      if (!strchr (str, ','))
-       return _cb_mailbox_ownership (str);
-      else
+      struct mu_wordsplit ws;
+      size_t i;
+      
+      ws.ws_delim = ",";
+      if (mu_wordsplit (str, &ws, MU_WRDSF_DEFFLAGS|MU_WRDSF_DELIM))
        {
-         struct mu_wordsplit ws;
-
-         ws.ws_delim = ",";
-         if (mu_wordsplit (str, &ws, MU_WRDSF_DEFFLAGS|MU_WRDSF_DELIM))
-           {
-             mu_error (_("cannot parse %s: %s"),
-                       str, mu_wordsplit_strerror (&ws));
-             return 1;
-           }
-
-         for (i = 0; i < ws.ws_wordc; i++)
-           if (_cb_mailbox_ownership (ws.ws_wordv[i]))
-             return 1;
-         mu_wordsplit_free (&ws);
-         return 0;
+         mu_error (_("cannot parse %s: %s"),
+                   str, mu_wordsplit_strerror (&ws));
+         return 1;
        }
-    }
-               
-  if (mu_cfg_assert_value_type (val, MU_CFG_LIST))
-    return 1;
 
-  for (i = 0; i < val->v.arg.c; i++)
-    {
-      if (mu_cfg_assert_value_type (&val->v.arg.v[i], MU_CFG_STRING))
-       return 1;
-      if (_cb_mailbox_ownership (val->v.arg.v[i].v.string))
-       return 1;
+      for (i = 0; i < ws.ws_wordc; i++)
+       if (set_mailbox_ownership (ws.ws_wordv[i]))
+         return 1;
+      mu_wordsplit_free (&ws);
+      return 0;
     }
-  return 0;
 }
 
 static int
-cb_onerror (void *data, mu_config_value_t *val)
+set_onerror_action (char const *str)
 {
   struct mu_wordsplit ws;
   static struct mu_kwd onerror_kw[] = {
@@ -334,15 +205,13 @@ cb_onerror (void *data, mu_config_value_t *val)
   };
   int i, flag;
   
-  if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
-    return 1;
-  if (strcmp (val->v.string, "abort") == 0)
+  if (strcmp (str, "abort") == 0)
     {
       onerror_flags = 0;
       return 0;
     }
   ws.ws_delim = ",";
-  if (mu_wordsplit (val->v.string, &ws,
+  if (mu_wordsplit (str, &ws,
                    MU_WRDSF_NOVAR | MU_WRDSF_NOCMD |
                    MU_WRDSF_DELIM | MU_WRDSF_WS))
     {
@@ -369,6 +238,99 @@ cb_onerror (void *data, mu_config_value_t *val)
   mu_wordsplit_free (&ws);
   return 0;
 }
+
+static void
+cli_mailbox_ownership (struct mu_parseopt *po, struct mu_option *opt,
+                      char const *arg)
+{
+  if (set_mailbox_ownership_list (arg))
+    exit (po->po_exit_error);
+}
+
+static void
+cli_onerror (struct mu_parseopt *po, struct mu_option *opt, char const *arg)
+{
+  if (set_onerror_action (arg))
+    exit (po->po_exit_error);
+}
+
+static struct mu_option movemail_options[] = {
+  { "preserve", 'p', NULL, MU_OPTION_DEFAULT,
+    N_("preserve the source mailbox"),
+    mu_c_bool, &preserve_mail },
+  { "keep-messages", 0, NULL, MU_OPTION_ALIAS },
+  
+  { "reverse",  'r', NULL, MU_OPTION_DEFAULT,
+    N_("reverse the sorting order"),
+    mu_c_bool, &reverse_order },
+  
+  { "emacs",      0, NULL, MU_OPTION_DEFAULT,
+    N_("output information used by Emacs rmail interface"),
+    mu_c_bool, &emacs_mode },
+  
+  { "uidl",     'u', NULL, MU_OPTION_DEFAULT,
+    N_("use UIDLs to avoid downloading the same message twice"),
+    mu_c_bool, &uidl_option },
+  
+  { "verbose",  'v', NULL, MU_OPTION_DEFAULT,
+    N_("increase verbosity level"),
+    mu_c_incr, &verbose_option },
+  
+  { "owner",    'P', N_("MODELIST"), MU_OPTION_DEFAULT,
+    N_("control mailbox ownership"),
+    mu_c_string, cli_mailbox_ownership },
+  
+  { "ignore-errors", 0, NULL, MU_OPTION_DEFAULT,
+    N_("try to continue after errors"),
+    mu_c_bool, &ignore_errors },
+  
+  { "onerror",       0, N_("KW[,KW...]"), MU_OPTION_DEFAULT,
+    N_("what to do on errors"),
+    mu_c_string, NULL, cli_onerror },
+  
+  { "program-id",    0, N_("FMT"), MU_OPTION_DEFAULT,
+    N_("set program identifier for diagnostics (default: program name)"),
+    mu_c_string, &program_id_option },
+  
+  { "max-messages",  0, N_("NUMBER"), MU_OPTION_DEFAULT,
+    N_("process at most NUMBER messages"),
+    mu_c_size, &max_messages_option },
+  
+  { "notify",        0, NULL,   MU_OPTION_DEFAULT,
+    N_("enable biff notification"),
+    mu_c_bool, &notify },
+
+  MU_OPTION_END
+}, *options[] = { movemail_options, NULL };
+
+static int
+cb_mailbox_ownership (void *data, mu_config_value_t *val)
+{
+  int i;
+  
+  if (val->type == MU_CFG_STRING)
+    set_mailbox_ownership_list (val->v.string);
+               
+  if (mu_cfg_assert_value_type (val, MU_CFG_LIST))
+    return 1;
+
+  for (i = 0; i < val->v.arg.c; i++)
+    {
+      if (mu_cfg_assert_value_type (&val->v.arg.v[i], MU_CFG_STRING))
+       return 1;
+      if (set_mailbox_ownership (val->v.arg.v[i].v.string))
+       return 1;
+    }
+  return 0;
+}
+
+static int
+cb_onerror (void *data, mu_config_value_t *val)
+{
+  if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
+    return 1;
+  return set_onerror_action (val->v.string);
+}
   
 struct mu_cfg_param movemail_cfg_param[] = {
   { "preserve", mu_c_bool, &preserve_mail, 0, NULL,
@@ -406,15 +368,20 @@ struct mu_cfg_param movemail_cfg_param[] = {
        "Setting onerror=abort reverts to the default behavior.") },
   { NULL }
 };
-
 
-static const char *movemail_capa[] = {
-  "mailutils",
-  "common",
+struct mu_cli_setup cli = {
+  options,
+  movemail_cfg_param,
+  N_("GNU movemail -- move messages across mailboxes."),
+  N_("inbox-url destfile [POP-password]")
+};
+
+static char *movemail_capa[] = {
   "debug",
   "locking",
   "mailbox",
   "auth",
+  "tls",
   NULL 
 };
 
@@ -863,7 +830,6 @@ set_program_id (const char *source_name, const char 
*dest_name)
 int
 main (int argc, char **argv)
 {
-  int index;
   size_t total;
   int rc = 0;
   char *source_name, *dest_name;
@@ -880,16 +846,8 @@ main (int argc, char **argv)
 
   /* argument parsing */
   
-#ifdef WITH_TLS
-  mu_gocs_register ("tls", mu_tls_module_init);
-#endif
-  mu_argp_init (NULL, NULL);
-  if (mu_app_init (&argp, movemail_capa, movemail_cfg_param, 
-                  argc, argv, 0, &index, NULL))
-    exit (1);
-
-  argc -= index;
-  argv += index;
+  mu_cli_capa_register (&mu_cli_capa_tls);
+  mu_cli (argc, argv, &cli, movemail_capa, NULL, &argc, &argv);
 
   if (argc < 2 || argc > 3)
     {
diff --git a/readmsg/Makefile.am b/readmsg/Makefile.am
index 66ffef6..57c9dc3 100644
--- a/readmsg/Makefile.am
+++ b/readmsg/Makefile.am
@@ -23,7 +23,7 @@ bin_PROGRAMS = readmsg
 readmsg_SOURCES = readmsg.c msglist.c readmsg.h
 
 readmsg_LDADD =\
- ${MU_APP_LIBRARIES}\
+ ${MU_APP_NEW_LIBRARIES}\
  ${MU_LIB_MBOX}\
  ${MU_LIB_IMAP}\
  ${MU_LIB_POP}\
diff --git a/readmsg/readmsg.c b/readmsg/readmsg.c
index 794c0f1..bbbabf5 100644
--- a/readmsg/readmsg.c
+++ b/readmsg/readmsg.c
@@ -20,7 +20,7 @@
 #endif
 
 #include "readmsg.h"
-#include "mailutils/libargp.h"
+#include "mailutils/cli.h"
 #include "mu_umaxtostr.h"
 
 #define WEEDLIST_SEPARATOR " :,"
@@ -30,41 +30,6 @@ static void print_header (mu_message_t, int, int, char **);
 static void print_body (mu_message_t);
 static int  string_starts_with (const char * s1, const char *s2);
 
-static char doc[] = N_("GNU readmsg -- print messages.");
-static error_t readmsg_parse_opt  (int key, char *arg, struct argp_state 
*astate);
-
-static struct argp_option options[] = 
-{
-  { "debug", 'd', 0, 0, N_("display debugging information"), 1 },
-  { "header", 'h', 0, 0, N_("display entire header"), 1 },
-  { "weedlist", 'w', N_("LIST"), 0,
-    N_("list of header names separated by whitespace or commas"), 1 },
-  { "folder", 'f', N_("FOLDER"), 0, N_("folder to use"), 1 },
-  { "no-header", 'n', 0, 0, N_("exclude all headers"), 1 },
-  { "form-feeds", 'p', 0, 0, N_("output formfeeds between messages"), 1 },
-  { "show-all-match", 'a', NULL, 0,
-    N_("print all messages matching pattern, not only the first"), 1 },
-  {0, 0, 0, 0}
-};
-
-static struct argp argp = {
-  options,
-  readmsg_parse_opt,
-  NULL,
-  doc,
-  NULL,
-  NULL, NULL
-};
-
-static const char *readmsg_argp_capa[] = {
-  "mailutils",
-  "common",
-  "debug",
-  "mailbox",
-  "locking",
-  NULL
-};
-
 int dbug = 0;
 const char *mailbox_name = NULL;
 const char *weedlist = NULL;
@@ -73,57 +38,30 @@ int all_header = 0;
 int form_feed = 0;
 int show_all = 0;
 
-static error_t
-readmsg_parse_opt (int key, char *arg, struct argp_state *astate)
+static struct mu_option readmsg_options[] = 
 {
-  static mu_list_t lst;
-
-  switch (key)
-    {
-    case 'd':
-      dbug++;
-      break;
-
-    case 'h':
-      mu_argp_node_list_new (lst, "header", "yes");
-      break;
-
-    case 'f':
-      mu_argp_node_list_new (lst, "folder", arg);
-      break;
-
-    case 'w':
-      mu_argp_node_list_new (lst, "weedlist", arg);
-      break;
-
-    case 'n':
-      mu_argp_node_list_new (lst, "no-header", "yes");
-      break;
-
-    case 'p':
-      mu_argp_node_list_new (lst, "form-feeds", "yes");
-      break;
-         
-    case 'a':
-      mu_argp_node_list_new (lst, "show-all-match", "yes");
-      break;
-
-    case ARGP_KEY_INIT:
-      mu_argp_node_list_init (&lst);
-      break;
-      
-    case ARGP_KEY_FINI:
-      if (dbug)
-       mu_argp_node_list_new (lst, "debug", mu_umaxtostr (0, dbug));
-      mu_argp_node_list_finish (lst, NULL, NULL);
-      break;
-      
-    default:
-      return ARGP_ERR_UNKNOWN;
-    }
-  return 0;
-}
-
+  { "debug", 'd', NULL, MU_OPTION_DEFAULT,
+    N_("display debugging information"),
+    mu_c_incr, &dbug },
+  { "header", 'h', NULL, MU_OPTION_DEFAULT,
+    N_("display entire headers"),
+    mu_c_bool, &all_header },
+  { "weedlist", 'w', N_("LIST"), MU_OPTION_DEFAULT,
+    N_("list of header names separated by whitespace or commas"),
+    mu_c_string, &weedlist },
+  { "folder", 'f', N_("FOLDER"), MU_OPTION_DEFAULT,
+    N_("folder to use"), mu_c_string, &mailbox_name },
+  { "no-header", 'n', NULL, MU_OPTION_DEFAULT,
+    N_("exclude all headers"),
+    mu_c_bool, &no_header },
+  { "form-feeds", 'p', NULL, MU_OPTION_DEFAULT,
+    N_("output formfeeds between messages"),
+    mu_c_bool, &form_feed },
+  { "show-all-match", 'a', NULL, MU_OPTION_DEFAULT,
+    N_("print all messages matching pattern, not only the first"),
+    mu_c_bool, &show_all },
+  MU_OPTION_END
+}, *options[] = { readmsg_options, NULL };
 
 struct mu_cfg_param readmsg_cfg_param[] = {
   { "debug", mu_c_int, &dbug, 0, NULL,
@@ -145,6 +83,21 @@ struct mu_cfg_param readmsg_cfg_param[] = {
   { NULL }
 };
 
+struct mu_cli_setup cli = {
+  options,
+  readmsg_cfg_param,
+  N_("GNU readmsg -- print messages."),
+  NULL
+};
+
+static char *readmsg_argp_capa[] = {
+  "debug",
+  "mailbox",
+  "locking",
+  "tls",
+  NULL
+};
+
 static int
 string_starts_with (const char * s1, const char *s2)
 {
@@ -158,7 +111,7 @@ string_starts_with (const char * s1, const char *s2)
 
   while (*p1 && *p2)
     {
-      if ((n = toupper (*p1++) - toupper (*p2++)) != 0)
+      if ((n = mu_toupper (*p1++) - mu_toupper (*p2++)) != 0)
        break;
     }
   return (n == 0);
@@ -276,7 +229,6 @@ main (int argc, char **argv)
   int *set = NULL;
   int n = 0;
   int i;
-  int index;
   mu_mailbox_t mbox = NULL;
   struct mu_wordsplit ws;
   char **weedv;
@@ -290,15 +242,9 @@ main (int argc, char **argv)
   mu_register_all_mbox_formats ();
   mu_register_extra_formats ();
 
-#ifdef WITH_TLS
-  mu_gocs_register ("tls", mu_tls_module_init);
-#endif
-  mu_argp_init (NULL, NULL);
-  if (mu_app_init (&argp, readmsg_argp_capa, readmsg_cfg_param, 
-                  argc, argv, 0, &index, NULL))
-    exit (1);
+  mu_cli_capa_register (&mu_cli_capa_tls);
 
-  argc -= index;
+  mu_cli (argc, argv, &cli, readmsg_argp_capa, NULL, &argc, &argv);
 
   if (argc == 0)
     {
@@ -376,7 +322,7 @@ main (int argc, char **argv)
     }
 
   /* Build an array containing the message number.  */
-  msglist (mbox, show_all, argc, &argv[index], &set, &n);
+  msglist (mbox, show_all, argc, argv, &set, &n);
 
   for (i = 0; i < n; ++i)
     {
diff --git a/sieve/Makefile.am b/sieve/Makefile.am
index d51db0c..2a294ba 100644
--- a/sieve/Makefile.am
+++ b/sieve/Makefile.am
@@ -22,7 +22,7 @@ EXTRA_DIST = examples
 bin_PROGRAMS = sieve
 sieve_SOURCES = sieve.c
 sieve_LDADD =\
- ${MU_APP_LIBRARIES}\
+ ${MU_APP_NEW_LIBRARIES}\
  ${MU_LIB_SIEVE}\
  ${MU_LIB_MBOX}\
  ${MU_LIB_IMAP}\
diff --git a/sieve/sieve.c b/sieve/sieve.c
index 32a8a0b..5de8e61 100644
--- a/sieve/sieve.c
+++ b/sieve/sieve.c
@@ -43,64 +43,10 @@
 #include <mailutils/stream.h>
 #include <mailutils/nls.h>
 #include <mailutils/tls.h>
-
-#include "mailutils/libargp.h"
-
-static char doc[] =
-N_("GNU sieve -- a mail filtering tool.")
-"\v"
-N_("Debug flags:\n\
-  g - main parser traces\n\
-  T - mailutils traces (same as --debug-level=sieve.trace0-trace1)\n\
-  P - network protocols (same as --debug-level=sieve.=prot)\n\
-  t - sieve trace (MU_SIEVE_DEBUG_TRACE)\n\
-  i - sieve instructions trace (MU_SIEVE_DEBUG_INSTR)\n");
+#include <mailutils/cli.h>
 
 #define D_DEFAULT "TPt"
 
-#define ARG_LINE_INFO 257
-#define ARG_NO_PROGRAM_NAME 258
-
-static struct argp_option options[] =
-{
-  {"no-actions", 'n', 0, 0,
-   N_("do not execute any actions, just print what would be done"), 0},
-  {"dry-run", 0, NULL, OPTION_ALIAS, NULL },
-  {"keep-going", 'k', 0, 0,
-   N_("keep on going if execution fails on a message"), 0},
-
-  {"compile-only", 'c', 0, 0,
-   N_("compile script and exit"), 0},
-
-  {"dump", 'D', 0, 0,
-   N_("compile script, dump disassembled sieve code to terminal and exit"), 0 
},
-  
-  {"mbox-url", 'f', N_("MBOX"), 0,
-   N_("mailbox to sieve (defaults to user's mail spool)"), 0},
-
-  {"ticket", 't', N_("TICKET"), 0,
-   N_("ticket file for user authentication"), 0},
-
-  {"debug", 'd', N_("FLAGS"), OPTION_ARG_OPTIONAL,
-   N_("debug flags (defaults to \"" D_DEFAULT "\")"), 0},
-
-  {"verbose", 'v', NULL, 0,
-   N_("log all actions"), 0},
-
-  {"line-info", ARG_LINE_INFO, N_("BOOL"), OPTION_ARG_OPTIONAL,
-   N_("print source location along with action logs (default)") },
-   
-  {"email", 'e', N_("ADDRESS"), 0,
-   N_("override user email address"), 0},
-  {"expression", 'E', NULL, 0,
-   N_("treat SCRIPT as Sieve program text"), 0},
-  
-  {"no-program-name", ARG_NO_PROGRAM_NAME, NULL, 0,
-   N_("do not prefix diagnostic messages with the program name"), 0},
-  
-  {0}
-};
-
 int keep_going;
 int compile_only;
 char *mbox_url;
@@ -112,17 +58,6 @@ int expression_option;
 static int sieve_print_locus = 1; /* Should the log messages include the
                                     locus */
 
-static int
-is_true_p (char *p)
-{
-  int rc;
-  if (!p)
-    return 1;
-  if ((rc = mu_true_answer_p (p)) == -1)
-    return 0;
-  return rc;
-}
-
 static void
 set_debug_level (const char *arg)
 {
@@ -164,98 +99,88 @@ set_debug_level (const char *arg)
     }
 }
 
-int
-mu_compat_printer (void *data, mu_log_level_t level, const char *buf)
+static void
+cli_dry_run (struct mu_parseopt *po, struct mu_option *opt, char const *arg)
 {
-  fputs (buf, stderr);
-  return 0;
+  sieve_debug |= MU_SIEVE_DRY_RUN;
+  verbose = 1;
 }
 
-static error_t
-parser (int key, char *arg, struct argp_state *state)
+static void
+cli_compile_and_dump (struct mu_parseopt *po, struct mu_option *opt,
+                     char const *arg)
 {
-  static mu_list_t lst;
-  
-  switch (key)
-    {
-    case 'E':
-      expression_option = 1;
-      break;
-      
-    case 'e':
-      mu_argp_node_list_new (lst, "email", arg);
-      break;
-      
-    case 'n':
-      sieve_debug |= MU_SIEVE_DRY_RUN;
-      mu_argp_node_list_new (lst, "verbose", "yes");
-      break;
-
-    case 'k':
-      mu_argp_node_list_new (lst, "keep-going", "yes");
-      break;
-
-    case 'c':
-      compile_only = 1;
-      break;
-
-    case 'D':
-      compile_only = 2;
-      break;
-      
-    case 'f':
-      mu_argp_node_list_new (lst, "mbox-url", arg);
-      break;
-      
-    case 't':
-      mu_argp_node_list_new (lst, "ticket", arg);
-      break;
-      
-    case 'd':
-      mu_argp_node_list_new (lst, "debug", arg ? arg : D_DEFAULT);
-      break;
-
-    case 'v':
-      mu_argp_node_list_new (lst, "verbose", "yes");
-      break;
-
-    case ARG_LINE_INFO:
-      mu_argp_node_list_new (lst, "line-info",
-                            is_true_p (arg) ? "yes" : "no");
-      break;
-
-    case ARG_NO_PROGRAM_NAME:
-      mu_log_tag = NULL;
-      break;
-      
-    case ARGP_KEY_ARG:
-      if (script)
-       argp_error (state, _("Only one SCRIPT can be specified"));
-      script = mu_tilde_expansion (arg, MU_HIERARCHY_DELIMITER, NULL);
-      break;
-
-    case ARGP_KEY_INIT:
-      mu_argp_node_list_init (&lst);
-      break;
-      
-    case ARGP_KEY_FINI:
-      mu_argp_node_list_finish (lst, NULL, NULL);
-      break;
-      
-    default:
-      return ARGP_ERR_UNKNOWN;
-    }
+  compile_only = 2;
+}
 
-  return 0;
+static void
+cli_debug (struct mu_parseopt *po, struct mu_option *opt, char const *arg)
+{
+  set_debug_level (arg);
 }
 
-static struct argp argp =
+static void
+cli_email (struct mu_parseopt *po, struct mu_option *opt, char const *arg)
 {
-  options,
-  parser,
-  N_("SCRIPT"),
-  doc
-};
+  int rc = mu_set_user_email (arg);
+  if (rc)
+    mu_parseopt_error (po, _("invalid email: %s"), mu_strerror (rc));
+}
+
+static void
+cli_no_program_name (struct mu_parseopt *po, struct mu_option *opt,
+                    char const *arg)
+{
+  mu_log_tag = NULL;
+}
+
+static struct mu_option sieve_options[] = {
+  { "no-actions", 'n', NULL, MU_OPTION_DEFAULT,
+    N_("do not execute any actions, just print what would be done"),
+    mu_c_string, NULL, cli_dry_run },
+  { "dry-run", 0, NULL, MU_OPTION_ALIAS },
+  { "keep-going", 'k', NULL, MU_OPTION_DEFAULT,
+    N_("keep on going if execution fails on a message"),
+    mu_c_bool, &keep_going },
+  { "compile-only", 'c', NULL, MU_OPTION_DEFAULT,
+    N_("compile script and exit"),
+    mu_c_bool, &compile_only },
+  { "dump", 'D', NULL, MU_OPTION_DEFAULT,
+    N_("compile script, dump disassembled sieve code to terminal and exit"),
+    mu_c_string, NULL, cli_compile_and_dump },  
+  { "mbox-url", 'f', N_("MBOX"), MU_OPTION_DEFAULT,
+    N_("mailbox to sieve (defaults to user's mail spool)"),
+    mu_c_string, &mbox_url },
+  { "ticket", 't', N_("TICKET"), MU_OPTION_DEFAULT,
+    N_("ticket file for user authentication"),
+    mu_c_string, &mu_ticket_file },
+  { "debug", 'd', N_("FLAGS"), MU_OPTION_ARG_OPTIONAL,
+    N_("debug flags (defaults to \"" D_DEFAULT "\")"),
+    mu_c_string, NULL, cli_debug },
+  { "verbose", 'v', NULL, MU_OPTION_DEFAULT,
+    N_("log all actions"), 
+    mu_c_bool, &verbose },
+  { "line-info", 0, N_("BOOL"), MU_OPTION_DEFAULT,
+    N_("print source location along with action logs (default)"),
+    mu_c_bool, &sieve_print_locus },
+  { "email", 'e', N_("ADDRESS"), MU_OPTION_DEFAULT,
+    N_("override user email address"),
+    mu_c_string, NULL, cli_email }, 
+  { "expression", 'E', NULL, MU_OPTION_DEFAULT,
+    N_("treat SCRIPT as Sieve program text"), 
+    mu_c_bool, &expression_option },
+  { "no-program-name", 0, NULL, MU_OPTION_DEFAULT,
+    N_("do not prefix diagnostic messages with the program name"),
+    mu_c_string, NULL, cli_no_program_name },
+  MU_OPTION_END
+}, *options[] = { sieve_options, NULL };
+
+int
+mu_compat_printer (void *data, mu_log_level_t level, const char *buf)
+{
+  fputs (buf, stderr);
+  return 0;
+}
 
 
 static int 
@@ -307,18 +232,24 @@ static struct mu_cfg_param sieve_cfg_param[] = {
 };
 
 
-static const char *sieve_argp_capa[] =
-{
-  "mailutils",
-  "common",
+static char *sieve_argp_capa[] = {
   "debug",
   "mailbox",
   "locking",
   "logging",
   "mailer",
+  "tls",
+  "sieve",
   NULL
 };
 
+static struct mu_cli_setup cli = {
+  options,
+  sieve_cfg_param,
+  N_("GNU sieve -- a mail filtering tool."),
+  "SCRIPT"
+};
+
 static void
 _sieve_action_log (void *unused,
                   mu_stream_t stream, size_t msgno,
@@ -456,25 +387,29 @@ main (int argc, char *argv[])
   /* Native Language Support */
   MU_APP_INIT_NLS ();
 
-  mu_argp_init (NULL, NULL);
-#ifdef WITH_TLS
-  mu_gocs_register ("tls", mu_tls_module_init);
-#endif
-  mu_gocs_register ("sieve", mu_sieve_module_init);
+  mu_cli_capa_register (&mu_cli_capa_tls);
+  mu_cli_capa_register (&mu_cli_capa_sieve);
   mu_sieve_debug_init ();
   
   mu_register_all_formats ();
 
-  if (mu_app_init (&argp, sieve_argp_capa, sieve_cfg_param, 
-                  argc, argv, ARGP_IN_ORDER, NULL, NULL))
-    exit (EX_USAGE);
-  
-  if (!script)
+  mu_cli (argc, argv, &cli, sieve_argp_capa, NULL, &argc, &argv);
+
+  if (argc == 0)
     {
       mu_error (_("script must be specified"));
       exit (EX_USAGE);
     }
-  
+  else if (argc == 1)
+    {
+      script = mu_tilde_expansion (argv[0], MU_HIERARCHY_DELIMITER, NULL);
+    }
+  else
+    {
+      mu_error (_("only one SCRIPT can be specified"));
+      exit (EX_USAGE);
+    }
+
   /* Sieve interpreter setup. */
   rc = mu_sieve_machine_init (&mach);
   if (rc)


hooks/post-receive
-- 
GNU Mailutils



reply via email to

[Prev in Thread] Current Thread [Next in Thread]